Design question: a CLI installer adds a small fixed set of exact tool-permission allow rules to a JSON settings file that users also edit by hand. Repair and uninstall must be idempotent and must never remove an allow rule the user had before install, never touch explicit deny rules, and never clobber concurrent hand edits.
The hard part is crash safety. The installer keeps an ownership journal recording which rules it introduced, but the journal write and the settings write are two separate file writes, so a crash can land between them. Journal-first risks over-claiming (a claim on a rule that was never written; if the user later adds that rule themselves, uninstall silently deletes their config). Settings-first risks under-claiming (an installed rule with no claim, left behind forever as residue).
Working hypothesis: bias every ambiguity toward "not ours" — two-phase journal entries (pending / owned / preexisting), a content fingerprint of the settings file captured before the write to disambiguate some pending entries on recovery, pending never promoted to owned during recovery, and uninstall refusing to remove anything when the journal is missing rather than falling back to removal-by-presence. Corollary framing: the journal is a permission-to-delete list, so absence of proof means no deletion, and residue is the acceptable failure mode.
Unknowns: whether folding the ownership record into a namespaced key inside the settings file itself (collapsing both writes into one atomic rename, eliminating the window) is worth polluting user config and risking schema-validation stripping; and how repair should treat a rule the user deliberately deleted after install.
Related prior conversations Revised hypothesis on write ordering. My opening framed journal-first vs settings-first as a symmetric trade (over-claim risks deleting user config, under-claim risks residue) and leaned toward settings-first as the safer single write. That framing was incomplete in one direction: an installed rule with no ownership record is not merely residue, because the *next* install observes it already present and records it as pre-existing, which promotes it to permanently unremovable. So under-claiming is not self-healing, it is self-cementing. That asymmetry breaks the tie in favor of journal-first.
The remaining objection to journal-first — a dangling claim on a rule that was never written becomes dangerous if the user later authors that same rule by hand, since uninstall would then delete their line — is answered by state rather than by ordering. The dangling entry must stay in the pending/intent state and must never be promoted to owned during recovery. Repair may re-attempt the write and only then claim ownership cleanly; uninstall treats pending as not-ours and leaves the rule alone. Combined: order journal first, but let only a completed write produce a removable claim.
Corollary worth stating as an invariant: the journal must record the *observed prior state* at the moment of observation (absent / already-present / explicitly-denied), not just the intent to add. Provenance cannot be reconstructed later from the file contents, because an installer-authored rule string and a user-authored one are identical. A distinct pre-existing/disclaimer entry is as load-bearing as a claim, since it is what stops a subsequent repair from adopting a user's rule.
Still uncertain: whether repair should re-add a rule the user deliberately deleted post-install (argues for a tombstone on user-initiated removal), and whether folding the ownership record into a namespaced key inside the settings file — collapsing both writes into one atomic rename and eliminating the window entirely — is worth the risk of schema validation stripping the unknown key.
No tests executed; this is invariant reasoning only.
New case in the same design: the user modifies an installer-owned rule AND edits unrelated parts of the settings file before uninstall. Three findings, all reasoning about invariants, no tests executed.
1. Unifying rule for write ordering across both directions: the claim's lifetime must strictly contain the effect's lifetime. That yields journal-first on install (claim begins before the effect exists) and journal-last on uninstall (claim ends after the effect is gone), which look opposite but are the same invariant. The failure mode it rules out is identical in both directions — an effect present in the file with no surviving ownership record, which the next install re-observes as pre-existing and thereby cements as permanently unremovable.
2. Two fingerprints that are easy to conflate, and conflating them is the actual bug this case exposes. The narrow effect fingerprint (the exact rule at its recorded path and scope) is the only thing allowed to gate removal. The broad file fingerprint is for compare-and-swap during writes and for crash disambiguation only, and must never be a precondition for removal — otherwise any unrelated edit the user makes between install and uninstall blocks cleanup forever. The corollary is that uninstall must be a targeted structural edit at the recorded path, never a restore of an install-time file snapshot, since a snapshot restore silently reverts the user's unrelated work.
3. Recovery asymmetry between install and uninstall. A dangling install intent is not decidable by observation, because ownership itself was what was in doubt, so it must downgrade to not-ours. A dangling uninstall intent is decidable, because ownership was already proven by a completed install, so recovery just re-runs the comparison and resumes.
Residual race worth flagging rather than claiming solved: if the user hand-adds the identical rule string after the uninstall's settings write but before the journal prune, recovery sees an intent-to-remove entry with a byte-identical effect present and would delete the user's line. Partial mitigation is to attribute presence by checking whether the file changed after the recorded removal, treating any change as someone else's authorship and preserving. That narrows the window but does not close it; closing it in general seems to require the ownership record and the effect to live in one atomic write.
Uncertain: whether duplicated instances of an owned rule should yield removal of exactly one instance or removal of none. Leaning toward none plus a reported conflict, since the instances are indistinguishable and residue is the recoverable direction.