Found by review on #230.
writeDeliveredFileSet (packages/cli/src/rules/deliver.ts) writes every file in the delivered set and removes nothing. A file already on disk that the set does not mention survives the write.
For rule create and rule iterate that is unremarkable. For the repair path added in #230 it matters more, because the reason we are writing at all is that the directory's trustworthiness is in question: an unsafe verdict means the on-disk rule diverged from what the server blessed.
Only check.ts is signed and reconciled. So a stray file elsewhere in the rule directory — a leftover under captures/, say — is never reported by reconcile, is not replaced by the repair, and goes on affecting what the rule matches. The rule reads as repaired and is not.
The delivery schema's own words point at the fix: files is described as "Every file the rule directory must contain". If that is the contract, the write should make the directory match the set rather than merge into it.
Not done in #230, because deleting files inside a repair needs its own care (scoped strictly to the rule directory, and with the create/iterate callers considered — they share the helper). #230 instead states only what it did: the notice says the check was rewritten with the blessed bytes rather than claiming the rule was restored.
Worth deciding as one question for all three callers rather than special-casing repair.
Found by review on #230.
writeDeliveredFileSet(packages/cli/src/rules/deliver.ts) writes every file in the delivered set and removes nothing. A file already on disk that the set does not mention survives the write.For
rule createandrule iteratethat is unremarkable. For the repair path added in #230 it matters more, because the reason we are writing at all is that the directory's trustworthiness is in question: anunsafeverdict means the on-disk rule diverged from what the server blessed.Only
check.tsis signed and reconciled. So a stray file elsewhere in the rule directory — a leftover undercaptures/, say — is never reported by reconcile, is not replaced by the repair, and goes on affecting what the rule matches. The rule reads as repaired and is not.The delivery schema's own words point at the fix:
filesis described as "Every file the rule directory must contain". If that is the contract, the write should make the directory match the set rather than merge into it.Not done in #230, because deleting files inside a repair needs its own care (scoped strictly to the rule directory, and with the create/iterate callers considered — they share the helper). #230 instead states only what it did: the notice says the check was rewritten with the blessed bytes rather than claiming the rule was restored.
Worth deciding as one question for all three callers rather than special-casing repair.