fix(docs): AGENTS.md-Contract-Prosa als Sitzungsarbeit klargestellt, doc-pull-through-Instruction (schliesst #90)
CI / verify (push) Successful in 53s
Release / release (push) Successful in 37s

Files changed:
- AGENTS.md
- CHANGES.md
- VERSION
- instructions/dev/doc-pull-through.md
- instructions/dev/stack-close/SKILL.md
- instructions/dev/stack-dev/SKILL.md
- instructions/dev/testing-conventions.md
- instructions/dev/version-parts.md
- tools/chemenu/commands/docs_verify.py
This commit is contained in:
2026-09-11 11:58:34 +02:00
parent 5b916c6d18
commit 441a8151ab
9 changed files with 148 additions and 19 deletions
+8 -5
View File
@@ -289,11 +289,14 @@ Changes to this schema, the contracts, the instruction layer, `tools/wikitool`,
READMEs go in [CHANGES.md](CHANGES.md) - never in an inline version-history table here. Wiki READMEs go in [CHANGES.md](CHANGES.md) - never in an inline version-history table here. Wiki
*content* operations are logged separately via `tools/wikitool log append` into `kb/log.md`. *content* operations are logged separately via `tools/wikitool log append` into `kb/log.md`.
**A stack change is not finished until the human docs describe it.** `README.md`, `EVALS.md` **A stack change is not finished until the human docs describe it.** `README.md`, `EVALS.md`,
and `tools/README.md` are part of the change that introduced a stage, a command or a workflow, `tools/README.md`, `tools/CONTRACT.md` and the touched `<stage>/CONTRACT.md` are part of the
not follow-up work: nobody comes back for them, and a document that describes a repo which no change that introduced a stage, a command or a workflow, not follow-up work: nobody comes back
longer exists is worse than none. The mechanical half - command tables, contracts, ignore for them, and a document that describes a repo which no longer exists is worse than none. What
canaries - is checked by `tools/wikitool docs verify`; the prose half is yours. `tools/wikitool docs verify` mechanically checks is exactly what its own `docs verify` row in
[tools/CONTRACT.md](tools/CONTRACT.md) lists - no more. **Every cell's text is outside that
check** - a command table entry's description, an error contract's wording, a stage contract's
prose - and is therefore session work, the same as the three README-shaped files.
`docs/` pages are held to a different clock than those three. A README goes stale on every new `docs/` pages are held to a different clock than those three. A README goes stale on every new
flag; a `docs/` page goes stale only when the reasoning it wrote down stops holding - a gate flag; a `docs/` page goes stale only when the reasoning it wrote down stops holding - a gate
+41 -1
View File
@@ -35,7 +35,7 @@ dev-checkout concern - readable here, never shipped as something to parse.
--- ---
## 5.0.0-beta.11 - 2026-09-11 - MCP submit-Tool: Quarantäne-Schreibpfad mit Upload Review Gate (schliesst #32) ## 5.0.0-beta.12 - 2026-09-11 - AGENTS.md-Changelog-Absatz korrigiert: Contract-Prosa ist Sitzungsarbeit, doc-pull-through-Instruction ergaenzt
**Author:** Torben Nehmer **Author:** Torben Nehmer
@@ -64,6 +64,7 @@ dev-checkout concern - readable here, never shipped as something to parse.
- Telemetrie-Default nach Installationsform, Byte-Deckel und Session-Retention - Telemetrie-Default nach Installationsform, Byte-Deckel und Session-Retention
- tools/CONTRACT.md: raw accept Doku auf Datums-Shard und Capture-Felder nachgezogen (schliesst #89) - tools/CONTRACT.md: raw accept Doku auf Datums-Shard und Capture-Felder nachgezogen (schliesst #89)
- MCP submit-Tool: Quarantäne-Schreibpfad mit Upload Review Gate (schliesst #32) - MCP submit-Tool: Quarantäne-Schreibpfad mit Upload Review Gate (schliesst #32)
- AGENTS.md-Changelog-Absatz korrigiert: Contract-Prosa ist Sitzungsarbeit, doc-pull-through-Instruction ergaenzt
<!-- /wikitool:bumps --> <!-- /wikitool:bumps -->
@@ -1177,6 +1178,45 @@ Geändert: `tools/chemenu/upload.py` (neu), `tools/chemenu/commands/upload_cmd.p
`instructions/ingest-queue.md` (neu), `raw/CONTRACT.md`, `docs/why-gates-are-code.md`, `instructions/ingest-queue.md` (neu), `raw/CONTRACT.md`, `docs/why-gates-are-code.md`,
`INSTALL-MCP.md`, `README.md`. Schließt #32. `INSTALL-MCP.md`, `README.md`. Schließt #32.
**AGENTS.md behauptete, `docs verify` prüfe die Contract-Prosa selbst - das stimmt nicht (#90).**
`check_cli_readme()` prüft nur, ob der gebacktickte Pfad einer Tabellenzeile registriert ist, nie
den Rest der Zelle: eine ausgetauschte Kommandobeschreibung oder ein neues `--flag` bleiben
unsichtbar, und `TABLE_CELL_RE` läuft über das ganze Dokument statt über eine abgegrenzte
"Kommandotabelle". `AGENTS.md` § Changelog zählte trotzdem "command tables, contracts, ignore
canaries" als maschinell geprüft auf und grenzte die Sitzungspflicht auf `README.md`/`EVALS.md`/
`tools/README.md` ein - `tools/CONTRACT.md` und jedes `<stage>/CONTRACT.md` standen damit auf
keiner Liste, die je jemand nachzieht.
Der Absatz nennt jetzt nur noch, was `docs verify`s eigene Zeile in `tools/CONTRACT.md`
tatsächlich auflistet (Verweis statt Kopie), und macht jede Zellenprosa - Kommandotabelle,
Fehlerkontrakt, Stage-Contract - ausdrücklich zur Sitzungsarbeit, neben den drei README-artigen
Dateien. Die Docstring von `check_cli_readme()` behauptet nicht mehr, sie prüfe
"tools/CONTRACT.md's command table" - sie beschreibt jetzt, dass `TABLE_CELL_RE` das ganze
Dokument scannt und nur den gebacktickten Pfad liest, nie die restliche Zelle.
Neue Instruction [instructions/dev/doc-pull-through.md](instructions/dev/doc-pull-through.md)
(dev-only) listet je berührter Fläche, welches Dokument eine Behauptung darüber trägt: beide
Tabellen in `tools/CONTRACT.md`, der berührte `<stage>/CONTRACT.md`, `AGENTS.md` bei
verschobener Regel/Gate/Invariante, die README-artigen Dateien, `docs/` bei verschobener
Begründung. `stack-dev/SKILL.md` bekommt dafür einen neuen Schritt 5 zwischen Versionsbump und
Verify/Publish (jetzt Schritt 6) - ein Satz plus Link, die Liste bleibt in der Instruction; die
Katalog-Liste in Schritt 2 und `stack-close/SKILL.md` Schritt 3 nennen die neue Instruction bzw.
die Contracts jetzt ebenfalls. `version-parts.md` und `testing-conventions.md` korrigieren dabei
zwei schon vorher falsche Schrittverweise auf `stack-dev` (Schritt 3 -> 4, Schritt 4 -> 6),
gefunden beim Nachziehen der Umnummerierung.
**MINOR, kein neuer Boundary-Crossing:** additiv und drop-in in beide Richtungen - eine
bestehende Instanz kopiert die neue Instruction und die korrigierte Prosa über sich, ohne
Migration oder Hand-Arbeit; kein Feld, kein Kommando, kein Flag ändert sich. Der Kandidat trägt
seine `--breaking`-Zeile bereits aus einem früheren Bump; diese Änderung fügt keine neue hinzu.
Geändert: `AGENTS.md`, `tools/chemenu/commands/docs_verify.py`,
`instructions/dev/doc-pull-through.md` (neu), `instructions/dev/stack-dev/SKILL.md`,
`instructions/dev/stack-close/SKILL.md`, `instructions/dev/version-parts.md`,
`instructions/dev/testing-conventions.md`. Verifiziert: `tools/wikitool docs verify`,
`tools/wikitool instructions verify` (nach `instructions sync`), volle `pytest`-Suite (1185
passed). Schließt #90.
--- ---
## 4.7.4 - 2026-09-04 - bootstrap.md nennt den session-id-WARN nach frischem Bootstrap explizit als erwartet ## 4.7.4 - 2026-09-04 - bootstrap.md nennt den session-id-WARN nach frischem Bootstrap explizit als erwartet
+1 -1
View File
@@ -1 +1 @@
5.0.0-beta.11 5.0.0-beta.12
+67
View File
@@ -0,0 +1,67 @@
---
type: types/instruction.md
name: doc-pull-through
description: Which document makes a claim about a surface you are about to change - a wikitool command's behaviour, a stage's rules, an AGENTS.md rule/gate/invariant, a README-shaped human doc, a docs/ page's reasoning - and so needs updating in the same session, since tools/wikitool docs verify never reads a cell's prose.
---
# Update every document that makes a claim about the surface you changed
`tools/wikitool docs verify` is a hard oracle over presence, not content: it checks that a
command is *listed*, that a contract *exists*, that an ignore canary is (or isn't) caught - never
what a table cell, a contract section, or a README paragraph actually *says*. A command's flag
can change, a gate's threshold can move, a contract's wording can go false, and every one of
those checks stays green (Gitea #90; Gitea #91 narrows what the command-table check matches, but
adds no reading of cell content). Content quality of every document below is therefore session
work, the same duty AGENTS.md's Changelog section states for `README.md`/`EVALS.md`/
`tools/README.md` - this instruction exists because that duty used to stop at those three files
while the contracts rotted next to a green check (ten stale error-contract rows accumulated this
way; see Gitea #89 for one).
## When to run
Before `tools/wikitool docs verify`/`publish` in a `stack-dev` session that changed behaviour -
`stack-dev` step 5 sends you here. Read the table below and update every row whose surface you
touched; a row that does not apply needs no action.
## Steps
1. **Name the surface(s) you changed.** A `wikitool` command's flags or behaviour, a stage's
rule, an `AGENTS.md`-level rule/gate/invariant, a workflow a human runs by hand, or the
reasoning behind a design decision - one change can touch more than one row.
2. **For each surface, update every document the table names - not only the one you were already
editing:**
| Touched surface | Document(s) that make a claim about it |
|---|---|
| A `wikitool` command's behaviour, flags, or interface | Both tables in [tools/CONTRACT.md](../tools/CONTRACT.md): the command reference row, and its per-command error contract (exit codes, atomicity, retry-safety) |
| A stage's authoring rules (`raw/`, `kb/`, `types/`, `reports/`, `work/`, `tools/`, `instructions/`) | The touched `<stage>/CONTRACT.md` |
| A rule, gate, or invariant `AGENTS.md` itself states | The relevant `AGENTS.md` section (Invariants, Gates, File naming, Routing, ...) |
| A workflow, stage, or command a human operates by hand | Whichever of `README.md`, `EVALS.md`, `tools/README.md`, `INSTALL.md`, `DEVELOPMENT.md` names it - AGENTS.md § File naming says which document is for which reader |
| The reasoning behind a gate, boundary, or design decision | The `docs/` page that carries it, if one exists (AGENTS.md § File naming lists all four) |
| A skill's own step sequence or catalogue | The skill's `SKILL.md` source under `instructions/<name>/` or `instructions/dev/<name>/` |
3. **Do not re-derive what `docs verify` already checks mechanically** - existence, table-row
membership, ignore-canary state. That enumeration lives once, in
[tools/CONTRACT.md](../tools/CONTRACT.md)'s own `docs verify` row; copying it here would be a
second copy that drifts, the exact failure this instruction exists to describe (Gitea #90).
This instruction is only about the prose no check reads.
## Decision points
- **The change touched no document in the table?** Nothing to do - not every stack change moves
a claim. A pure bugfix with an unchanged interface is the common case.
- **Unsure whether a `docs/` page's reasoning moved?** Read it. A `docs/` page carries no
normative sentence and nothing verifies it by construction (AGENTS.md § File naming), so an
unsure guess defaults to reading the page rather than skipping the question -
[`stack-close`](stack-close/SKILL.md) step 3 asks it again at the end of the session as a
backstop, not as the only time it is asked.
- **The surface is a whole new stage, collection, or gate?** The table's rows are the steady
state; a new row-worthy category is itself a change to this instruction - add the row here
rather than leaving the next session to rediscover the gap.
## Scope
Applies to `stack-dev` sessions only - wiki content changes have their own provenance and
cross-reference rules (`kb/CONTRACT.md`, `wiki-manage`), which already pull the relevant pages
through as part of the normal skill. Not a replacement for `stack-close` step 3, which re-asks
the `docs/`-staleness question after publish as the second, session-final check.
+10 -6
View File
@@ -75,12 +75,16 @@ and a fresh subagent starts without the session's context).
#45 both closed exactly this way on the old, single-skill shape, the second an hour after the #45 both closed exactly this way on the old, single-skill shape, the second an hour after the
rule was first written down. rule was first written down.
3. **Check whether a `docs/` page or new human doc went stale.** A `docs/` page carries no 3. **Check whether a `docs/` page, a contract, or a new human doc went stale.** A `docs/` page
normative sentence, so nothing verifies it by construction (AGENTS.md § File naming) - the carries no normative sentence, so nothing verifies it by construction (AGENTS.md § File
same is true of `README.md`/`INSTALL.md`/`DEVELOPMENT.md` prose and a new instruction's own naming) - the same is true of `tools/CONTRACT.md`'s two tables and any touched
wording, which `instructions verify` checks structurally but never for what it claims. If the `<stage>/CONTRACT.md`, whose prose `docs verify` checks only for presence and table-row
change this package shipped moved the reasoning one of these pages documents, update it now; membership, never for what a cell or a section actually says
if none did, say so rather than leaving the question unasked. ([doc-pull-through.md](../doc-pull-through.md)); of `README.md`/`INSTALL.md`/`DEVELOPMENT.md`
prose; and of a new instruction's own wording, which `instructions verify` checks structurally
but never for what it claims. If the change this package shipped moved the reasoning or the
behaviour one of these documents describes, update it now; if none did, say so rather than
leaving the question unasked.
4. **Name which model ran which phase - not only this one.** This is the handover in full, not 4. **Name which model ran which phase - not only this one.** This is the handover in full, not
a note about the tail alone: state the model for the design/version-part/boundary-judgment a note about the tail alone: state the model for the design/version-part/boundary-judgment
+10 -2
View File
@@ -48,7 +48,7 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li
moves, so an interrupted session leaves a body the next one can resume from, *and* rewrite it moves, so an interrupted session leaves a body the next one can resume from, *and* rewrite it
to its final state before closing. Both halves bind; the second is what to its final state before closing. Both halves bind; the second is what
[`stack-close`](../stack-close/SKILL.md) carries out once this skill's own work is published - [`stack-close`](../stack-close/SKILL.md) carries out once this skill's own work is published -
see step 5 below. An issue labelled `status/incoming` is the exception to all of that: it is a see step 6 below. An issue labelled `status/incoming` is the exception to all of that: it is a
human's stub, not a spec, and it is **never implemented as it stands** - it gets worked out and human's stub, not a spec, and it is **never implemented as it stands** - it gets worked out and
triaged first. Read this file before filing something for later, before editing or closing an triaged first. Read this file before filing something for later, before editing or closing an
issue, before picking up an incoming stub, or before deciding what to pick up next. issue, before picking up an incoming stub, or before deciding what to pick up next.
@@ -62,6 +62,10 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li
demo/testbed `kb/`, the measurable floors that define it, and what a reactive fix may and may demo/testbed `kb/`, the measurable floors that define it, and what a reactive fix may and may
not do to corpus content. Read it before judging whether the corpus can exercise a change, or not do to corpus content. Read it before judging whether the corpus can exercise a change, or
before any fix that would touch `kb/` content. before any fix that would touch `kb/` content.
[doc-pull-through.md](../doc-pull-through.md) - which document makes a claim about a touched
surface (a `wikitool` command, a stage's rules, an `AGENTS.md` rule/gate/invariant, a
README-shaped human doc, a `docs/` page's reasoning) and therefore needs updating alongside
the code, since `docs verify` never reads a cell's prose. Read it before step 6.
More instructions are added here incrementally as stack-development needs come up - this More instructions are added here incrementally as stack-development needs come up - this
list grows without needing this skill file to change shape. list grows without needing this skill file to change shape.
3. **Settle the design before building - and break there for the model switch.** These are two 3. **Settle the design before building - and break there for the model switch.** These are two
@@ -135,7 +139,11 @@ stack development happens in the origin repo instead (see AGENTS.md's routing li
Prose-only changes (`README.md`, `INSTALL.md`, `EVALS.md`) and the workflows under `.gitea/` Prose-only changes (`README.md`, `INSTALL.md`, `EVALS.md`) and the workflows under `.gitea/`
do not need a bump - CI's version gate is scoped to what changes behaviour. do not need a bump - CI's version gate is scoped to what changes behaviour.
5. **Verify, then publish.** `tools/wikitool docs verify`, `tools/wikitool instructions verify`, 5. **Pull through every document that makes a claim about the surface you touched - `docs verify`
checks a cell's presence, never its prose.** [doc-pull-through.md](../doc-pull-through.md) has
the table of which document that is, per surface.
6. **Verify, then publish.** `tools/wikitool docs verify`, `tools/wikitool instructions verify`,
and the relevant `pytest` run in `tools/` - the same checks any stack change must pass, run and the relevant `pytest` run in `tools/` - the same checks any stack change must pass, run
explicitly rather than assumed. CI (`.gitea/workflows/ci.yml`) runs these plus a full explicitly rather than assumed. CI (`.gitea/workflows/ci.yml`) runs these plus a full
`setup-instance.md` replay against a fresh `dist export`; a push to `main` that moves `VERSION` `setup-instance.md` replay against a fresh `dist export`; a push to `main` that moves `VERSION`
+1 -1
View File
@@ -177,6 +177,6 @@ Whenever you add or change a test under `tools/chemenu/tests/`.
## Scope ## Scope
Applies to `tools/chemenu/tests/` only. It says nothing about what to test - the test/review Applies to `tools/chemenu/tests/` only. It says nothing about what to test - the test/review
expectations for a stack change are the `stack-dev` skill's step 4 (`docs verify`, expectations for a stack change are the `stack-dev` skill's step 6 (`docs verify`,
`instructions verify`, pytest). CI runs the suite once, unhardened, because the fixture makes a `instructions verify`, pytest). CI runs the suite once, unhardened, because the fixture makes a
second hardened run redundant; see the note on the Tests step in `.gitea/workflows/ci.yml`. second hardened run redundant; see the note on the Tests step in `.gitea/workflows/ci.yml`.
+1 -1
View File
@@ -65,7 +65,7 @@ a new one, and only `version release` turns it into something the release workfl
## When to run ## When to run
Before every `tools/wikitool version bump` - the `stack-dev` skill's step 3 sends you here. Before every `tools/wikitool version bump` - the `stack-dev` skill's step 4 sends you here.
Read it in full the first time a change looks like it might be boundary-crossing; afterwards Read it in full the first time a change looks like it might be boundary-crossing; afterwards
the three-line test below is usually enough. the three-line test below is usually enough.
+9 -2
View File
@@ -213,8 +213,15 @@ def documented_commands(readme_text: str) -> list[str]:
def check_cli_readme() -> list[str]: def check_cli_readme() -> list[str]:
"""Every registered command must appear in tools/CONTRACT.md's command """Every registered command must appear in tools/CONTRACT.md, and every
table, and every command documented there must exist. command documented there must exist.
`TABLE_CELL_RE` scans the whole file for any markdown table row whose
first cell is backticked - there is no separate "command table" region it
is scoped to, so a match in the error-contract table (or any other table
shaped the same way) counts too. It reads only the backticked path itself,
never the rest of the cell: a changed flag or a rewritten description in
an existing row is invisible to this check.
The reverse check matches a documented cell against the full registered The reverse check matches a documented cell against the full registered
command path (e.g. `xref add`, `migrate verify`), not just its first command path (e.g. `xref add`, `migrate verify`), not just its first