diff --git a/CHANGES.md b/CHANGES.md index b30a524..6553a1d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -35,7 +35,7 @@ dev-checkout concern - readable here, never shipped as something to parse. --- -## 4.8.0-beta.10 - 2026-09-09 - instructions/CONTRACT.md: Skill-H1, Referenztiefe und Begruendungsprosa praezisiert (#71, #72, #79) +## 4.8.0-beta.11 - 2026-09-09 - SKILL.md-Sanierung: Checklisten, Kommandolisten, wiki-status-Hard-Rule, wiki-query-Filingpruefung (#70, #74, #75, #78) **Author:** Torben Nehmer @@ -51,6 +51,7 @@ dev-checkout concern - readable here, never shipped as something to parse. - raw accept: Datums-Shard statt Typverzeichnis, fidelity/authority am Drop-Punkt (schliesst #67) - source_type ist Instanzsache: Profilkatalog, Setup-Frage, evolve-subtypes-Instruction (#68) - instructions/CONTRACT.md: Skill-H1, Referenztiefe und Begruendungsprosa praezisiert (#71, #72, #79) +- SKILL.md-Sanierung: Checklisten, Kommandolisten, wiki-status-Hard-Rule, wiki-query-Filingpruefung (#70, #74, #75, #78) Das Label `status/incoming` gibt es seit heute in Gitea: der Mensch legt einen @@ -648,6 +649,107 @@ Unterabschnitte), `instructions/wiki-ingest/SKILL.md` (Schritte 1 und 6). Schließt #71, #72 und #79. +### Vier Befunde in der Skill-Prosa, ein Publish + +Der Rest der #65-Analyse, soweit er die fünf `SKILL.md` selbst betrifft. Vier +Issues, fünf Dateien, kein Codeanteil. + +**Die Hard Rule von `wiki-status` war falsch (#70).** Sie sagte „read-only. +Never writes, scaffolds, or modifies any file" — und Schritt 2 ruft `lint`, +schreibt also einen Report, was Schritt 2 sogar selbst beschreibt. Ein Agent, +der die Regel wörtlich nimmt, kann den Skill nicht ausführen; einer, der ihn +ausführt, hat die stärkste Aussage des Dokuments gebrochen, bevor er Schritt 5 +erreicht. Das ist die teurere Sorte Widerspruch, weil die Hard Rule genau die +Stelle ist, an der ein Konflikt entschieden wird. Sie lautet jetzt wie die von +`wiki-query` — read-only gegenüber Wiki-*Inhalt* — und benennt den einen Write +mitsamt Grund: `reports/` ist gitignored und trägt keine Wiki-Seite. Schritt 5 +behauptet nicht mehr, es sei keine Datei geschrieben worden, sondern sagt, was +mit der geschriebenen *nicht* passiert (Semantic Review bleibt leer, nichts +wird ausgetragen — das ist `wiki-lint` Schritt 9). Der Decision Point „Never +publishes — nothing was written" trägt jetzt den wahren Grund: unter `kb/` hat +sich nichts geändert, und der Report kann gar nicht in einen Commit geraten. + +**`wiki-ingest` und `wiki-lint` bekommen einen Abhak-Block (#74).** Anthropics +Skill-Doku empfiehlt für „particularly complex workflows" eine Checkliste, die +der Agent in die Antwort kopiert und mitführt. Zwölf Schritte fallen +unzweifelhaft darunter. Der Ausschlag gibt aber nicht die Länge, sondern was +still ausfällt: `## Not Extracted` in Schritt 6, die Coverage-Prüfung in +Schritt 10, die Lint-Kadenz in Schritt 12 — keiner davon erzeugt eine +Fehlermeldung, wenn er ausbleibt. + +Die offene Frage des Issues — ob `wiki-lint` denselben Block bekommt — ist mit +ja beantwortet: neun Schritte, davon 3-6 reines Judgment, und ein Lauf, der +leise nur seine mechanische Hälfte gemacht hat, sieht aus wie ein +vollständiger. Damit haben zwei von fünf Skills einen Block und drei nicht, und +genau das wäre ohne festgeschriebenes Kriterium die nächste strukturelle +Ungleichheit im Sinne von #78. `instructions/CONTRACT.md` § Writing an +instruction trägt sie deshalb jetzt: ein Block, wenn **ein** Ablauf acht +Schritte oder mehr hat **und** darin still ausfallende Schritte stehen. Beide +Hälften nötig — ein langer Ablauf aus reinen Tool-Calls meldet seine Lücken +selbst, weil der nächste Call ohne den vorigen scheitert. Der Abschnitt nennt +die drei anderen Skills mit ihren Schrittzahlen, damit niemand aus Symmetrie +einen vierten Block nachrüstet. + +**`wiki-query` prüfte nicht, bevor es filete (#75).** Die drei Kriterien +(Synthese über mehrere Seiten, etwas noch nicht Dokumentiertes, wird wieder +gefragt) standen im Filing-Schritt selbst, und der Skill darf mehrere Seiten +je Sitzung anlegen — es gab also keine Stelle, an der *jede* geplante Seite +einzeln gemessen wurde. Neuer Schritt 5 vor dem ersten `new`: Kandidaten +benennen, jeden für sich gegen alle drei halten, ein Stapel wird nie als Stapel +beurteilt. Wer durchfällt, wird nicht angelegt, sondern in der Antwort mit +einem Satz genannt — der Nutzer kann ihn trotzdem verlangen. Der bisherige +Filing-Schritt ist Schritt 6, `log append` Schritt 7, die Hard Rule zieht mit. +Der Mass-Update-Gate-Hinweis bleibt, sagt aber jetzt dazu, dass er keine +Ersatzprüfung ist: das Gate zählt Dateien und weiß nichts über Berechtigung, +und ein Stapel unter der Schwelle ist von ihm nicht freigegeben, nur nicht +angehalten worden. Dazu die `session-setup.md`-Zeile in derselben Form wie in +den drei anderen — Schritt 7 läuft *immer* und der Filing-Pfad zieht `new`, +`xref add` und die Rebuilds nach sich. + +**Die Kommandolisten gingen mit den Schritten auseinander (#78).** +`cite add` fehlte in `wiki-ingest` und `wiki-manage`, obwohl beide es +ausdrücklich vorschreiben; `types describe` fehlte in `wiki-ingest`, wo +Schritt 6 die `source_type`-Werte daraus zieht; `xref add` fehlte in +`wiki-lint`, wo Schritt 1 das Umlabeln einer schwachen Kante darauf stützt; +`publish` fehlte in `wiki-lint` und `wiki-query`, wo je ein Decision Point es +beim Namen nennt. In die andere Richtung: `rm` stand in `wiki-lint`s Liste, +ohne dass ein Schritt es begründet — die gefährlichere Richtung der Drift, weil +`rm` Seiten löscht. Dazu `log status` (entscheidet den Trigger, gelaufen wird +es von `wiki-ingest`) und die nie benutzten Flags `lint --markdown` und +`lint --json`. Beide Streichungen stehen jetzt als **Deliberately absent** unter +der Liste, mit Grund — sonst trägt sie jemand aus Vollständigkeit wieder ein. + +Nicht als Drift gezählt und bewusst gelistet geblieben: `publish`, +`log append`, `index rebuild` und `sources rebuild-index`, wo ein Skill sie +über `publish-cycle.md` delegiert. Ebenso `xref remove` in `wiki-manage`, das +zum Unlinking-Fall gehört, den der Skill als Ganzes an `page-lifecycle.md` +abgibt; auch das steht jetzt als Satz dort, nicht als stille Annahme. + +Der zweite Teil von #78 ist die Symmetrie: `wiki-manage` und `wiki-status` +tragen jetzt einen Beispielblock wie die drei anderen. Fünf Skills mit +demselben Aufbau sollten denselben Aufbau haben — ein fehlender Abschnitt liest +sich sonst als Aussage („hier gibt es keine typischen Fälle"), die niemand +gemeint hat. + +Die offene Frage aus #78 — ob `instructions verify` diesen Abgleich künftig +selbst macht — bleibt offen und ist ein eigenes Issue. Der Abgleich ist +mechanisch, aber nicht trivial: die drei Ausnahmen oben (Delegation, benannte +Delegation, „Deliberately absent") müsste ein Prüfer alle kennen, sonst meldet +er dieselben vier Stellen bei jedem Lauf. + +**PATCH**, geprüft gegen den Drop-in-Test: eine Instanz kopiert `instructions/` +über sich, nichts wird umbenannt oder entfernt, kein Kommando, kein Flag, kein +maschinengelesenes Format, und der Rückweg funktioniert genauso. Kein +`--breaking`, kein Migrationsdokument. + +Geändert: `instructions/wiki-status/SKILL.md`, `instructions/wiki-query/SKILL.md`, +`instructions/wiki-ingest/SKILL.md`, `instructions/wiki-lint/SKILL.md`, +`instructions/wiki-manage/SKILL.md`, `instructions/CONTRACT.md` (§ Writing an +instruction, neuer Unterabschnitt „When a skill carries a copy-in checklist"). +`wiki-ingest` bleibt mit 233 Zeilen unter Anthropics 500er-Schwelle. + +Schließt #70, #74, #75 und #78. + --- ## 4.7.4 - 2026-09-04 - bootstrap.md nennt den session-id-WARN nach frischem Bootstrap explizit als erwartet diff --git a/VERSION b/VERSION index a58ddb9..e78f0e6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -4.8.0-beta.10 +4.8.0-beta.11 diff --git a/instructions/CONTRACT.md b/instructions/CONTRACT.md index 8fbf9ce..81e4e28 100644 --- a/instructions/CONTRACT.md +++ b/instructions/CONTRACT.md @@ -217,6 +217,29 @@ reads, and no tool hook is wired on the primary harness at all - so a `head -100 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. +### When a skill carries a copy-in checklist + +Anthropic's skill-authoring guidance suggests, for a "particularly complex workflow", a checklist +the agent copies into its response and ticks off as it goes. It names no threshold, so this repo +sets one - otherwise the two skills that have such a block and the three that do not read as an +accident rather than a decision. + +A `SKILL.md` carries the block when **one** of its flows runs to eight steps or more *and* that +flow contains steps whose omission is silent - a judgment call, a field filled by hand, a +cadence check, anything no tool error and no validator would report missing. Both halves are +required. Length alone is not the problem: a long flow of tool calls announces its own gaps, +because the next call fails without the previous one. + +Two skills qualify today, and the block names each of their numbered steps once, verbatim: +`wiki-ingest` (twelve steps, of which `## Not Extracted` in step 6, the coverage check in step 10 +and the lint cadence in step 12 all fail quietly) and `wiki-lint` (nine, with steps 3-6 pure +judgment). The other three do not, and the reason is worth stating so nobody adds one out of +symmetry: `wiki-manage` has two flows of seven, `wiki-query` six, `wiki-status` five, and none of +them is long enough for a reader to lose the thread. + +The block says that it is to be copied and carried, not read. A checklist read once is the table +of contents it replaced. + ### How much reasoning a step may carry "Cut the reasoning" and "keep enough to decide an edge case" are one sentence pulling two ways, diff --git a/instructions/wiki-ingest/SKILL.md b/instructions/wiki-ingest/SKILL.md index a243eb6..99c8ba6 100644 --- a/instructions/wiki-ingest/SKILL.md +++ b/instructions/wiki-ingest/SKILL.md @@ -16,6 +16,27 @@ Contracts are read **when the step needs them**, not upfront: a source that prod pages should never have cost the concept contract. Field-level requirements always come from `tools/wikitool types describe `, never from memory. +## Run checklist + +Copy this block into your first reply of the run and tick each line as you reach it. It is +carried through the run, not read once: several steps below fail silently - nothing errors, no +validator complains - and the ticked list is the only record that they happened. + +```markdown +- [ ] 1. Promote from `incoming/` if that is where the file sits +- [ ] 2. Read the source +- [ ] 3. Extract metadata +- [ ] 4. Check what the wiki already knows +- [ ] 5. Discuss with the user +- [ ] 6. Create the source page (incl. `## Not Extracted`) +- [ ] 7. Create or update entity pages +- [ ] 8. Create or update concept pages +- [ ] 9. Cross-reference +- [ ] 10. Check coverage +- [ ] 11. Close out +- [ ] 12. Check the lint cadence +``` + ## Steps 1. **Promote from `incoming/` if that is where the file sits.** Read @@ -201,9 +222,9 @@ pages should never have cost the concept contract. Field-level requirements alwa ## wikitool commands used -`raw accept`, `search`, `new source`, `new entity`, `new concept`, `touch`, `xref add`, -`xref link-source`, `sources coverage`, `sources rebuild-index`, `index rebuild`, `log append`, -`log status`, `publish` +`raw accept`, `search`, `types describe`, `new source`, `new entity`, `new concept`, `touch`, +`cite add`, `xref add`, `xref link-source`, `sources coverage`, `sources rebuild-index`, +`index rebuild`, `log append`, `log status`, `publish` ## Output diff --git a/instructions/wiki-lint/SKILL.md b/instructions/wiki-lint/SKILL.md index b4ae2a3..8767c3b 100644 --- a/instructions/wiki-lint/SKILL.md +++ b/instructions/wiki-lint/SKILL.md @@ -13,6 +13,24 @@ never something an agent has to remember. **Before the first `wikitool` call:** [session-setup.md](../session-setup.md). +## Run checklist + +Copy this block into your first reply of the pass and tick each line as you reach it. Steps 3-6 +are pure judgment: nothing errors when they are skipped, and a pass that quietly ran only its +mechanical half looks exactly like a complete one. + +```markdown +- [ ] 1. Structural scan +- [ ] 2. Raw coverage +- [ ] 3. Contradictions (judgment) +- [ ] 4. Stale claims (judgment) +- [ ] 5. Missing pages (judgment) +- [ ] 6. Duplicated rules (judgment) +- [ ] 7. Repair what is mechanical +- [ ] 8. Refresh confidence and verify the stack +- [ ] 9. Rebuild, write the report, carry its findings out +``` + ## Steps 1. **Structural scan.** @@ -119,9 +137,13 @@ never something an agent has to remember. ## wikitool commands used -`lint`, `lint --markdown`, `search`, `log status`, `sources coverage`, `xref remove`, `rename`, -`rm`, `new`, `confidence decay --apply`, `confidence init-base --apply`, `docs verify`, -`instructions verify`, `sources rebuild-index`, `index rebuild`, `log append` +`lint`, `search`, `sources coverage`, `xref add`, `xref remove`, `rename`, `new`, +`confidence decay --apply`, `confidence init-base --apply`, `docs verify`, `instructions verify`, +`sources rebuild-index`, `index rebuild`, `log append`, `publish` (only if asked) + +**Deliberately absent:** `rm` - a lint pass never deletes a page, and +[page-lifecycle.md](../page-lifecycle.md) is where a deletion belongs. `log status` - it decides +this skill's *trigger*, but `wiki-ingest`'s last step is what runs it. ## Output diff --git a/instructions/wiki-manage/SKILL.md b/instructions/wiki-manage/SKILL.md index 2ea53ec..22efd77 100644 --- a/instructions/wiki-manage/SKILL.md +++ b/instructions/wiki-manage/SKILL.md @@ -102,9 +102,17 @@ page, so none of it is a file operation. ## wikitool commands used -`search`, `types list`, `types describe`, `new`, `touch`, `xref add`, `xref remove`, +`search`, `types list`, `types describe`, `new`, `touch`, `cite add`, `xref add`, `xref remove`, `sources rebuild-index`, `index rebuild`, `log append`, `publish` +`xref remove` belongs to the unlinking case, which this skill delegates whole to +[page-lifecycle.md](../page-lifecycle.md) rather than describing in a step of its own. + ## Output A new or updated page, published to `origin/main`. + +**Example triggers:** + +- "Create a concept page for the deployment pipeline we just discussed" +- "Update the Index Scaling page with what the new lint run showed" diff --git a/instructions/wiki-query/SKILL.md b/instructions/wiki-query/SKILL.md index 368cd83..5a0387d 100644 --- a/instructions/wiki-query/SKILL.md +++ b/instructions/wiki-query/SKILL.md @@ -9,9 +9,11 @@ description: Answer a question using the LLM wiki's compiled knowledge - read-on **Trigger:** User asks a question. +**Before the first `wikitool` call:** [session-setup.md](../session-setup.md). + **Hard rule:** read-only with respect to wiki *content*. Never modify, hand-edit, or scaffold a -page while answering. Two exceptions, both mechanical: step 5 (filing a valuable answer through -`wikitool new`, never by hand) and step 6 (one audit entry via `wikitool log append`). If the +page while answering. Two exceptions, both mechanical: step 6 (filing a valuable answer through +`wikitool new`, never by hand) and step 7 (one audit entry via `wikitool log append`). If the wiki has no confident source, say so - per AGENTS.md's "never file an unsourced answer" invariant - rather than synthesizing a plausible-sounding answer from general knowledge. @@ -46,12 +48,22 @@ invariant - rather than synthesizing a plausible-sounding answer from general kn Hedge to the page's confidence: below 0.6 write "possibly"/"may"; below 0.4 write "uncertain"/"unconfirmed". -5. **File it back, if it earns a page.** Only when the answer required synthesis across several - pages, revealed something not already written down, and will be asked again. Then scaffold - it - `tools/wikitool new ...` - and follow `wiki-manage`. Never write the page by hand, and - never file an answer no source backs. +5. **Decide what earns a page - before the first `new`.** Name every page you are considering, + then hold each one on its own against all three criteria: the answer required synthesis + across several pages, it revealed something not yet written down, and it will be asked + again. All three, per candidate. A batch is never judged as a batch - one page clearing the + bar says nothing about the next one. -6. **Log it.** + A candidate that misses any of the three is not scaffolded. Put one line in the answer + naming what was considered and why it stays unwritten, and let the user ask for it anyway. + That is the whole cost of being wrong here in the cautious direction; the other direction is + a page nobody asked for, which reads exactly like a page the wiki needed and is far harder to + find again than a sentence in a chat log. + +6. **File back what survived.** Scaffold it - `tools/wikitool new ...` - and follow + `wiki-manage`. Never write the page by hand, and never file an answer no source backs. + +7. **Log it.** ```bash tools/wikitool log append --op query --title "" --body "" @@ -65,12 +77,14 @@ invariant - rather than synthesizing a plausible-sounding answer from general kn - **Filed a page?** Query does **not** auto-publish. Run `tools/wikitool publish` only if asked; the sequence is in [publish-cycle.md](../publish-cycle.md). - **Several answers filed at once?** That can trip the Mass-Update Gate - see - [gates.md](../gates.md). + [gates.md](../gates.md). The gate is a brake, not the check: it counts files and knows nothing + about whether any of them earned a page. Step 5 is what decides that, and a batch small enough + to pass the gate has not been cleared by it. ## wikitool commands used `search`, `log append`. If filing an answer back: `new`, `xref add`, `sources rebuild-index`, -`index rebuild`. +`index rebuild`, and `publish` only if asked. ## Output diff --git a/instructions/wiki-status/SKILL.md b/instructions/wiki-status/SKILL.md index a183af7..b07199c 100644 --- a/instructions/wiki-status/SKILL.md +++ b/instructions/wiki-status/SKILL.md @@ -10,8 +10,12 @@ semantic review a lint pass does. **Trigger:** User asks for wiki statistics, "what's new", or a quick health snapshot. -**Hard rule:** read-only. Never writes, scaffolds, or modifies any file. If something looks -wrong, point the user at `wiki-lint` or `wiki-manage` instead of fixing it here. +**Hard rule:** read-only with respect to wiki *content*. Never create, modify, or scaffold a +page, never repair a finding, never publish. One file does get written: the report `lint` +produces in step 2. That is not an exception being stretched - `reports/` is gitignored and holds +no wiki page ([reports/CONTRACT.md](../../reports/CONTRACT.md)), so the write leaves nothing +behind that the wiki ships. If something looks wrong, point the user at `wiki-lint` or +`wiki-manage` instead of fixing it here. ## Steps @@ -36,18 +40,23 @@ wrong, point the user at `wiki-lint` or `wiki-manage` instead of fixing it here. 4. **Recent activity.** Read the last few entries of `kb/log.md`. 5. **Summarize in chat.** Counts by type, N orphan pages, N uncovered raw files, most-connected - pages, and what changed recently. Do not write a report file - that is `wiki-lint`'s job. + pages, and what changed recently. Leave the step-2 report as `lint` left it: its "Semantic + Review" section stays empty and its findings are not carried into any page or into + `kb/log.md`. That is `wiki-lint`'s step 9, and it is what separates a snapshot from a pass. ## Decision points - **Findings worth acting on?** Point at `wiki-lint` (repairs) or `wiki-manage` (content). Do not fix anything here. -- **Never publishes** - nothing was written. +- **Never publishes.** Nothing under `kb/` changed, and the step-2 report is gitignored, so + there is nothing a commit could pick up. ## wikitool commands used -`lint` (no flags), `lint --json` (optional, for the link-graph data). +`lint` (no flags). ## Output A short chat summary, plus a pointer to `wiki-lint` if deeper investigation is warranted. + +**Example trigger:** "Give me a quick wiki status"