build: no gate asserts that tool-owned paths stay out of autofixing formatter scope #102
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Surfaced while fixing an
apm audit --cifailure on branchrefactor/trim-skills-agents-context(see that PR).The failure mode
.claude/settings.jsonis apm-owned per ADR-0018/0019 — its committed content must be exactly what apm writes. Butpretty-format-json --autofixin.pre-commit-config.yamlsorts JSON object keys unless--no-sort-keysis passed, and itsexclude:pattern listed fifteen generated manifests without listing this one.So from commit
2e395a4onward — the commit that first wrote aSessionStarthook entry into that file — apm's insertion-ordered output was silently re-sorted on the way into every commit. apm replayed the install, produced its own key order, and reported drift against a file no human had touched.Content was byte-identical throughout. Only key order differed.
Why this failure mode is unusually bad
The drift never appears in
git diff. The file matchedHEADexactly, so every instinct says nothing changed here. The real diff exists only between the formatter's input and its output, which nothing stores.The fix is self-undoing. Correcting the file alone does not work — the hook re-breaks it during staging. The exclude has to land in the same commit as the corrected content.
The structural gap
.claude/settings.jsonwas the sixteenth exclude on that hook, and nothing prevents a seventeenth. This repo gates several drift classes deterministically:check-plugin-content-synccheck-marketplace-mirror-synccheck-vale-style-synccheck-scope-walkup-synccheck-executables-allow-syncThere is no equivalent gate asserting that tool-owned paths stay out of autofixing hook scope. Any future path a tool claims ownership of — a new apm-deployed file, a generated manifest, a compiled artifact — silently acquires this bug unless someone remembers to add an exclude at the moment ownership is declared.
Possible shapes (not a decision)
check-formatter-scope-sync.shpre-push hook that derives the set of tool-owned paths (apm deployment ledger, generated-manifest lists) and asserts each one is excluded from every autofixing hook in.pre-commit-config.yaml.--no-sort-keysglobally and make key-sorting opt-in per path. Smaller mechanism, but it reformats every other JSON file in the repo, so it needs its own migration.This is arguably ADR-sized, since it is a decision about how far deterministic drift gating extends.
Automated note from the PR #135 review follow-up. This issue's own conclusion, state and labels are untouched — this comment only records which of the gates it cites still exist, so the issue stays actionable.
Three of the five precedent gates are gone
Still present:
check-scope-walkup-synccheck-executables-allow-syncDeleted by PR #135's ADR-0024 / ADR-0025 work:
check-plugin-content-synccheck-marketplace-mirror-synccheck-vale-style-syncThe argument this issue makes from precedent still stands on the two surviving gates, but three of the five examples will not resolve any more and should be re-pointed or dropped when the issue is picked up.
Nothing else in this issue was re-validated.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01NwD8Egs5r4ndqeFLmhusX2