Kommando-Datensätze: Text widerspricht dem Code (Sammelbefund aus #142) #146

Closed
opened 2026-09-26 06:48:06 +00:00 by torben · 3 comments
Owner

Erledigt (2026-09-26). Alle Abweichungen zwischen cli_contract-Datensatz und Code, die beim redaktionellen Umbau in #142 aufgefallen sind, sind entschieden – in jedem Fall zugunsten des Codes – und am Text angeglichen. Kein Verhalten hat sich geändert. Ausgeliefert in 8d5fc6e (7.1.0-beta.25) und 8f61209 (7.1.0-beta.26, Nachschärfung des Tests). Größere Einzelbefunde aus #142 haben eigene Issues (#144 network:, #145 log append --body-file, #147 Traceback nach Budget-Gate-Verweigerung, #148 Hilfe-Patch in cli.py).

Entscheidungen

D1 – lint: Einheit des Zitatlimits. Der Code gilt. Er zählt Zitatblöcke (lint_core.count_quote_blocks, QUOTE_LIMIT = 2): Eine Folge zusammenhängender >-Zeilen ist ein Zitat, und Code wird vorher ausgeblendet. Die Einheit hat #22 bewusst gewechselt, weil die Zeilenzählung die Umbruchbreite maß und nicht die Menge fremden Wortlauts. Veraltet waren zwei Stellen. Die eine ist die normative in kb/CONTRACT.md § Quotation cap („At most 2 blockquoted lines per page“), die erst bei der Prüfung für dieses Issue aufgefallen ist. Die andere sind die NOTES im lint-Datensatz. Beide nennen jetzt das Zitat als Einheit. kb/CONTRACT.md erklärt zusätzlich, was ein Zitat ist und dass die Regel nicht die Länge eines umbrochenen Zitats misst.

D2 – docs contract: fehlende Exit-1-Ursache (Nachtrag aus #143). Der Code gilt. contract_command bricht mit fail() ab, wenn tools/CONTRACT.md fehlt, und das ist richtig: Die Datei trägt handgeschriebene Prosa um die Region herum, eine neu angelegte Datei wäre ein stiller Verlust. Der Datensatz hatte failures=(). Er führt jetzt die Ursache „tools/CONTRACT.md is missing“ mit der Reaktion „Not transient - restore the file, which carries hand-written prose around the region this command does not generate, then retry“. Der Index zeigt exit:0,1, und fail() zeigt diese Reaktion statt der see:-Zeile.

D3 – xref add, atomic. Der Code gilt. Der Text beschrieb zwei Schreibvorgänge (A, dann B) und zwei Verweigerungen. Der Code schreibt nur A, die eigenen NOTES sagen „B is not touched“, und es gibt drei Verweigerungen, die alle vor dem Schreiben liegen. Jetzt steht dort: „Yes - a single write to A; B is never touched, and every refusal happens before it“. xref remove („writes A then B“) stimmt und blieb unverändert.

D4 – publish, atomic: die Korrektur aus #142 präzisiert. Der Code gilt. Die Aussage „every gate runs before staging“ stimmte nur für den Normalpfad. Beim einen Retry eines abgewiesenen Push kann das Rebase-Review-Gate mit 42 abbrechen, nachdem der lokale Commit schon existiert. Das Verhalten ist richtig: Gepusht wird nichts, und der Wiederholungsaufruf mit --confirm-rebase pusht den liegengebliebenen Commit. Der Text nennt diese Ausnahme jetzt.

Bestätigt – bleibt wie von #142 angeglichen

  • dist upgrade, gleiche Quellversion → Exit 0 (9d6ca6b): success("Already at … Nothing to do.") nach den lokalen Vorbedingungen.
  • dist upgrade, atomic: „Yes for every refusal“ (9d6ca6b): Jedes fail() und der --dry-run-Rücksprung liegen vor dem ersten shutil.copy2.
  • log status: fehlende Datei „reported as nothing logged“ (df8ff2f): success("No kb/log.md yet; nothing logged.").
  • xref add: „A's type declares no related: field“ (a1f3c47): Nur A wird geprüft. Das ist richtig, weil B nicht geschrieben wird.
  • docs toc, Index exit:0: Weder toc_command noch toc.py ruft fail() oder wirft eine Ausnahme.
  • publish, atomic: „every gate“ (fd0f60b): nicht bestätigt, durch D4 ersetzt.

Akzeptanzkriterien

  • Weder kb/CONTRACT.md noch der lint-Datensatz noch die generierte tools/CONTRACT.md spricht von „blockquoted lines“. grep -rn "blockquoted lines" findet nur noch den historischen CHANGES-Eintrag aus #142.
  • tools/CONTRACT.md zeigt für docs contract die neue EXIT-STATUS-Zeile, -h rendert aus demselben Datensatz.
  • Ein Test belegt, dass docs contract ohne tools/CONTRACT.md mit Exit 1 und dem ON-FAILURE-Text aus D2 endet: test_cli.py::test_stderr_hint_follows_the_error_line_when_streams_are_merged. Der erste Stand in 8d5fc6e verglich nur gegen render_failure_hint() desselben Datensatzes und wäre auch ohne die Ursache grün geblieben, weil beide Seiten auf dieselbe see:-Zeile zurückfallen. 8f61209 prüft die Kopfzeile und die Ursache wörtlich. Gegenprobe: Mit failures=() schlägt der Test fehl. Den see:-Fallback selbst deckt weiterhin test_cli_contract.py::test_render_failure_hint_falls_back_to_a_bare_pointer ab.
  • Der atomic-Text von xref add nennt einen einzigen Schreibvorgang und keine Schreibung von B.
  • Der atomic-Text von publish nennt den Retry-Pfad als Ausnahme.
  • Geprüft: docs verify, instructions verify und die volle pytest-Suite (1540 Tests) waren vor beiden Publishes grün. CI grün: Läufe 412/413 für 8d5fc6e, 414/415 für 8f61209.

Bewusst nicht gemacht

  • Bei den übrigen acht Datensätzen mit failures=() wurde nur nach direkten fail()- und needs_clearance()-Aufrufen im Kommandokörper gesucht; der einzige Treffer war docs contract. Ob die acht über Hilfsfunktionen scheitern können, ist nicht geprüft.
  • xref add führt einen OSError beim Schreiben (fail(f"Failed to write …")) nicht als Ursache. Das gehört zur Klasse „Schreibfehler“, die #142 nur bei rename, rm, move und cite sync ergänzt hat. Ein Sweep über alle schreibenden Kommandos ist ein eigenes Thema und gehört nicht in diesen Sammelbefund.

Ablauf

Den Entwurf (Prüfung am Code, Entscheidungen D1–D4, Plan) hat Claude Opus 5.5 gemacht. Die mechanische Umsetzung in 8d5fc6e (Code, Test, Bump auf beta.25, CHANGES-Eintrag) lief auf Claude Sonnet 5. Den Abschluss hat wieder Claude Opus 5.5 übernommen. Beim Gegenlesen fielen dabei der tautologische Test und drei ungenaue Aussagen im CHANGES-Eintrag auf („Four more“ neben dem Titel „three more“, „source-page edge“, „after the commit already landed“). Beides ist in 8f61209 (beta.26) korrigiert.

**Erledigt (2026-09-26).** Alle Abweichungen zwischen `cli_contract`-Datensatz und Code, die beim redaktionellen Umbau in #142 aufgefallen sind, sind entschieden – **in jedem Fall zugunsten des Codes** – und am Text angeglichen. Kein Verhalten hat sich geändert. Ausgeliefert in `8d5fc6e` (7.1.0-beta.25) und `8f61209` (7.1.0-beta.26, Nachschärfung des Tests). Größere Einzelbefunde aus #142 haben eigene Issues (#144 `network:`, #145 `log append --body-file`, #147 Traceback nach Budget-Gate-Verweigerung, #148 Hilfe-Patch in `cli.py`). ## Entscheidungen **D1 – `lint`: Einheit des Zitatlimits. Der Code gilt.** Er zählt Zitat*blöcke* (`lint_core.count_quote_blocks`, `QUOTE_LIMIT = 2`): Eine Folge zusammenhängender `>`-Zeilen ist ein Zitat, und Code wird vorher ausgeblendet. Die Einheit hat #22 bewusst gewechselt, weil die Zeilenzählung die Umbruchbreite maß und nicht die Menge fremden Wortlauts. Veraltet waren zwei Stellen. Die eine ist die normative in `kb/CONTRACT.md` § Quotation cap („At most 2 blockquoted lines per page“), die erst bei der Prüfung für dieses Issue aufgefallen ist. Die andere sind die NOTES im `lint`-Datensatz. Beide nennen jetzt das Zitat als Einheit. `kb/CONTRACT.md` erklärt zusätzlich, was ein Zitat ist und dass die Regel nicht die Länge eines umbrochenen Zitats misst. **D2 – `docs contract`: fehlende Exit-1-Ursache (Nachtrag aus #143). Der Code gilt.** `contract_command` bricht mit `fail()` ab, wenn `tools/CONTRACT.md` fehlt, und das ist richtig: Die Datei trägt handgeschriebene Prosa um die Region herum, eine neu angelegte Datei wäre ein stiller Verlust. Der Datensatz hatte `failures=()`. Er führt jetzt die Ursache „`tools/CONTRACT.md` is missing“ mit der Reaktion „Not transient - restore the file, which carries hand-written prose around the region this command does not generate, then retry“. Der Index zeigt `exit:0,1`, und `fail()` zeigt diese Reaktion statt der `see:`-Zeile. **D3 – `xref add`, `atomic`. Der Code gilt.** Der Text beschrieb zwei Schreibvorgänge (A, dann B) und zwei Verweigerungen. Der Code schreibt nur A, die eigenen NOTES sagen „B is not touched“, und es gibt drei Verweigerungen, die alle vor dem Schreiben liegen. Jetzt steht dort: „Yes - a single write to A; B is never touched, and every refusal happens before it“. `xref remove` („writes A then B“) stimmt und blieb unverändert. **D4 – `publish`, `atomic`: die Korrektur aus #142 präzisiert. Der Code gilt.** Die Aussage „every gate runs before staging“ stimmte nur für den Normalpfad. Beim einen Retry eines abgewiesenen Push kann das Rebase-Review-Gate mit 42 abbrechen, nachdem der lokale Commit schon existiert. Das Verhalten ist richtig: Gepusht wird nichts, und der Wiederholungsaufruf mit `--confirm-rebase` pusht den liegengebliebenen Commit. Der Text nennt diese Ausnahme jetzt. ## Bestätigt – bleibt wie von #142 angeglichen - [x] **`dist upgrade`, gleiche Quellversion → Exit 0** (`9d6ca6b`): `success("Already at … Nothing to do.")` nach den lokalen Vorbedingungen. - [x] **`dist upgrade`, `atomic`: „Yes for every refusal“** (`9d6ca6b`): Jedes `fail()` und der `--dry-run`-Rücksprung liegen vor dem ersten `shutil.copy2`. - [x] **`log status`: fehlende Datei „reported as nothing logged“** (`df8ff2f`): `success("No kb/log.md yet; nothing logged.")`. - [x] **`xref add`: „A's type declares no `related:` field“** (`a1f3c47`): Nur A wird geprüft. Das ist richtig, weil B nicht geschrieben wird. - [x] **`docs toc`, Index `exit:0`**: Weder `toc_command` noch `toc.py` ruft `fail()` oder wirft eine Ausnahme. - [x] ~~**`publish`, `atomic`: „every gate“**~~ (`fd0f60b`): nicht bestätigt, durch D4 ersetzt. ## Akzeptanzkriterien - [x] Weder `kb/CONTRACT.md` noch der `lint`-Datensatz noch die generierte `tools/CONTRACT.md` spricht von „blockquoted lines“. `grep -rn "blockquoted lines"` findet nur noch den historischen CHANGES-Eintrag aus #142. - [x] `tools/CONTRACT.md` zeigt für `docs contract` die neue EXIT-STATUS-Zeile, `-h` rendert aus demselben Datensatz. - [x] Ein Test belegt, dass `docs contract` ohne `tools/CONTRACT.md` mit Exit 1 und dem ON-FAILURE-Text aus D2 endet: `test_cli.py::test_stderr_hint_follows_the_error_line_when_streams_are_merged`. Der erste Stand in `8d5fc6e` verglich nur gegen `render_failure_hint()` desselben Datensatzes und wäre auch ohne die Ursache grün geblieben, weil beide Seiten auf dieselbe `see:`-Zeile zurückfallen. `8f61209` prüft die Kopfzeile und die Ursache wörtlich. Gegenprobe: Mit `failures=()` schlägt der Test fehl. Den `see:`-Fallback selbst deckt weiterhin `test_cli_contract.py::test_render_failure_hint_falls_back_to_a_bare_pointer` ab. - [x] Der `atomic`-Text von `xref add` nennt einen einzigen Schreibvorgang und keine Schreibung von B. - [x] Der `atomic`-Text von `publish` nennt den Retry-Pfad als Ausnahme. - [x] Geprüft: `docs verify`, `instructions verify` und die volle `pytest`-Suite (1540 Tests) waren vor beiden Publishes grün. CI grün: Läufe 412/413 für `8d5fc6e`, 414/415 für `8f61209`. ## Bewusst nicht gemacht - Bei den übrigen acht Datensätzen mit `failures=()` wurde nur nach *direkten* `fail()`- und `needs_clearance()`-Aufrufen im Kommandokörper gesucht; der einzige Treffer war `docs contract`. Ob die acht über Hilfsfunktionen scheitern können, ist nicht geprüft. - `xref add` führt einen `OSError` beim Schreiben (`fail(f"Failed to write …")`) nicht als Ursache. Das gehört zur Klasse „Schreibfehler“, die #142 nur bei `rename`, `rm`, `move` und `cite sync` ergänzt hat. Ein Sweep über alle schreibenden Kommandos ist ein eigenes Thema und gehört nicht in diesen Sammelbefund. ## Ablauf Den Entwurf (Prüfung am Code, Entscheidungen D1–D4, Plan) hat Claude Opus 5.5 gemacht. Die mechanische Umsetzung in `8d5fc6e` (Code, Test, Bump auf beta.25, CHANGES-Eintrag) lief auf Claude Sonnet 5. Den Abschluss hat wieder Claude Opus 5.5 übernommen. Beim Gegenlesen fielen dabei der tautologische Test und drei ungenaue Aussagen im CHANGES-Eintrag auf („Four more“ neben dem Titel „three more“, „source-page edge“, „after the commit already landed“). Beides ist in `8f61209` (beta.26) korrigiert.
torben added the prio/plannedsize/Sarea/processkind/defect labels 2026-09-26 06:48:06 +00:00
Author
Owner

Nachtrag (aus #143, 2026-09-26): docs contract trägt failures=(), sein Code ruft aber fail(f"{rel_path(CLI_README)} is missing."), wenn tools/CONTRACT.md fehlt (docs_verify.py, contract_command). Die Ursache fehlt also in EXIT STATUS und ON FAILURE; im Index steht exit:0. Nach #143 zeigt fail() für dieses Kommando nur die see:-Zeile als Rückfall. Bitte in den Sammelbefund aufnehmen, falls der Body ihn noch nicht führt.

**Nachtrag (aus #143, 2026-09-26):** `docs contract` trägt `failures=()`, sein Code ruft aber `fail(f"{rel_path(CLI_README)} is missing.")`, wenn `tools/CONTRACT.md` fehlt (`docs_verify.py`, `contract_command`). Die Ursache fehlt also in EXIT STATUS und ON FAILURE; im Index steht `exit:0`. Nach #143 zeigt `fail()` für dieses Kommando nur die `see:`-Zeile als Rückfall. Bitte in den Sammelbefund aufnehmen, falls der Body ihn noch nicht führt.
Author
Owner

Changelog: Alle Punkte am Code geprüft und entschieden, jedes Mal gilt der Code. Neu im Body: D1 nennt jetzt auch kb/CONTRACT.md § Quotation cap, weil dort dieselbe veraltete Einheit steht. Außerdem D2 (docs contract, Nachtrag aus dem Kommentar oben), D3 (xref add atomic, neu gefunden) und D4 (publish atomic: die Korrektur aus #142 gilt nicht für den Push-Retry-Pfad). Fünf der sechs Angleichungen sind bestätigt, die sechste ist durch D4 ersetzt. Umsetzungsplan, prüfbare Akzeptanzkriterien und die Abgrenzung „Nicht im Umfang“ sind ergänzt.

**Changelog:** Alle Punkte am Code geprüft und entschieden, jedes Mal gilt der Code. Neu im Body: D1 nennt jetzt auch `kb/CONTRACT.md` § Quotation cap, weil dort dieselbe veraltete Einheit steht. Außerdem D2 (`docs contract`, Nachtrag aus dem Kommentar oben), D3 (`xref add` `atomic`, neu gefunden) und D4 (`publish` `atomic`: die Korrektur aus #142 gilt nicht für den Push-Retry-Pfad). Fünf der sechs Angleichungen sind bestätigt, die sechste ist durch D4 ersetzt. Umsetzungsplan, prüfbare Akzeptanzkriterien und die Abgrenzung „Nicht im Umfang“ sind ergänzt.
Author
Owner

Changelog: Body in die Endfassung gebracht. Der Umsetzungsplan ist weggefallen, die Akzeptanzkriterien sind abgehakt, die geprüften Punkte und die CI-Läufe 412–415 sind genannt. Neu dazugekommen ist das Nachschärfen des Tests in 8f61209: Der erste Stand war tautologisch.

**Changelog:** Body in die Endfassung gebracht. Der Umsetzungsplan ist weggefallen, die Akzeptanzkriterien sind abgehakt, die geprüften Punkte und die CI-Läufe 412–415 sind genannt. Neu dazugekommen ist das Nachschärfen des Tests in `8f61209`: Der erste Stand war tautologisch.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: torben/chemenu#146