Files
chemenu/kb/sources/transcripts/Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md
torben 00220f8b07 backfill: fidelity/authority auf allen 29 Source-Seiten (#67, Publish 2/3)
Files changed:
- kb/index.md
- kb/log.md
- kb/sources/analyses/Source - Copilot Skill Restructure Instructions.md
- kb/sources/analyses/Source - LLM Improvements Codex Analysis.md
- kb/sources/analyses/Source - LLM Improvements Production Agent Gaps 2026.md
- kb/sources/analyses/Source - LLM Improvements Sonnet Analysis.md
- kb/sources/articles/Source - AMD Powermanagement CPU.md
- kb/sources/articles/Source - LLM Wiki Pattern.md
- kb/sources/articles/Source - LLM Wiki v2.md
- kb/sources/documents/Source - qmd - GitHub Repository.md
- kb/sources/notes/Source - Arch Linux Cheat Sheet.md
- kb/sources/notes/Source - Docker Cheatsheet.md
- kb/sources/notes/Source - Wine.md
- kb/sources/trackers/Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02.md
- kb/sources/trackers/Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04.md
- kb/sources/transcripts/Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04.md
- kb/sources/transcripts/Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md
- kb/sources/transcripts/Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30.md
- kb/sources/transcripts/Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md
- kb/sources/transcripts/Source - MCP Read Server Implementation Session 2026-09-02.md
- kb/sources/transcripts/Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md
- kb/sources/transcripts/Source - Public Release, Corpus Purge and History Squash Session 2026-09-01.md
- kb/sources/transcripts/Source - Publish-Remote Gate and Issue Triage Session 2026-09-01.md
- kb/sources/transcripts/Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02.md
- work/backfill-capture-fields/README.md
- work/backfill-capture-fields/plan.md
2026-09-09 06:50:01 +02:00

8.9 KiB

type, source_type, author, raw_files, source_language, date, tags, entities, concepts, summary, fidelity, authority
type source_type author raw_files source_language date tags entities concepts summary fidelity authority
types/source.md transcript Claude Code (claude-opus-5)
raw/notes/Conversation Transcript - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md
en 2026-08-31
wikitool
cli
frontmatter
touch
schema
idempotenz
gitea
wikitool
Chemenu
Gitea
AGENTS.md
Write-Once Frontmatter Fields
Denylist over Allowlist
Sitzung, die write-once-Frontmatterfelder reparierbar macht: touch bekommt --set/--add/--remove ueber eine Denylist statt einer Allowlist, ein idempotentes --remove und einen bewusst engen Scope (Stack 1.4.0, Gitea-Issue #14) verbatim reporting

Source: Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31

Autor: Claude Code (claude-opus-5)
Datum: 2026-08-31
Raw-Dateien: raw/notes/Conversation Transcript - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md
Typ: Notes

Zusammenfassung

Das Transkript ist eine zusammenfassende Rekonstruktion der Sitzung, kein wörtliches Protokoll. Die zitierten Befehlsausgaben sind echt, Torbens drei Entwurfsentscheidungen sind samt der ihm vorgelegten Optionen festgehalten, die Begründungen des Assistenten sind verdichtet. Es ist eines von zwei Transkripten dieses Sitzungsabschnitts; das zweite behandelt die Zählregel des Mass-Update Gate und die gemessene Kalibrierung des Iteration Budget und wird getrennt eingelesen.

Gegenstand ist Gitea-Issue #14, ausgeliefert als touch --set/--add/--remove in Stack-Version 1.4.0 (Commit dbe2f73, 9 Dateien, 674 Tests grün). Der Defekt, den es schließt: ein Feld, das new einmal geschrieben hat, war danach nicht mehr erreichbar. touch kannte nur die Felder modified, summary, provenance und confidence_base; Handeditierung ist genau das, was der Stack verhindern soll; Löschen und Neuanlegen zerreißt jede bestehende Referenz auf die Seite; und new ist nicht idempotent, das Zeitfenster für den richtigen Wert war also genau einen Befehl breit.

Den bleibenden Wert der Sitzung tragen drei Entscheidungen, die Torben mit ausgewiesenen Trade-offs vorgelegt wurden: Denylist statt Allowlist für die schreibbaren Felder, Ersetzen plus --add/--remove für Listenfelder, und ein bewusst enger Auslieferungsschnitt, der raw rename als Issue #16 abspaltet.

Kernaussagen

  • Die Vorarbeit lag schon im Code. validate_fields() in touch.py validiert pro Feld statt pro Dokument - genau die Form, die ein --set braucht. Der Grund steht im Docstring: eine Validierung über das ganze Dokument würde sich weigern, modified: auf einer Seite zu bumpen, die aus einem unbeteiligten Grund ungültig ist, also auf der Seite, die Wartung am dringendsten braucht.
  • Entscheidung 1 - Denylist statt Allowlist. Schreibbar ist alles, was das Schema für den Seitentyp deklariert, abzüglich einer kurzen begründeten Sperrliste. Das Argument, das den Ausschlag gab: eine gepflegte Allowlist ist eine zweite Kopie des Schemas, und die Kopie ist die Seite, die driftet - Invariante 8 aus AGENTS.md, angewandt auf eine Konstante. Der Preis der Allowlist wäre gewesen, dass jedes neue Schema-Feld eine Codeänderung braucht.
  • Gesperrt sind vier Gruppen, jede mit dem Befehl benannt, dem das Feld gehört: type: ändert Schema und Verzeichnis der Seite und gehört nach page-lifecycle.md; confidence: ist aus confidence_base abgeleitet und nicht autorisiert; related:, sources:, entities: und concepts: gehören xref, weil ein blanker Frontmatter-Schreibvorgang die Gegenrichtung und die Body-Bullets stehen ließe.
  • Entscheidung 2 - Ersetzen plus --add/--remove. Reines Ersetzen wäre eine Regel gewesen, hätte aber verlangt, für ein einzelnes Tag die ganze Liste zu nennen. Der Preis der gewählten Variante sind drei Optionen statt einer.
  • Die Teilfrage, was --remove mit einem nicht vorhandenen Element tut, entschied der Assistent selbst und wies das aus: es gelingt und wird gemeldet. Idempotent wie xref remove, weil ein Reparaturbefehl, der sich beim zweiten Lauf verweigert, nicht skriptbar ist - aber nie stillschweigend, weil ein stiller No-op genauso aussieht wie eine gelungene Entfernung, und genau so verbirgt sich ein vertippter Elementname.
  • Entscheidung 3 - enger Schnitt. Nur touch --set; die Dateiverschiebung bleibt zweistufig (git mv, dann touch --set raw_files=…). Die Alternative, raw rename mitzuliefern, hätte Issue #14 vollständig geschlossen und den Zwischenzustand vermieden, zum Preis von size/M: Rückwärtssuche über alle raw_files:-Referenzen, Verhalten bei mehreren Besitzern, Contract-Zeilen für zwei Befehle. raw rename wurde Issue #16 (prio/2, size/S).
  • Zwei Kommandos, eine Implementierung. _coerce_set_value, _parse_set_fields und _check_raw_files_exist wanderten aus new_page.py nach commands/_util.py und verloren ihren führenden Unterstrich. Ohne das hätte touch --set den Komma-Defekt aus Issue #12 am ersten Tag geerbt; ein Test deckt genau diesen Fall ab, mit einer Rohdatei, deren Name ein Komma enthält, referenziert über \, und als ein Pfad zurückgelesen.
  • Der Existenzcheck für raw_files: gilt auch für touch, identisch zu dem, den new ausführt. Er ist I/O und keine Datenform, also kann kein Schema ihn ausdrücken.
  • Die beiden Ablehnungen sind bewusst unterschiedlich formuliert. Ein gesperrtes Feld ist ein Routing-Problem, die Meldung nennt deshalb den zuständigen Befehl. Ein unbekanntes Feld ist ein Tippfehler oder der falsche Seitentyp, die Meldung listet deshalb auf, welche Felder die Seite tatsächlich hat - der Nutzwert liegt darin, zu erfahren, dass tags gemeint war.
  • Eine Falle im Testaufbau, einmal beseitigt. test_touch.py rief den Typer-Callback direkt mit vollständiger Argumentliste auf; drei neue Optionen brachen sieben Aufrufstellen mit TypeError: 'OptionInfo' object is not iterable, weil ein direkt aufgerufener Callback für jedes ausgelassene Argument ein OptionInfo-Objekt bekommt. Die Tests laufen jetzt über einen _touch(**overrides)-Helper, der jede Option belegt; die nächste Option kostet eine Zeile statt sieben.
  • Der Beleg am realen Korpus: Diff-Reviewable Agent Edits war Stunden zuvor von einem Ingest angelegt worden, dessen --set tags=-Wert ein Komma am Ende trug, worauf alles hinter dem Trennzeichen verlorenging. Der Subagent hatte alle drei Auswege korrekt geprüft und verworfen - touch konnte tags: nicht setzen, Handeditierung kommt Invariante 1 zu nahe, rm plus new hätte die concepts:-Referenz der Source-Seite zerrissen. Die Seite behielt [agent-workflow] dauerhaft, wegen eines Kommas. Mit touch --add trägt sie jetzt [agent-workflow, context-engineering, tooling].
  • Der zweite Aufruf desselben --add meldete "already up to date; nothing to change", der --remove eines nicht vorhandenen Elements meldete "not present, nothing removed" und endete ebenfalls erfolgreich - die zugesagte Idempotenz, an der Kommandozeile gezeigt.
  • Dass dies eine Rate und kein Einzelfall war: drei Fehlschläge in drei aufeinanderfolgenden Ingests desselben Tages, an zwei verschiedenen Feldern, von drei verschiedenen Agenten. Einer davon war ein nachgestelltes Komma.
  • Ergebnis: 1.4.0 als MINOR (neue Fähigkeit, rückwärtskompatibel), Commit dbe2f73 über 9 Dateien, 674 Tests grün in der normalen und in der gehärteten Umgebung, Issue #14 geschlossen mit den drei Entscheidungen im Protokoll, Issue #16 eröffnet.

Aufgaben

  • Gitea-Issue #16 - raw rename, das git mv und jede referenzierende Source-Seite in einem Schritt erledigt (prio/2, size/S)

Nicht übernommen

  • Die Modul- und Funktionsnamen der Testumbauten über den _touch-Helper hinaus. Der Umbau selbst ist eine dauerhafte Aussage über die Testschnittstelle, die einzelnen sieben Aufrufstellen sind es nicht.
  • Der vollständige Wortlaut der beiden Fehlermeldungen. Übernommen ist die Entwurfsregel dahinter - Routing-Problem nennt den Befehl, Tippfehler nennt die vorhandenen Felder -, weil der Wortlaut sich ändern kann und die Regel nicht.
  • Das Schwestertranskript desselben Sitzungsabschnitts (Zählregel des Mass-Update Gate, gemessene Kalibrierung des Iteration Budget). Es wird getrennt eingelesen und bekommt eine eigene Source-Seite; hier stünde es unbelegt.
  • Die Einzelheiten der 674 Tests. Übernommen sind die Gesamtzahl und die Testfalle, die sich daran zeigte.
  • Issue #14 als eigene Seite. Es ist geschlossen, und sein Ergebnis steht auf wikitool, Write-Once Frontmatter Fields und Detect-Repair Asymmetry.

Verwandte Entities

Verwandte Concepts

Beziehungen

Siehe auch