Commit Graph

7 Commits

Author SHA1 Message Date
a6eedacfd8 fix(skill-frontmatter): check every file, scope checks to frontmatter
The hook is `entry: bash` with `args: ['-c', <script>]`. pre-commit appends filenames after the
script string, so the first becomes `$0` and never enters `"$@"` — on a single-file commit, the
common case, the loop body never ran and the hook reported Passed having measured nothing.
ADR-0022 leans on this hook as the enforcement for a mandatory `metadata.version`, so the vacuous
green was the whole gate.

Implementation notes:
- An arg0 placeholder absorbs `$0` so every filename lands in `"$@"`.
- Checks now run against the YAML frontmatter block only, extracted with awk. The old
  `grep -A10 "^metadata:"` matched a `metadata:` inside a body code fence, spanned past the block
  into a following `source:` entry's `version:`, accepted any indentation, and missed a `version:`
  more than ten lines in. An unreadable frontmatter block is now an error, never a pass.
- The value is asserted against three-part semver. `write-docs` carried "1.0" through the entire
  ADR-0022 retrofit undetected, which a presence-only check cannot catch.

Impact: `tests/test-skill-frontmatter.sh` is the first test this hook has ever had. It drives the
real `entry`/`args` composition read out of the config rather than a copy of the script, which is
the only shape that catches the arg0 bug; against the pre-fix hook it scores 7/20.

gates.md described the hook wrongly in both directions and is rewritten, with a carve-out
explaining why this one stays a shell parser next to the "python3 and PyYAML are hard
requirements" reasoning that argues otherwise.

Refs: #127
ADR: 0022
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP
2026-09-09 05:13:52 +00:00
Claude Code AI - Gitea MCP
598a7c326a refactor(skills): retrofit the corpus to the ADR-0020 context contract (#129)
Retrofits all 39 skills to ADR-0020's description/body context contract, then fixes what six rounds of independent review found in that retrofit — including four ways the hot gate itself failed open.

Closes #99, #107, #108, #110, #111, #114, #115, #120.

## The retrofit (waves 1-5)

| | Start | Now |
|---|---|---|
| Description FAILs (>400 chars) | 26 | **0** |
| Body FAILs (>900 words, body-only) | 9 | **0** |
| Dangling routing targets | 2 | **0** |
| `Kyberforge.CompositionNote` | 10 | **0** |
| Preload tax | 21,005 chars | **~10,500** |

Under the 12,000-char success criterion. Per-wave detail is on #99.

## The review fixes

**The gate failed open four ways, three of them found after the retrofit shipped.** An unrecognised follower token made a dangling target vanish. A skill directory with no `SKILL.md` resolved as a valid target, so a commit could be green locally and red in a fresh clone — three existing fixtures were relying on that, one of which made the install-leak A/B pass vacuously. Then the free-standing `/name` sweep turned out to be gated on the sentence carrying a boundary marker, so route notation in any other sentence was invisible — not an ERROR, not a SUGGESTION, not an INFO — which left the documented "`/name` always blocks" promise false from a second direction. All four fixed and pinned.

**Two checks were silently not running.** `validate-provenance.sh` checks 7-8 were dead across nine skills. Waking them exposed a deeper problem: they assume `Research doc:` names a source index, but 30 of 121 entries point at topic content documents, so every new check-7 INFO was a false positive and check 8 was saved from a false-FAIL flood only by an *unannounced* skip. Checks 7/8 are now scoped to source indexes and every skip announces itself (#121).

**The retrofit's own anti-goal, four times.** ADR-0020 warns that a blunt gate gets satisfied by deleting content rather than relocating it. `diagnose` and `skill-audit` relocated prose and then read it unconditionally; `prototype` and `vale-config` deleted rules outright that survived nowhere. All four addressed.

## Verification

- `bash tests/run-tests.sh --strict` — 24 suites, 0 skipped, 0 failed
- `bash tests/run-bats.sh` — 325 tests, 0 failures
- `pre-commit run --all-files` — 17/17
- `pre-commit run --hook-stage pre-push --all-files` — 16/16, with `apm marketplace check` and `apm pack --check-clean` run against the remote, not skipped
- `scripts/skill-size-check.sh` over all 39 skills — rc 0, 0 ERROR/FAIL, SUGGESTION-only
- Preload tax measured at **10,498 chars**, max description 390 — both inside budget
- Every new test proven non-vacuous by a deliberate mutation of the behaviour it covers

**Per-commit sync, stated accurately:** the ten commits from the latest review round each pass `check-plugin-content-sync` in isolation, verified by checking each out in a detached worktree with a clean between. The earlier gitea window (`dfacf05..bedbd1d`, nine commits) does **not** — its mirror was regenerated in one batch at `bbc7300`. An earlier revision of this description claimed the property held for every commit; it does not, and a bisect through that window lands on a red commit. **Squash-merge** to collapse it, or accept that this range is not bisectable.

## Version bump

Six plugins and the catalog take a **patch**, not a minor. The branch is **89 commits — 40 `fix` / 30 `refactor` / 12 `docs` / 5 `chore` / 2 `test` — zero `feat`, zero `!`, zero `BREAKING CHANGE`** — and adds no skill, agent, command or hook. (Two earlier revisions of this section cited a stale histogram, most recently 78 commits; the figures above are measured at HEAD.) Both rules this repo ships (`forge/references/version-bump.md`, landing in this PR, and `git-commits/references/conventional-commits-spec.md`) make that a patch, and the catalog set is unchanged at 7 entries.

Not settled by that: four published files were removed from the installed tree, three moved, and `caveman` gained `disable-model-invocation`, retiring its old triggers. Under a strict reading those are major-class and currently ship under `refactor:` with no marker. Whether the deployed skill surface is a public contract is written down nowhere — worth deciding, but it outlives this PR.

## Deliberately not in scope

#112 (cherry-pick ownership, now resolved in favour of `git-commits`), #113 (`rtk git` normalisation), #116 (research fan-out), #101 (audit-skill merge), #122 (non-spec skill-root files), #123 (no PRD producer) stay open. #117 is the one worth reading: the contract's remedy is to move prose into `references/`, which is exactly where neither the size gate nor Vale looks — and the blind spot is wider than #117 currently records, since there is no root `.vale.ini` at all, so every ADR, `CONTEXT.md` and `README.md` is unlinted too.

That blind spot let this branch carry two `level: error` `Kyberforge.SentenceOpenerThereIs` violations into `references/` files it created — `provider-adapter-author/references/provider-matrix.md:31` and `agent-audit/references/finding-criteria.md:95`. Both are reworded in `afadaae`, confirmed by routing each file through the audit's own `vale-wrap.sh` (1 error each before, 0 after). Five further occurrences sit in `references/` files already on `main`; those are the pre-existing corpus and stay with #117, which is the real fix.

Also unfixed and not this PR's: `apm install` appends a duplicate `SessionStart` entry to `.claude/settings.json`, so a fresh clone cannot get pre-push green without an edit AGENTS.md warns against. Reproduces identically on `main`.

Co-authored-by: Defame1297 <gitea@rkdr.net>
Reviewed-on: https://git.dev.rkdr.net/Defame1297/holocron/pulls/129
Co-authored-by: Claude Code AI - Gitea MCP <claude@noreply.git.dev.rkdr.net>
Co-committed-by: Claude Code AI - Gitea MCP <claude@noreply.git.dev.rkdr.net>
2026-09-01 13:47:46 +00:00
d42f6368fe fix(docs): correct claims the first fix round asserted without measuring
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
2026-08-17 13:18:55 +00:00
c68e864159 docs(spec): correct eight claims the trim carried into the new files
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
2026-08-17 12:29:16 +00:00
b0ef503485 docs: correct plugin scope, hook ordering and the setup gap
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.
2026-08-17 10:11:59 +00:00
b9c7762463 docs: trim CONTEXT.md to a glossary and demote VISION.md
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
2026-08-17 09:28:01 +00:00
1929ffd2da docs: slim AGENTS.md to per-session context only
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.
2026-08-17 08:56:37 +00:00