diff --git a/CONTEXT.md b/CONTEXT.md index d9dd395..5e9754d 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -16,8 +16,12 @@ decisions. **Preload tax**: The always-on context cost of every installed skill's `name` and `description`, charged from the -first token of every session whether the skill is invoked or not. Measurement method and current -figure: ADR-0020. +first token of every session whether the skill is invoked or not. Measurement method: ADR-0020. Its +**23,427 characters is the pre-retrofit baseline, not a current reading** — measured at the decision +commit, before #99. Across the same 39 skills it is **10,478 characters** (~2,620 tokens) as of +2026-09-01. Both figures move with the corpus, so re-derive rather than quote either: sum +`len(name) + len(description)` over the frontmatter of every `plugins/*/.apm/skills/*/SKILL.md`, +folding block scalars as `scripts/skill-size-check.sh` does. _Avoid_: context cost, token overhead **Skill context contract**: @@ -44,7 +48,7 @@ _Avoid_: router body, thin body A skill reached only by typing its slash command, declared `disable-model-invocation: true`. The host withholds it from the model-visible listing entirely, so it pays no preload tax and its description becomes human-facing text. The flag also hard-blocks the Skill tool, so **no other skill can route to -a hand-invoked skill** — a `Call \`x\`` step in another skill's body stops working the moment `x` +a hand-invoked skill** — a `` Call `x` `` step in another skill's body stops working the moment `x` takes the flag. Check inbound routes before declaring one. Exemplar: `zoom-out`. _Avoid_: manual skill, disabled skill diff --git a/docs/adr/0020-skill-description-and-body-context-contract.md b/docs/adr/0020-skill-description-and-body-context-contract.md index ef38558..09b7da2 100644 --- a/docs/adr/0020-skill-description-and-body-context-contract.md +++ b/docs/adr/0020-skill-description-and-body-context-contract.md @@ -127,8 +127,15 @@ clause**, and a **boundary clause**. Capability enumeration, output-format detai gate shipping hot with no baseline cannot give two answers. Under the walk-up those four resolve because sibling plugins are in the universe — no plugin here declares a cross-plugin apm dependency, and none needs to. Verified: a tree holding only `plugins/` and the root `apm.yml`, - with no `.claude/` or `.agents/` anywhere, now produces findings identical to the working tree — - 26 description FAILs, 9 body FAILs, 2 dangling targets, 0 missing references, 58 SUGGESTIONs. + with no `.claude/` or `.agents/` anywhere, produced findings identical to the working tree. The + figures that reproduction recorded — 26 description FAILs, 9 body FAILs, 2 dangling targets, 0 + missing references, 58 SUGGESTIONs — are the **pre-retrofit** corpus as it stood when the + experiment ran, kept here as the evidence for the install-independence claim, not as a current + reading. *Amended 2026-09-01: the #99 retrofit took the first three to zero. Measured at that + date over the same install-free tree: 0 description FAILs, 0 body FAILs, 0 dangling targets, 0 + missing references, 29 SUGGESTIONs.* What the experiment establishes is that the two trees agree, + not what either measured; re-derive rather than quote — + `bash scripts/skill-size-check.sh plugins/*/.apm/skills/*/SKILL.md`. - **The universe is the apm marketplace, and nothing else.** A routing target resolves to a skill or an agent, or it does not resolve. Host built-ins are deliberately outside it: `/compact`, `/clear` and `/init` are Claude Code slash commands with no counterpart in Copilot CLI or Codex, so a @@ -185,8 +192,11 @@ becomes the system prompt of a fresh context. The rationale for the 900-word FAI That exemption is expressed in `agent-audit/scripts/validate.sh`, which has no body constant, and in the `files:` pattern of the `skill-size-check` pre-commit hook, which is `SKILL.md`-only. It is *not* expressed in `scripts/skill-size-check.sh` itself, which measures whatever path it is handed — -running it directly over `plugins/*/.apm/agents/*.agent.md` today reports 900-word body FAILs on -`git-orchestrate` (933), `gitea-orchestrate` (1,199) and `apm-orchestrate` (1,080). Agents escape by +running it directly over `plugins/*/.apm/agents/*.agent.md` exits 1 with 900-word body FAILs on +`git-orchestrate` and `gitea-orchestrate`. *Amended 2026-09-01: this sentence named a third agent, +`apm-orchestrate`, at 1,080 words. It is 876 today — a SUGGESTION, not a FAIL. Counts are +deliberately no longer pinned here: agent bodies are edited like any other file and a figure in this +paragraph goes stale the moment one is trimmed. Run the command.* Agents escape by file pattern, not by the script knowing the difference. Anyone widening that pattern to cover agents would silently enforce a gate this ADR declines to set. @@ -245,7 +255,7 @@ which tier each rule is in, because the failure this ADR is most exposed to is a | description characters (250 SUGGESTION † / 400 FAIL) | skills, agents | deterministic | `scripts/skill-size-check.sh`; constants mirrored in `skill-audit/scripts/validate.sh` and `agent-audit/scripts/validate.sh` | | body-only words (600 SUGGESTION / 900 FAIL) | skills | deterministic | `skill-size-check.sh`, `skill-audit/scripts/validate.sh` | | description present and non-empty (ERROR) | skills, agents | deterministic | same | -| boundary target resolves to a real skill or agent (ERROR when written in route notation — `/name`, or any arrow form; or when a *terminal* bare name's own sentence names another target that resolves; SUGGESTION otherwise) | skills, agents | deterministic | same | +| boundary target resolves to a real skill or agent — **three** verdicts, not two (ERROR when written in route notation — `/name`, or any arrow form; or when a *terminal* bare name's own sentence names another target that resolves. SUGGESTION otherwise. INFO, "DID NOT RUN", exit 0, when no skill universe could be determined for the path at all — no authoring root above it, no apm package root, no declared apm dependencies, no deployed `.claude/` or `.agents/` tree: the targets are named and left unchecked) | skills, agents | deterministic | same | | boundary clause absent — `absent` (SUGGESTION) † | skills, agents | deterministic | same | | an arrow clause is present but no target can be read out of it — `unparsed` (SUGGESTION) † | skills, agents | deterministic | same | | one arrow clause naming two or more targets, of which only the first is resolved (SUGGESTION, issue #107) † | skills, agents | deterministic | same | @@ -378,10 +388,17 @@ carries is the ordinary one for hot gates: a gate expensive enough to be inconve with `SKIP=` and loses its authority. **A second hot gate ships alongside it, and it is easy to miss.** `Kyberforge.CompositionNote` is -`level: error` like every other rule in that style, so `pre-commit run --all-files` is red on 10 -alerts across `gitea-issues`, `gitea-labels-milestones`, `gitea-prs` and `gitea-workflow` -independently of anything `skill-size-check` reports. Someone scoping the #99 retrofit off the size -findings alone will fix those and still be blocked. The two gates want fixing together. +`level: error` like every other rule in that style, so at decision time `pre-commit run --all-files` +was red on 10 alerts across `gitea-issues`, `gitea-labels-milestones`, `gitea-prs` and +`gitea-workflow` independently of anything `skill-size-check` reports. Someone scoping the #99 +retrofit off the size findings alone would have fixed those and still been blocked. The two gates +wanted fixing together, and were. *Amended 2026-09-01: that figure is historical. The Vale prefilter +over the same 39 files now reports 0 errors, 0 warnings and 0 suggestions, so +`Kyberforge.CompositionNote` fires nowhere in the corpus today. The rule is still hot and still +independent of `skill-size-check`, so a new description can reintroduce it; `skill-size-check` does +not cover the Vale half, and no `references/` file is linted by anything (`docs/spec/gates.md` has +both causes, issue #117 tracks them). Re-derive rather than quote —* +`bash plugins/kyberforge/.apm/skills/skill-audit/scripts/vale-wrap.sh plugins/*/.apm/skills/*/SKILL.md`. **A ceiling does not produce an average.** If every author writes to the 400-character FAIL, the preload lands at 39 × 400 = 15,600 chars — a 33% cut off 23,427, not the ~50% intended. Writing to