docs: correct the apm-only change after a five-agent review
A five-agent review of718c79aandd2480b8found no skill, agent or hook regressions (39 skills before and after) and confirmed both hook removals are genuinely moot -- verified against the tree, not taken on the commit's word. It did find one functional regression (fixed separately) and this documentation drift. Counting errors, all from a git pathspec `*` crossing `/`: - 17 .bats files shipped to consumers is really 10; 17 counted tracked paths merely containing /tests/, one of them a template asset - "roughly 88s off every push" is ~92.4s; 88 omitted validate-plugins - "roughly 70% of each plugin remains live" holds only for kyberforge; the real spread is 44.3% (bin) to 70.6%, now a table - the pre-push enforcement row was half-corrected: 33 entries stood unstruck (now 27) and 14 -> 11 switched counting basis mid-sentence - the root .claude-plugin/plugin.json was described as "kept"; it has never been tracked gates.md said "Ten hooks" above a nine-row table (11 was decremented for one removal, not two), and "both need the claude CLI" for one remaining validator. Its pretty-format-json exclude rationale claimed six alternations expanding to sixteen files in a passage headed "Mind which number you are quoting" -- four alternations, two live files; the two dead ones are dropped from the pattern. check-useless-excludes could not catch this: it only flags an exclude matching nothing at all. ADR-0024 cited ADR-0006 for a patch-bump rule it does not contain and which ADR-0015 explicitly retired; stated apm's marketplace probe order backwards (.claude-plugin/ is the last candidate, not the first, so the earlier .github/plugin/ deletion only demoted resolution); undercounted apm's skill-deploying targets as seven when there are fifteen; and never recorded that validate-plugins was removed. The symlink hedge is resolved: apm_cli/security/gate.py's ignore_non_content() drops symlinks silently on deploy while apm_modules/ materialization dereferences them, so content survives that far and vanishes at install. Accepted with no replacement guard, per decision -- kyberforge/docs/hooks.md previously asserted a guard that had been deleted with its script. Four plugin READMEs still advertised `claude plugin install`; ADRs 0001, 0006, 0013, 0014, 0015 and 0019 described deleted machinery in the present tense, 0019 most consequentially as the live justification for the SessionStart hook's .apm/ path. CONTEXT.md's "apm package" entry forbade "plugin" while using it in its own body, and "Output profile" lost the antecedent for "one catalogue serves both". run-tests.sh gains the .claude/skills/ exclusion run-bats.sh already had. Latent today -- no test-*.sh lives under any .apm/skills/*/tests/ -- but apm now deploys those directories, so one would be discovered twice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YR2CjVumUbEGWcMikcoXBD
This commit is contained in:
@@ -5,9 +5,10 @@ as this repo's authoring source of truth) and, for plugin-scope agent files spec
|
||||
ADR-0016 (plugin-scope `.apm/agents/*.agent.md` drops provider-specific fields). Since issue
|
||||
#90's conversion executed, plugin content is authored under `plugins/<name>/apm.yml` +
|
||||
`.apm/{skills,agents,hooks}/` — not the flat `skills/`/`agents/` layout this ADR describes —
|
||||
and `.claude-plugin/plugin.json`/`.github/plugin/plugin.json` are compiled output of `apm pack`,
|
||||
not hand-authored. This ADR's content is kept below as the historical record of the
|
||||
pre-APM decision; it is no longer the current model.
|
||||
and `.claude-plugin/plugin.json`/`.github/plugin/plugin.json` were compiled output of `apm pack`,
|
||||
not hand-authored — and as of ADR-0024 (2026-09-14) both are deleted, along with native
|
||||
`claude plugin install` support; `apm install` is the only route. This ADR's content is kept
|
||||
below as the historical record of the pre-APM decision; it is no longer the current model.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -11,6 +11,11 @@ divergence is no longer possible by construction. `plugin-author`, the skill tha
|
||||
invariant, is deleted per ADR-0015 rather than adapted. Kept below as the historical record of
|
||||
the pre-APM decision.
|
||||
|
||||
**Fully void as of ADR-0024 (2026-09-14).** Both manifests are now deleted outright, so the two
|
||||
files this ADR was about no longer exist in any form, compiled or hand-authored. `apm.yml`'s
|
||||
`version:` is the only version field a plugin has. This ADR states no patch-bump rule and never
|
||||
did — ADR-0015 retired that rule explicitly; do not cite this ADR as the source of one.
|
||||
|
||||
---
|
||||
|
||||
Each plugin has two manifests: `plugin.json` (Copilot CLI) and `.claude-plugin/plugin.json` (Claude Code). Both tools support a `version` field. Prior to this decision, only the CC manifest carried `version`; the Copilot manifest omitted it.
|
||||
|
||||
@@ -22,8 +22,10 @@ spec-governed content, and `plugin.json` is JSON, not prose Vale can meaningfull
|
||||
|
||||
**Rule categories are prose-pattern-matchable only.** Structural, schema, and security concerns
|
||||
stay out of this Vale-based harness because this repo already has dedicated tools for them:
|
||||
`skill-frontmatter` (required frontmatter fields), `validate-plugins`/`validate-marketplace`
|
||||
`skill-frontmatter` (required frontmatter fields), `validate-marketplace`
|
||||
(`claude plugin validate --strict`, schema), and `gitleaks`/`detect-private-key` (secrets).
|
||||
(ADR-0024 removed the companion `validate-plugins` gate along with the per-plugin manifests it
|
||||
checked; the argument here is unaffected.)
|
||||
Duplicating those concerns as Vale rules would fight tools that already own them better.
|
||||
|
||||
**Governance docs are excluded as a rule source.** `docs/research/governance_principles/CONTROLS.md`
|
||||
|
||||
@@ -115,6 +115,9 @@ doesn't wonder if it was overlooked.
|
||||
- `plugins/kyberforge`'s `plugin.json` and `.claude-plugin/plugin.json` both patch-bump for every
|
||||
shipped content change (per ADR-0006's version-parity invariant): `1.2.5` for the relocation
|
||||
itself, `1.2.6` for the self-locating `vale-wrap.sh` that followed.
|
||||
**Amended 2026-09-14 (ADR-0024):** a record of what was done then, not current practice. Both
|
||||
manifests are deleted and `apm.yml`'s `version:` is a plugin's only version field; ADR-0015
|
||||
retired the parity/patch-bump rule this bullet invokes.
|
||||
- **`.pre-commit-hooks.yaml` entries are a bare script path and nothing else — a constraint, not a
|
||||
house style, and it binds every future hook here, not just the Vale two.** Since pre-commit
|
||||
rewrites only `entry[0]` into the hook-repo clone, no argument token in any entry can reference
|
||||
|
||||
@@ -180,4 +180,7 @@ correction) sorted what they document into three buckets:
|
||||
marketplace. The manifest-compilation deliverable this ADR describes was genuinely complete;
|
||||
runtime discoverability was not. Fixed in ADR-0017 (a second, compiled flat-directory content
|
||||
mirror at each plugin root, generated by `scripts/sync-plugin-content.sh`) — see that ADR for
|
||||
the root cause and the fix.
|
||||
the root cause and the fix. **Superseded 2026-09-14:** ADR-0024 deleted that mirror and its
|
||||
generator along with native `claude plugin install` support. The discoverability gap this
|
||||
paragraph describes is therefore no longer bridged — it is no longer a gap this repo has, because
|
||||
apm is now the only supported install path and apm reads `.apm/` directly.
|
||||
|
||||
@@ -105,6 +105,15 @@ resolves to the mirror, where the script does not exist — verified, apm report
|
||||
`plugins/kyberforge/hooks/` either: that directory is `rm -rf`'d by every content sync (ADR-0017).
|
||||
A test pins the reference.
|
||||
|
||||
> **Amendment (2026-09-14) — the mirror half of that reasoning is gone; the conclusion is not.**
|
||||
> ADR-0024 deleted the flat mirror and `scripts/sync-plugin-content.sh`, so neither the `apm pack`
|
||||
> mirror-filtering behaviour nor the `rm -rf` content sync described above still happens. The
|
||||
> reference must stay exactly as written, for the reason that survives independently: `.apm/` is the
|
||||
> sole hand-edited authoring source (ADR-0015), it is what ships in the installed package root, and
|
||||
> `plugins/kyberforge/hooks/` no longer exists at all — so `${CLAUDE_PLUGIN_ROOT}/hooks/...` still
|
||||
> names a path with nothing at it, now because the directory is gone rather than because a sync
|
||||
> emptied it. `tests/test-apm-current-hook.sh` still pins the literal string.
|
||||
|
||||
**Session startup gets slower when the install is stale.** Measured: ~0.7 s for the `apm outdated`
|
||||
check when everything is current, ~10.4 s when six packages are behind and the refresh runs. The
|
||||
hook declares `timeout: 380` to cover a cold multi-package fetch. That number is not free-standing:
|
||||
|
||||
@@ -28,12 +28,15 @@ What that audience costs is measurable:
|
||||
|---|---|
|
||||
| Tracked mirror files under `plugins/*/{skills,agents,hooks}/` | 213 files, ~20,000 lines |
|
||||
| `scripts/sync-plugin-content.sh` | 813 lines |
|
||||
| `tests/test-sync-plugin-content.sh` | 1,291 lines, 92 cases, ~83 seconds |
|
||||
| `tests/test-sync-plugin-content.sh` | 1,289 lines, 92 cases, ~83 s |
|
||||
| `scripts/lib/marketplace-plugins.sh` | helper, used only by the above |
|
||||
| `check-plugin-content-sync` pre-push hook | ~5 seconds per push |
|
||||
| `check-plugin-content-sync` pre-push hook | ~4.5 s per push |
|
||||
| `validate-plugins` pre-push hook | ~4.9 s per push (6 × `claude plugin validate --strict`) |
|
||||
|
||||
Roughly 22,000 lines of tracked content and tooling, and about 88 seconds on every push. The test
|
||||
alone is close to 30% of `run-tests`' wall time — the single largest item in it.
|
||||
Roughly 22,000 lines of tracked content and tooling, and about 92 seconds on every push (83 + 4.5 +
|
||||
4.9; the two hook timings are the 2026-09-10 baseline measurements recorded in
|
||||
`SIMPLIFICATION-AUDIT.md`, not re-measured here). The test alone is close to 30% of `run-tests`'
|
||||
wall time — the single largest item in it.
|
||||
|
||||
**The native path's automated gate does not gate anything.** ADR-0017 cites
|
||||
`claude plugin validate --strict` passing on all six plugins as one of two verifications. That
|
||||
@@ -50,8 +53,13 @@ not that the mirror works.
|
||||
cheap rather than a trade. apm's skills convergence deploys skills to `.agents/skills/<name>/SKILL.md`,
|
||||
the shared path read by Copilot, Cursor, Codex, Gemini, OpenCode and Windsurf, with Claude Code as
|
||||
the special case at `.claude/skills/`. The mirror served two hosts (Claude Code and Copilot, the
|
||||
latter only ever partially — see ADR-0017's own `hooks` amendment). apm serves seven. A consumer who
|
||||
installs holocron through apm gets strictly more than one who installed it natively.
|
||||
latter only ever partially — see ADR-0017's own `hooks` amendment). apm serves eleven through those
|
||||
two roots: ten targets resolve to `.agents/skills/` — the six named above plus `agent-skills`,
|
||||
`antigravity`, `hermes` and `openclaw`, which are rooted there natively rather than by an explicit
|
||||
`deploy_root` — and `claude` is the eleventh at `.claude/skills/`. Four further targets (`kiro`,
|
||||
`grok-build`, `grok-cloud`, `copilot-cowork`) deploy skills under roots of their own, for fifteen in
|
||||
total; counted from `apm_cli/integration/targets.py` this session. A consumer who installs holocron
|
||||
through apm gets strictly more than one who installed it natively.
|
||||
|
||||
**Verified empirically, not reasoned about.** In a scratch clone with the mirror and the six
|
||||
per-plugin manifest pairs deleted:
|
||||
@@ -81,6 +89,11 @@ load-bearing for apm resolution; they were load-bearing only for the native inst
|
||||
the six per-plugin manifest pairs (`.claude-plugin/plugin.json`, `.github/plugin/plugin.json`).
|
||||
- Delete `scripts/sync-plugin-content.sh`, `tests/test-sync-plugin-content.sh`,
|
||||
`scripts/lib/marketplace-plugins.sh`, and the `check-plugin-content-sync` pre-push hook.
|
||||
- Delete the `validate-plugins` pre-push hook (`claude plugin validate --strict` over every plugin
|
||||
directory). It is removed on the evidence above — it reads manifests only, so with the per-plugin
|
||||
manifest pairs gone it has nothing left to read, and even while they existed it could not detect
|
||||
the empty-content defect. `validate-marketplace`, which validates the one manifest this repo still
|
||||
ships, is **kept**.
|
||||
- **Keep** the root `marketplace:` block in `apm.yml` and the compiled
|
||||
`.claude-plugin/marketplace.json`. apm's own marketplace consumers read that same file; removing
|
||||
it would stop holocron being an apm marketplace at all.
|
||||
@@ -92,7 +105,7 @@ content is what ends native support; keeping the catalogue is what preserves apm
|
||||
|
||||
## Considered options
|
||||
|
||||
**Status quo — keep mirroring on every branch (rejected).** Pays ~22,000 tracked lines and ~88
|
||||
**Status quo — keep mirroring on every branch (rejected).** Pays ~22,000 tracked lines and ~92
|
||||
seconds per push for a path with no users and no working gate. It is not free in author attention
|
||||
either: ADR-0017 accrued four amendments in two days, every one of them about a detail of the
|
||||
mirroring mechanism rather than about the content being mirrored.
|
||||
@@ -106,7 +119,7 @@ exact shape: the `mattpocock-skills` entry removed from root `apm.yml` on 2026-0
|
||||
|
||||
Rejected on three grounds, stacking:
|
||||
|
||||
1. It keeps the 813-line script and the 1,291-line test alive in full. It reduces how often they
|
||||
1. It keeps the 813-line script and the 1,289-line test alive in full. It reduces how often they
|
||||
run, not how much there is to maintain — and the maintenance, not the runtime, is what ADR-0017's
|
||||
amendment history shows to be the real cost.
|
||||
2. It requires per-package tagging discipline this repo does not practise. `git tag` lists
|
||||
@@ -121,11 +134,20 @@ Rejected on three grounds, stacking:
|
||||
|
||||
**Also delete the marketplace catalogue (proposed, then rejected on evidence).** The initial shape
|
||||
of this decision deleted `.claude-plugin/marketplace.json` along with everything else, on the
|
||||
reasoning that it is a Claude Code artifact. That is wrong. `apm marketplace add` reads
|
||||
`.claude-plugin/marketplace.json` — falling back to `.github/plugin/marketplace.json`, which this
|
||||
repo already deleted — and that read is what makes holocron an apm marketplace and what gives
|
||||
consumers the `<name>@holocron` short-name form. Deleting it would have broken apm consumers in
|
||||
order to remove a file whose format Claude Code merely happens to share.
|
||||
reasoning that it is a Claude Code artifact. That is wrong. `apm marketplace add` probes
|
||||
`_MARKETPLACE_PATHS` in `apm_cli/marketplace/client.py` — `marketplace.json`, then
|
||||
`.github/plugin/marketplace.json`, then `.claude-plugin/marketplace.json`, first hit wins — and that
|
||||
read is what makes holocron an apm marketplace and what gives consumers the `<name>@holocron`
|
||||
short-name form. Deleting it would have broken apm consumers in order to remove a file whose format
|
||||
Claude Code merely happens to share.
|
||||
|
||||
Note the probe order: `.claude-plugin/marketplace.json` is the **last** resort, not the first, and
|
||||
the `.github/plugin/marketplace.json` this repo deleted earlier outranked it. That deletion was
|
||||
still inconsequential, but for a reason that has to be established rather than assumed — dropping a
|
||||
higher-priority candidate only demotes resolution to the next one, and a reviewer reproduced
|
||||
`apm marketplace add` against the post-deletion tree: it registered, found all 6 plugins, and
|
||||
resolved via `.claude-plugin/marketplace.json`. What would break is deleting the last candidate,
|
||||
which is exactly what this option proposed.
|
||||
|
||||
**Declare holocron an apm marketplace as a new step (moot).** Considered as a follow-on to the
|
||||
above, and found to be already done: the `marketplace:` block in root `apm.yml` *is* the
|
||||
@@ -145,7 +167,7 @@ README note is the only available mitigation, and a note is not a gate.
|
||||
|
||||
**2. Consumers now receive dev-fixture files.** apm installs from `.apm/`, and `.apm/` contains the
|
||||
per-skill `tests/` directories the mirror explicitly stripped (ADR-0017's depth-scoped
|
||||
`<category>/<name>/tests` exclusion). 17 `.bats` files across 6 skills therefore now deploy into
|
||||
`<category>/<name>/tests` exclusion). 10 `.bats` files across 6 skills therefore now deploy into
|
||||
every consumer's skill directories. Suppressing them would mean switching all six `apm.yml` files
|
||||
from `includes: auto` to explicit include lists — and an explicit list that is wrong silently drops
|
||||
content, which is the same failure class ADR-0017 was written to fix. Trading a cosmetic problem for
|
||||
@@ -157,9 +179,15 @@ now discoverable in the install output and would otherwise be found and double-r
|
||||
they do not belong to — exactly the `apm_modules/` problem ADR-0018 recorded, arriving by a second
|
||||
route. Any future script that walks this repo's tree needs both exclusions.
|
||||
|
||||
**4. No version bumps.** ADR-0006 patch-bumps a plugin when its shipped content changes. Nothing
|
||||
under `.apm/` is touched here; only compiled artifacts are removed. The shipped content is
|
||||
byte-identical, so no bump is owed. This also avoids triggering the `executables.allow`
|
||||
**4. No version bumps.** There is no standing rule that would require one. The patch-bump-on-content-
|
||||
change convention this repo once followed was ADR-0006's, and ADR-0015 explicitly retired it as a
|
||||
dual-manifest artifact: "Conventions that existed only because of hand-authored dual manifests
|
||||
(ADR-0006's version-parity/patch-bump rule …) are obsolete under `apm.yml`'s single-manifest model
|
||||
and were deliberately dropped." ADR-0015 also records that apm "has no native version-bump
|
||||
automation at all", so nothing mechanical demands one either. What remains is the substantive test,
|
||||
and it is satisfied independently: nothing under `.apm/` is touched here, only compiled artifacts are
|
||||
removed, so the content every apm consumer receives is byte-identical before and after. This also
|
||||
avoids triggering the `executables.allow`
|
||||
`kyberforge#<version>` pin cascade ADR-0019 describes, which would otherwise turn a cleanup into a
|
||||
multi-file coordinated edit for no functional gain.
|
||||
|
||||
@@ -195,14 +223,32 @@ because each was a decision someone spent real effort on:
|
||||
- The `hooks/hooks.json` path-correction amendment (2026-08-14) is moot: there is no mirrored hooks
|
||||
file to place.
|
||||
- The symlink amendment (2026-08-14) is **not** moot, and this is the one real regression.
|
||||
`check_apm_symlinks()` read the `.apm/` source tree directly to report symlinks, because apm's
|
||||
bundle exporter filters them out silently and the resulting content loss is invisible to any
|
||||
mirror-versus-mirror diff. That check dies with the script. Whether `apm install`'s own copy path
|
||||
drops symlinks the same way the bundle exporter does was **not verified this session** — the
|
||||
exporter's `is_file() and not is_symlink()` test is in `apm_cli/bundle/plugin_exporter.py`, a
|
||||
different code path from dependency installation. If it does, symlinked content under `.apm/` is
|
||||
now silently lost with nothing reporting it. No symlink exists under any `.apm/` today, so this is
|
||||
a latent gap rather than an active one, but it should be re-checked before anyone adds one.
|
||||
`check_apm_symlinks()` read the `.apm/` source tree directly to report symlinks, because apm
|
||||
filters them out silently and the resulting content loss is invisible to any mirror-versus-mirror
|
||||
diff. That check dies with the script.
|
||||
|
||||
A previous revision of this ADR left open whether `apm install`'s own copy path drops symlinks the
|
||||
way the bundle exporter does. It does, and the mechanism is now confirmed by reading the installed
|
||||
apm source. Deployment filters them: `ignore_non_content()` in `apm_cli/security/gate.py` is a
|
||||
`shutil.copytree` ignore callback whose docstring states "Excludes symlinks (security)", and
|
||||
`apm_cli/integration/skill_integrator.py` passes it — or the equivalent `_build_copy_ignore()` —
|
||||
to every `copytree` that materialises a skill (`:424`, `:791`, `:1152`), with further per-file
|
||||
`is_symlink()` drops for `bin/` entries and the plugin manifest at `:1671` and `:1696`. None of
|
||||
these log the skip. Materialization into `apm_modules/`, by contrast, **dereferences**: for git
|
||||
sources `deps/github_downloader.py` copies the checkout out with `robust_copytree`/`robust_copy2`
|
||||
and no symlink filter, and for local sources `install/phases/local_content.py`'s
|
||||
`_copy_tree_dereferencing_validated()` resolves each in-package symlink and copies its content as
|
||||
a real file (erroring on dangling, escaping or circular ones). So a symlink under `.apm/` survives
|
||||
into `apm_modules/` as real content and is then silently dropped on deploy — the failure is at the
|
||||
deploy step, not the fetch, which is why it would not show up in a cache inspection.
|
||||
|
||||
**This is accepted, and no replacement guard is added.** No symlink exists under any `.apm/`
|
||||
today, and the mitigations available are worse than the exposure: a standalone repo-side checker
|
||||
would be a new script to maintain for a condition that has never occurred, and it could only warn,
|
||||
since the drop happens inside apm. The operative rule is therefore a convention rather than a
|
||||
gate: do not introduce a symlink under any `plugins/*/.apm/` tree. If one is ever needed, the
|
||||
filtering above is the reason it will not reach consumers, and closing the gap properly means an
|
||||
upstream change in apm, not a local one.
|
||||
|
||||
**8. ADR-0017's own exit condition was different from this one, and that is worth noting.** Its
|
||||
final consequence anticipated deletion, but conditioned it on an upstream fix: "a future apm release
|
||||
|
||||
@@ -38,7 +38,7 @@ a PR merged through Gitea's merge button, where no local push happens at all.
|
||||
|
||||
## The pre-push gate
|
||||
|
||||
Ten hooks, grouped below by what they guard rather than by the order `.pre-commit-config.yaml` declares them in.
|
||||
Nine hooks, grouped below by what they guard rather than by the order `.pre-commit-config.yaml` declares them in.
|
||||
|
||||
**Core checks**
|
||||
|
||||
@@ -70,7 +70,7 @@ drift in generated text.
|
||||
| `apm-audit-ci` | `apm audit --ci` once per manifest — root plus each of the six plugin packages |
|
||||
| `apm-pack-check-clean` | `apm pack --check-versions --check-clean --dry-run` — the compiled marketplace still matches what `apm.yml` + `.apm/` would generate, and per-package versions agree with the `per_package` strategy |
|
||||
|
||||
**Host validators** (both need the `claude` CLI on PATH)
|
||||
**Host validators** (needs the `claude` CLI on PATH)
|
||||
|
||||
| Hook | Guards |
|
||||
|---|---|
|
||||
@@ -116,9 +116,9 @@ git ls-files | grep -E '^plugins/[^/]+/\.apm/skills/.*SKILL\.md$' \
|
||||
```
|
||||
|
||||
The first count equals the number of skill directories (`ls -d plugins/*/.apm/skills/*/ | wc -l`);
|
||||
the second returns exactly the template. The remaining unmatched `SKILL.md` files in the tree are the
|
||||
generated flat mirror, which is excluded by the `.apm/` segment on purpose — a mirror edit is drift,
|
||||
not an authoring change.
|
||||
the second returns exactly the template. Every other tracked `SKILL.md` in the tree is one of the
|
||||
four vendored `plugins/kyberforge/docs/research/examples/skill-write/` corpus files, excluded by the
|
||||
`.apm/skills/` segment — the first of the two deliberate exclusions above.
|
||||
|
||||
### Two independent gate families, neither replaced the other
|
||||
|
||||
@@ -613,9 +613,11 @@ Two prefilter hooks, with `.apm/`-scoped `files:` patterns:
|
||||
| `vale-audit-prefilter-skill` | `^plugins/[^/]+/\.apm/skills/[^/]+/SKILL\.md$` |
|
||||
| `vale-audit-prefilter-agent` | `^plugins/[^/]+/\.apm/agents/[^/]+\.agent\.md$` |
|
||||
|
||||
Only the **authoring source** triggers them. A `SKILL.md` in the generated flat mirror matches
|
||||
neither pattern, so prose findings surface only when you edit the file you are supposed to be
|
||||
editing. Without the binary the hooks fail with a bare "command not found" and no install pointer.
|
||||
Only the **authoring source** triggers them. The `skill-author` scaffold template and the four
|
||||
vendored research-corpus `SKILL.md` files match neither pattern (see
|
||||
[Skill and agent context gates](#skill-and-agent-context-gates-adr-0020), which uses the same scope
|
||||
for `skill-size-check`), so prose findings surface only when you edit a file this repo actually
|
||||
authors. Without the binary the hooks fail with a bare "command not found" and no install pointer.
|
||||
|
||||
**Two hooks, not one combined hook.** Both manifests split the prefilter in two precisely because a
|
||||
single hook can point at only one copy, and that copy would silently 0-file-skip the other file
|
||||
@@ -864,10 +866,9 @@ does not deploy and the replay does not compare; shared enforcement belongs in
|
||||
|
||||
### Why it is excluded from `pretty-format-json`
|
||||
|
||||
It is the **sixth and last alternation** in that hook's `exclude:` pattern, and the only one there
|
||||
for a reason other than "generated manifest". Mind which number you are quoting: **six alternations,
|
||||
expanding to sixteen real files** — 3 root marketplace manifests, 2 per plugin × 6 plugins, plus this
|
||||
one.
|
||||
It is the **second and last alternation** in that hook's `exclude:` pattern, and the only one there
|
||||
for a reason other than "generated manifest". Mind which number you are quoting: **two alternations,
|
||||
expanding to two real files** — `.claude-plugin/marketplace.json`, plus this one.
|
||||
|
||||
`pretty-format-json --autofix` sorts object keys unless `--no-sort-keys` is passed, while apm's hook
|
||||
integrator emits insertion order (`matcher` before `hooks`, `type` before `command`). Leaving the
|
||||
@@ -895,10 +896,13 @@ this remote before any network call.
|
||||
enforcement table (deterministic vs. auditor judgment), and every rejected alternative
|
||||
- `docs/adr/0019-session-start-hook-keeps-the-apm-install-current.md` — the `SessionStart` hook, the
|
||||
executable-trust gate, and the version-pinned allow key
|
||||
- `docs/adr/0017-plugin-content-mirror-bridges-apm-to-host-discovery.md`,
|
||||
`docs/adr/0015-apm-replaces-plugin-marketplace-authoring.md`,
|
||||
`docs/adr/0014-vale-prefilter-ships-from-the-plugin.md` — plugin content sync, apm-generated
|
||||
manifests, committed Vale styles
|
||||
- `docs/adr/0024-apm-is-the-only-supported-install-path.md` — apm as the sole install path, and the
|
||||
deletion of the flat content mirror and its `check-plugin-content-sync` gate. It supersedes
|
||||
`docs/adr/0017-plugin-content-mirror-bridges-apm-to-host-discovery.md` (**superseded** — plugin
|
||||
content sync, kept as the historical record)
|
||||
- `docs/adr/0015-apm-replaces-plugin-marketplace-authoring.md`,
|
||||
`docs/adr/0014-vale-prefilter-ships-from-the-plugin.md` — apm-generated manifests, committed Vale
|
||||
styles
|
||||
- `docs/spec/architecture.md` — directory structure, install pipeline, what is generated and what is
|
||||
hand-authored
|
||||
- `.pre-commit-config.yaml` — the hooks themselves, with inline rationale comments
|
||||
|
||||
Reference in New Issue
Block a user