raw/notes/Conversation Transcript - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md
en
2026-08-31
wikitool
cite
xref
footnotes
schema
tests
gitea
wikitool
Chemenu
Gitea
Command Round-Trip Integrity
Green Suite Blind Spot
Detect-Repair Asymmetry
Write-Once Frontmatter Fields
Denylist over Allowlist
Sitzung, die zwei Datenintegritaetsdefekte in wikitool findet und behebt: cite add loeschte Inhalt hinter dem Fussnotenblock (1.5.1, #17) und die Ref-Arrays einer Source-Seite waren unerreichbar (1.6.0, #18) - beide unter vollstaendig gruener Testsuite
verbatim
reporting
Source: Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31
Autor: Claude Code (claude-opus-5) Datum: 2026-08-31 Raw-Dateien: raw/notes/Conversation Transcript - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md Typ: Notes
Zusammenfassung
Das Transkript ist eine zusammenfassende Rekonstruktion der Sitzung, kein wörtliches Protokoll;
die zitierten Befehlsausgaben und die gemessenen Zahlen sind echt. Gegenstand sind zwei
Datenintegritätsdefekte in wikitool, beide am 2026-08-31 gefunden und am selben Tag
behoben. Der erste: cite add löschte jeden Inhalt hinter dem Fußnotenblock (Gitea-Issue #17,
Stack 1.5.1, Commit bb4123b). Der zweite: die Referenz-Arrays einer Source-Seite waren nach
dem Anlegen unerreichbar, während xref add dort ein undeklariertes related: schrieb, das
xref remove nicht mehr räumen konnte (Issue #18, 1.6.0, Commit ce03749). Beide waren
prio/1.
Beide Befunde stammen aus einem Ingest: ein Subagent meldete, worauf er gestoßen war. Der
Bericht wurde nicht übernommen, sondern am Code nachgestellt, und die Prüfung erweiterte den
Umfang beide Male. Zwischen Befund und Reparatur lagen zwei Issues - was offen ist, gehört in
den Tracker, bevor Code angefasst wird.
Die Verallgemeinerung, die die Sitzung über sich selbst zieht, ist die dauerhaftere Aussage:
beide Defekte lebten unter einer vollständig grünen Testsuite, weil nie ein Test das falsche
Verhalten festgehalten hatte. Eine Suite prüft, wovon sie weiß.
Kernaussagen
Defekt 1, der Mechanismus.split_cite_block() nahm alles von der Überschrift
## Fußnoten bis zum Dateiende als Block und behielt daraus nur die Zitatdefinitionszeilen; jeder
Aufrufer setzte die Seite anschließend als head + gerenderter Block wieder zusammen. Da
xref add seine Abschnitte ans Dateiende hängt, entschied allein die Reihenfolge der beiden
Kommandos, ob eine Seite ihre Querverweise behielt.
Der Umfang wurde gemessen, nicht geschätzt: 8 Seiten mit zusammen 74 Zeilen standen in
der gefährdeten Position, Detect-Repair Asymmetry mit 14 Zeilen am schlimmsten. Der
laufende zweite Ingest wurde an dieser Stelle angehalten, weil er cite add auf Seiten aus
genau dieser Liste aufgerufen hätte.
Zwei weitere Befehle waren betroffen, die das Issue nicht genannt hatte.rename
benutzt denselben Codepfad und hätte denselben Inhalt gelöscht. Und eine Fußnotenreferenz, die nur in
einem Abschnitt hinter dem Block stand, galt als unreferenziert, worauf
cite sync seine Definition als verwaist gelöscht hätte - ein zweiter Verlustpfad mit
derselben Ursache.
Der Fix macht die Seite selbstheilend. Der Block endet jetzt an der nächsten Überschrift
statt am Dateiende, alles dahinter wird auf den Kopf zurückgefaltet, und der gerenderte Block
wird immer zuletzt ausgegeben. Damit bringt die erste Zitatoperation eine verrutschte Seite
von selbst wieder in Ordnung, und xref add darf weiter am Dateiende anhängen: der
Widerspruch zwischen beiden Kommandos ist aufgelöst statt umgangen.
Loser Text im Block wird gerettet, nicht abgelehnt. Das dritte Akzeptanzkriterium des
Issues verlangte einen Abbruch. Das wurde mit Begründung abgelehnt: derselbe Codepfad läuft
unter lint und corpus_diff, wo eine Ausnahme das Lesen der Seite verweigern würde,
statt den Befund zu melden.
Der Test wurde rot bewiesen, bevor ihm geglaubt wurde. Statt zu behaupten, der neue Test
hätte den Defekt gefangen, wurde die alte Implementierung rekonstruiert und gegen ihn laufen
gelassen: ALTER Code -> Beziehungen erhalten: False, NEUER Code -> Beziehungen erhalten: True.
Der Korpus wurde repariert und nachgemessen.cite sync --all normalisierte elf Seiten -
die acht gefährdeten plus drei, die nur neu sortiert werden mussten. Danach: 0 Seiten mit
Inhalt hinter dem Block, bei je Seite unveränderter Zahl an Zitatdefinitionen und Bullets.
Die Zeilendifferenz im Diff kam vom neu umbrochenen summary:, nicht von verlorenem Inhalt.
Defekt 2, drei Symptome mit einer Ursache.xref_link_source schrieb nur die Zielseiten
und nie die eigenen Arrays der Source-Seite. types/source.md deklariert
page_ref_fields: [entities, concepts], das von xref add dort geschriebene related: war
also undeklariert. Und strip_frontmatter_ref() räumte nur deklarierte Felder. Ein Kommando
erzeugte damit einen Zustand, den ein anderes nicht rückgängig machen konnte.
Die Feldwahl folgt der Collection, nicht einer Tabelle.kb/entities/ bekommt
entities:, kb/concepts/ bekommt concepts:; das Verzeichnis ist der Feldname. Eine
neue Collection braucht hier deshalb keine Codeänderung, sondern einen Typ, der das passende
Feld deklariert. Eine Typ-zu-Feld-Zuordnung wurde genau deswegen verworfen: sie wäre eine
zweite Kopie dessen, was die Type-Specs bereits sagen.
xref add prüft beide Seiten, bevor es eine schreibt, damit eine Ablehnung keine halbe
Verknüpfung hinterlässt; die Meldung nennt die Felder, die der Typ tatsächlich deklariert.
xref remove fegt undeklarierte Reste mit Feldnamen aus den Type-Specs und löscht den
Schlüssel ganz, sobald er leer ist - related: [] würde die Seite weiter an der Validierung
scheitern lassen.
Der Beleg, dass die beiden Kommandos Inversen sind: die referenzierende Concept-Seite kam
byteidentisch aus dem Zyklus zurück, nachdem xref remove die Rückreferenz beidseitig
geräumt und xref link-source sie exakt wiederhergestellt hatte. Repariert wurde
ausschließlich mit dem Werkzeug, ohne rm --yes und ohne Handeditierung von Frontmatter.
Die Denylist aus 1.4.0 war richtig, ihr Verweisziel nicht. Sie lehnte
Seiten-Referenz-Felder mit dem Hinweis ab, xref add und xref remove seien dafür zuständig -
eine ungeprüfte Behauptung über die Fähigkeiten eines anderen Kommandos, und für genau die
Felder einer Source-Seite falsch. Eine Ablehnung, die auf ein anderes Kommando verweist,
gehört mit einem Test ausgeliefert, der zeigt, dass jenes Kommando den Fall abdeckt.
Beide Defekte lebten unter einer vollständig grünen Suite. 678 Tests waren grün, bevor
die Zitat-Tests geschrieben wurden; 67 Gate-Tests waren grün vor der Zählungsänderung
desselben Tages. In keinem der beiden Fälle hatte je ein Test das falsche Verhalten
festgehalten, und genau so hat es überlebt. Der Befund stützt die Prämisse von Gitea-Issue #8.
Ein Bericht aus zweiter Hand wurde nachgestellt statt übernommen. Die Befunde des
Subagenten wurden am Code nachvollzogen, bevor irgendetwas geändert wurde, und die Prüfung
erweiterte den Umfang zweimal: beim ersten Defekt um rename und den cite sync-Verlustpfad,
beim zweiten um die Feststellung, dass xref remove das undeklarierte Feld gar nicht
erreichen konnte.
Beide Befunde wurden als Issues abgelegt, bevor Code angefasst wurde (#17, #18), nach
instructions/capture-session.md: was noch offen ist, gehört in den Tracker und nicht in ein
Transkript oder in jemandes Kopf.
Ergebnis:1.5.1 als PATCH und 1.6.0 als MINOR, Commits bb4123b und ce03749, 689
Tests grün in der normalen und in der gehärteten Umgebung (11 neue), 8 Seiten entschärft und
normalisiert, der Schema-Fehler auf main repariert, Issues #17 und #18 geschlossen.
Aufgaben
Gitea-Issue #8 - die Prämisse „eine Suite prüft nur, wovon sie weiß" ist mit dieser
Sitzung belegt; das Issue selbst bleibt offen
Nicht übernommen
Die Liste der acht gefährdeten Seiten. Übernommen sind die Zahl, die Zeilensumme und die
am stärksten betroffene Seite. Die Liste beschreibt einen Zustand, den cite sync --all im
selben Lauf beseitigt hat, und wäre ab dem Reparaturcommit falsch.
Der Wortlaut der Ablehnungsmeldung von xref add. Übernommen ist die Entwurfsregel
dahinter - beide Seiten prüfen, bevor eine geschrieben wird, und auf das zuständige Kommando
routen -, weil der Wortlaut sich ändern kann und die Regel nicht.
Die Einzelheiten der elf neuen Tests. Übernommen sind die Gesamtzahl 689 und die
Vorgehensweise, den Test gegen die rekonstruierte alte Implementierung rot zu beweisen.
Die interne Modul- und Funktionsstruktur über split_cite_block(), xref_link_source()
und strip_frontmatter_ref() hinaus. Diese drei tragen die Erklärung des Defekts; die
übrigen Aufrufstellen sind Implementierungsdetail und ändern sich.