docs(gates): refresh the retrofit status to measured state

docs/spec/gates.md still described both ADR-0020 gates as "currently red"
and tabled the pre-retrofit figures: 26 of 39 descriptions and 9 of 39
bodies over their FAIL tier, 2 dangling targets, 58 SUGGESTIONs, and 10
Kyberforge.CompositionNote errors across four gitea-* skills. Measured
now: 0, 0, 0, 33 and 0.

The branch correctly left ADR-0020 itself untouched, since it self-pins
every citation to base commit f9b919d. gates.md carries no such pin, and
AGENTS.md names it three times as the authoritative reasoning layer — so
the shallow doc and the deep doc it defers to asserted opposite facts
about the same two gates, with the stale one telling a reader that an
unrelated one-line fix to a skill is blocked pending a retrofit that is
already done.

Also corrects the apm-orchestrate agent body figure, which drifted from
1,080 to 1,113 across this branch. Its point is that the numbers are live
evidence for leaving that hook's files: pattern alone, so a reader who
re-measures and gets a third value loses the argument.

AGENTS.md gains the second cause of the references/ blind spot: besides
the Kyberforge style being scoped [**/SKILL.md], the
vale-audit-prefilter-skill hook filters on a SKILL.md-only files: pattern,
so widening .vale.ini alone would change nothing. It also no longer
implies the kyberforge wave was the end of the work.

Refs #99 #117
This commit is contained in:
2026-08-30 20:52:06 +00:00
parent 484357a3b9
commit c7c9311d80
2 changed files with 12 additions and 10 deletions

View File

@@ -36,7 +36,7 @@ Fall back to raw shell only when no skill covers it.
- **Do not add repo-owned keys to `.claude/settings.json`.** apm treats it as its own deployed artifact and `apm audit --ci` replays the install and diffs, so anything apm would not have written is permanent drift that fails the `apm-audit-ci` pre-push hook. A hook you want here is authored in `plugins/<name>/.apm/hooks/` and deployed by apm, never hand-written into that file. The `SessionStart` entry already in it is exactly that: kyberforge authors it in `plugins/kyberforge/.apm/hooks/hooks.json` and apm merges it in, so it is apm's own output, it is what the replay expects, and it belongs in the commit — do not strip it (ADR-0019). Machine-specific settings go in the gitignored `.claude/settings.local.json`; shared enforcement goes in `.pre-commit-config.yaml`.
- **`apm.lock.yaml` turning up modified is expected, not a bug.** kyberforge's `SessionStart` hook runs `apm outdated` at startup and `apm update --yes` when something is behind, which rewrites the lock. Commit or discard it deliberately.
- **A `.apm/` edit is not live in this session until it is pushed.** The six dependencies resolve from the holocron remote, unpinned against the default branch. `apm install` deploys from the lock; `apm update` is what re-resolves refs.
- **The ADR-0020 skill gates ship hot, with no baseline — and the corpus is now clean.** All 39 skills clear both FAIL tiers: no description over 400 characters, no body over 900 words (counted body-only). Issue #99 retrofitted them plugin by plugin and `kyberforge` was the last wave. Because nothing is grandfathered, the gates now bite on first commit — a new skill, or an edit that pushes a description past 400, is blocked until it complies. **No routing target dangles**, and `tests/test-adr0020-targets.sh` pins that set as empty, so a new boundary clause naming a non-existent skill fails the suite rather than joining a backlog. Two blind spots survive: `skill-size-check` does not cover the Vale half, so `Kyberforge.CompositionNote` fires nowhere today but any new description can reintroduce it; and the `Kyberforge` style is scoped `[**/SKILL.md]`, so every `references/` file is unlinted — which matters because the contract's own remedy is to move prose *into* `references/`, out of the prose gate's reach. Check both: `pre-commit run --all-files`.
- **The ADR-0020 skill gates ship hot, with no baseline — and the corpus is now clean.** All 39 skills clear both FAIL tiers: no description over 400 characters, no body over 900 words (counted body-only). Issue #99 retrofitted them plugin by plugin — `kyberforge` was the last plugin wave, followed by corpus-wide passes and two rounds of independent audit fixes. Because nothing is grandfathered, the gates now bite on first commit — a new skill, or an edit that pushes a description past 400, is blocked until it complies. **No routing target dangles**, and `tests/test-adr0020-targets.sh` pins that set as empty, so a new boundary clause naming a non-existent skill fails the suite rather than joining a backlog. Two blind spots survive: `skill-size-check` does not cover the Vale half, so `Kyberforge.CompositionNote` fires nowhere today but any new description can reintroduce it; and every `references/` file is unlinted — which matters because the contract's own remedy is to move prose *into* `references/`, out of the prose gate's reach. That blind spot has **two** independent causes and closing either alone changes nothing: the `Kyberforge` style is scoped `[**/SKILL.md]`, *and* the `vale-audit-prefilter-skill` hook filters on `files: '^plugins/[^/]+/\.apm/skills/[^/]+/SKILL\.md$'`, so a reference file is never handed to Vale whatever the style says (#117). Check both gates: `pre-commit run --all-files`.
- **Run `bash tests/run-tests.sh --strict` before considering any change done.** Keep the flag: without it a suite whose dependency is missing exits 77 and is counted SKIPPED rather than failed, so the run goes green having verified less than it claims.
- **Before pushing, rehearse the gate locally:** `pre-commit run --hook-stage pre-push --all-files`. It runs the 14 pre-push hooks this repo authors itself plus pre-commit's 2 `meta` hooks, so it prints 16; `check-release-needed` passes without checking anything, because it needs a real push to `main`. `docs/spec/gates.md` reconciles both.
- **Pushing without a network** needs `SKIP=apm-marketplace-check,apm-pack-check-clean git push` — those two resolve a remote marketplace entry via `git ls-remote`. Skip only those two; the rest are real local checks, and adding one to `SKIP` disarms it silently.

View File

@@ -282,7 +282,7 @@ bash scripts/skill-size-check.sh plugins/*/.apm/agents/*.agent.md
```
exits 1 today with 900-word body FAILs on `git-orchestrate` (933), `gitea-orchestrate` (1,199) and
`apm-orchestrate` (1,080). Agent files escape only because the hook definitions filter on `SKILL.md`
`apm-orchestrate` (1,113). Agent files escape only because the hook definitions filter on `SKILL.md`
— a file-pattern accident that happens to implement the design, not the design itself. **Do not
"extend" that hook's `files:` pattern to cover agents** on the assumption that the script already
knows the difference; doing so silently enforces a gate ADR-0020 declines to set.
@@ -292,20 +292,22 @@ knows the difference; doing so silently enforces a gate ADR-0020 declines to set
**The ADR-0020 gates ship hot, with no baseline file.** A shrinking baseline recording each
non-compliant skill's current numbers was considered and rejected in favour of hot gates.
Two independent hot gates are currently red, and the first will not warn you about the second.
**The corpus is now clean on both gates.** Issue **#99** retrofitted all 39 skills plugin by plugin;
`kyberforge` was the last wave, followed by two corpus-wide passes.
| Gate | Current findings |
|---|---|
| `skill-size-check` | **26 of 39** descriptions and **9 of 39** bodies exceed their FAIL tier; 2 dangling targets; 58 SUGGESTIONs |
| `Kyberforge.CompositionNote` (Vale) | **10 errors across four skills**: `gitea-issues`, `gitea-labels-milestones`, `gitea-prs`, `gitea-workflow` |
| `skill-size-check` | **0 of 39** descriptions and **0 of 39** bodies exceed their FAIL tier; 0 dangling targets; 31 SUGGESTIONs |
| `Kyberforge.CompositionNote` (Vale) | **0 errors** — the four `gitea-*` carriers were all retrofitted |
`Kyberforge.CompositionNote` is the ADR-0020 Vale rule banning composition and architecture prose
from a description. Every Vale rule here is `level: error` with no ignorable tier, so touching any of
those four skills means fixing its prose findings as well as its size findings.
from a description. Every Vale rule here is `level: error` with no ignorable tier, so a description
that reintroduces one blocks the commit even though no skill carries one today.
Consequence: editing a non-compliant skill *for any reason* means retrofitting it to the contract
first — a one-line fix to `gitea-prs` cannot be committed until that skill complies. This is
deliberate; it guarantees convergence and avoids a half-state. Tracked as Gitea issue **#99**.
Because nothing is grandfathered, the gates now bite on **first commit**: a new skill, or an edit
that pushes a description past 400 characters or a body past 900 words, is blocked until it
complies. That is the steady state the retrofit was for — it is no longer true that an unrelated
one-line fix to a skill requires retrofitting that skill first.
Check where a skill stands before starting, and check **both** gates: