fix(apm): commit the hook ownership sidecar so fresh installs stay idempotent

apm recognises its own settings.json hook entries only through the
.claude/apm-hooks.json sidecar. With the sidecar gitignored, apm install
in a fresh clone keeps the committed SessionStart entry as user-owned and
appends a duplicate, so apm audit --ci reports drift and the apm-audit-ci
pre-push hook fails. Reproduced on main and this branch with apm 0.28.0.

Commit the sidecar in apm's exact serialisation, exclude it from
pretty-format-json alongside settings.json, and record the correction
in ADR-0019.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-16 15:26:56 +00:00
parent 55221d099f
commit 3a9d257225
4 changed files with 37 additions and 8 deletions

View File

@@ -187,6 +187,16 @@ settings file remains committed, now with apm-generated content in it. ADR-0018'
committed content is exactly `{"hooks": {}}` is superseded on that point only — the rule it was
protecting, that nothing repo-authored goes in that file, is unchanged.
> **Correction (2026-09-16) — the sidecar is committed, not ignored.** apm keeps no ownership marker
> inside `settings.json`; it recognises its own entries by matching them against
> `.claude/apm-hooks.json`, then replaces them. With the sidecar gitignored, a fresh clone holds the
> committed `SessionStart` entry but no sidecar, so `apm install` treats the entry as user-owned,
> keeps it, and adds its own identical copy. `apm audit --ci` then reports `settings.json` drift and
> the `apm-audit-ci` pre-push hook fails. Reproduced on `main` (`a712f2c`) and on this branch with
> apm 0.28.0; committing the sidecar makes the install idempotent and the audit pass. The sidecar
> is apm output like the settings entry it describes, so it is committed for the same reason and
> changes only when the owning package is renamed or moved. `.claude/hooks/` stays ignored.
**Native consumers are protected by a guard, not by the gate.** A host installing holocron through
`claude plugin install` auto-discovers `hooks/hooks.json` and does not consult apm's trust gate at
all. The script therefore exits silently when there is no `apm.lock.yaml` in the working directory,