docs: close the PR #135 documentation review findings
Group 3 of the validated PR #135 review fixes. Every figure and commit citation below was re-verified at HEAD before being written. ADR and architecture: - #7 ADR-0025 cited 61b0b9c, which no published branch reaches. Repointed to620f20b(identical parent tree, reachable from the PR branch), with a note that neither is reachable from origin/main. The parser-drift paragraph now credits598a7c3(the reachable PR #129 squash) and keeps484357aonly as a pre-squash parenthetical. - #8 architecture.md dropped the pointer at the LESSONS.md entry this branch deleted. - #9 architecture.md's ADR entry points now name ADR-0015 (the one compiler) and ADR-0024, and list ADR-0024 as superseding ADR-0017. - #10 ADR-0024 section 4 rewritten: the standing patch-bump rule is apm-workflow's configure.md, not ADR-0006's, and this change does not trigger it. ADR-0015:93 carries a correction for the misattribution. - N5 ADR-0021 gained a Correction note for the deleted scripts/check-manifests.sh (e647f14). gates.md: - #11a the four ADR-0020 constants live in lib-checks-skill.sh:313-316 and lib-checks-agent.sh:164-165, not in validate.sh. - #11b the pretty-format-json exclude is two alternations expanding to three tracked files, including .claude/apm-hooks.json. - #11c the ADR-0020 contract suite runs 28 -> 27 -> 29 (620f20b,4de5b6b,ef27c97), 29 at HEAD; the unverifiable 25 is dropped. - #11d the boundary resolver is one copy sinceef27c97. - #12 apm-audit-ci documents the 10 root checks and the 1 plugin check apm 0.28.0 actually runs, that content-integrity IS the hidden-Unicode scan, that manifest-parse is not a named check, and that the hook needs a completed apm install. The offline claim is qualified accordingly. - N9 gates.md:142-146 verified to still match the hook description. AGENTS.md: - #12 the no-network session rule is qualified to a populated apm_modules/. Audit note: - A1 hook counts corrected to 27/9 -> 26/8 -> 27/9 -> 26/8 (26 and 8 at HEAD) and the dangling pointer dropped. - A2 skill-size-check.sh is 509 lines with the resolver sourced, not 1,522 embedded; citations repointed to skill-size-check.sh:323-335 and lib-checks-skill.sh:235-283 (fail() at :265 and :280), and that library is 627 lines. - A3 consumers receive 15 test files across 5 skills; 16 tracked test paths repo-wide. - A4 the "do not run apm update on this branch" instruction is marked superseded, with the branch-aware guidance in its place. - Finding 31's "true orphans" claim corrected for HOTL and Sycophancy, both still used in core/ai-constitution.md. Same class, found during group 2: - skill-author's deployment-modes.md no longer points at .mcp.json configs (deleted inc96ca9c); metadata.version 1.0.2 -> 1.0.3. - git-orchestrate's context contract clarifies that user_config_overrides is caller-supplied session state, not a config read. The field name is unchanged. - B3 root apm.yml's executables.allow comment: grants are version-blind in apm 0.28.0, so the #2.0.0 suffix is cosmetic to apm and a bump does not break the hook; the suffix stays because check-executables-allow-sync.sh requires it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NwD8Egs5r4ndqeFLmhusX2
This commit is contained in:
@@ -93,6 +93,13 @@ correction) sorted what they document into three buckets:
|
||||
because of hand-authored dual manifests (ADR-0006's version-parity/patch-bump rule, the
|
||||
CC-vs-Copilot field-placement split, dual-file mirroring) are obsolete under `apm.yml`'s
|
||||
single-manifest model and were deliberately dropped.
|
||||
> **Correction (2026-09-19):** "ADR-0006's version-parity/patch-bump rule" misattributes the
|
||||
> patch-bump half. ADR-0006 states a version-*parity* rule and nothing about patch bumps — the
|
||||
> string `patch` does not appear in it (`git show origin/main:docs/adr/0006-plugin-version-parity.md`).
|
||||
> Only the parity half was ADR-0006's, and only that half was dropped. A patch-bump rule does
|
||||
> exist and is live: `plugins/kyberforge/.apm/skills/apm-workflow/references/configure.md` —
|
||||
> bump a package's own `apm.yml` `version:` whenever anything reaching its compiled output
|
||||
> changes. ADR-0024 §4 repeated this misattribution and is corrected there too.
|
||||
- **Holocron policy choice — resolved in #90.** `marketplace-author`'s catalog-version convention
|
||||
(minor bump for package add/remove, patch bump for field-only updates) isn't an APM mechanic —
|
||||
`apm` doesn't enforce it, and has no native version-bump automation at all — so rather than
|
||||
|
||||
@@ -85,7 +85,15 @@ unnamed in `git`'s corrected description, though `65bac15`'s own commit message
|
||||
`gitea`'s. Across the three plugins, 23 of 27 skills are named at the third attempt.
|
||||
|
||||
**Nothing checks any of this.** `scripts/check-manifests.sh` does not contain the string
|
||||
`description`. The three ADR-0020 validators (`scripts/skill-size-check.sh` and skill-audit's and
|
||||
`description`.
|
||||
|
||||
**Correction (2026-09-19): that script no longer exists.** `e647f14` deleted
|
||||
`scripts/check-manifests.sh` (282 lines), `tests/test-check-manifests.sh` (771 lines) and the
|
||||
`check-manifests` pre-commit hook entry with them. The conclusion is unchanged and now holds a
|
||||
fortiori: the gate that did not read `description:` is gone, so nothing in its place reads it
|
||||
either.
|
||||
|
||||
The three ADR-0020 validators (`scripts/skill-size-check.sh` and skill-audit's and
|
||||
agent-audit's `validate.sh` — two since ADR-0025 merged the audit pair into `factory-audit`, whose
|
||||
single auto-detecting `validate.sh` carries both) gate on SKILL.md and agent frontmatter; they do open `apm.yml`, but only
|
||||
to read `dependencies.apm` when resolving the boundary-target universe — none of them reads the
|
||||
|
||||
@@ -179,14 +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.** 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
|
||||
**4. No version bumps.** There *is* a standing rule, and it is not triggered here.
|
||||
`plugins/kyberforge/.apm/skills/apm-workflow/references/configure.md` states it: **bump a package's
|
||||
own `apm.yml` `version:` whenever anything that reaches its compiled output changes** — either its
|
||||
`.apm/` content (a new or removed skill/agent/hook, or a substantive edit to one) or its own
|
||||
manifest metadata (`description`, `keywords`, `author`, `license`, `homepage`, `repository`, all
|
||||
compiled verbatim into `plugin.json`). This change touches neither: nothing under `.apm/` is edited,
|
||||
no manifest metadata changes, and only compiled artifacts are removed, so the content every apm
|
||||
consumer receives is byte-identical before and after. apm also "has no native version-bump
|
||||
automation at all" (ADR-0015), so nothing mechanical demands one either. 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.
|
||||
|
||||
@@ -46,9 +46,16 @@ On top of that, `scripts/check-vale-style-sync.sh` (413 lines) and
|
||||
gate was a copy diff**; it was not, and saying so would overstate the case for deleting it. The
|
||||
script has **17 assertion sites**: 13 `err` calls and 4 hard-fail exits. Its closing
|
||||
`exit 1` only reports the `err` count, so it is not an assertion. Count them with
|
||||
`git show 61b0b9c^:scripts/check-vale-style-sync.sh`. An earlier revision of this ADR said 18. No
|
||||
`git show 620f20b^:scripts/check-vale-style-sync.sh`. An earlier revision of this ADR said 18. No
|
||||
reproducible counting rule gives 18, and it is corrected here.
|
||||
|
||||
> **Repointed (2026-09-19):** this ADR originally cited `61b0b9c^`. `61b0b9c` is a pre-squash commit
|
||||
> that no published branch reaches, so the `git show` failed for anyone but its author. `620f20b` is
|
||||
> the reachable squash of the same work on `docs/simplification-audit`, and `61b0b9c^` and `620f20b^`
|
||||
> have identical trees (`git diff 61b0b9c^ 620f20b^` is empty), so every figure taken at the old
|
||||
> parent reproduces at the new one. Note that `620f20b` is not reachable from `origin/main` either —
|
||||
> fetch the PR branch (`git fetch origin docs/simplification-audit`) before running the command.
|
||||
|
||||
| Class | Old line | What it asserted | Now |
|
||||
|---|---|---|---|
|
||||
| **Moot (6)** | 19 | `REPO_ROOT` is a directory | nothing to guard; no script |
|
||||
@@ -217,10 +224,13 @@ it stops pinning that two `validate-provenance.sh` copies of the Contributing-fi
|
||||
byte-identical, and starts pinning that `lib-contributing-files.sh` is a single sourced copy that has
|
||||
not been re-inlined into either mode library. The claim it protects is the same one — the parser has
|
||||
exactly one authority — stated against the new structure. The drift history behind it is smaller than
|
||||
an earlier revision of this ADR implied. `484357a` (2026-08-30) added the bullet-form parser to both
|
||||
copies with two different spellings of the loop: a temporary `rest` in skill-audit and an inline
|
||||
slice in agent-audit. The two were behaviourally identical. `598a7c3` (2026-09-01) unified the
|
||||
spellings and added the `SHARED CONTRIBUTING-FILES PARSER` markers that 1b hashed. From then until
|
||||
an earlier revision of this ADR implied. `598a7c3` (2026-09-01, the squash of PR #129) is where the
|
||||
bullet-form parser landed on a published branch, in both copies, already carrying the
|
||||
`SHARED CONTRIBUTING-FILES PARSER` markers that 1b hashed. The drift it is named for happened inside
|
||||
that PR's own history: `484357a` (2026-08-30, pre-squash, not on any published branch) added the
|
||||
parser with two different spellings of the loop — a temporary `rest` in skill-audit and an inline
|
||||
slice in agent-audit — which were behaviourally identical, and a later commit on the same branch
|
||||
unified the spellings before the squash. From then until
|
||||
the merge's parent the two marker blocks were byte-identical (`md5 0857272d…` both). So the parser
|
||||
never *parsed* differently. What the gate never covered was the prose around the block, and a
|
||||
docstring there asserted identity the loop did not have. One sourced library removes the question.
|
||||
@@ -388,7 +398,8 @@ so the correction is not re-derived from scratch later.**
|
||||
description content rather than accumulating it: the `Not a skill directory -> skill-audit` clause
|
||||
loses its referent, and the `"is this ready to ship"` trigger was duplicated verbatim across both.
|
||||
The two descriptions it replaces measure **239** (skill-audit) and **250** (agent-audit) at
|
||||
`61b0b9c^`. The description this skill ships measures **241**, inside the 250 SUGGESTION target.
|
||||
`620f20b^` (see the repointing note above). The description this skill ships measures **241**,
|
||||
inside the 250 SUGGESTION target.
|
||||
It carries one arrow per boundary target (`Not applying skill fixes -> skill-author. Not applying
|
||||
agent fixes -> agent-author.`), because ADR-0020 resolves only the first target after an arrow, so
|
||||
a one-arrow form would leave `agent-author` checked by nothing. The real blocker was the body: 1,532
|
||||
|
||||
@@ -23,7 +23,7 @@ Counting convention: line counts are hand-edited `.apm/` source unless marked "i
|
||||
>
|
||||
> > **Re-measured (2026-09-14, at `a6434e0`):** the right-hand column originally read 31,473 / 6,050 / 3,471 / 2,360 / 923 / 2,083 = 46,360 and was labelled "Today" against "the current working tree". It did not reconcile to its own commit's tree — at `061bb3d`, where it was written, the six plugins measured 31,435 / 6,048 / 3,474 / 2,358 / 926 / 2,087 = 46,328 — and "the current working tree" is a basis that goes stale silently. Re-counted at `a6434e0` and the column now names its SHA. The baseline column is confirmed exact against `9eb8bc7`. Commits after `061bb3d` (`c96ca9c`, which deleted the six plugin-root `.mcp.json` files) account for most of the remaining drift.
|
||||
|
||||
> **Re-derived (2026-09-16, at HEAD on `docs/simplification-audit`):** the 2026-09-15 notes recording finding 14's merge (~~`467bbd7`~~ → `620f20b`, ADR-0025) and the pipefail fix (~~`4059cb4`~~ → `ffcbed6`) were written without correcting the headlines they annotate, so this pass re-counted every figure those two commits could have moved and corrected each in place above and below. Everything re-measured here came from a command run at HEAD — `git ls-files`, `wc -l`, `grep -c`, and `bash tests/run-tests.sh --strict` — never from an earlier note. What moved: finding 2 (two surviving sync gates → one), the `.pre-commit-config.yaml` hook counts (27/9 → 26/8, then back to 27/9 — see the correction at the end of this note), the skill census (39 → 38 and everything derived from it), finding 11's validator and `sources.md` figures, finding 16's whole numeric basis, and the stale `skill-audit/`, `agent-audit/` and `formatting-and-scripts.md` paths in findings 18, 19 and 33. §1's three rows re-measured: ~~**469**~~ → **471** tracked files (~~465~~ → 467 regular plus the 4 submodule gitlinks) / ~~**74,594**~~ → **75,441** lines (pinned to `c07ca07`; see the note below); `plugins/` ~~**46,106** (62%)~~ → **46,127** (61%); the 38 `SKILL.md` bodies **2,409** (5.2% of plugin lines); enforcement ~~**20 `tests/test-*.sh` totalling 10,189 lines**~~ → ~~**21 `tests/test-*.sh` totalling 10,608 lines**~~ → **19 totalling 10,088** at `baa2f5d`, the two runners **502** (`run-tests.sh` 283 + `run-bats.sh` 219), and `scripts/` ~~**2,901**~~ → **3,139**; kyberforge's validator scripts and their bats tests ~~**5,861**~~ → **5,876** + **6,015** (the merge deduplicated scripts and left the test corpus larger, not smaller — `git ls-files 'plugins/kyberforge/.apm/skills/*/scripts/*.sh'` and `.../tests/*.bats`). `run-tests.sh --strict` reports ~~**20 passed, 0 skipped, 0 failed**~~ → ~~**21 passed, 0 skipped, 0 failed**~~ → **19 passed, 0 skipped, 0 failed** at `baa2f5d` (`4de5b6b` deleted two suites).
|
||||
> **Re-derived (2026-09-16, at HEAD on `docs/simplification-audit`):** the 2026-09-15 notes recording finding 14's merge (~~`467bbd7`~~ → `620f20b`, ADR-0025) and the pipefail fix (~~`4059cb4`~~ → `ffcbed6`) were written without correcting the headlines they annotate, so this pass re-counted every figure those two commits could have moved and corrected each in place above and below. Everything re-measured here came from a command run at HEAD — `git ls-files`, `wc -l`, `grep -c`, and `bash tests/run-tests.sh --strict` — never from an earlier note. What moved: finding 2 (two surviving sync gates → one), the `.pre-commit-config.yaml` hook counts (27/9 → 26/8 → 27/9 → 26/8, the chain spelled out in §3's table note below; **26** `- id:` entries and **8** `stages: [pre-push]` at HEAD, `grep -c -- "- id:"` and `grep -c "stages: \[pre-push\]"`), the skill census (39 → 38 and everything derived from it), finding 11's validator and `sources.md` figures, finding 16's whole numeric basis, and the stale `skill-audit/`, `agent-audit/` and `formatting-and-scripts.md` paths in findings 18, 19 and 33. §1's three rows re-measured: ~~**469**~~ → **471** tracked files (~~465~~ → 467 regular plus the 4 submodule gitlinks) / ~~**74,594**~~ → **75,441** lines (pinned to `c07ca07`; see the note below); `plugins/` ~~**46,106** (62%)~~ → **46,127** (61%); the 38 `SKILL.md` bodies **2,409** (5.2% of plugin lines); enforcement ~~**20 `tests/test-*.sh` totalling 10,189 lines**~~ → ~~**21 `tests/test-*.sh` totalling 10,608 lines**~~ → **19 totalling 10,088** at `baa2f5d`, the two runners **502** (`run-tests.sh` 283 + `run-bats.sh` 219), and `scripts/` ~~**2,901**~~ → **3,139**; kyberforge's validator scripts and their bats tests ~~**5,861**~~ → **5,876** + **6,015** (the merge deduplicated scripts and left the test corpus larger, not smaller — `git ls-files 'plugins/kyberforge/.apm/skills/*/scripts/*.sh'` and `.../tests/*.bats`). `run-tests.sh --strict` reports ~~**20 passed, 0 skipped, 0 failed**~~ → ~~**21 passed, 0 skipped, 0 failed**~~ → **19 passed, 0 skipped, 0 failed** at `baa2f5d` (`4de5b6b` deleted two suites).
|
||||
>
|
||||
> > **Re-measured (2026-09-16, at `c07ca07`):** commit `8451169` added `check-skill-version-bump` — a pre-push hook, `scripts/check-skill-version-bump.sh` (238 lines) and `tests/test-skill-version-bump.sh` (410) — after the figures above were taken, so each was one short. `.pre-commit-config.yaml` now has **27** `- id:` entries and **9** `stages: [pre-push]` (`grep -c -- "- id:"`; `grep -c "stages: \[pre-push\]"`), all nine repo-authored. The struck figures are replaced from these commands. They were run against the working tree, and every figure reproduces exactly from the committed tree at `c07ca07`: `git ls-files | wc -l`; `cat` over every non-gitlink tracked path `| wc -l`; `git ls-files plugins | xargs cat | wc -l`; `git ls-files scripts | xargs wc -l` (no untracked files under `scripts/`); `ls tests/test-*.sh | wc -l` and `cat tests/test-*.sh | wc -l`; `bash tests/run-tests.sh --strict`. The earlier 469 / 74,594 / 46,106 did not reproduce exactly at `8451169^` either (469 / 74,638 / 46,121), so they were taken at an earlier commit than this note's "at HEAD" says. Re-checked and unchanged, so left alone: `docs/research/` inside plugins (19,030) and repo-level `docs/research/` + `docs/notes/` (4,488). Not re-measured, and still carrying their last stated basis: the preload-tax and commit-share rows, §2's timings, and the per-plugin table in the note above.
|
||||
>
|
||||
@@ -227,6 +227,8 @@ The shared pattern: per-skill `README.md` files no model reads, a `docs/research
|
||||
>
|
||||
> **Re-measured (2026-09-16, at HEAD) — the basis of every figure below changed when ADR-0025 landed; the refutation is unaffected.** There are no longer three validators or two `vale-wrap.sh` copies. The headline's "ported twice" is void, and its `1,677` and `526` no longer name anything. At HEAD: `scripts/skill-size-check.sh` is **1,522** (the note below's 1,517 was correct at `a6434e0`); `factory-audit`'s validator is **2,663** lines across four files (`validate.sh` 255 + `lib-checks-skill.sh` 621 + `lib-checks-agent.sh` 683 + `lib-boundary-resolver.sh` 1,104); `vale-wrap.sh` is **535**, one copy. Validator total **4,185**, of which the resolver is **2,165** (the 1,061-line block still embedded in `skill-size-check.sh`, plus `lib-boundary-resolver.sh`'s 1,104 — the same 1,061 block wrapped in 43 lines of library preamble, which is why the byte-identity test compares the block and not the files). So the resolver is now **52%** of validator lines, not 65%, and **2,020** lines remain once it is excised, not 1,749. Tests: the six repo suites over `skill-size-check.sh` are **3,907** (was 3,619) and the two in-skill validator bats files **2,248** (`validate-skill.bats` 1,029 + `validate-agent.bats` 1,219), for **6,155**, not 5,506. The 200-line target is off by the same order of magnitude it was. (All figures `wc -l`; the resolver block by `awk '/BEGIN ADR-0020 SHARED BOUNDARY RESOLVER/,/END .../'`.)
|
||||
>
|
||||
> > **Superseded by `ef27c97` (re-measured 2026-09-19, at HEAD).** The paragraph above is a dated snapshot and its two load-bearing claims no longer hold. `scripts/skill-size-check.sh` is **509** lines, not 1,522 — it shrank by 1,013 — and the resolver is **no longer embedded in it**: `ef27c97` excised the 1,061-line block and the hook now sources `factory-audit`'s `lib-boundary-resolver.sh` by path (`RESOLVER_LIB` at `:483`, `. "$RESOLVER_LIB"` at `:492`), failing closed if the library is missing or defines no resolver. The single remaining `BEGIN ADR-0020 SHARED BOUNDARY RESOLVER` string in the hook is that fail-closed guard, not a copy. `factory-audit`'s four validator files now total **2,671** (`validate.sh` 255 + `lib-checks-skill.sh` 627 + `lib-checks-agent.sh` 685 + `lib-boundary-resolver.sh` 1,104) and `vale-wrap.sh` is **536**. So there is **one** resolver copy repo-wide, not two, and the "resolver is 52% of validator lines" arithmetic above is void along with its inputs. Only the refutation of finding 16 survives all of this unchanged.
|
||||
>
|
||||
> The three validators are **not three implementations**. They contain **one block, 1,061 lines, byte-identical in all three**, delimited by `# ===== BEGIN/END ADR-0020 SHARED BOUNDARY RESOLVER =====` and hashed by `tests/test-adr0020-contract.sh`. So 3,183 of 4,932 validator lines (65%) are that block × 3, and **what is left once the resolver is excised is 1,749 lines across all three** — 1,580 non-blank, 992 with comments and blanks both stripped. The duplication is forced by the self-containment constraint, which is why *merging* is the lever and *shrinking* is not.
|
||||
>
|
||||
> Corrected figures: `skill-size-check.sh` is **1,517**. The finding's 1,497 was correct when written — `git show 9eb8bc7:scripts/skill-size-check.sh` is 1,497 lines, and `9eb8bc7` (2026-09-10) is this audit's own first commit. It went stale two days *after*, at `c8a7c9e` (2026-09-12), the commit that folded `skill-frontmatter` in — which is why the finding's "frontmatter present" target is now work already done, not why its number was wrong. agent-audit's `validate.sh` is **1,738**, a superset, not a 1,677-line port. `vale-wrap.sh` 526 × 2 is exact.
|
||||
@@ -391,6 +393,7 @@ The shared pattern: per-skill `README.md` files no model reads, a `docs/research
|
||||
|
||||
31. [x] ~~**`CONTEXT.md`: 28 terms, most used only by gates.md, scripts, or tests rather than by skills;** two (Preload tax, Skill context contract) are never used outside `CONTEXT.md` and ADR-0020. The preload-tax entry quotes two dated numbers then says not to quote them. The example dialogue and flagged-ambiguities sections are grill residue. Cut to about 20 one-line terms. Effort S.~~
|
||||
> **Corrected then done (2026-09-13):** see commits `124ce6e` and follow-up on `docs/simplification-audit`. Independent re-verification found "most used only by gates.md/scripts/tests" overstated: 13 of 28 terms are actually referenced from model-facing `references/*.md` files skills load in normal use (Routing target, Hand-invoked skill, Dispatch body, Near-miss, Thin adapter, Provenance chain, Output profile, apm package, Plugin marketplace, HITL, Skill composition, Delegation discipline, holocron) and were kept untouched. Only the 9 terms confirmed as true orphans were removed after a fresh independent grep: Content mirror, apm-consumed install, Vale audit prefilter, Vacuous green, Management Application, Sycophancy, HOTL, Preload tax, Skill context contract — 28 → 19 terms.
|
||||
> > **Corrected (2026-09-19) — "true orphans" is wrong for two of the nine.** **HOTL** and **Sycophancy** are both still used in `core/ai-constitution.md` (HOTL spelled out at `:111-112`, sycophancy at `:72-87`), and HOTL also in `docs/research/governance_principles/ai-governance-research.md:340-344`. The removals themselves were still right, for a different reason than the one given: the constitution **defines both terms itself, at the point of use**, so a second definition in `CONTEXT.md` was duplication rather than the only authority. Only the orphan justification is corrected here; the other seven and the 28 → 19 count are unaffected.
|
||||
> **Re-counted (2026-09-14, at `a6434e0`): 18 terms, not 19.** The "28 → 19" above is an accurate record of this finding's own commit (`124ce6e`) and is left standing. `718c79a` then removed a twentieth-to-nineteenth entry this finding never touched: the standalone **Plugin** term, folded into **apm package** when ADR-0024 made "plugin" and "apm package" the same thing. Counted as bolded term entries between `## Language` and `## Relationships` in `CONTEXT.md`: 19 at `124ce6e`, 18 at `718c79a` and unchanged at `a6434e0`. The finding's own target ("about 20 one-line terms") is met either way. The preload-tax self-contradiction (quotes 23,427/10,478-char figures then says not to quote either) was confirmed verbatim and resolved by the entry's own deletion. The "example dialogue" and "flagged ambiguities" sections were found to be mandated by `grill-with-docs/references/context-format.md`'s template spec, not grill residue — left untouched, except one dangling bolded cross-reference to the now-deleted "Preload tax" term in a Flagged-ambiguities line, which was unbolded/de-referenced in place (the ambiguity resolution itself still holds without a defined glossary entry to point at).
|
||||
|
||||
32. [x] ~~**Structure is described three ways** (README layout table, architecture.md plugin table, AGENTS.md structure bullets), and `VISION.md` carries a 35-line stack spec for a product that lives in another repo. One layout table in README; architecture.md keeps mechanics only; VISION drops the stack detail. Effort S.~~
|
||||
@@ -413,10 +416,10 @@ Not covered by the area audits above; found on a final sweep of the root config
|
||||
>
|
||||
> Corrected headline: ~~**two** hand-maintained per-plugin locations (**three** for kyberforge)~~ → **one** hand-maintained per-plugin version location, `plugins/<name>/apm.yml` (**two** for kyberforge, adding the `executables.allow` key), not four. `2def060` deleted the root `packages[].version` lines (corrected 2026-09-16, review round). The root `packages[].description:` duplicates dropped in the same round are a separate duplication, not a version location, so they do not change this count — the audit's own "already done" note records the `plugin.json` deletion but never fixed the headline. Gitea skills drift across **six** values (`0.1.2, 0.1.3, 0.1.4, 0.1.5, 0.1.6, 1.0.1`), not five — ~~still six at HEAD on 2026-09-16~~ → **five** again at HEAD (`b426460`) on 2026-09-16 (`0.1.2, 0.1.4, 0.1.5, 0.1.6, 1.0.1`), because `8451169` bumped `gitea-branches` 0.1.3 → 0.1.4 under the new version-bump gate and it was the only skill at 0.1.3; re-derived by parsing `metadata.version` out of each `plugins/gitea/.apm/skills/*/SKILL.md` with PyYAML. ~~39 `SKILL.md` files ✓~~ → **38** carry it, and all 38 do (re-measured 2026-09-16; ADR-0025's merge took one). The `0.4.6` duplication between root `version:` and `marketplace.version:` is **forced by apm, not a repo choice** — deleting `marketplace.version` makes `--check-clean` go dirty.
|
||||
>
|
||||
> **"Nothing consumes `metadata.version`" is false twice over.** Machine enforcers: ~~`scripts/skill-size-check.sh:1365-1374`~~ → `scripts/skill-size-check.sh:1370-1379` and ~~`skill-audit/scripts/validate.sh:1292-1332`~~ → `plugins/kyberforge/.apm/skills/factory-audit/scripts/lib-checks-skill.sh:235-277`, both FAIL tier, the latter citing ADR-0022 by name, with four dedicated bats cases and ~10 fixture generators baking the field in.
|
||||
> **"Nothing consumes `metadata.version`" is false twice over.** Machine enforcers: ~~`scripts/skill-size-check.sh:1365-1374`~~ → ~~`scripts/skill-size-check.sh:1370-1379`~~ → `scripts/skill-size-check.sh:323-335` and ~~`skill-audit/scripts/validate.sh:1292-1332`~~ → `plugins/kyberforge/.apm/skills/factory-audit/scripts/lib-checks-skill.sh:235-283`, both FAIL tier, the latter citing ADR-0022 by name, with four dedicated bats cases and ~10 fixture generators baking the field in.
|
||||
> Instruction-level consumers: `skill-author/SKILL.md:60` (bump minor on create, patch on improve), `create.md:89,101`, `improve.md:82`, and `forge/SKILL.md:54` + `references/version-bump.md`. apm parses it for Chatmode/Instruction/Context primitives but not for Skills, and never emits it. Precise statement: the value is written, shape-validated, and never read *downstream* — it is an agent-visible revision counter, and the drift table shows the counter is not being maintained.
|
||||
>
|
||||
> > **Repointed (2026-09-16, at HEAD):** `skill-audit/scripts/validate.sh` no longer exists — ADR-0025's merge moved the ADR-0022 check into `factory-audit`'s skill-side check library, where it is the `SEMVER_RE` block (comment header at `:235`, `fail()` calls at `:261` and `:275`). `skill-size-check.sh` grew by 5 lines above the block since `062ca47`, hence the shifted range there. All five instruction-level citations still resolve at HEAD, verified with `sed -n`.
|
||||
> > **Repointed (2026-09-16, at HEAD; re-verified and corrected 2026-09-19):** `skill-audit/scripts/validate.sh` no longer exists — ADR-0025's merge moved the ADR-0022 check into `factory-audit`'s skill-side check library, where it is the `SEMVER_RE` block: comment header at `:235`, `SEMVER_RE` itself at `:254`, `fail()` calls at ~~`:261` and `:275`~~ → `:265` and `:280`, the block running `:235-283` (the next section header, `# SKILL.md size ceilings`, is at `:285`). That library is **627** lines, not 621. In `skill-size-check.sh` the check is at `:323-335`; the earlier note said the file "grew by 5 lines above the block", which is the wrong direction by two orders of magnitude — `ef27c97` excised the embedded resolver and the file **shrank** from 1,522 to **509** lines, which is why the range moved from the 1,300s to the 320s. All five instruction-level citations still resolve at HEAD, verified with `sed -n`.
|
||||
>
|
||||
> **ADR-0022 already considered and rejected dropping the field**, on the grounds that `skill-author` depends on it to decide whether a pass owes a bump — a rationale still live today. Superseding costs: rewrite skill-author's bump rule, delete `forge`'s version-bump route premise, strip two scripts, delete four bats cases, fix ~10 fixture generators, edit the scaffold template, update ~~`gates.md:97`~~ → ~~`gates.md:145`~~ → `gates.md:146` — and re-open the "is this field present here?" question issue #127 closed, just from the other side. *(Repointed 2026-09-16, at HEAD `b426460`: the `metadata.version` frontmatter sentence formerly at `gates.md:97` was at `:143-146`, the field itself on `:145`, and is at `:143-147` / `:146` at `4b17703`; verified with `grep -n "metadata.version" docs/spec/gates.md`.)* **Recommendation: keep it and fix the actual defect, which is that nobody bumps it.** Either enforce the bump in the skill-author workflow or declare the values advisory in the ADR.
|
||||
>
|
||||
@@ -543,7 +546,7 @@ Recorded here so they are not rediscovered as defects. All follow from commit `7
|
||||
**Two accepted residuals.**
|
||||
|
||||
- **Native install still half-works, and cannot be prevented.** apm reuses Claude's catalogue format by design, so a Claude Code user can still register holocron natively and will install six plugins containing zero skills. Accepted, not overlooked: no schema change closes this, because the format that makes it possible is the format apm's own consumers need.
|
||||
- **Consumers now receive test fixtures.** apm installs from `.apm/`, which carries the `tests/` directories the mirror used to strip, so a consumer installing from this branch receives **10 `.bats` files across 6 skills**, plus those skills' 6 `tests/README.md` files — 16 files. (Repo-wide, 17 tracked paths contain `/tests/`: the 10 `.bats` and 7 `README.md`, one of which is a template asset under `skill-author/assets/templates/tests/` and is not a test fixture.) This is what consumers *receive*, not what this checkout shows: `.claude/skills/` here currently holds zero `.bats` files, because that deployed tree is stale and predates this branch. The mechanism was confirmed empirically on a ref-pinned consumer clone — the 16 files are absent at the parent commit and present at HEAD. Suppressing them means switching all six `apm.yml` files from `includes: auto` to explicit lists, where a wrong list silently drops content — worse failure mode than the noise. Deferred deliberately.
|
||||
- **Consumers now receive test fixtures.** apm installs from `.apm/`, which carries the `tests/` directories the mirror used to strip, so a consumer installing from this branch receives **10 `.bats` files across 5 skills**, plus those skills' 5 `tests/README.md` files — ~~16~~ → **15** files. (Repo-wide, ~~17~~ → **16** tracked paths contain `/tests/`: the 10 `.bats` and 6 `README.md`, one of which is a template asset under `skill-author/assets/templates/tests/` and is not a test fixture. Re-counted 2026-09-19 at HEAD with `git ls-files | grep '/tests/'`; the earlier figures predate ADR-0025's merge, which collapsed `skill-audit` and `agent-audit` into one skill and took the skill count from 6 to 5.) This is what consumers *receive*, not what this checkout shows: `.claude/skills/` here currently holds zero `.bats` files, because that deployed tree is stale and predates this branch. The mechanism was confirmed empirically on a ref-pinned consumer clone — the files are absent at the parent commit and present at HEAD. Suppressing them means switching all six `apm.yml` files from `includes: auto` to explicit lists, where a wrong list silently drops content — worse failure mode than the noise. Deferred deliberately.
|
||||
|
||||
**Negative result — do not re-litigate.** Deleting native install does *not* relax the self-containment constraint. `plugins/kyberforge/.apm/skills/skill-author/references/deployment-modes.md`, sourced from the agentskills.io spec, states it independently for APM package mode: the spec defines no cross-skill sharing. So ~~findings 14 and 15 still require~~ → finding 14 required *merging* skills (done, ADR-0025), and finding 15 would have too (refuted on measurement, 2026-09-16); sharing one file between two skills remains impossible, and §8's "one-script-per-skill install constraint" bullet is unchanged by this decision.
|
||||
|
||||
@@ -604,8 +607,9 @@ The recurring failure mode is worth naming, because it has now produced six wron
|
||||
### Two defects to fix independently of any finding
|
||||
|
||||
- **~~A live bug in always-on context.~~ Fixed (2026-09-15).** The deployed `core/instructions/governance.md` cited `docs/HUMANS.md`, which does not exist — the file is `docs/wiki/HUMANS.md`. Five occurrences across three files (`governance.md:82`, which was self-inconsistent against its own correct line 73; `CONTROLS.md:5,101,106`; `ai-constitution.md:238`), in a file `@`-imported into every session in every project. All five now point at `docs/wiki/HUMANS.md`. ~~Note the deployed copy under `~/.claude/` no longer matches the repo until `scripts/install.sh` re-runs.~~ **Deployed (2026-09-16):** the fixed file was copied to `~/.claude/core/instructions/governance.md` and `diff -rq core ~/.claude/core` is clean. `install.sh` itself was deliberately not run: it overwrites `~/.claude/settings.json` wholesale, and the deployed copy carried machine-local keys (`model`, `extraKnownMarketplaces`, `autoMemoryEnabled`, notification flags) that the repo's `providers/claude-code/settings.json` does not.
|
||||
- **This checkout's install is stale and there is a branch hazard.** At the time of the wave `apm outdated` reported 6 outdated dependencies, 9 commits behind `main`, with a clean tree and nothing reporting it. **Do not run `apm update` on this branch** — it resolves against `main` and restores the obsidian MCP server that commit `c96ca9c` removed here. Reproduced. The mechanism is worse than "reinstalls `plugins/bin/.mcp.json`": apm never writes into `plugins/`, it re-materialises the file under `apm_modules/` and regenerates the repo-root `/.mcp.json` — which `c96ca9c` gitignored, so the restoration would not appear in `git status` at all. This belongs in ADR-0019's Consequences; see finding 34.
|
||||
- **This checkout's install is stale and there is a branch hazard.** At the time of the wave `apm outdated` reported 6 outdated dependencies, 9 commits behind `main`, with a clean tree and nothing reporting it. ~~**Do not run `apm update` on this branch**~~ — it resolves against `main` and restores the obsidian MCP server that commit `c96ca9c` removed here. Reproduced. The mechanism is worse than "reinstalls `plugins/bin/.mcp.json`": apm never writes into `plugins/`, it re-materialises the file under `apm_modules/` and regenerates the repo-root `/.mcp.json` — which `c96ca9c` gitignored, so the restoration would not appear in `git status` at all. This belongs in ADR-0019's Consequences; see finding 34.
|
||||
> **Landed (2026-09-16):** commit `afcf477` amended ADR-0019's Consequences with the feature-branch hazard, and the discard guidance for a feature branch is now also in `AGENTS.md` and `README.md` (`dd0b923`). The reason those two files and ADR-0019 gave for discarding the lock was wrong, and the review round below corrected it. See finding 34's closing note.
|
||||
> **Superseded (2026-09-19) — the "do not run `apm update`" instruction above no longer stands.** It was never enforceable and is now contradicted three ways. kyberforge's `SessionStart` hook runs `apm update --yes` on **every** branch, so the command runs on this branch at every session start whether or not anyone types it. ADR-0019's 2026-09-16 amendment considered skipping the refresh off the default branch and **explicitly rejected it**: it would not make the branch live, only freeze the session on an older `main` — the silent staleness the ADR exists to prevent. And `AGENTS.md`'s session rules and `README.md`'s install section now carry the branch-aware guidance that replaces the prohibition: on a feature branch, discard the rewritten lock (`git checkout -- apm.lock.yaml`, then `apm install`), which keeps unrelated lock churn out of the branch diff and keeps `apm pack --check-clean` consistent with the committed lock. **Current guidance: let the refresh run, then discard the lock on a feature branch.** The observation the instruction was built on is untouched and still worth reading — the obsidian server does come back, apm re-materialises it under `apm_modules/` and regenerates the gitignored root `.mcp.json`, and `git status` shows none of it. The redeployed content goes away once the branch merges, and the next `apm update`/`apm install` that resolves a tree no longer declaring the server removes it via `MCPIntegrator.remove_stale`.
|
||||
|
||||
## 11. Review round on the grill commits (2026-09-16)
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ Both `CLAUDE.md` files are thin adapters: they import from their respective `AGE
|
||||
|
||||
This repo also has a `CLAUDE.md` at its root — the Claude Code entry point for working in this repo. It imports `AGENTS.md` and nothing else; there is no `@CONTEXT.md` import. It is not import-only either: below the import sits a fenced `<!-- rtk-instructions v2 -->` … `<!-- /rtk-instructions -->` block carrying the RTK command-prefix convention, which is tool-specific content with no `AGENTS.md` source. This is distinct from `providers/claude-code/CLAUDE.md`, which is the global config deployed to `~/.claude/`.
|
||||
|
||||
`CONTEXT.md` is therefore **not** always-loaded. `AGENTS.md` instructs agents to read it at session start, which is a behavioural instruction, not an `@import` guarantee — `LESSONS.md`'s 2026-05-17 entry proposed adding the import and it was never applied. Treat that entry as open work rather than a record of a landed change.
|
||||
`CONTEXT.md` is therefore **not** always-loaded. `AGENTS.md` instructs agents to read it at session start, which is a behavioural instruction, not an `@import` guarantee.
|
||||
|
||||
## Reference conventions
|
||||
|
||||
@@ -87,4 +87,4 @@ The stated convention is that files referencing other files declare those refere
|
||||
|
||||
## Architectural decisions
|
||||
|
||||
Key hard-to-reverse decisions are recorded as ADRs in `docs/adr/`. There is no index file — the directory holds numbered ADRs whose filenames state their decision, so `ls docs/adr/` is the index. Read a superseding ADR before the one it supersedes: ADR-0015 (apm as the authoring source of truth) supersedes ADR-0001 and moots ADR-0006, ADR-0017 corrects ADR-0015's host-discovery gap, and ADR-0019 supersedes one claim in ADR-0018 (that `.claude/settings.json`'s committed content is exactly `{"hooks": {}}`) while keeping the rule behind it. Entry points for the structure described on this page: ADR-0002 (two-tier CLAUDE.md), ADR-0003 (AGENTS.md as the provider-agnostic entry point), ADR-0015 and ADR-0017 (the two compilers behind the plugin roots).
|
||||
Key hard-to-reverse decisions are recorded as ADRs in `docs/adr/`. There is no index file — the directory holds numbered ADRs whose filenames state their decision, so `ls docs/adr/` is the index. Read a superseding ADR before the one it supersedes: ADR-0015 (apm as the authoring source of truth) supersedes ADR-0001 and moots ADR-0006, ADR-0024 supersedes ADR-0017 (which had corrected ADR-0015's host-discovery gap with a compiled flat content mirror, now deleted), and ADR-0019 supersedes one claim in ADR-0018 (that `.claude/settings.json`'s committed content is exactly `{"hooks": {}}`) while keeping the rule behind it. Entry points for the structure described on this page: ADR-0002 (two-tier CLAUDE.md), ADR-0003 (AGENTS.md as the provider-agnostic entry point), ADR-0015 (`apm pack`, the one compiler behind the plugin roots) and ADR-0024 (apm as the only install path).
|
||||
|
||||
@@ -403,10 +403,13 @@ findings.
|
||||
|
||||
### Duplicated constants
|
||||
|
||||
`factory-audit`'s `validate.sh` holds a second copy of the four ADR-0020 constants
|
||||
(`DESC_SUGGEST_CHARS` / `DESC_MAX_CHARS` / `BODY_SUGGEST_WORDS` / `BODY_MAX_WORDS`) — the two
|
||||
description constants apply to both artifact types it handles, the two body constants only to
|
||||
skills. They are copied rather than imported because a skill's files may not reach outside that skill's own
|
||||
`factory-audit` holds a second copy of the four ADR-0020 constants
|
||||
(`DESC_SUGGEST_CHARS` / `DESC_MAX_CHARS` / `BODY_SUGGEST_WORDS` / `BODY_MAX_WORDS`). They are not in
|
||||
its `validate.sh`, which carries none of them: they live in the mode libraries it sources —
|
||||
`scripts/lib-checks-skill.sh:313-316` carries all four, and `scripts/lib-checks-agent.sh:164-165`
|
||||
carries the two description constants only. That split is the contract stated directly: the two
|
||||
description constants apply to both artifact types `factory-audit` handles, the two body constants
|
||||
only to skills. They are copied rather than imported because a skill's files may not reach outside that skill's own
|
||||
directory (the self-contained constraint in `docs/spec/architecture.md`, "Plugin model"), and
|
||||
`scripts/skill-size-check.sh` does not ship with the plugin. `tests/test-skill-size-check.sh` asserts the copies agree,
|
||||
so drift fails CI rather than silently letting an audit bless a skill the commit hook then rejects.
|
||||
@@ -428,9 +431,14 @@ and duplicate the `skill)` arm's, and the file-wide count is still 2 and the ass
|
||||
with the agent path running no resolver or some other one. It is now a **per-arm structural check** —
|
||||
each arm of `validate.sh`'s `case "$MODE" in` block must carry exactly one `source` line inside its
|
||||
own body, and the file must carry exactly those two — with a mutation self-test that performs that
|
||||
exact count-preserving edit on a copy and requires the check to fail on it. The suite went 25 → 28
|
||||
cases. It stood at 27 before the 2026-09-16 change and 29 after it, which replaced the two-copy
|
||||
hash and its line-count floor with the six one-copy assertions above.
|
||||
exact count-preserving edit on a copy and requires the check to fail on it. The suite's case count
|
||||
runs **28 → 27 → 29**, and is **29** at HEAD: 28 at `620f20b` (the ADR-0025 merge), 27 after
|
||||
`4de5b6b` retired the `.pre-commit-hooks.yaml` export, and 29 after `ef27c97` replaced the two-copy
|
||||
hash and its line-count floor with the six one-copy assertions above. There are two 2026-09-16
|
||||
changes here, not one, which is what an earlier revision of this section conflated. Each figure is
|
||||
`bash tests/test-adr0020-contract.sh` run in a worktree at that commit, reading its `Results:` line.
|
||||
An earlier revision also opened the chain at 25; that predates the branch squash, no reachable
|
||||
commit reproduces it, and it is dropped as unverifiable rather than carried.
|
||||
|
||||
### `python3` and PyYAML are hard requirements
|
||||
|
||||
@@ -1030,14 +1038,29 @@ because the root-only invocation audits the marketplace manifest and **nothing e
|
||||
dependency entry passes `apm pack --check-versions --check-clean --dry-run` and fails
|
||||
`apm audit --ci` in that package's directory. Costs ~0.5s per package.
|
||||
|
||||
It verifies **exactly two things** per manifest and claims no more:
|
||||
**What it actually runs is asymmetric**, and the two manifest classes are not comparable. Verified by
|
||||
running `apm audit --ci` (apm 0.28.0) at the repo root and in `plugins/lint/`, reading the check
|
||||
names straight off its own compliance table:
|
||||
|
||||
- **manifest-parse** — each `apm.yml` parses as a valid APM manifest. Unconditional; verified to fire
|
||||
on a dependency entry missing its `git`/`path`/`registry` field (`Cannot parse apm.yml`).
|
||||
- **lockfile-exists** — any package declaring dependencies has a consistent `apm.lock.yaml`.
|
||||
Conditional, and vacuous while every plugin `apm.yml` declares `dependencies: {apm: [], mcp: []}`;
|
||||
it arms itself the moment one does not (verified by adding a git dependency to
|
||||
`plugins/lint/apm.yml`).
|
||||
On the **root** manifest, **10 checks**: `lockfile-exists`, `ref-consistency`,
|
||||
`deployment-ledger-owners`, `deployed-files-present`, `no-orphaned-packages`,
|
||||
`skill-subset-consistency`, `config-consistency`, `content-integrity`, `includes-consent`, `drift`.
|
||||
|
||||
On each **plugin** manifest, **1 check**: `lockfile-exists`. Conditional, and vacuous while every
|
||||
plugin `apm.yml` declares `dependencies: {apm: [], mcp: []}` — it reports `No dependencies declared
|
||||
-- lockfile not required` and arms itself the moment one does not (verified by adding a git
|
||||
dependency to `plugins/lint/apm.yml`). Everything else in the list above is root-only, because it is
|
||||
the root install that has a lockfile, a deployment ledger and deployed files to check.
|
||||
|
||||
**`manifest-parse` is not a named check** in apm 0.28.0's output, and an earlier revision of this
|
||||
section listed it as one. Parsing is still enforced — a dependency entry missing its
|
||||
`git`/`path`/`registry` field fails with `Cannot parse apm.yml` — but it fails the invocation before
|
||||
the table is built rather than appearing as a row in it.
|
||||
|
||||
**The hook needs a completed `apm install`.** `deployed-files-present` checks the install output on
|
||||
disk, so on a fresh clone it fails with `303 deployed file(s) missing` and takes the push with it.
|
||||
That is not a defect in the gate; it is the gate correctly reporting that nothing has been installed
|
||||
yet. Run `apm install` before the first push from a new checkout.
|
||||
|
||||
It does **not** enforce an org policy. apm discovers one from the git remote and only understands
|
||||
github.com and Azure DevOps, so against this repo's self-hosted Gitea remote it prints:
|
||||
@@ -1052,9 +1075,13 @@ not make the check meaningful, it makes it permanently red — `apm audit --ci`
|
||||
`No org policy found at unknown (policy.fetch_failure_default=block)` on every push, forever. A gate
|
||||
that can never go green is not a gate. Revisit only if this repo gains a policy source apm can reach.
|
||||
|
||||
It also does not scan for hidden Unicode: that scan is plain `apm audit`, a different mode (`--ci`
|
||||
refuses to combine with `--file`/`--strip`/`--dry-run`/`PACKAGE`), and plain `apm audit` here reports
|
||||
`No apm.lock.yaml found -- nothing to scan` and exits 0. Adding it would buy a second vacuous check.
|
||||
**It does scan for hidden Unicode.** An earlier revision of this section said the opposite. The
|
||||
`content-integrity` check in the root table *is* that scan — it reports `No critical hidden Unicode
|
||||
or hash drift detected` — so the root invocation already covers it and nothing needs adding. What
|
||||
remains true is that the *standalone* mode is different: plain `apm audit` (`--ci` refuses to combine
|
||||
with `--file`/`--strip`/`--dry-run`/`PACKAGE`) run in a plugin directory reports
|
||||
`No apm.lock.yaml found -- nothing to scan` and exits 0, because only the root has a lockfile.
|
||||
Plugin manifests get `lockfile-exists` and nothing else; they are not Unicode-scanned.
|
||||
|
||||
### `check-executables-allow-sync`
|
||||
|
||||
@@ -1092,9 +1119,12 @@ does not deploy and the replay does not compare; shared enforcement belongs in
|
||||
|
||||
### Why it is excluded from `pretty-format-json`
|
||||
|
||||
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.
|
||||
It is in the **second and last alternation** in that hook's `exclude:` pattern, and that alternation
|
||||
is the only one there for a reason other than "generated manifest". Mind which number you are
|
||||
quoting: the pattern is `^(\.claude-plugin/marketplace\.json|\.claude/(settings|apm-hooks)\.json)$`
|
||||
— **two top-level alternations, expanding to three real tracked files**:
|
||||
`.claude-plugin/marketplace.json`, this one, and its committed `.claude/apm-hooks.json` sidecar,
|
||||
which is apm output under the same byte-for-byte replay and is excluded for the same reason.
|
||||
|
||||
`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
|
||||
@@ -1108,11 +1138,18 @@ fix.
|
||||
|
||||
## Pushing without a network
|
||||
|
||||
No pre-push hook needs the network. Every entry in root `apm.yml`'s `marketplace.packages[]`
|
||||
resolves from a local `./plugins/<name>` path, so `apm-pack-check-clean` never calls `git ls-remote`.
|
||||
No pre-push hook needs the network **once `apm install` has populated `apm_modules/`**. Every entry
|
||||
in root `apm.yml`'s `marketplace.packages[]` resolves from a local `./plugins/<name>` path, so
|
||||
`apm-pack-check-clean` never calls `git ls-remote`.
|
||||
|
||||
`apm-audit-ci` calls `apm` too but was always local: its org-policy discovery resolves nothing on
|
||||
this remote before any network call.
|
||||
`apm-audit-ci` calls `apm` too, and its org-policy discovery resolves nothing on this remote before
|
||||
any network call. But it is local only against a populated install: `drift` and `config-consistency`
|
||||
replay the install to diff scratch against the working tree, and that replay is cache-only —
|
||||
`[>] Replaying install (cache-only)` — which is exactly why it costs no network here. On a **fresh
|
||||
clone** there is no cache to replay from, so the replay clones from the holocron remote and those two
|
||||
checks fail offline, with `deployed-files-present` already failing for the same reason (see
|
||||
`apm-audit-ci` above). The offline guarantee is a property of a populated `apm_modules/`, not of the
|
||||
hook set: run `apm install` once on a new checkout and it holds from then on.
|
||||
|
||||
---
|
||||
|
||||
@@ -1131,7 +1168,8 @@ this remote before any network call.
|
||||
styles
|
||||
- `docs/adr/0025-skill-audit-and-agent-audit-merge-into-factory-audit.md` — the audit-pair merge that
|
||||
collapsed the two Vale copies to one, removed the `check-vale-style-sync` hook, and took the shared
|
||||
boundary resolver from three copies to two. It amends ADR-0014 and ADR-0020 on those points
|
||||
boundary resolver from three copies to two (one since `ef27c97`). It amends ADR-0014 and ADR-0020
|
||||
on those points
|
||||
- `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