Beobachtet im Ingest vom 2026-08-30, der das Budget von 30 Aufrufen erschöpfte und publish nur noch mit --override-budget erreichte. Zwei der Aufrufe waren vermeidbar, und beide gehen auf das Werkzeug zurück, nicht auf die Aufgabe.
1. Ein Validierungsfehler verbraucht einen Budget-Slot, obwohl nichts geschah
$ tools/wikitool new source --name "..." --set "raw_files=...Versioning, CI-CD..."
ERROR raw_files path does not exist: raw/notes/Conversation Transcript -
Versioning
Der Aufruf schrieb keine Datei und änderte keinen Zustand, wurde aber gezählt. tools/CONTRACT.md führt genau diesen Fall als „Not transient; fix the argument and retry once" — die vorgeschriebene Reaktion kostet also zwangsläufig zwei Slots für eine Operation.
Das Budget existiert, um Iterieren zu begrenzen. Ein Aufruf, der an der Argumentprüfung scheitert, ist kein Iterationsschritt; er ist ein Tippfehler.
Vorschlag: Nicht zählen, wenn die Ausführung vor jeder Zustandsänderung an einer Validierung abbricht. Der Loop-Breaker (3 identische Aufrufe hintereinander) fängt den Fall ab, dass jemand denselben falschen Aufruf wiederholt, und ist dafür das passendere Werkzeug.
2. lint nennt seinen Report-Pfad nicht, also wird es erneut aufgerufen
Der Bericht ist lang; wer ihn abschnittsweise liest, schneidet mit head/tail und braucht dann einen zweiten Blick auf einen anderen Teil. lint schreibt den Bericht nach reports/, sagt aber im Terminal nicht, wohin — so ist der naheliegende Reflex ein zweiter lint-Aufruf statt ein kostenloser Read auf die Datei. Im genannten Ingest passierte genau das, zweimal.
Erschwerend: In reports/ liegt ein Unterverzeichnis telemetry/, sodass ein ls -t reports/ | head -1 auf ein Verzeichnis zeigt statt auf den jüngsten Bericht.
Vorschläge:
lint gibt am Ende eine Zeile mit dem geschriebenen Report-Pfad aus (OK Report written to reports/Lint Report YYYY-MM-DD.md), analog zu index rebuild und sources rebuild-index.
Optional lint --summary, das nur die Abschnitte mit Befunden ausgibt. Der Vollbericht ist beim sauberen Korpus zu über 90 % „None found."
Die Ausgabe von lint könnte, wie search, vom Budget ausgenommen sein: Sie ist eine Leseoperation über den Korpus und ändert nichts. Das ist die weitergehende Variante und sollte getrennt entschieden werden.
Kontext
Beide Punkte betreffen den in instructions/gates.md kalibrierten Rahmen: „15-25 Aufrufe für einen komplexen Multi-Tool-Workflow wie einen Ingest". Der Ingest vom 2026-08-30 lag inhaltlich in diesem Rahmen; die Überschreitung kam aus dem Werkzeug.
Verwandt: #12 (--set kann keine Array-Werte mit Komma ausdrücken) — der Auslöser des ersten Punkts.
Beobachtet im Ingest vom 2026-08-30, der das Budget von 30 Aufrufen erschöpfte und `publish` nur noch mit `--override-budget` erreichte. Zwei der Aufrufe waren vermeidbar, und beide gehen auf das Werkzeug zurück, nicht auf die Aufgabe.
## 1. Ein Validierungsfehler verbraucht einen Budget-Slot, obwohl nichts geschah
```
$ tools/wikitool new source --name "..." --set "raw_files=...Versioning, CI-CD..."
ERROR raw_files path does not exist: raw/notes/Conversation Transcript -
Versioning
```
Der Aufruf schrieb keine Datei und änderte keinen Zustand, wurde aber gezählt. `tools/CONTRACT.md` führt genau diesen Fall als „Not transient; fix the argument and **retry once**" — die vorgeschriebene Reaktion kostet also zwangsläufig zwei Slots für eine Operation.
Das Budget existiert, um Iterieren zu begrenzen. Ein Aufruf, der an der Argumentprüfung scheitert, ist kein Iterationsschritt; er ist ein Tippfehler.
**Vorschlag:** Nicht zählen, wenn die Ausführung vor jeder Zustandsänderung an einer Validierung abbricht. Der Loop-Breaker (3 identische Aufrufe hintereinander) fängt den Fall ab, dass jemand denselben falschen Aufruf wiederholt, und ist dafür das passendere Werkzeug.
## 2. `lint` nennt seinen Report-Pfad nicht, also wird es erneut aufgerufen
Der Bericht ist lang; wer ihn abschnittsweise liest, schneidet mit `head`/`tail` und braucht dann einen zweiten Blick auf einen anderen Teil. `lint` schreibt den Bericht nach `reports/`, sagt aber im Terminal nicht, wohin — so ist der naheliegende Reflex ein zweiter `lint`-Aufruf statt ein kostenloser `Read` auf die Datei. Im genannten Ingest passierte genau das, zweimal.
Erschwerend: In `reports/` liegt ein Unterverzeichnis `telemetry/`, sodass ein `ls -t reports/ | head -1` auf ein Verzeichnis zeigt statt auf den jüngsten Bericht.
**Vorschläge:**
- `lint` gibt am Ende eine Zeile mit dem geschriebenen Report-Pfad aus (`OK Report written to reports/Lint Report YYYY-MM-DD.md`), analog zu `index rebuild` und `sources rebuild-index`.
- Optional `lint --summary`, das nur die Abschnitte mit Befunden ausgibt. Der Vollbericht ist beim sauberen Korpus zu über 90 % „None found."
- Die Ausgabe von `lint` könnte, wie `search`, vom Budget ausgenommen sein: Sie ist eine Leseoperation über den Korpus und ändert nichts. Das ist die weitergehende Variante und sollte getrennt entschieden werden.
## Kontext
Beide Punkte betreffen den in `instructions/gates.md` kalibrierten Rahmen: „15-25 Aufrufe für einen komplexen Multi-Tool-Workflow wie einen Ingest". Der Ingest vom 2026-08-30 lag inhaltlich in diesem Rahmen; die Überschreitung kam aus dem Werkzeug.
Verwandt: #12 (`--set` kann keine Array-Werte mit Komma ausdrücken) — der Auslöser des ersten Punkts.
Behoben in 1.2.0 (40adbb7). Zwei der drei Vorschläge umgesetzt, der dritte bewusst nicht.
1. Validierungsfehler kostet keinen Slot mehr
Ein Aufruf, der über _util.fail() mit Exit 1 endet, wird zurückerstattet (run_budget.refund(), ausgelöst in cli._run_traced).
Die Abgrenzung liegt bewusst an fail() und nicht am Exit-Code: fail() heißt „das Kommando hat abgelehnt" — abgewiesenes Argument oder ein lesender Check, der Befunde meldet. Ein Kommando, das seine Arbeit schon getan hat und dann ungleich null endet, wirft typer.Exit(1) direkt und bleibt gezählt. lint --fail-on-error ist genau dieser Fall: es hat den Bericht bereits geschrieben.
Die Historie bleibt. Der Aufruf landet weiter in recent, der Loop-Breaker sieht ihn also. Drei identische kaputte Aufrufe brechen weiterhin ab — es gibt einen Test dafür, weil das die Gegenprobe zur Erstattung ist.
Real nachgemessen:
$ tools/wikitool new source --name "Refund Probe" --set "raw_files=raw/notes/Versioning, CI-CD.md"
ERROR raw_files path does not exist: raw/notes/Versioning
This is one element after splitting the value on commas. ...
$ tools/wikitool budget status
Calls so far: 0 (limit 60)
Recent calls:
- new source --name Refund Probe --set raw_files=raw/notes/Versioning, CI-CD.md
2. lint nennt seinen Reportpfad
Der Befund im Issue war schärfer als die Überschrift: ohne --markdown schrieb lint gar keine Datei, es kippte den Vollbericht nach stdout. Deshalb gab es keinen Pfad zu nennen — und keinen Weg zurück zum übersprungenen Teil außer einem zweiten Lauf.
Der Vollbericht wird jetzt immer geschrieben, per Default nach reports/Lint Report <date>.md, und der Pfad wird ausgegeben. --markdown überschreibt das Ziel wie bisher.
Gedruckt werden nur die Abschnitte mit Befunden (--summary aus dem Issue ist damit das Standardverhalten, nicht ein Flag). --full druckt alles, --json schreibt weiterhin nichts.
wiki-lint und wiki-status sagen jetzt beide ausdrücklich: die Datei lesen, nicht lint erneut aufrufen. wiki-status Schritt 3 holt die Hub-Statistik aus dem Bericht — sie ist kein Befund und steht deshalb nicht mehr in der Zusammenfassung.
Der reports/-Unterordner telemetry/, der ls -t in die Irre führte, ist damit kein Problem mehr: der Pfad steht in der Ausgabe.
3. Ceiling 30 → 60
Auf Anweisung mit umgesetzt. Das Kalibrierungsband (5-15 einfach, 15-25 komplex) bleibt unverändert — es beschreibt die Arbeit. Die Decke beschrieb bisher nichts: sie lag so dicht am Band, dass der Overhead eines echten Ingests sie allein erreichte. AGENTS.md, instructions/gates.md, tools/CONTRACT.md, README.md, das work plan-Template und die Unit-Größe in migrate-corpus.md (jetzt „nahe 55 Seiten; ziele auf 48") sind mitgezogen.
Der Loop-Breaker bleibt bei 3. Er ist kein Budget, sondern ein Detektor für dreimal denselben Aufruf; ihn zu verdoppeln hieße, einen feststeckenden Agenten doppelt so lange laufen zu lassen.
Nicht umgesetzt
lint ganz vom Budget zu befreien — das Issue sagt selbst, das gehört getrennt entschieden. Der Fall hat sich außerdem verschoben: lint schreibt jetzt eine Datei, ist also nicht mehr rein lesend.
Behoben in **1.2.0** (`40adbb7`). Zwei der drei Vorschläge umgesetzt, der dritte bewusst nicht.
## 1. Validierungsfehler kostet keinen Slot mehr
Ein Aufruf, der über `_util.fail()` mit Exit 1 endet, wird zurückerstattet (`run_budget.refund()`, ausgelöst in `cli._run_traced`).
Die Abgrenzung liegt bewusst an `fail()` und nicht am Exit-Code: `fail()` heißt „das Kommando hat abgelehnt" — abgewiesenes Argument oder ein lesender Check, der Befunde meldet. Ein Kommando, das seine Arbeit schon getan hat und *dann* ungleich null endet, wirft `typer.Exit(1)` direkt und bleibt gezählt. `lint --fail-on-error` ist genau dieser Fall: es hat den Bericht bereits geschrieben.
**Die Historie bleibt.** Der Aufruf landet weiter in `recent`, der Loop-Breaker sieht ihn also. Drei identische kaputte Aufrufe brechen weiterhin ab — es gibt einen Test dafür, weil das die Gegenprobe zur Erstattung ist.
Real nachgemessen:
```
$ tools/wikitool new source --name "Refund Probe" --set "raw_files=raw/notes/Versioning, CI-CD.md"
ERROR raw_files path does not exist: raw/notes/Versioning
This is one element after splitting the value on commas. ...
$ tools/wikitool budget status
Calls so far: 0 (limit 60)
Recent calls:
- new source --name Refund Probe --set raw_files=raw/notes/Versioning, CI-CD.md
```
## 2. `lint` nennt seinen Reportpfad
Der Befund im Issue war schärfer als die Überschrift: ohne `--markdown` schrieb `lint` gar keine Datei, es kippte den Vollbericht nach stdout. Deshalb gab es keinen Pfad zu nennen — und keinen Weg zurück zum übersprungenen Teil außer einem zweiten Lauf.
- Der Vollbericht wird jetzt **immer** geschrieben, per Default nach `reports/Lint Report <date>.md`, und der Pfad wird ausgegeben. `--markdown` überschreibt das Ziel wie bisher.
- Gedruckt werden nur die Abschnitte mit Befunden (`--summary` aus dem Issue ist damit das Standardverhalten, nicht ein Flag). `--full` druckt alles, `--json` schreibt weiterhin nichts.
- `wiki-lint` und `wiki-status` sagen jetzt beide ausdrücklich: die Datei lesen, nicht `lint` erneut aufrufen. `wiki-status` Schritt 3 holt die Hub-Statistik aus dem Bericht — sie ist kein Befund und steht deshalb nicht mehr in der Zusammenfassung.
Der `reports/`-Unterordner `telemetry/`, der `ls -t` in die Irre führte, ist damit kein Problem mehr: der Pfad steht in der Ausgabe.
## 3. Ceiling 30 → 60
Auf Anweisung mit umgesetzt. Das Kalibrierungsband (5-15 einfach, 15-25 komplex) bleibt unverändert — es beschreibt die Arbeit. Die Decke beschrieb bisher nichts: sie lag so dicht am Band, dass der Overhead eines echten Ingests sie allein erreichte. `AGENTS.md`, `instructions/gates.md`, `tools/CONTRACT.md`, `README.md`, das `work plan`-Template und die Unit-Größe in `migrate-corpus.md` (jetzt „nahe 55 Seiten; ziele auf 48") sind mitgezogen.
**Der Loop-Breaker bleibt bei 3.** Er ist kein Budget, sondern ein Detektor für dreimal denselben Aufruf; ihn zu verdoppeln hieße, einen feststeckenden Agenten doppelt so lange laufen zu lassen.
## Nicht umgesetzt
`lint` ganz vom Budget zu befreien — das Issue sagt selbst, das gehört getrennt entschieden. Der Fall hat sich außerdem verschoben: `lint` schreibt jetzt eine Datei, ist also nicht mehr rein lesend.
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.
Beobachtet im Ingest vom 2026-08-30, der das Budget von 30 Aufrufen erschöpfte und
publishnur noch mit--override-budgeterreichte. Zwei der Aufrufe waren vermeidbar, und beide gehen auf das Werkzeug zurück, nicht auf die Aufgabe.1. Ein Validierungsfehler verbraucht einen Budget-Slot, obwohl nichts geschah
Der Aufruf schrieb keine Datei und änderte keinen Zustand, wurde aber gezählt.
tools/CONTRACT.mdführt genau diesen Fall als „Not transient; fix the argument and retry once" — die vorgeschriebene Reaktion kostet also zwangsläufig zwei Slots für eine Operation.Das Budget existiert, um Iterieren zu begrenzen. Ein Aufruf, der an der Argumentprüfung scheitert, ist kein Iterationsschritt; er ist ein Tippfehler.
Vorschlag: Nicht zählen, wenn die Ausführung vor jeder Zustandsänderung an einer Validierung abbricht. Der Loop-Breaker (3 identische Aufrufe hintereinander) fängt den Fall ab, dass jemand denselben falschen Aufruf wiederholt, und ist dafür das passendere Werkzeug.
2.
lintnennt seinen Report-Pfad nicht, also wird es erneut aufgerufenDer Bericht ist lang; wer ihn abschnittsweise liest, schneidet mit
head/tailund braucht dann einen zweiten Blick auf einen anderen Teil.lintschreibt den Bericht nachreports/, sagt aber im Terminal nicht, wohin — so ist der naheliegende Reflex ein zweiterlint-Aufruf statt ein kostenloserReadauf die Datei. Im genannten Ingest passierte genau das, zweimal.Erschwerend: In
reports/liegt ein Unterverzeichnistelemetry/, sodass einls -t reports/ | head -1auf ein Verzeichnis zeigt statt auf den jüngsten Bericht.Vorschläge:
lintgibt am Ende eine Zeile mit dem geschriebenen Report-Pfad aus (OK Report written to reports/Lint Report YYYY-MM-DD.md), analog zuindex rebuildundsources rebuild-index.lint --summary, das nur die Abschnitte mit Befunden ausgibt. Der Vollbericht ist beim sauberen Korpus zu über 90 % „None found."lintkönnte, wiesearch, vom Budget ausgenommen sein: Sie ist eine Leseoperation über den Korpus und ändert nichts. Das ist die weitergehende Variante und sollte getrennt entschieden werden.Kontext
Beide Punkte betreffen den in
instructions/gates.mdkalibrierten Rahmen: „15-25 Aufrufe für einen komplexen Multi-Tool-Workflow wie einen Ingest". Der Ingest vom 2026-08-30 lag inhaltlich in diesem Rahmen; die Überschreitung kam aus dem Werkzeug.Verwandt: #12 (
--setkann keine Array-Werte mit Komma ausdrücken) — der Auslöser des ersten Punkts.Behoben in 1.2.0 (
40adbb7). Zwei der drei Vorschläge umgesetzt, der dritte bewusst nicht.1. Validierungsfehler kostet keinen Slot mehr
Ein Aufruf, der über
_util.fail()mit Exit 1 endet, wird zurückerstattet (run_budget.refund(), ausgelöst incli._run_traced).Die Abgrenzung liegt bewusst an
fail()und nicht am Exit-Code:fail()heißt „das Kommando hat abgelehnt" — abgewiesenes Argument oder ein lesender Check, der Befunde meldet. Ein Kommando, das seine Arbeit schon getan hat und dann ungleich null endet, wirfttyper.Exit(1)direkt und bleibt gezählt.lint --fail-on-errorist genau dieser Fall: es hat den Bericht bereits geschrieben.Die Historie bleibt. Der Aufruf landet weiter in
recent, der Loop-Breaker sieht ihn also. Drei identische kaputte Aufrufe brechen weiterhin ab — es gibt einen Test dafür, weil das die Gegenprobe zur Erstattung ist.Real nachgemessen:
2.
lintnennt seinen ReportpfadDer Befund im Issue war schärfer als die Überschrift: ohne
--markdownschrieblintgar keine Datei, es kippte den Vollbericht nach stdout. Deshalb gab es keinen Pfad zu nennen — und keinen Weg zurück zum übersprungenen Teil außer einem zweiten Lauf.reports/Lint Report <date>.md, und der Pfad wird ausgegeben.--markdownüberschreibt das Ziel wie bisher.--summaryaus dem Issue ist damit das Standardverhalten, nicht ein Flag).--fulldruckt alles,--jsonschreibt weiterhin nichts.wiki-lintundwiki-statussagen jetzt beide ausdrücklich: die Datei lesen, nichtlinterneut aufrufen.wiki-statusSchritt 3 holt die Hub-Statistik aus dem Bericht — sie ist kein Befund und steht deshalb nicht mehr in der Zusammenfassung.Der
reports/-Unterordnertelemetry/, derls -tin die Irre führte, ist damit kein Problem mehr: der Pfad steht in der Ausgabe.3. Ceiling 30 → 60
Auf Anweisung mit umgesetzt. Das Kalibrierungsband (5-15 einfach, 15-25 komplex) bleibt unverändert — es beschreibt die Arbeit. Die Decke beschrieb bisher nichts: sie lag so dicht am Band, dass der Overhead eines echten Ingests sie allein erreichte.
AGENTS.md,instructions/gates.md,tools/CONTRACT.md,README.md, daswork plan-Template und die Unit-Größe inmigrate-corpus.md(jetzt „nahe 55 Seiten; ziele auf 48") sind mitgezogen.Der Loop-Breaker bleibt bei 3. Er ist kein Budget, sondern ein Detektor für dreimal denselben Aufruf; ihn zu verdoppeln hieße, einen feststeckenden Agenten doppelt so lange laufen zu lassen.
Nicht umgesetzt
lintganz vom Budget zu befreien — das Issue sagt selbst, das gehört getrennt entschieden. Der Fall hat sich außerdem verschoben:lintschreibt jetzt eine Datei, ist also nicht mehr rein lesend.