instructions/CONTRACT.md: Skill-H1, Referenztiefe und Begruendungsprosa praezisiert (schliesst #71, #72, #79)
CI / verify (push) Successful in 57s
Release / release (push) Successful in 37s

Files changed:
- CHANGES.md
- VERSION
- instructions/CONTRACT.md
- instructions/wiki-ingest/SKILL.md
This commit is contained in:
2026-09-09 16:25:34 +02:00
parent 7bc5da6e0d
commit 663b1c046c
4 changed files with 177 additions and 21 deletions
+94 -5
View File
@@ -142,16 +142,105 @@ does not survive being archived or copied. The price of a copy is drift, and dri
Scaffold with `tools/wikitool new instruction --name "<name>"`; the contract is
`tools/wikitool types describe instruction`.
- **Imperative title.** It answers "what does this tell me to do?".
- **Imperative title.** It answers "what does this tell me to do?". This binds the flat
`instructions/<name>.md` form only - a skill's H1 is a different case, below.
- **`description` is the retrieval wire.** Write it to match the question an agent would ask
when it needs this procedure, not as a label for the file.
- **Frontload.** Self-contained enough for an agent with no prior context: define terms
inline, do not assume other documents are loaded.
- **Keep reasoning out of the body.** Cut the explanation of *why* each step exists. If it is
worth preserving, it is a concept page under `kb/concepts/`, linked from here. Keep only
enough reasoning to decide edge cases.
inline, do not assume other documents are loaded. What this does and does not say about
linking a shared contract: below.
- **Reasoning earns its place by deciding something.** Keep what an agent needs in order to get
*this* decision right, at the step where it falls; cut the explanation of why the step exists
at all. If that is worth preserving, it is a concept page under `kb/concepts/`, linked from
here. Where the line runs, and how to test a passage against it: below.
- **State scope boundaries.** When does this *not* apply, and what to do instead.
### A skill's H1 is a name, not an imperative
`instructions/<name>/SKILL.md` takes a name-shaped H1 matching its `name:` frontmatter -
`# Wiki Ingest`, not `# Ingest a source file into the wiki`. The imperative-title rule is
written for the flat form and stops there.
The heading lies on no retrieval path. What decides whether a skill is picked up is
`description`, which sits in the agent's context from session start; the body is read only once
the skill is already open, and by then the title has nothing left to decide. Anthropic's
skill-authoring guidance agrees by omission and by example: it normalises `name` and
`description` and says nothing about the body's heading, and its own worked examples are noun
phrases (`# PDF Processing`, `# BigQuery Data Analysis`). So does the vendored `commonplace`
corpus, which arrived at the imperative-title rule independently and carves out the same
exception in the same breath - "for promoted skills, the skill name is the title".
That is the whole exception. Everything else in this section binds a `SKILL.md` exactly as it
binds an instruction.
### Reference depth: bundled files, not repo-wide contracts
Anthropic's skill-authoring guidance asks that reference files stay **one level deep from
`SKILL.md`**, because a file reached at the second hop may be previewed rather than read -
`head -100` instead of the whole file - leaving the step to run on incomplete information.
That rule governs **skill-bundled** material: files sitting in `instructions/<name>/` beside the
`SKILL.md`. The guidance's own worked example is a bundle (`SKILL.md``REDLINING.md`,
`OOXML.md`), and it says nothing about files outside the skill directory. No skill in this repo
has a bundled file today, so as written the rule currently binds nothing here.
A link from a skill to a repo-wide contract - [kb/CONTRACT.md](../kb/CONTRACT.md),
[tools/CONTRACT.md](../tools/CONTRACT.md), [gates.md](gates.md) - is a different category, and
the two halves of the question have different answers:
- **The mechanic is real and directory-independent.** A contract reached at the second hop can
be read partially exactly as a bundled file would be. Nothing about the path makes it safe.
- **The rule is not.** Reading its scope wider than it states would attribute a rule to a source
that does not carry it - the same move invariant 3 forbids about facts.
So the shared contracts stay shared and stay linked once. AGENTS.md invariant 8 is what put them
there: copying `kb/CONTRACT.md` into five `SKILL.md` files is precisely the second copy that
drifts. § Frontload does not ask for that either - it asks that a **step** be decidable without
prior context, not that every rule the step obeys be restated at it.
What the mechanic does oblige is cheaper than either: **a link says what the step needs from the
file it points at.** A bare "read X first" leaves a partial read undetectable; naming what is to
be taken from it - the field, the section, the decision - keeps the step decidable even when the
read came up short, and tells the next author which reference is actually load-bearing.
`wiki-ingest` step 7 is the shape: three contracts linked, each with the clause that says why
this step needs it.
This is a narrower posture than the vendored `commonplace` corpus takes, which makes outbound
links exceptional in its instruction collection and frontloads the rest. That works for a corpus
whose procedures do not share a contract; here they do, and invariant 8 outranks the preview
risk.
**All of the above is a judgment, not a measurement**, and it is worth knowing why it cannot be
the second. Whether the mechanic bites here is not something this repo can currently observe:
the L2 trajectory scorers read `wikitool` calls, gates and publishes, never an agent's file
reads, and no tool hook is wired on the primary harness at all - so a `head -100` leaves nothing
to score. The other half of the claim, what ended up in the context window, produces no event
anywhere by construction. Gitea #72 records what a test would cost and why it was not bought.
### How much reasoning a step may carry
"Cut the reasoning" and "keep enough to decide an edge case" are one sentence pulling two ways,
and the largest instruction in this repo lives in the gap. The line runs here:
| Keep | Cut |
|---|---|
| What an agent must know to get this decision right, at the step where it falls | Why the step exists at all |
| The consequence of the wrong choice, when nothing later catches it | The consequence, when a validator, a gate or a later step catches it |
| Why a plausible-looking default is the wrong answer | Background about the design that produced the field |
Two tests, both cheap:
- **Substitution.** Delete the passage and read the step again. Does an agent with no prior
context still make the same call? If yes, it was background. If it now guesses, it was a
decision aid, and it stays - however long it runs.
- **Once.** A decision aid belongs at the step where the decision falls, and at exactly one such
step (AGENTS.md invariant 8). Where the same decision falls at two steps - `wiki-ingest` asks
for `fidelity`/`authority` in step 1 and again in step 6 - the reasoning is written at the
first and the second carries the instruction plus a pointer, never a second telling.
A passage that survives both is not an exception to the rule. Deciding an edge case is the part
the rule keeps; the length it takes to do that is not the measure.
## Instruction duality
These files are both content and running system. Changing one changes agent behaviour