Why: two blind verifiers re-ran the five preceding commits and found four
defects of the same class this branch exists to close -- a confidently stated
measured claim that does not survive re-measurement -- this time inside the
fixes themselves.
- AGENTS.md:41 still carried both phrasings c68e864 reports having corrected.
`grep -rn repo-defined` returned exactly one hit repo-wide: that line, in the
file every session preloads. 4d336bb edited the line directly above it.
- ADR-0021 asserted twice, in the section justifying that no gate is added,
that the ADR-0020 validators "never open an apm.yml". All three open and
yaml.safe_load it (skill-size-check.sh:342, both validate.sh). The conclusion
survives -- none reads the description: key, and their globs are SKILL.md and
*.agent.md only -- but the stated mechanism is falsified by one grep.
- architecture.md said the ADR directory holds 20 numbered ADRs; c7ba3d2 made
it 21, and c68e864 audited that file for exactly this class of stale count.
The number is dropped rather than corrected: `ls docs/adr/` is already the
index, so a count in prose is a second thing to maintain.
- gates.md's new three-verdict table said `-> name` promotes an unresolved
target to ERROR. Reproduced with fixtures: NAME_HYPH (skill-size-check.sh:543)
requires a hyphen, so `-> gitea-prs` is checked and `-> triage` is not
extracted at all, and the unicode arrow is never recognised. The SUGGESTION
text advises that spelling, so taking its advice can silence the finding. The
gap is now documented as a defect; nothing covers it, since the one arrow case
in test-adr0020-targets.sh happens to use a hyphenated target.
Implementation notes:
- AGENTS.md:48's coverage claim is shrunk rather than chased. Restoring six
glossary entries did not make it true: 12 more sampled terms are undefined,
three of them (trigger/capability/boundary clause) used inside CONTEXT.md
itself. It now says CONTEXT.md is the glossary and is not exhaustive.
- CONTEXT.md's output profile and near-miss entries are corrected against their
sources. The first stated a false exclusion -- .github/plugin/plugin.json IS
apm-generated; only the marketplace mirror has no profile. The second
inverted its source's referent: description-quality.md defines a near-miss as
a query, not a sibling skill.
- The strict-mode message named jq, which no suite guards on (`command -v jq`
appears nowhere in tests/), while omitting python3/PyYAML, which three do.
- README's git and gitea bullets now name git-workflow and gitea-workflow.
ADR-0021 leaves README the only inventory and architecture.md now points at
it, so the two bullets that were short had to be completed.
- ADR-0018's 2026-08-14 correction is marked superseded in place. It asserted
machine state in the present tense that its own 2026-08-17 note retracts.
- ADR-0021's remaining errors: six files -> four (measured from de84d1b), the
wiki description's length 114 -> 96 chars, the codex self-contradiction, the
cost argument overstating bumps already owed for any skill addition, and two
claims about files this branch went on to edit.
- The "15 of 17 suites" figure is restored where I had removed it: it is a dated
record of one incident, not a live count, and four sites now describe it the
same way.
Impact: 16/16 pre-push hooks pass, suite 24 passed 0 skipped 0 failed. No
behaviour change; every edit is prose or a comment.
Refs: #105
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w
Why: the relocation into gates.md and architecture.md moved text faster than it
verified it, and a review found eight assertions that do not survive contact
with the repo.
- gates.md cited docs/research/examples/, which does not exist; the tree is at
plugins/kyberforge/docs/research/examples/. The same wrong string survives at
ADR-0013:98, where it originated, and is tracked separately.
- gates.md's description-budget arithmetic was built on 23,427, a figure
ADR-0020 measured at f9b919d and pins there, and compared a name-inclusive
total against a description-only ceiling. Dropped rather than re-measured,
following the precedent this branch set for CONTEXT.md's token figure: a
second live copy is a second thing to go stale.
- gates.md listed "every boundary-clause routing target must resolve" as a hard
FAIL. skill-size-check.sh emits unresolved targets as SUGGESTION by default,
promotes to ERROR only when terminal and either route-notated or corroborated
by a resolving target in the same sentence, and reports INFO DID NOT RUN when
no universe resolves. Verified with five fixtures; replaced with a
three-verdict table.
- gates.md and README called `pre-commit run --hook-stage pre-push --all-files`
the whole push gate. check-release-needed.sh exits 0 unless
PRE_COMMIT_REMOTE_BRANCH is refs/heads/main, which only the real git hook
exports -- its own header comment titles this a "Known gap".
- "repo-defined" was loose: the two meta hooks are also declared here, and what
separates them is repo: meta from repo: local.
- architecture.md claimed `when:` appears in two of 39 skill sources. Exactly
one SKILL.md carries it; the second hit is a META.md. The likely origin is
skill-implementation-workflow.md:233, which claims META.md sits alongside
every skill when one exists in the whole tree.
- architecture.md said core/AGENTS.md is "deployed beside" CLAUDE.md.
deploy-manifest.sh sends them to ~/.claude/ and ~/.agents/ respectively; the
relation is import, not adjacency.
- gates.md's see-also cited ADRs as bare stems where its neighbours use paths.
Implementation notes: architecture.md's closing pointer sent readers to the
published description "for what a consumer actually gets", which was true
against an enumeration and is not after ADR-0021. It now names the boundary
relationship and points at the skills tree and README for an inventory. README's
bin bullet gains caveman and zoom-out, since ADR-0021 leaves it the only place
an inventory lives.
Impact: 16/16 pre-push hooks pass. Deliberately not fixed here and tracked
separately: the 12 pre-commit-stage hooks gates.md does not document, its own
SentenceOpenerThereIs violation, and README's missing scripts/install.sh step.
Refs: #105
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w
Why: enumerating a plugin's skills in its published description has now failed
three times in four days, the third time inside the correction for the second.
bb9158d (Aug 14) fixed core's description, which described bin's skills. That
failure was wrong content, not an incomplete list -- a syntactically perfect
four-item enumeration that belonged to a different plugin -- so enumerating
harder could not have caught it, and bb9158d's own fix replaced the enumeration
with a domain boundary. 65bac15 and de84d1b then cited that precedent while
doing the opposite, and the re-enumeration is itself incomplete: caveman and
zoom-out are unnamed in bin, git-workflow is unnamed in git despite 65bac15's
message claiming it was added, and gitea-workflow is unnamed in gitea. 23 of 27
skills named at the third attempt.
Nothing checks any of this. check-manifests.sh does not contain the string
"description"; apm audit --ci, apm pack --check-clean and
sync-plugin-content.sh --check all compare compiled output against apm.yml, so
their job is to propagate whatever it says byte-for-byte. The wiki claim passed
all fourteen pre-push hooks every day it was published. Enumeration also makes a
marketplace release the consequence of a directory appearing.
Implementation notes:
- ADR-0021 records the decision, the three failures, and why no gate is added:
the check is one-directional, cannot see an invented capability, and a
correspondence map would relocate the same per-skill maintenance one file over.
- bin 1.1.4 -> 1.1.5, git 1.3.4 -> 1.3.5, gitea 1.3.5 -> 1.3.6,
marketplace.version 0.4.4 -> 0.4.5, all PATCH under per_package.
- apm.yml's top-level version: is restored to lockstep at 0.4.5. It has moved
with marketplace.version in all eleven commits that ever touched the file
until this branch left it at 0.4.2, and apm.yml's own comment records it as
live and consumed by apm audit.
- git's boundary names the pre-commit hooks explicitly: pc-author and pc-run are
not git operations, and a boundary drawn narrower than the contents is the
same defect one level up.
- Regenerated with apm pack for the marketplace manifests and
sync-plugin-content.sh --all for the per-plugin ones; both mirrors verified
byte-identical.
Impact: consumer-facing. 16/16 pre-push hooks pass, suite green, generated diff
is 26 insertions and 26 deletions across 8 files with no incidental churn.
Refs: #105
ADR: 0021
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w
Why: four defects in the files every session pays for, all introduced or left
behind by the trim.
AGENTS.md told agents the `<plugin>:` form still resolves "because user-scope
native installs were left enabled on purpose", and that a working namespaced
call "is not something to fix". That premise is false on this machine:
installed_plugins.json is empty, no enabledPlugins key exists in ~/.claude.json,
and ~/.apm/marketplaces.json is empty. ADR-0018 already reversed itself once on
this exact claim (Correction 2026-08-14) using that same enablement as its
evidence, so flipping the assertion again would be the third revision in three.
Both files now assert nothing about install state at all, which removes the
flip-flop surface instead of re-aiming it.
The other three are guard-rails whose instruction survived the trim while the
caveat that made it safe did not:
- The run-tests.sh line omitted --strict, so it named the one invocation that
reports SKIPPED rather than failed when a dependency is missing. gates.md
records this gate going green having verified 15 of 17 suites on a vale-less
PATH. .pre-commit-config.yaml:70 already uses --strict for that reason.
- The .claude/settings.json prohibition lost its ADR-0019 exception, so an agent
applying it literally would strip apm's own merged SessionStart entry and
create the drift the rule exists to prevent.
- LESSONS.md still routed graduated rules to CONTEXT.md's Principles section,
which this branch deleted.
Implementation notes: the six terms the trim dropped while AGENTS.md still
claimed CONTEXT.md glosses everything -- authoring root, content mirror, apm
package, output profile, near-miss, vacuous green -- are restored as one-line
entries per CONTEXT-FORMAT.md, sourced from architecture.md, gates.md and
skill-audit's description-quality.md rather than reworded. ADR-0018 gets a third
dated note recording the observation and the fact that the state has now been
described two ways, and its stale user-scope inventory is replaced by a pointer
to it; the decision it records is untouched. LESSONS.md:3 carried the identical
stale claim as :5 and is fixed with it.
Impact: preloaded context is now free of assertions about machine state.
Refs: #105
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w
Why: this branch moved the prerequisites list out of AGENTS.md into README.md
but left three references behind. The worst is run-tests.sh's --strict failure
message, which a developer is handed at the exact moment a push gate fails and
they need the dependency list: it named AGENTS.md, which no longer documents
vale, apm or jq anywhere. 56cc173 re-anchored this same class of citation in
.pre-commit-config.yaml, scripts/check-vale-style-sync.sh,
scripts/sync-marketplace-mirror.sh and tests/test-check-vale-style-sync.sh --
tests/run-tests.sh was missed, and it is the only one a human actually reads.
Implementation notes:
- run-tests.sh:262 (user-visible), run-tests.sh:16 (header rationale) and
test-run-tests.sh:395 all now cite README.md's Prerequisites table, verified
to name vale, apm, jq, python3/PyYAML and the claude CLI.
- Every assertion on this message greps for "a skip is a SETUP ERROR", which
sits before the changed clause, so no test needed updating.
- test-vale-wrap.sh's bash 3.2 citation is corrected in the same pass: it
credited LESSONS.md and the script headers, but LESSONS.md's only mention of
3.2 is an aside inside an unrelated lesson, not a target declaration. It now
cites scripts/lib/batch-run.sh and providers/claude-code/statusline-command.sh,
which do declare it. The citation 56cc173 replaced was already false, so this
finishes a half-fix rather than correcting a regression.
Impact: forced the strict-failure path with vale removed from PATH and confirmed
the corrected message printing -- 21 passed, 3 skipped, exit 1. Full suite with
vale present: 24 passed, 0 skipped, 0 failed.
Refs: #105
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w
Why: bd2bf66 restored the `apm pack` guard-rail by appending it to the `Fix:`
command after `--`, which made the printed line stop being runnable. Pasting it
ran the script with ~24 stray argv entries: `${1:-}` became `--`, so CHECK
stayed 0, no shift occurred, and `[[ $# -eq 0 ]] || usage` printed usage and
exited 1. The user got a usage error from the tool meant to fix their problem,
and the mirror stayed stale.
The unquoted backticks around `apm pack` were a second hazard in the same line:
the paste command-substituted a real `apm pack` run before this script was ever
reached, so the first error a user saw came from apm, not from here.
Implementation notes:
- The runnable command now stands alone on its own line, and the rationale
follows as a separate `Note:` echo.
- Backticks downgraded to single quotes; a line printed next to a
copy-pasteable command must not contain shell metacharacters.
- The guard-rail text is otherwise preserved verbatim. It exists because apm
ships no output profile targeting this path, so `apm pack` does not refresh
it, and expecting it to is the drift this hook prevents.
Impact: reproduced the break on a scratch copy, then verified the fix by pasting
the printed command verbatim — exit 0, mirror synced, re-check clean.
tests/test-sync-marketplace-mirror.sh asserts only exit codes and file contents,
so nothing pins this message and it could regress silently; tracked separately.
Refs: #105
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TmFqzpuExLJv3m114XVE9w
Why: bin's marketplace description read "A place for things to be binned" — a
routing boundary sitting in the enumeration slot, phrased as a joke. It is what
a consumer sees in the marketplace listing for a plugin shipping eleven
substantive skills: research, write-docs, tdd, prototype, triage, diagnose,
improve-codebase-architecture, grill-me, grill-with-docs, zoom-out and caveman.
This is the same category error b0ef503 fixed for git and gitea, and the same
text bb9158d moved out of core's description in August — "triage, diagnosis,
architecture review" left core precisely because those skills live in bin, so
bin is where it should have landed.
Implementation notes: bin 1.1.3 -> 1.1.4, marketplace 0.4.3 -> 0.4.4, PATCH for
metadata under the per_package strategy. README's bin line mirrors the new
description. architecture.md's routing boundary is deliberately left as
"unsorted skills that have not earned a home yet" — that is still true, and it
answers a different question than the listing does.
Impact: consumer-facing. apm-pack-check-clean, check-plugin-content-sync,
check-marketplace-mirror-sync, validate-marketplace, validate-plugins and
apm-audit-ci all pass.
Why: both plugins' published descriptions named capabilities that do not exist
and omitted ones that do. `gitea` advertised wikis — no wiki skill exists and
`grep -ri wiki plugins/gitea/.apm/` is empty — while omitting gitea-branches and
gitea-files. `git` advertised pull requests, which are gitea's, while omitting
pc-author/pc-run, git-submodules and git-workflow. These are compiled into
plugin.json and both marketplace.json files, so they are published metadata, not
internal notes.
This is the same defect bb9158d fixed on `core` in August, so the fix follows
that precedent exactly: correct the package apm.yml and the root marketplace
entry together — fixing only the package manifest leaves it half-propagated,
since the root entry is what reaches the compiled marketplace.
Implementation notes:
- git 1.3.3 -> 1.3.4, gitea 1.3.4 -> 1.3.5, marketplace 0.4.2 -> 0.4.3, all
PATCH for metadata under the per_package strategy at apm.yml:76.
- Regenerated with `apm pack` for the two marketplace manifests and
`scripts/sync-plugin-content.sh --all` for the four per-plugin plugin.json
files; `apm pack` alone does not touch those. `scripts/sync-marketplace-mirror.sh`
refreshed the Copilot legacy mirror, which no apm profile targets.
- README's gitea line mirrors the new published description. The routing
boundaries in architecture.md deliberately do not, since they answer a
different question.
Impact: consumer-facing. Anyone reading the marketplace now sees what these
plugins ship. apm-pack-check-clean, check-plugin-content-sync,
check-marketplace-mirror-sync, validate-marketplace and apm-audit-ci all pass.
Why: the review found architecture.md's plugin table and README's plugin list
were both written by enumerating what happened to be in each plugin, so both
went stale immediately — README credited `git` with pull requests it has no
skill for, and both omitted `pc-author`/`pc-run`. bb9158d fixed this same class
on `core` in August and it recurred here, so the fix is to stop enumerating in
the place whose job is routing.
Implementation notes:
- architecture.md's table now states routing boundaries only, with a note saying
so and pointing at each plugin's published apm.yml description for the actual
inventory. Two boundaries are named explicitly: `core` vs `kyberforge` (kept),
and `git` vs `gitea` — wire protocol against a local clone versus the forge's
HTTP API, which is why git-branches and gitea-branches are not duplicates.
- The `git` row is widened to cover git hook tooling rather than moving
pc-author/pc-run elsewhere. pre-commit manages .git/hooks/, so the placement
was always right and the row was simply under-described.
- README's setup block had a comment where step 2's command should be. It now
carries `pre-commit install -t pre-commit -t commit-msg -t pre-push`, verified
against the three stages in .pre-commit-config.yaml and the three hooks in
.git/hooks/. pc-run is still named, as the option rather than the only path.
- README:11 said each plugin carries agents, hooks and MCP servers. Only
kyberforge ships hooks and only bin ships an MCP server.
- gates.md:30 claimed its hook list was in config order; it is grouped by
concern, which is the better layout, so the claim is corrected to match.
Impact: docs-only. gitea's published description is corrected separately, since
that regenerates consumer-facing manifests.
Why: 1929ffd and b9c7762 preserved every constant, hook ID and error string,
but two don't-re-litigate notes were lost. Both were guard-rails — they fired
from preloaded context, before the mistake. Restoring the sentence to an
on-demand spec doc restores the text without restoring the function, since an
on-demand file is opened after a plan is formed, not before.
Implementation notes: placed by when each note must fire, not by what it is
about.
- "Do not expect `apm pack` to refresh the .github/plugin/marketplace.json
mirror" now lives in the DRIFT failure message of the script and hook that
already catch that exact mistake. It costs no preloaded tokens, fires at the
moment of the error, and cannot be missed. No test asserts on that message;
--check and shellcheck both pass.
- Plugin self-containment has no gate that fires on it, so it goes in
architecture.md's Plugin model beside "self-contained plugin units", stated as
the constraint it is rather than a description, with the two consequences that
make it load-bearing: the duplicated Vale styles (ADR-0014) and ADR-0020's
constants copied into three validators.
Impact: the every-session set is unchanged — neither note returns to AGENTS.md.
Why: b9c7762 gave dated amendments to ADR-0013, ADR-0015 and ADR-0017, but two
pointers were missed. ADR-0007 cited the "Provider-agnostic issue tracker"
glossary entry, which the trim renamed to "Issue". ADR-0015 cited the "lint
plugin" entry, which the trim deleted outright — and ADR-0015 was amended for
its other CONTEXT.md pointer in the same commit, so this one was missed inside
an already-edited file.
Implementation notes: ADR-0007 gets a dated parenthetical matching the pattern
the other three carry, confirming the entry survived under a new name rather
than being dropped. ADR-0015's Considered-options parenthetical is re-pointed
at docs/spec/architecture.md's plugin scope table, which now carries the
repo-agnostic-versus-marketplace-specific argument the deleted entry held, and
its existing 2026-08-17 supersession note is extended to record that second
redirect in one place.
Impact: all four ADRs that referenced moved CONTEXT.md content now say where the
content went. No decision is altered.
Why: eight comments and one status note cited CONTEXT.md or AGENTS.md text that
b9c7762 and 1929ffd moved or deleted. All are inert at runtime, but they are the
rationale comments that tell the next maintainer why an assertion exists, and
they now name a file that no longer explains it.
Implementation notes: re-anchored by what the citation is for, not uniformly.
- Four sites quoted facts ADR-0013 owns — every rule is `level: error` with no
ignorable tier (ADR-0013:59-70), and KyberforgeCopilot's `.agent.md`-only
scope (ADR-0013:43-46). These now cite ADR-0013. ADRs are append-only here;
the spec docs are refactored, which is what caused this rot.
- Two sites quoted the glob location-independence property, which no ADR owns.
The quote was already inline and carried the full rationale, so the citation
added a rot surface and no information — dropped, statement kept.
- sync-marketplace-mirror.sh's header attributed the mirror-not-a-profile fact
to CONTEXT.md; the parenthetical beside it already carries the evidence, so
the attribution is dropped rather than re-pointed.
- .pre-commit-config.yaml cited an AGENTS.md instruction that no longer exists;
generalised to "the documented instruction".
- LESSONS.md:29 misquoted AGENTS.md's current session-start line.
Also corrects a pre-existing misattribution at tests/test-vale-wrap.sh:454:
AGENTS.md has never named bash 3.2 as a repo target (`git log -S'3.2'` on it is
empty). LESSONS.md and the script headers do.
Impact: no behaviour change. test-check-vale-style-sync.sh and test-vale-wrap.sh
both pass (42 passed, 0 failed).
Why: CONTEXT.md is an instructed every-session read, so a wrong assertion in it
is cited downstream without being checked. The b9c7762 rewrite introduced one
broken pointer and carried over two claims that were already false.
Implementation notes:
- The Preload tax entry pointed at docs/spec/gates.md for the measurement
method. gates.md has no such method — it uses the 23,427-char figure once, in
passing, without deriving it. The method and the current figure both live in
ADR-0020, which is where a dated measurement belongs: it is superseded there
deliberately, and issue #99 tracks its drift.
- Dropped the "~5,900 tokens across 39 skills" measurement rather than
re-measuring it. It was already wrong three days after being written (~5,340
today) and it was the only live number in the file. Every sibling entry is one
definitional sentence plus a pointer fragment; this one now matches, and
CONTEXT-FORMAT.md:43 asks for exactly that.
- Dropped "Written by the session-handoff skill or directly by the human" from
the LESSONS.md entry. No session-handoff skill exists — LESSONS.md:7 records
it as planned work. Who writes a file is not its definition.
Impact: removes the only rot surface in the file and the only assertion in it
that names an artifact the repo does not have.
Refs: #99
Why: CONTEXT.md is an instructed every-session read at 33,799 bytes (~8,450
tokens), and CONTEXT.md:17 layered docs/VISION.md on top. After the AGENTS.md
trim, that left ~9,650 tokens of instructed reads sitting behind a file whose
own format contract — grill-with-docs/CONTEXT-FORMAT.md:43, "Keep definitions
tight. One sentence max." — it was not following. 22 glossary entries averaged
190 words; the top four were 55% of the file, and one ("Vale audit prefilter")
was 1,444 words of pre-commit forensics filed as a definition.
Implementation notes:
- CONTEXT.md rewritten to CONTEXT-FORMAT.md's prescribed template: ## Language
(five clusters, 22 terms with _Avoid_ aliases), ## Relationships,
## Example dialogue, ## Flagged ambiguities. 33,799 -> 9,762 bytes.
- Vale prefilter forensics moved to docs/spec/gates.md under nine subsections:
the two-copy style layout, vale-wrap.sh and the Vale 3.15.2
text.frontmatter.description limitation, the --config argv defect (E100),
glob scoping, the rule inventory, and 0-files-means-NOT-RUN.
- Instruction-file format and the bidirectional-reference principle moved to
docs/spec/architecture.md, the latter flagged as aspirational: no instruction
file carries a `when:` field, only 2 of 39 skills do, and the reference
scanner script it names does not exist.
- Added a per-plugin scope table to architecture.md so "which plugin owns this
skill" survives the trim, and corrected its claim that the content index
lives in providers/claude-code/CLAUDE.md — that file is now two import lines
and the index sits in core/AGENTS.md.
- "Repo and Gitea are the only source of truth" moved from CONTEXT.md's
Principles into AGENTS.md session rules; it was operative guidance in a
glossary. docs/VISION.md and LESSONS.md added to the on-demand list.
- The apm-consumed install entry (432 words) was deleted outright: all four
consequences are already carried by README.md, ADR-0018, gates.md and
AGENTS.md.
- ADR-0013, ADR-0015 and ADR-0017 each pointed at CONTEXT.md sections that
moved; amended with dated supersession notes rather than left dangling.
Impact: the every-session set drops from ~15,700 to ~4,140 tokens across both
passes (-74%). The deleted "lint plugin" entry was also stale on a safety
claim — it said lint-runner inherits Edit, but ADR-0016 restored
`disallowedTools: Edit, Write, NotebookEdit` and CONTEXT.md was never updated.
Refs: #99
Why: AGENTS.md is preloaded into every session via CLAUDE.md's @AGENTS.md
import, so every word is a tax paid whether or not it is relevant. It had
grown to 3,371 words (~4,550 tokens), 75% of it a single "Setup and testing"
section that was mostly neither: roughly 1,600 words were gate forensics —
why a hook is shaped the way it is, what was tried and rejected, verification
numbers — and only ~390 words were genuine one-time setup.
Implementation notes: split three ways by audience rather than by heading.
One-time setup, prerequisites and test commands move to a new root README.md,
which did not previously exist. The gate forensics move to a new
docs/spec/gates.md, preserving every constant, hook ID, error string and
tried-and-rejected note (policy.fetch_failure_default, the removed fallback
frontmatter reader, extending skill-size-check's files: pattern to agents,
tidying .claude/settings.json out of the pretty-format-json exclude list) —
these exist to stop settled decisions being re-litigated, so none were
dropped. AGENTS.md keeps only what applies every session, at one clause of
rationale per rule. The .apm/-mirror section collapses to a pointer because
docs/spec/architecture.md already covers it in full. The hot ADR-0020 gate
counts stay in AGENTS.md deliberately: they block any skill edit today.
Also corrects docs/spec/architecture.md's stale claim of 19 ADRs; ADR-0020
landed without updating the count.
Impact: per-session preload drops from ~4,550 to ~1,116 tokens, a 75% cut.
agentsmd-audit passes: secrets clean, drift clean, 4 informational findings
for sections deliberately relocated to the README.
Why: kyberforge's SessionStart hook found six packages behind the holocron
default branch and ran `apm update --yes`, which re-resolved every unpinned
dependency ref and rewrote the lock. The dependencies are declared unpinned
against the default branch, so this churn is expected rather than a defect.
Impact: pins the deployed skill and agent set to the refs resolved this
session. No manifest or plugin content changed.