Chemenu 2.1.0 - deterministischer Wissenskompiler
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.
This commit is contained in:
+146
@@ -0,0 +1,146 @@
|
||||
---
|
||||
type: types/source.md
|
||||
source_type: notes
|
||||
author: Claude Code (claude-opus-5)
|
||||
raw_files: [raw/notes/Conversation Transcript - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md]
|
||||
source_language: en
|
||||
date: 2026-08-31
|
||||
tags: [wikitool, cite, xref, footnotes, schema, tests, gitea]
|
||||
entities: [wikitool, Chemenu, Gitea]
|
||||
concepts: [Command Round-Trip Integrity, Green Suite Blind Spot, Detect-Repair Asymmetry, Write-Once Frontmatter Fields, Denylist over Allowlist]
|
||||
summary: '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'
|
||||
---
|
||||
# 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.
|
||||
- **Issues #17 und #18 als eigene Seiten.** Beide sind geschlossen; ihr Ergebnis steht auf
|
||||
[[wikitool]], [[Command Round-Trip Integrity]] und [[Green Suite Blind Spot]].
|
||||
|
||||
## Verwandte Entities
|
||||
|
||||
- [[wikitool]]
|
||||
- [[Chemenu]]
|
||||
- [[Gitea]]
|
||||
|
||||
## Verwandte Concepts
|
||||
|
||||
- [[Command Round-Trip Integrity]]
|
||||
- [[Green Suite Blind Spot]]
|
||||
- [[Detect-Repair Asymmetry]]
|
||||
- [[Write-Once Frontmatter Fields]]
|
||||
- [[Denylist over Allowlist]]
|
||||
Reference in New Issue
Block a user