Eine Sitzung hat nach tools/wikitool search "<Begriff>" zusätzlich grep -rl "<Begriff>" kb/ laufen lassen. Das Transkript steht wörtlich im ersten Kommentar.
Der Grep war redundant — aber die Ausgabe von search gab ihr drei Gründe dafür. Das war der eigentliche Befund: nicht das Verhalten der Sitzung, sondern das Ausgabeformat, das es rational machte. Behoben in 6.0.0-beta.8, publiziert als bb097f6.
Zuschnitt:search-scoped, nicht skill-scoped — die Befunde trafen wiki-query, wiki-manage und wiki-ingest gleichermaßen. Alle drei wurden in einem Paket behoben, nicht getrennt.
Die Befunde
Der Grep war vollständig redundant
searchist ein Grep über kb/. search/ripgrep.py::build_argv baut rg --json --smart-case --glob '*.md' --fixed-strings -- <text> kb/ und verwirft anschließend jeden Treffer, dessen Pfad nicht in pages liegt. pages kommt aus kb_scan.iter_kb_pages, das die kb-Root-Metadateien, jede COLLECTION.md und jede generierte INDEX.md auslässt.
Die drei Dateien, die der Grep zusätzlich fand — kb/provenance.md, kb/log.md, kb/sources/INDEX.md — waren exakt diese Ausnahmen, alle drei nach Invariante 1 generiert. Ein eigener Grep über kb/ konnte also keine Seite finden, die search nicht hatte.
Befund 1 — kein Pfad, und der Titel wurde gekappt
render_table schrieb score, title (auf 34 Zeichen gekappt), kind/subtype, summary. Keinen Pfad — obwohl wiki-query Schritt 3 verlangt, nur die Seiten zu lesen, auf die die Suche zeigt.
Dazu fehlte der vollständige Titel, nach Invariante 2 der einzige Identifier einer Seite und das Argument, das touch --page, xref add --a und cite add --page nehmen. Im gemeldeten Transkript waren vier von fünf Titeln abgeschnitten. Die Sitzung hatte weder etwas zum Öffnen noch etwas zum Weiterreichen; grep -rl lieferte genau beides. Das -l war der Beleg.
Befund 2 — N result(s) war die gekappte Zahl
--limit stand auf 20, run_search gab nur hits[: query.limit] zurück, und jeder Adapter zählte danach. 20 result(s). auf einer Anfrage mit 182 Treffern war von einem vollständigen Ergebnis nicht unterscheidbar — eine Vollständigkeitsaussage, zu der die Ausgabe nicht berechtigt war, und die einzige Möglichkeit, die echte Zahl zu erfahren, war ein zweiter vollständiger Lauf mit --limit 0.
Befund 3 — nichts sagte, dass search für kb/ erschöpfend ist
Weder AGENTS.md § Routing noch die Skills noch die search-Zeile in tools/CONTRACT.md sagten, dass ein eigener Grep über kb/ nichts hinzufügt. Die Contract-Zeile nannte den Zweck, nicht die Zusicherung.
Was umgesetzt wurde
Behoben statt hingenommen — auch mit Blick auf #35: ein Ausgabeformat, dem Sitzungen nicht trauen, trägt keine Erweiterung.
Felder: score | kind/subtype | titel | pfad | summary. Titel und Pfad werden nie gekappt; die Summary ist das einzige verlustige Feld und steht am Ende, wo ein | in Prosa beim Trennen mit maxsplit=4 folgenlos bleibt (ein | im Titel schließt die Wikilink-Syntax ohnehin aus).
JSON als Default wurde erwogen und verworfen: ein Treffer ist flach, JSON kostet dafür ein Vielfaches an Tokens, und search existiert laut eigenem Modul-Docstring dafür, Retrieval billig zu machen. Der Fehler war ein fehlendes Feld, kein Parse-Problem. --json, api.search und MCP bleiben für alle, die Struktur brauchen.
Trunkierung wird benannt.run_search gibt ein SearchResult (Treffer, Gesamtzahl, Limit) zurück. Tabelle: 50 of 182 result(s) - raise --limit (0 for all) or narrow the query. JSON rein additiv: total/truncated/limit neben count, das seine Bedeutung behält (len(results)). api.search und MCP-search tragen dieselben Felder.
Default-Limit 20 → 50, als eine Konstante DEFAULT_LIMIT statt drei Literalen in drei Adaptern. Gekappt wurden vor allem die strukturellen Sweeps (--field '!sources'), die alphabetisch und nicht nach Relevanz sortiert sind — dort wirft die Kappung eine beliebige Scheibe der Antwort weg statt ihres schwächsten Endes. Dass sie jetzt sichtbar ist, macht ein endliches Default überhaupt erst unbedenklich.
Die Regel steht an genau einer Stelle: AGENTS.md § Routing, wo „search, do not read the catalog" schon stand. tools/CONTRACT.md trägt daneben nur den Mechanismus (was das Backend scannt, welche Dateien es auslässt), nicht die Regel ein zweites Mal.
Abnahmekriterien
Jeder Treffer nennt vollständigen Pfad und vollständigen, ungekappten Titel. Test: ein 56-Zeichen-Titel erscheint vollständig, nur die Summary trägt ein ….
Eine gekappte Suche ist von einer vollständigen unterscheidbar — Tabelle, --json, api.search, MCP-search, ohne zweiten Aufruf. search "e" sagt jetzt 50 of 182 result(s).
Eine nicht gekappte Suche meldet keine Trunkierung; --limit 0 gilt nie als gekappt.
Ein Default-Limit als eine Konstante; ein Test prüft die drei Adapter gegeneinander (MCP-Tool-Schema, Corpus.search-Signatur, Typer-Option).
count bedeutet unverändert len(results); total/truncated/limit additiv. Der MCP-Golden-Test hält CLI und Server auf den neuen Feldern zusammen.
Genau ein Ort trägt die Regel (AGENTS.md § Routing); tools/CONTRACT.md nur den Mechanismus.
Doku-Durchzug: search-Zeile in tools/CONTRACT.md, AGENTS.md § Routing, instructions/wiki-query/SKILL.md (das --limit 30-Beispiel unterbot das neue Default und ist jetzt --limit 0 als bewusster Sweep). instructions/mcp-read-server.md nannte das Limit nicht — nichts zu tun. Die search-Fehlervertragszeile blieb unverändert, weil kein neuer Fehlerfall entstand.
tools/wikitool docs verify und tools/wikitool instructions verify grün.
pytest 1272 grün, davon 9 neue Tests: Pfad vorhanden; Titel und Pfad ungekappt bei langem Titel; eine Trefferzeile zerfällt trotz | in der Prosa in ihre fünf Felder; ein gekapptes Ergebnis nennt die Gesamtzahl, ein ungekapptes behauptet nichts; --limit 0 nie gekappt; die Gesamtzahl überlebt das Limit in run_search; api.search meldet dasselbe; alle drei Adapter teilen ein Default-Limit.
Coverage 88,2 % gegen eine Untergrenze von 85 %.
Publiziert als bb097f6 nach Mass-Update-Gate-Freigabe durch den Betreiber (13 Dateien).
Version
6.0.0-beta.8, --minor, kein neuer Grenzübertritt. Drop-in in beide Richtungen: kein Flag entfernt oder umbenannt, keine Umgebungsvariable, keine maschinengelesene Datei in ihrer Form verändert, JSON rein additiv; die Tabelle liest ein Agent, kein Skript. Der Kandidat hatte die Grenze bereits überschritten, --breaking war nicht erneut fällig.
Was bewusst nicht getan wurde
Kein docs/-Nachzug. Keine docs/-Seite trägt die Begründung für das Retrieval-Ausgabeformat; geprüft wurden alle sechs.
Kein Nachzug in README.md, kb/CONTRACT.md, EVALS.md. Alle drei beschreiben, wassearch tut (read-only, budget-frei, suchen statt blättern) — keine Aussage darüber wurde falsch. Die Grep-Regel dort zu wiederholen wäre eine zweite Kopie (Invariante 8).
Kein Nachzug in wiki-manage/wiki-ingest/wiki-lint. Sie behaupten nichts über Ausgabeform oder Limit; die Regel erreicht sie über AGENTS.md, das jede Sitzung lädt.
Beweislage
Der Korpus aus dem Transkript existierte zum Zeitpunkt der Analyse nicht mehr — Pelletofenkondensator fand weder search noch rg in kb/. Das Transkript ist als Beweis auf 2026-09-13 datiert; alle Befunde wurden gegen den damals aktuellen Baum und Korpus reproduziert.
Berührt, aber nicht blockiert: #35 (semantisches Backend) und #6 (Backlink-Ranking) ändern, wassearch findet, nicht wie vollständig die Ausgabe sich darstellt. Beide erben das hier festgelegte Format.
Eine Sitzung hat nach `tools/wikitool search "<Begriff>"` zusätzlich `grep -rl "<Begriff>" kb/` laufen lassen. Das Transkript steht wörtlich im ersten Kommentar.
Der Grep war redundant — aber die Ausgabe von `search` gab ihr drei Gründe dafür. Das war der eigentliche Befund: nicht das Verhalten der Sitzung, sondern das Ausgabeformat, das es rational machte. Behoben in `6.0.0-beta.8`, publiziert als `bb097f6`.
**Zuschnitt:** `search`-scoped, nicht skill-scoped — die Befunde trafen `wiki-query`, `wiki-manage` und `wiki-ingest` gleichermaßen. Alle drei wurden in einem Paket behoben, nicht getrennt.
## Die Befunde
### Der Grep war vollständig redundant
`search` **ist** ein Grep über `kb/`. `search/ripgrep.py::build_argv` baut `rg --json --smart-case --glob '*.md' --fixed-strings -- <text> kb/` und verwirft anschließend jeden Treffer, dessen Pfad nicht in `pages` liegt. `pages` kommt aus `kb_scan.iter_kb_pages`, das die kb-Root-Metadateien, jede `COLLECTION.md` und jede generierte `INDEX.md` auslässt.
Die drei Dateien, die der Grep zusätzlich fand — `kb/provenance.md`, `kb/log.md`, `kb/sources/INDEX.md` — waren exakt diese Ausnahmen, alle drei nach Invariante 1 generiert. Ein eigener Grep über `kb/` konnte also keine Seite finden, die `search` nicht hatte.
### Befund 1 — kein Pfad, und der Titel wurde gekappt
`render_table` schrieb `score`, `title` (auf 34 Zeichen gekappt), `kind/subtype`, `summary`. Keinen Pfad — obwohl `wiki-query` Schritt 3 verlangt, nur die Seiten zu lesen, auf die die Suche zeigt.
Dazu fehlte der vollständige **Titel**, nach Invariante 2 der einzige Identifier einer Seite und das Argument, das `touch --page`, `xref add --a` und `cite add --page` nehmen. Im gemeldeten Transkript waren vier von fünf Titeln abgeschnitten. Die Sitzung hatte weder etwas zum Öffnen noch etwas zum Weiterreichen; `grep -rl` lieferte genau beides. Das `-l` war der Beleg.
### Befund 2 — `N result(s)` war die gekappte Zahl
`--limit` stand auf 20, `run_search` gab nur `hits[: query.limit]` zurück, und jeder Adapter zählte danach. `20 result(s).` auf einer Anfrage mit 182 Treffern war von einem vollständigen Ergebnis nicht unterscheidbar — eine Vollständigkeitsaussage, zu der die Ausgabe nicht berechtigt war, und die einzige Möglichkeit, die echte Zahl zu erfahren, war ein zweiter vollständiger Lauf mit `--limit 0`.
### Befund 3 — nichts sagte, dass `search` für `kb/` erschöpfend ist
Weder AGENTS.md § Routing noch die Skills noch die `search`-Zeile in `tools/CONTRACT.md` sagten, dass ein eigener Grep über `kb/` nichts hinzufügt. Die Contract-Zeile nannte den Zweck, nicht die Zusicherung.
## Was umgesetzt wurde
1. **Behoben statt hingenommen** — auch mit Blick auf #35: ein Ausgabeformat, dem Sitzungen nicht trauen, trägt keine Erweiterung.
2. **Neue Trefferzeile**, ohne Spaltenauffüllung:
```
13.0 | entity/system | E3DC | kb/entities/systems/E3DC.md | Deutsches Heim-Energiespeichersystem, das …
```
Felder: `score | kind/subtype | titel | pfad | summary`. Titel und Pfad werden nie gekappt; die Summary ist das einzige verlustige Feld und steht am Ende, wo ein `|` in Prosa beim Trennen mit `maxsplit=4` folgenlos bleibt (ein `|` im Titel schließt die Wikilink-Syntax ohnehin aus).
**JSON als Default wurde erwogen und verworfen:** ein Treffer ist flach, JSON kostet dafür ein Vielfaches an Tokens, und `search` existiert laut eigenem Modul-Docstring dafür, Retrieval billig zu machen. Der Fehler war ein fehlendes Feld, kein Parse-Problem. `--json`, `api.search` und MCP bleiben für alle, die Struktur brauchen.
3. **Trunkierung wird benannt.** `run_search` gibt ein `SearchResult` (Treffer, Gesamtzahl, Limit) zurück. Tabelle: `50 of 182 result(s) - raise --limit (0 for all) or narrow the query.` JSON rein additiv: `total`/`truncated`/`limit` neben `count`, das seine Bedeutung behält (`len(results)`). `api.search` und MCP-`search` tragen dieselben Felder.
4. **Default-Limit 20 → 50**, als eine Konstante `DEFAULT_LIMIT` statt drei Literalen in drei Adaptern. Gekappt wurden vor allem die strukturellen Sweeps (`--field '!sources'`), die alphabetisch und nicht nach Relevanz sortiert sind — dort wirft die Kappung eine beliebige Scheibe der Antwort weg statt ihres schwächsten Endes. Dass sie jetzt sichtbar ist, macht ein endliches Default überhaupt erst unbedenklich.
5. **Die Regel steht an genau einer Stelle: AGENTS.md § Routing**, wo „search, do not read the catalog" schon stand. `tools/CONTRACT.md` trägt daneben nur den Mechanismus (was das Backend scannt, welche Dateien es auslässt), nicht die Regel ein zweites Mal.
## Abnahmekriterien
- [x] Jeder Treffer nennt vollständigen Pfad und vollständigen, ungekappten Titel. Test: ein 56-Zeichen-Titel erscheint vollständig, nur die Summary trägt ein `…`.
- [x] Eine gekappte Suche ist von einer vollständigen unterscheidbar — Tabelle, `--json`, `api.search`, MCP-`search`, ohne zweiten Aufruf. `search "e"` sagt jetzt `50 of 182 result(s)`.
- [x] Eine nicht gekappte Suche meldet keine Trunkierung; `--limit 0` gilt nie als gekappt.
- [x] Ein Default-Limit als eine Konstante; ein Test prüft die drei Adapter gegeneinander (MCP-Tool-Schema, `Corpus.search`-Signatur, Typer-Option).
- [x] `count` bedeutet unverändert `len(results)`; `total`/`truncated`/`limit` additiv. Der MCP-Golden-Test hält CLI und Server auf den neuen Feldern zusammen.
- [x] Genau ein Ort trägt die Regel (AGENTS.md § Routing); `tools/CONTRACT.md` nur den Mechanismus.
- [x] Doku-Durchzug: `search`-Zeile in `tools/CONTRACT.md`, AGENTS.md § Routing, `instructions/wiki-query/SKILL.md` (das `--limit 30`-Beispiel unterbot das neue Default und ist jetzt `--limit 0` als bewusster Sweep). `instructions/mcp-read-server.md` nannte das Limit nicht — nichts zu tun. Die `search`-Fehlervertragszeile blieb unverändert, weil kein neuer Fehlerfall entstand.
- [x] `pytest` 1272 grün (9 neu), `docs verify`, `instructions verify` grün.
## Verifiziert
- `tools/wikitool docs verify` und `tools/wikitool instructions verify` grün.
- `pytest` 1272 grün, davon 9 neue Tests: Pfad vorhanden; Titel und Pfad ungekappt bei langem Titel; eine Trefferzeile zerfällt trotz `|` in der Prosa in ihre fünf Felder; ein gekapptes Ergebnis nennt die Gesamtzahl, ein ungekapptes behauptet nichts; `--limit 0` nie gekappt; die Gesamtzahl überlebt das Limit in `run_search`; `api.search` meldet dasselbe; alle drei Adapter teilen ein Default-Limit.
- Coverage 88,2 % gegen eine Untergrenze von 85 %.
- Publiziert als `bb097f6` nach Mass-Update-Gate-Freigabe durch den Betreiber (13 Dateien).
## Version
`6.0.0-beta.8`, `--minor`, kein neuer Grenzübertritt. Drop-in in beide Richtungen: kein Flag entfernt oder umbenannt, keine Umgebungsvariable, keine maschinengelesene Datei in ihrer Form verändert, JSON rein additiv; die Tabelle liest ein Agent, kein Skript. Der Kandidat hatte die Grenze bereits überschritten, `--breaking` war nicht erneut fällig.
## Was bewusst nicht getan wurde
- **Kein `docs/`-Nachzug.** Keine `docs/`-Seite trägt die Begründung für das Retrieval-Ausgabeformat; geprüft wurden alle sechs.
- **Kein Nachzug in `README.md`, `kb/CONTRACT.md`, `EVALS.md`.** Alle drei beschreiben, *was* `search` tut (read-only, budget-frei, suchen statt blättern) — keine Aussage darüber wurde falsch. Die Grep-Regel dort zu wiederholen wäre eine zweite Kopie (Invariante 8).
- **Kein Nachzug in `wiki-manage`/`wiki-ingest`/`wiki-lint`.** Sie behaupten nichts über Ausgabeform oder Limit; die Regel erreicht sie über AGENTS.md, das jede Sitzung lädt.
## Beweislage
Der Korpus aus dem Transkript existierte zum Zeitpunkt der Analyse nicht mehr — `Pelletofenkondensator` fand weder `search` noch `rg` in `kb/`. Das Transkript ist als Beweis auf 2026-09-13 datiert; alle Befunde wurden gegen den damals aktuellen Baum und Korpus reproduziert.
Berührt, aber nicht blockiert: #35 (semantisches Backend) und #6 (Backlink-Ranking) ändern, *was* `search` findet, nicht wie vollständig die Ausgabe sich darstellt. Beide erben das hier festgelegte Format.
Changelog:status/incoming ausgearbeitet. Der Stub-Text ist unten wörtlich erhalten, der Body ist gegen den Baum geprüft und neu geschrieben. Drei prüfbare Befunde statt einer Beobachtung; der Grep im Transkript war nachweislich redundant, aber zwei Eigenschaften der search-Ausgabe geben einem Agenten einen rationalen Grund dafür. Die Frage, ob und wo das gefixt wird, bleibt offen (kind/decision). Labels gesetzt: area/kb, kind/decision, prio/planned, size/M; status/incoming und status/unconfirmed entfernt.
Ursprünglicher Stub, wörtlich:
tool calls:
Ausgeführt
einem Befehl
tools/wikitool search "Pelletofenkondensator"
6.0 Source - Pelletofenkondensator un… source/llm-session Perplexity-Recherche zur Identifikation, Ersatzteilbeschaffung und Verkabelung des …
2.0 Pelletofen (De Dietrich Remeha) entity/system Pelletofen (Modell CPO 8.5) im Haushalt des Nutzers, Steuereinheit von De Dietrich/…
2.0 Polung bei Wechselstrom-Motorkond… concept/pattern Warum MKP-Motorbetriebskondensatoren für Wechselstrommotoren im Gegensatz zu Elektr…
2.0 Verdrahtung mit Aderendhülsen und… concept/workflow Handwerkstechnik zum sicheren Anschluss feindrähtiger Litze an 230-V-WAGO-Hebelklem…
1.0 Source - Abisolierwerkzeug Auswah… source/llm-session Perplexity-Recherche zur Auswahl eines Abisolierwerkzeugs für Maker-/Elektronikarbe…
5 result(s).
Ausgeführt
einem Befehl
grep -rl "Pelletofenkondensator" kb/ --include=.md -l | head -20
(eval):1: no matches found: --include=.md
Ausgeführt
einem Befehl
grep -rl "Pelletofenkondensator" kb/ 2>/dev/null
kb/provenance.md
kb/log.md
kb/sources/INDEX.md
kb/sources/llm-sessions/Source - Pelletofenkondensator und Verkabelung Recherche.md
kb/sources/llm-sessions/Source - Abisolierwerkzeug Auswahl Recherche.md
kb/entities/systems/Pelletofen (De Dietrich Remeha).md
kb/concepts/patterns/Polung bei Wechselstrom-Motorkondensatoren.md
kb/concepts/workflows/Verdrahtung mit Aderendhülsen und WAGO-Hebelklemmen.md
**Changelog:** `status/incoming` ausgearbeitet. Der Stub-Text ist unten wörtlich erhalten, der Body ist gegen den Baum geprüft und neu geschrieben. Drei prüfbare Befunde statt einer Beobachtung; der Grep im Transkript war nachweislich redundant, aber zwei Eigenschaften der `search`-Ausgabe geben einem Agenten einen rationalen Grund dafür. Die Frage, ob und wo das gefixt wird, bleibt offen (`kind/decision`). Labels gesetzt: `area/kb`, `kind/decision`, `prio/planned`, `size/M`; `status/incoming` und `status/unconfirmed` entfernt.
---
**Ursprünglicher Stub, wörtlich:**
> tool calls:
>
> Ausgeführt
> einem Befehl
>
> tools/wikitool search "Pelletofenkondensator"
> 6.0 Source - Pelletofenkondensator un… source/llm-session Perplexity-Recherche zur Identifikation, Ersatzteilbeschaffung und Verkabelung des …
> 2.0 Pelletofen (De Dietrich Remeha) entity/system Pelletofen (Modell CPO 8.5) im Haushalt des Nutzers, Steuereinheit von De Dietrich/…
> 2.0 Polung bei Wechselstrom-Motorkond… concept/pattern Warum MKP-Motorbetriebskondensatoren für Wechselstrommotoren im Gegensatz zu Elektr…
> 2.0 Verdrahtung mit Aderendhülsen und… concept/workflow Handwerkstechnik zum sicheren Anschluss feindrähtiger Litze an 230-V-WAGO-Hebelklem…
> 1.0 Source - Abisolierwerkzeug Auswah… source/llm-session Perplexity-Recherche zur Auswahl eines Abisolierwerkzeugs für Maker-/Elektronikarbe…
>
> 5 result(s).
>
> Ausgeführt
> einem Befehl
> grep -rl "Pelletofenkondensator" kb/ --include=*.md -l | head -20
> (eval):1: no matches found: --include=*.md
>
> Ausgeführt
> einem Befehl
> grep -rl "Pelletofenkondensator" kb/ 2>/dev/null
> kb/provenance.md
> kb/log.md
> kb/sources/INDEX.md
> kb/sources/llm-sessions/Source - Pelletofenkondensator und Verkabelung Recherche.md
> kb/sources/llm-sessions/Source - Abisolierwerkzeug Auswahl Recherche.md
> kb/entities/systems/Pelletofen (De Dietrich Remeha).md
> kb/concepts/patterns/Polung bei Wechselstrom-Motorkondensatoren.md
> kb/concepts/workflows/Verdrahtung mit Aderendhülsen und WAGO-Hebelklemmen.md
torben
changed title from wiki-manage greppt zusätzlich zu wikitool search to wikitool search: Ausgabe nennt keinen Pfad, kappt den Titel und verschweigt die Trunkierung2026-09-15 19:18:23 +00:00
Changelog: Alle fünf offenen Fragen vom Betreiber entschieden, Abschnitt „Offene Fragen" durch „Entscheidungen" ersetzt. kind/decision → kind/build. Titel umbenannt, weil Frage 4 den Zuschnitt auf search festgelegt hat und die alte Zuschreibung auf wiki-manage damit falsch war (alt: „wiki-manage greppt zusätzlich zu wikitool search"). Neu in Befund 1: der Titel wird auf 34 Zeichen gekappt — im Transkript des Stubs traf das vier von fünf Treffern, was erklärt, warum die Sitzung Dateinamen wollte. Abnahmekriterien und Versionsteil (--minor, kein Boundary-Crossing) ergänzt. JSON als Default-Ausgabe erwogen und mit Begründung verworfen.
**Changelog:** Alle fünf offenen Fragen vom Betreiber entschieden, Abschnitt „Offene Fragen" durch „Entscheidungen" ersetzt. `kind/decision` → `kind/build`. Titel umbenannt, weil Frage 4 den Zuschnitt auf `search` festgelegt hat und die alte Zuschreibung auf `wiki-manage` damit falsch war (alt: „wiki-manage greppt zusätzlich zu wikitool search"). Neu in Befund 1: der Titel wird auf 34 Zeichen gekappt — im Transkript des Stubs traf das vier von fünf Treffern, was erklärt, warum die Sitzung Dateinamen wollte. Abnahmekriterien und Versionsteil (`--minor`, kein Boundary-Crossing) ergänzt. JSON als Default-Ausgabe erwogen und mit Begründung verworfen.
Changelog: Abschlussstand. Befunde in die Vergangenheitsform gesetzt, „Entscheidungen" zu „Was umgesetzt wurde" geworden, alle acht Abnahmekriterien abgehakt. Neu: Abschnitte „Verifiziert" (Commit bb097f6, 1272 Tests, Coverage 88,2 %, beide verify-Läufe) und „Was bewusst nicht getan wurde" (kein docs/-, README.md-, kb/CONTRACT.md-, EVALS.md- oder Skill-Nachzug, jeweils mit Grund). Zwei Präzisierungen gegenüber dem Planstand: das --limit 30-Beispiel in wiki-query wurde --limit 0, weil 30 das neue Default von 50 unterboten hätte, und instructions/mcp-read-server.md nannte das Limit gar nicht — dort war nichts zu tun.
Modellzuordnung: Design- und Versionsteil-Phase, mechanische Mitte (Code, Tests, Bump) und diese Abschlussphase liefen alle auf Opus 5. Der Modellwechsel wurde am Designbruch einmal angeboten und nicht gezogen.
**Changelog:** Abschlussstand. Befunde in die Vergangenheitsform gesetzt, „Entscheidungen" zu „Was umgesetzt wurde" geworden, alle acht Abnahmekriterien abgehakt. Neu: Abschnitte „Verifiziert" (Commit `bb097f6`, 1272 Tests, Coverage 88,2 %, beide verify-Läufe) und „Was bewusst nicht getan wurde" (kein `docs/`-, `README.md`-, `kb/CONTRACT.md`-, `EVALS.md`- oder Skill-Nachzug, jeweils mit Grund). Zwei Präzisierungen gegenüber dem Planstand: das `--limit 30`-Beispiel in `wiki-query` wurde `--limit 0`, weil 30 das neue Default von 50 unterboten hätte, und `instructions/mcp-read-server.md` nannte das Limit gar nicht — dort war nichts zu tun.
Modellzuordnung: Design- und Versionsteil-Phase, mechanische Mitte (Code, Tests, Bump) und diese Abschlussphase liefen alle auf Opus 5. Der Modellwechsel wurde am Designbruch einmal angeboten und nicht gezogen.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Eine Sitzung hat nach
tools/wikitool search "<Begriff>"zusätzlichgrep -rl "<Begriff>" kb/laufen lassen. Das Transkript steht wörtlich im ersten Kommentar.Der Grep war redundant — aber die Ausgabe von
searchgab ihr drei Gründe dafür. Das war der eigentliche Befund: nicht das Verhalten der Sitzung, sondern das Ausgabeformat, das es rational machte. Behoben in6.0.0-beta.8, publiziert alsbb097f6.Zuschnitt:
search-scoped, nicht skill-scoped — die Befunde trafenwiki-query,wiki-manageundwiki-ingestgleichermaßen. Alle drei wurden in einem Paket behoben, nicht getrennt.Die Befunde
Der Grep war vollständig redundant
searchist ein Grep überkb/.search/ripgrep.py::build_argvbautrg --json --smart-case --glob '*.md' --fixed-strings -- <text> kb/und verwirft anschließend jeden Treffer, dessen Pfad nicht inpagesliegt.pageskommt auskb_scan.iter_kb_pages, das die kb-Root-Metadateien, jedeCOLLECTION.mdund jede generierteINDEX.mdauslässt.Die drei Dateien, die der Grep zusätzlich fand —
kb/provenance.md,kb/log.md,kb/sources/INDEX.md— waren exakt diese Ausnahmen, alle drei nach Invariante 1 generiert. Ein eigener Grep überkb/konnte also keine Seite finden, diesearchnicht hatte.Befund 1 — kein Pfad, und der Titel wurde gekappt
render_tableschriebscore,title(auf 34 Zeichen gekappt),kind/subtype,summary. Keinen Pfad — obwohlwiki-querySchritt 3 verlangt, nur die Seiten zu lesen, auf die die Suche zeigt.Dazu fehlte der vollständige Titel, nach Invariante 2 der einzige Identifier einer Seite und das Argument, das
touch --page,xref add --aundcite add --pagenehmen. Im gemeldeten Transkript waren vier von fünf Titeln abgeschnitten. Die Sitzung hatte weder etwas zum Öffnen noch etwas zum Weiterreichen;grep -rllieferte genau beides. Das-lwar der Beleg.Befund 2 —
N result(s)war die gekappte Zahl--limitstand auf 20,run_searchgab nurhits[: query.limit]zurück, und jeder Adapter zählte danach.20 result(s).auf einer Anfrage mit 182 Treffern war von einem vollständigen Ergebnis nicht unterscheidbar — eine Vollständigkeitsaussage, zu der die Ausgabe nicht berechtigt war, und die einzige Möglichkeit, die echte Zahl zu erfahren, war ein zweiter vollständiger Lauf mit--limit 0.Befund 3 — nichts sagte, dass
searchfürkb/erschöpfend istWeder AGENTS.md § Routing noch die Skills noch die
search-Zeile intools/CONTRACT.mdsagten, dass ein eigener Grep überkb/nichts hinzufügt. Die Contract-Zeile nannte den Zweck, nicht die Zusicherung.Was umgesetzt wurde
Behoben statt hingenommen — auch mit Blick auf #35: ein Ausgabeformat, dem Sitzungen nicht trauen, trägt keine Erweiterung.
Neue Trefferzeile, ohne Spaltenauffüllung:
Felder:
score | kind/subtype | titel | pfad | summary. Titel und Pfad werden nie gekappt; die Summary ist das einzige verlustige Feld und steht am Ende, wo ein|in Prosa beim Trennen mitmaxsplit=4folgenlos bleibt (ein|im Titel schließt die Wikilink-Syntax ohnehin aus).JSON als Default wurde erwogen und verworfen: ein Treffer ist flach, JSON kostet dafür ein Vielfaches an Tokens, und
searchexistiert laut eigenem Modul-Docstring dafür, Retrieval billig zu machen. Der Fehler war ein fehlendes Feld, kein Parse-Problem.--json,api.searchund MCP bleiben für alle, die Struktur brauchen.Trunkierung wird benannt.
run_searchgibt einSearchResult(Treffer, Gesamtzahl, Limit) zurück. Tabelle:50 of 182 result(s) - raise --limit (0 for all) or narrow the query.JSON rein additiv:total/truncated/limitnebencount, das seine Bedeutung behält (len(results)).api.searchund MCP-searchtragen dieselben Felder.Default-Limit 20 → 50, als eine Konstante
DEFAULT_LIMITstatt drei Literalen in drei Adaptern. Gekappt wurden vor allem die strukturellen Sweeps (--field '!sources'), die alphabetisch und nicht nach Relevanz sortiert sind — dort wirft die Kappung eine beliebige Scheibe der Antwort weg statt ihres schwächsten Endes. Dass sie jetzt sichtbar ist, macht ein endliches Default überhaupt erst unbedenklich.Die Regel steht an genau einer Stelle: AGENTS.md § Routing, wo „search, do not read the catalog" schon stand.
tools/CONTRACT.mdträgt daneben nur den Mechanismus (was das Backend scannt, welche Dateien es auslässt), nicht die Regel ein zweites Mal.Abnahmekriterien
….--json,api.search, MCP-search, ohne zweiten Aufruf.search "e"sagt jetzt50 of 182 result(s).--limit 0gilt nie als gekappt.Corpus.search-Signatur, Typer-Option).countbedeutet unverändertlen(results);total/truncated/limitadditiv. Der MCP-Golden-Test hält CLI und Server auf den neuen Feldern zusammen.tools/CONTRACT.mdnur den Mechanismus.search-Zeile intools/CONTRACT.md, AGENTS.md § Routing,instructions/wiki-query/SKILL.md(das--limit 30-Beispiel unterbot das neue Default und ist jetzt--limit 0als bewusster Sweep).instructions/mcp-read-server.mdnannte das Limit nicht — nichts zu tun. Diesearch-Fehlervertragszeile blieb unverändert, weil kein neuer Fehlerfall entstand.pytest1272 grün (9 neu),docs verify,instructions verifygrün.Verifiziert
tools/wikitool docs verifyundtools/wikitool instructions verifygrün.pytest1272 grün, davon 9 neue Tests: Pfad vorhanden; Titel und Pfad ungekappt bei langem Titel; eine Trefferzeile zerfällt trotz|in der Prosa in ihre fünf Felder; ein gekapptes Ergebnis nennt die Gesamtzahl, ein ungekapptes behauptet nichts;--limit 0nie gekappt; die Gesamtzahl überlebt das Limit inrun_search;api.searchmeldet dasselbe; alle drei Adapter teilen ein Default-Limit.bb097f6nach Mass-Update-Gate-Freigabe durch den Betreiber (13 Dateien).Version
6.0.0-beta.8,--minor, kein neuer Grenzübertritt. Drop-in in beide Richtungen: kein Flag entfernt oder umbenannt, keine Umgebungsvariable, keine maschinengelesene Datei in ihrer Form verändert, JSON rein additiv; die Tabelle liest ein Agent, kein Skript. Der Kandidat hatte die Grenze bereits überschritten,--breakingwar nicht erneut fällig.Was bewusst nicht getan wurde
docs/-Nachzug. Keinedocs/-Seite trägt die Begründung für das Retrieval-Ausgabeformat; geprüft wurden alle sechs.README.md,kb/CONTRACT.md,EVALS.md. Alle drei beschreiben, wassearchtut (read-only, budget-frei, suchen statt blättern) — keine Aussage darüber wurde falsch. Die Grep-Regel dort zu wiederholen wäre eine zweite Kopie (Invariante 8).wiki-manage/wiki-ingest/wiki-lint. Sie behaupten nichts über Ausgabeform oder Limit; die Regel erreicht sie über AGENTS.md, das jede Sitzung lädt.Beweislage
Der Korpus aus dem Transkript existierte zum Zeitpunkt der Analyse nicht mehr —
Pelletofenkondensatorfand wedersearchnochrginkb/. Das Transkript ist als Beweis auf 2026-09-13 datiert; alle Befunde wurden gegen den damals aktuellen Baum und Korpus reproduziert.Berührt, aber nicht blockiert: #35 (semantisches Backend) und #6 (Backlink-Ranking) ändern, was
searchfindet, nicht wie vollständig die Ausgabe sich darstellt. Beide erben das hier festgelegte Format.Changelog:
status/incomingausgearbeitet. Der Stub-Text ist unten wörtlich erhalten, der Body ist gegen den Baum geprüft und neu geschrieben. Drei prüfbare Befunde statt einer Beobachtung; der Grep im Transkript war nachweislich redundant, aber zwei Eigenschaften dersearch-Ausgabe geben einem Agenten einen rationalen Grund dafür. Die Frage, ob und wo das gefixt wird, bleibt offen (kind/decision). Labels gesetzt:area/kb,kind/decision,prio/planned,size/M;status/incomingundstatus/unconfirmedentfernt.Ursprünglicher Stub, wörtlich:
wiki-manage greppt zusätzlich zu wikitool searchto wikitool search: Ausgabe nennt keinen Pfad, kappt den Titel und verschweigt die TrunkierungChangelog: Alle fünf offenen Fragen vom Betreiber entschieden, Abschnitt „Offene Fragen" durch „Entscheidungen" ersetzt.
kind/decision→kind/build. Titel umbenannt, weil Frage 4 den Zuschnitt aufsearchfestgelegt hat und die alte Zuschreibung aufwiki-managedamit falsch war (alt: „wiki-manage greppt zusätzlich zu wikitool search"). Neu in Befund 1: der Titel wird auf 34 Zeichen gekappt — im Transkript des Stubs traf das vier von fünf Treffern, was erklärt, warum die Sitzung Dateinamen wollte. Abnahmekriterien und Versionsteil (--minor, kein Boundary-Crossing) ergänzt. JSON als Default-Ausgabe erwogen und mit Begründung verworfen.Changelog: Abschlussstand. Befunde in die Vergangenheitsform gesetzt, „Entscheidungen" zu „Was umgesetzt wurde" geworden, alle acht Abnahmekriterien abgehakt. Neu: Abschnitte „Verifiziert" (Commit
bb097f6, 1272 Tests, Coverage 88,2 %, beide verify-Läufe) und „Was bewusst nicht getan wurde" (keindocs/-,README.md-,kb/CONTRACT.md-,EVALS.md- oder Skill-Nachzug, jeweils mit Grund). Zwei Präzisierungen gegenüber dem Planstand: das--limit 30-Beispiel inwiki-querywurde--limit 0, weil 30 das neue Default von 50 unterboten hätte, undinstructions/mcp-read-server.mdnannte das Limit gar nicht — dort war nichts zu tun.Modellzuordnung: Design- und Versionsteil-Phase, mechanische Mitte (Code, Tests, Bump) und diese Abschlussphase liefen alle auf Opus 5. Der Modellwechsel wurde am Designbruch einmal angeboten und nicht gezogen.