Chemenu kompiliert Rohnotizen zu einem verlinkten, quellengebundenen Wiki:
raw/ -> types/ + tools/ -> kb/ -> reports/. Was mechanisch ist, macht
tools/wikitool; was Urteil braucht, macht ein Agent unter Contracts, deren
Grenzen in Code durchgesetzt sind statt im Prompt.
Dieser Commit ist der Startpunkt der oeffentlichen Historie. Die vorherige
Entwicklung fand in einer privaten Instanz statt und ist nicht Teil dieses
Repositorys; ihre Erzaehlung steht vollstaendig in CHANGES.md, das mit 44
Eintraegen von 0.1.0 bis 2.1.0 erhalten geblieben ist.
Der mitgelieferte Korpus ist ein Testbett und eine Demo: 170 Seiten ueber den
Stack selbst - Gates, Lint, Versionierung, Suche, das Wiki-Muster. Er
dokumentiert das Werkzeug mit den eigenen Mitteln des Werkzeugs.
Lizenz: AGPL-3.0 fuer den Stack (tools/, types/), CC-BY-4.0 fuer die Inhalte.
Die Grenze zwischen beiden ist der Dateiplan, den dist export berechnet -
siehe NOTICE.
Sitzung, die Komma-Werte in --set ausdrueckbar macht, das Flow-Quoting im Frontmatter repariert, abgelehnte Aufrufe dem Iteration Budget zurueckerstattet, die Obergrenze auf 60 hebt und lint seinen Reportpfad nennen laesst (Stack 1.2.0)
Das Transkript ist eine vom Assistenten am Sitzungsende rekonstruierte Zusammenfassung, kein
wörtliches Protokoll; die zitierten Befehlsausgaben sind echt, Torbens Anweisungen kurz und
wörtlich, die Begründungen des Assistenten verdichtet. Es ist eines von drei Transkripten
derselben Sitzung; die beiden anderen behandeln Issue-Triage und den auto-Berechtigungsmodus
des Harness und werden getrennt eingelesen.
Die Sitzung schloss die Gitea-Issues #12 und #13 und lieferte Stack-Version 1.2.0 aus
(Commit 40adbb7), gefolgt von einer Inhaltskorrektur (5426a6e). Inhaltlich sind es vier
Änderungen: --set kann Arraywerte mit Komma ausdrücken (Escape \, und wiederholtes --set,
das anhängt statt zu ersetzen), dump_frontmatter quotet solche Werte beim Schreiben korrekt,
das Iteration-Budget erstattet einen Slot zurück, wenn ein Aufruf abgelehnt wurde, und die
Obergrenze steigt von 30 auf 60. Dazu nennt lint jetzt den Pfad seines Reports und schreibt
ihn immer.
Der Fix machte eine ältere Contract-Verletzung reparierbar: eine Rohdatei war beim Ingest vom
2026-08-30 umbenannt worden, um zum Flag zu passen. Sie bekam ihren ursprünglichen Namen
zurück. Dabei fiel die Lücke auf, die als Issue #14 offen ist - kein wikitool-Befehl schreibt
raw_files: auf einer bestehenden Seite, obwohl lint und sources coverage kaputte
Referenzen zuverlässig melden. Das ist der Fall, den Detect-Repair Asymmetry beschreibt.
Kernaussagen
Ein Trennzeichen ohne Escape macht legale Daten unausdrückbar.parse_list() splittete
hart auf ,. Shell-Quoting hilft nicht: die Quotes sind längst weg, bevor der Wert den
Parser erreicht. Ein raw_files:-Pfad mit Komma im Dateinamen war damit nicht ausdrückbar -
und der Ausweg, den ein Agent tatsächlich nahm, war, die Rohdatei umzubenennen, also die
Immutabilitätsregel aus raw/CONTRACT.md zu brechen.
Beide Vorschläge aus Issue #12 wurden umgesetzt, weil sie verschiedene Fälle bedienen:\, als literales Komma über einen Lookbehind (re.compile(r"(?<!\\),")) plus Unescape je
Element, und wiederholtes --set auf einem Array-Feld hängt an statt zu ersetzen. Skalare
behalten „last one wins", weil es dort nichts anzuhängen gibt. Die Append-Form ist die
trennzeichenfreie und damit die richtige, wenn ein Element selbst ein Komma enthält. Der
Escape reicht über denselben Helper auch bis xref add --entities.
Der zweite Defekt kam vom Test, nicht vom Issue. Der End-to-End-Test - Rohdatei mit Komma
anlegen, mit \, referenzieren, die geschriebene Seite zurücklesen - fiel weiterhin durch.
Escape und Append waren korrekt; die Datei war es nicht. dump_frontmatter schreibt Listen
im Flow-Stil ([a, b]), aber _format_scalar entschied über das Quoting mit einer
Round-Trip-Probe auf Dokumentebene, wo ein Komma ein gewöhnliches Zeichen ist. Innerhalb von
[...] ist es ein Indikator, und raw_files: [raw/notes/Versioning, CI-CD.md] liest sich als
zwei Elemente zurück.
Behoben in frontmatter_io.py, ohne das Designprinzip der Datei aufzugeben:_round_trips_as_string(text, flow=True) probt in genau dem Kontext, in dem der Wert
geschrieben wird, und fragt weiterhin den YAML-Loader, statt Regeln aufzuzählen. Der neue
Helper _quote() lässt sich vom Dumper eine einelementige Flow-Sequenz geben und streift die
Klammern ab, weil ein blanker Plain-Scalar aus safe_dump einen ...-Dokumentende-Marker
mitbringt - für ein Dokument richtig, in einer Liste Unsinn.
Bestehende Ausgabe bleibt unverändert:tags: [k8s, ci-cd] bleibt ungequotet,
year: '1945' bleibt exakt wie zuvor gequotet. Neu gequotet werden nur Werte, die vorher
still zerbrochen sind.
Das Budget zählte Reibung statt Iteration. Die Rückerstattung ist nicht auf Exit-Code 1
gekeyt - das hätte lint --fail-on-error gratis gemacht, sobald es etwas findet - sondern
auf _util.fail(). fail() heißt: der Befehl hat abgelehnt (zurückgewiesenes Argument
oder ein lesender Check, der Befunde meldet), es ist nichts passiert, also Erstattung. Ein
Befehl, der seine Arbeit getan hat und danach ein Nicht-Null-Ergebnis meldet, wirft
typer.Exit(1) direkt und bleibt gezählt; lint --fail-on-error ist genau dieser Fall, denn
es hat seinen Report vorher geschrieben.
Mechanik der Erstattung:record_and_check() meldet zurück, ob es belastet hat, und
cli._run_traced ruft im finally-Block run_budget.refund(), wenn der Prozess durch
fail() verlassen wurde. Der Aufruf bleibt in recent, damit der Loop-Breaker ihn weiterhin
sieht - für eine wiederholt kaputte Invokation ist der Loop-Breaker das richtige Instrument,
nicht der Zähler.
Verworfen: Schreibvorgänge an den Schreibstellen zu markieren (35 Stellen in 15 Dateien),
um die Erstattung auf „es wurde nichts geschrieben" zu keyen. Das ist fail-open: eine neue
Schreibstelle, die den Marker vergisst, schwächt still ein Gate.
Obergrenze 30 → 60 auf Torbens Anweisung („verdopple die Tool call Limits zusätzlich").
Das Kalibrierungsband (5-15 einfach, 15-25 komplex) blieb unangetastet, weil es die Arbeit
beschreibt; die Obergrenze beschrieb nichts und lag so dicht am Band, dass der Overhead eines
realen Ingests sie allein erreichte. Nachgezogen in AGENTS.md, instructions/gates.md,
tools/CONTRACT.md, README.md, der work plan-Vorlage und der Einheitengröße in
migrate-corpus.md (jetzt „near 55 pages; aim for 48 or fewer").
Der Loop-Breaker blieb bewusst bei 3 und wurde zurückgemeldet statt still mitverdoppelt:
er ist ein Detektor für drei identische Aufrufe, kein Budget, und eine Verdopplung ließe
einen festgefahrenen Agenten doppelt so lange kreisen.
lint schrieb ohne --markdown gar keine Datei und kippte den vollen Report nach
stdout. Es gab also keinen Pfad zu nennen und keinen Weg zurück in einen übersprungenen
Abschnitt außer einem zweiten Lauf. Jetzt wird der volle Report immer geschrieben,
standardmäßig nach reports/Lint Report <datum>.md, und der Pfad ausgegeben; --markdown
überschreibt weiterhin das Ziel. Gedruckt werden nur Abschnitte mit Befunden, --full druckt
alles, --json druckt die Befunde und schreibt nichts.
Die Skills wurden mitgezogen:wiki-lint und wiki-status sagen jetzt beide, die Datei
zu lesen statt lint erneut aufzurufen. wiki-status Schritt 3 nimmt die Hub-Statistik aus
der Reportdatei, weil sie eine Statistik und kein Befund ist und deshalb nicht mehr in der
gedruckten Zusammenfassung auftaucht.
Nicht umgesetzt:lint ganz vom Budget auszunehmen, der dritte Vorschlag aus Issue #13.
Das Issue selbst verweist die Frage in eine eigene Entscheidung, und der Fall hat sich
verschoben, seit lint eine Datei schreibt.
658 Tests grün, in der normalen und in der gehärteten Umgebung aus Issue #8
(GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null HOME=<leer>). Zwei neue Tests
fielen dort zunächst mit ERROR No author configured for this instance - der dritte und
vierte Fall derselben stillen Umgebungsabhängigkeit; behoben, indem die Tests WIKI_AUTHOR
selbst setzen.
Das Mass-Update Gate hielt an einem 21-Dateien-Changeset, druckte die Aufschlüsselung
nach Bereich und die --confirm-Zeile; der Assistent gab die vollständige Liste wieder und
stoppte. Torbens Freigabe war ein Wort, danach entstand 40adbb7 mit 21 geänderten Dateien,
593 Einfügungen und 73 Löschungen. Verifiziert wurde anschließend gegen das Repository, dass
HEAD gleich origin/main ist, der Baum sauber und VERSION gleich 1.2.0 - nicht gegen
die Erfolgszeile des Werkzeugs.
Die Rückbenennung der Rohdatei lief über git mv mit 100 % Ähnlichkeit, also mit
erhaltener Historie; raw_files: und die **Raw-Dateien:**-Prosazeile der betroffenen
Source-Seite wurden korrigiert, sources rebuild-index baute den Provenance-Index neu,
sources coverage meldete 0 nicht abgedeckte und 0 kaputte Referenzen, lint war über 255
Seiten sauber. Der korrigierte Wert steht seither gequotet im Frontmatter - ohne den zweiten
Fix hätte die Rückbenennung sich beim Schreiben selbst wieder zerlegt.
Issue #14 - die Lücke, die dabei sichtbar wurde: kein wikitool-Befehl schreibt
raw_files: auf einer bestehenden Seite. touch deckt die Felder ab, die die Seite selbst
beschreiben, xref die Seiten-Referenz-Arrays, und raw_files: ist keines von beidem, weil
es auf einen Pfad zeigt und nicht auf einen Seitentitel. Invariante 1 aus AGENTS.md
verbietet die Handeditierung dieses Feldes nicht - es steht in keiner ihrer Aufzählungen -,
aber sie widerspricht dem Kernprinzip, dass Mechanisches das Werkzeug erledigt. Vorgeschlagen
sind sources relink oder, näher am Problem, ein raw rename, das git mv und jede
referenzierende Source-Seite in einem Schritt erledigt: die einzige Form, in der der
Zwischenzustand „Datei weg, Referenz hängt" nie existiert.
Aufgaben
Gitea-Issue #14 - raw rename bzw. sources relink, damit raw_files: auf einer
bestehenden Seite nicht mehr von Hand korrigiert werden muss
Offen und bewusst vertagt: ob lint ganz vom Iteration Budget ausgenommen wird (dritter
Vorschlag aus Issue #13)
Nicht übernommen
Die vollständige Dateiliste des 21-Dateien-Changesets aus der Gate-Ausgabe. Sie ist
Betriebsdetail eines einzelnen Publishes; nach dem Commit trägt sie keine dauerhafte Aussage
mehr, und der Commit selbst ist genannt.
Die beiden Schwestertranskripte derselben Sitzung (Issue-Triage und Label-Schema,
auto-Berechtigungsmodus). Sie werden getrennt eingelesen und bekommen eigene Source-Seiten;
hier stünden sie unbelegt.
Die Gitea-Läufe 62, 63 und 64 als eigene Artefakte. CI-Grün zu einem Zeitpunkt ist ein
Zustand, keine dauerhafte Aussage; die Testzahl und der Umgebungsdefekt sind übernommen.
Die Einzelheiten der 658 Tests. Übernommen sind nur die Gesamtzahl und der Defekt, der
sich daran zeigte.