Fifth failure: uninstall removes a rule the developer intentionally modified, destroying their work.
Scenario: Installer records ownership of rule R with content C1. Developer manually changes R to content C2 because their workflow needs a variation. Developer also edits unrelated settings. When uninstall runs, it finds R in the journal, sees R still exists in settings, and removes it, destroying the user's modification. The developer loses work and may not notice until the modified behavior is missing.
Prevention requires compare-before-remove: before removing an owned rule, retrieve its current content and compare it to the content recorded in the journal at install time. Three outcomes:
- Content matches exactly: the rule is unmodified since install, safe to remove.
- Rule is absent: already handled by the tombstone mechanism described in the second refinement.
- Content differs: the developer has modified the rule. Removing it would destroy their work.
For case three, the installer must preserve the modified version. The safest behavior is to skip removal, log an ownership conflict message identifying the rule and explaining that the modified version was preserved, and mark the journal entry as released so repair does not attempt to restore the original. This protects user work at the cost of leaving a modified rule behind, which is the correct tradeoff because uninstall should never destroy data the user created.
An alternative is to prompt the user, but non-interactive uninstall contexts such as package manager automation cannot prompt, so the preserve-by-default strategy is more robust.
The journal entry must record the exact installed content to make this comparison possible. A cryptographic hash alone is insufficient because the installer cannot regenerate the original content from the hash to show the user what changed. Recording the full rule content in the journal allows both comparison and user-facing diff output in the conflict log.
Partially completed uninstall recovery follows the same two-phase commit pattern as install. The uninstall operation writes a pending record to the journal containing the rules to be removed and a fresh random witness token, updates settings with the witness included, then on successful settings write marks the journal record as completed.
If uninstall crashes between the two writes, recovery on the next run detects the incomplete operation. The journal shows pending removal, the settings file either contains the witness proving the removals landed or does not contain it proving they did not. Two recovery paths:
- Witness is present: the removals landed, but the journal record was never marked complete. Mark it complete now and proceed. Do not attempt to remove rules again.
- Witness is absent: the removals did not land, the settings file is unchanged. Attempt the removal again, generating a new witness token for the new attempt. The old witness can never appear because the write failed.
Compare-before-remove applies during recovery exactly as in normal uninstall. If a rule the journal says should be removed has been modified since install, preserve it and log the conflict, even in the recovery path. This handles the case where the crash happened after partial removal: some rules removed, some not, and the user edited one of the not-yet-removed rules before the next run. Modified rules stay protected regardless of timing.
The journal structure for uninstall must include the operation type distinguishing install from uninstall, the random witness token expected in settings, the list of rules to remove each with full content for comparison, and the operation status pending or completed. On completion, the installer can either retain the completed record for audit or delete it since it no longer affects future operations.
One edge case: the witness metadata key itself should not be removed until after all rule removals and the journal completion write. If the installer removes the witness first and then crashes, recovery cannot distinguish landed from not landed. Remove rules first, mark journal complete, then remove witness as a final cleanup step. If the witness removal crashes, the next run sees a completed uninstall and a stale witness, which it can safely delete.
This prevents uninstall from destroying user edits, makes uninstall recoverable from crash at any point, and maintains the invariant that any interrupted operation is either fully completed or safely retried without duplication or data loss.