b138fd8e64
Files changed: - CHANGES.md - VERSION - instructions/dev/corpus-policy.md - instructions/wiki-ingest/SKILL.md - kb/index.md - kb/log.md - kb/sources/COLLECTION.md - kb/sources/INDEX.md - kb/sources/Source - AMD Powermanagement CPU.md - kb/sources/Source - Arch Linux Cheat Sheet.md - kb/sources/Source - Conversation - AGENTS.md Skill Restructuring Session 2026-08-04.md - kb/sources/Source - Conversation - Auto Mode and Tool Choice Session 2026-08-31.md - kb/sources/Source - Conversation - Comma Bug Budget Refund and Lint Report Path Session 2026-08-31.md - kb/sources/Source - Conversation - ENVIRONMENT.md as an Optional Third Session-Level File Session 2026-08-31.md - kb/sources/Source - Conversation - Gate Counting and Measured Calibration Session 2026-08-31.md - kb/sources/Source - Conversation - Hardening the Test Suite Against Silent Environment Dependencies Session 2026-08-31.md - kb/sources/Source - Conversation - Issue Triage Labels and TODO Retirement Session 2026-08-31.md - kb/sources/Source - Conversation - Nightly Drift-Check Workflow and doctor's Bootstrap Gap Session 2026-08-31.md - kb/sources/Source - Conversation - Two Round-Trip Defects Found by an Ingest Session 2026-08-31.md - kb/sources/Source - Conversation - Versioning CI-CD and Content Migration Session 2026-08-30.md - kb/sources/Source - Conversation - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md - kb/sources/Source - Copilot Skill Restructure Instructions.md - kb/sources/Source - Docker Cheatsheet.md - kb/sources/Source - Gitea Issue 41 - Issue Management and Label Scheme 2026-09-02.md - kb/sources/Source - Gitea Issues 62-63 - status-incoming Label Introduction 2026-09-04.md - kb/sources/Source - LLM Improvements Codex Analysis.md - kb/sources/Source - LLM Improvements Production Agent Gaps 2026.md - kb/sources/Source - LLM Improvements Sonnet Analysis.md - kb/sources/Source - LLM Wiki Pattern.md - kb/sources/Source - LLM Wiki v2.md - kb/sources/Source - MCP Read Server Implementation Session 2026-09-02.md - kb/sources/Source - Private-Instance Merge Correction and Issue 30 Session 2026-09-01.md - kb/sources/Source - Public Release, Corpus Purge and History Squash Session 2026-09-01.md - kb/sources/Source - Publish-Remote Gate and Issue Triage Session 2026-09-01.md - kb/sources/Source - Version Part Nomenclature and Breaking Change Gate Session 2026-09-02.md - kb/sources/Source - Wine.md - kb/sources/Source - qmd - GitHub Repository.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 - tools/CONTRACT.md - tools/chemenu/lint_core.py - tools/chemenu/tests/conftest.py - tools/chemenu/tests/test_lint.py - tools/chemenu/tests/test_new_page.py - tools/chemenu/tests/test_provenance.py - tools/chemenu/tests/test_touch.py - tools/chemenu/tests/test_type_resolver.py - tools/chemenu/tests/test_xref.py - types/source.md - types/source.schema.yaml - types/type-spec.md - work/reclassify-source-types/README.md - work/reclassify-source-types/plan.md
145 lines
8.9 KiB
Markdown
145 lines
8.9 KiB
Markdown
---
|
|
type: types/source.md
|
|
source_type: transcript
|
|
author: Claude Code (claude-opus-5)
|
|
raw_files: [raw/notes/Conversation Transcript - Write-Once Frontmatter Fields and touch --set Session 2026-08-31.md]
|
|
source_language: en
|
|
date: 2026-08-31
|
|
tags: [wikitool, cli, frontmatter, touch, schema, idempotenz, gitea]
|
|
entities: [wikitool, Chemenu, Gitea, AGENTS.md]
|
|
concepts: [Write-Once Frontmatter Fields, Denylist over Allowlist]
|
|
summary: '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)'
|
|
---
|
|
# 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
|
|
|
|
- [[wikitool]]
|
|
- [[Chemenu]]
|
|
- [[Gitea]]
|
|
- [[AGENTS.md]]
|
|
|
|
## Verwandte Concepts
|
|
|
|
- [[Denylist over Allowlist]]
|
|
- [[Detect-Repair Asymmetry]]
|
|
- [[Diff-Reviewable Agent Edits]]
|
|
|
|
## Beziehungen
|
|
|
|
|
|
## Siehe auch
|
|
|