wikitool new project legt Seite und Tracker-Projekt unter einem Namen an #126

Closed
opened 2026-09-19 14:57:50 +00:00 by torben · 1 comment
Owner

Paket 5 aus #119 (D8, D31). Ein Geburtsort, ein Name.

Erledigt (e4260fc + 6324024, Stack 7.0.0-beta.5). wikitool new project --name X --set responsibility=Y [--resume] legt jetzt Seite und Tracker-Projekt unter einem Namen an, mit der
in diesem Issue vorgezeichneten Fehlerbehandlung. Alle offenen Designfragen sind entschieden
(siehe "Ergebnis" unten); dieses Issue steht ab jetzt nur noch als Nachschlagewerk für das Warum.

Warum hier und nicht in einem eigenen Kommando

Der Moment, in dem ein Vorhaben entsteht, ist der einzige, an dem die Eindeutigkeitspruefung aus
D8 natuerlich sitzt. Unter Muster 4 ist der Name die einzige Kopplung zwischen kb/ und
Tracker; er erbt damit die Pflichten eines Identifiers, und ein Identifier wird bei der Geburt
vergeben, nicht nachtraeglich repariert.

Ein eigenes task new haette zwei Geburtsorte fuer einen Namen - und der Preflight saesse dann
an zwei Stellen oder faehlte an einer.

Was gebaut wurde

tools/wikitool new project --name "Küche renovieren" --set responsibility=haus [--resume]
  1. Preflight: Ist der Name - case-normalisiert - in kb/ frei? Und im Tracker?
  2. Tracker-Projekt anlegen (_ensure_tracker_project in commands/new_page.py, ueber die
    neuen, geteilten chemenu.tasks.build_reader/build_writer).
  3. Seite anlegen, wie new es ohnehin tut.

Ergebnis: die Retry-Frage aus "Schritt 2 fuer einen Provider ohne Schreibpfad"

Der urspruengliche Text unten (aus #124s Befund) sah vor, dass ein erneuter Aufruf "ueber den
Lesepfad verifiziert, bevor er fortfaehrt". In der Umsetzung zeigte sich: ein zustandsloser
CLI-Prozess kann eine echte Namenskollision im Tracker nicht von "der Mensch hat gerade getan,
worum genau dieses Kommando gebeten hat" unterscheiden - beides sieht am Lesepfad identisch aus
(Tracker hat den Namen, kb/ noch keine Seite), und ein automatisches "Treffer im Tracker = schon
erledigt" haette die im AC-Punkt "Kollision samt Fundort" geforderte harte Ablehnung fuer den
Normalfall stillschweigend aufgeweicht.

Entschieden (mit dem Betreiber, per Rueckfrage): ein explizites --resume. Ohne --resume
bleibt jeder Tracker-Treffer eine Ablehnung samt Fundort, auch bei einem Wiederholungsaufruf; mit
--resume liest ein Tracker-Treffer als bestaetigte Fortsetzung, und --resume ohne einen
tatsaechlich vorhandenen Tracker-Eintrag wirft dieselbe HumanInterventionRequired-Meldung
erneut. chemenu.errors.HumanInterventionRequireds Dokumentation ist entsprechend nachgezogen
(sie beschrieb urspruenglich ein automatisches verify() als den Weg fuer einen neuen Prozess).

Die Reihenfolge ist die Fehlerbehandlung

Tracker zuerst, Seite danach - und das ist kein Detail. new ist laut AGENTS.md
§ Tool error contract nicht idempotent; ein halb gelungener Lauf ueber zwei Systeme ist
deshalb der gefaehrlichste Fall, den dieses Kommando hat.

Was scheitert Zustand danach Bewertung
Preflight nichts angelegt sauber
Tracker-Anlage (inkl. HumanInterventionRequired, solange --resume nicht bestaetigt) nichts angelegt sauber
Seiten-Anlage Tracker-Projekt ohne Seite ein Zustand, den das System bereits kennt und meldet - Pruefung 3 in #125

Andersherum - Seite zuerst - entstuende eine kb/-Seite ohne Tracker-Projekt. Die meldet
Pruefung 4 zwar auch, aber sie behauptet dabei ein Vorhaben, an dem niemand arbeiten kann.
Die gewaehlte Reihenfolge laesst jeden Teilfehler in einem Zustand landen, fuer den der
Rueckblick schon eine Meldung hat. Eigens getestet (Seiten-Schreibfehler erzwungen nach
bereits bestaetigtem Tracker-Projekt): die Meldung nennt, dass die Tracker-Seite schon steht
und nur die kb/-Seite fehlt, nie umgekehrt.

Akzeptanzkriterien

  • Nach jedem Abbruch gilt: entweder existieren beide, oder nur das Tracker-Projekt, oder
    keines - nie nur die Seite.
    Ein Test erzwingt einen Fehler in Schritt 3 und prueft
    genau das. (test_new_project_never_leaves_only_the_page_when_the_write_fails)
  • Scheitert ein Schritt, benennt die Meldung, welche der beiden Seiten existiert, statt
    nur den Fehler zu melden.
  • Ist der Name in kb/ oder im Tracker vergeben (case-normalisiert), legt das Kommando
    nichts an und nennt die Kollision samt Fundort. (Ohne --resume; siehe "Ergebnis"
    oben fuer die praezisierte Retry-Semantik.)
  • Ohne konfigurierten Provider legt es nur die Seite an und sagt das ausdruecklich.
  • Wirft create_project HumanInterventionRequired, zeigt das Kommando die Anweisung
    ueber needs_clearance()/Exit 42 und legt nichts an; ein erneuter Aufruf mit
    --resume verifiziert ueber den Lesepfad (find_project), bevor er fortfaehrt, statt
    einer Nutzerbestaetigung allein zu glauben.
  • --responsibility ist erforderlich; ein Wert ohne layout:-Eintrag wird abgelehnt. (Galt
    schon generisch ueber types/project.schema.yaml aus #123, hier nur nachgetestet.)
  • Der Rest von wikitool new verhaelt sich unveraendert - fuer jeden anderen Typ ist das
    erzeugte Scaffold byte-identisch mit dem vor der Aenderung. (Volle Bestandssuite gruen,
    1382 Tests.)
  • docs verify, instructions verify, pytest gruen.
  • tools/CONTRACT.md: die new-Zeile (und die eigene new project-Fehlervertragszeile)
    nennt das erweiterte Verhalten, die Nicht-Atomizitaet ueber zwei Systeme, und den
    HumanInterventionRequired/--resume-Ablauf.

Abhaengigkeiten

War status/blocked auf #123 (der Typ) und #124 (der Schreibpfad) - beide erledigt, Label
entfernt.

Verifiziert

  • pytest (tools/chemenu): 1382 gruen, hermetisch (env -i mit leerem HOME) wie unhermetisch.
  • tools/wikitool docs verify / instructions verify: gruen.
  • Version: --minor (Paket-Bump selbst), fortlaufend --patch fuer den Nachtrag - beide auf dem
    bereits seit #123 grenzuebertretenden Kandidaten 7.0.0-beta.5 (siehe CHANGES.md).
Paket 5 aus #119 (D8, D31). Ein Geburtsort, ein Name. **Erledigt** (`e4260fc` + `6324024`, Stack 7.0.0-beta.5). `wikitool new project --name X --set responsibility=Y [--resume]` legt jetzt Seite und Tracker-Projekt unter einem Namen an, mit der in diesem Issue vorgezeichneten Fehlerbehandlung. Alle offenen Designfragen sind entschieden (siehe "Ergebnis" unten); dieses Issue steht ab jetzt nur noch als Nachschlagewerk für das Warum. ## Warum hier und nicht in einem eigenen Kommando Der Moment, in dem ein Vorhaben entsteht, ist der einzige, an dem die Eindeutigkeitspruefung aus D8 natuerlich sitzt. Unter Muster 4 ist der Name die **einzige** Kopplung zwischen `kb/` und Tracker; er erbt damit die Pflichten eines Identifiers, und ein Identifier wird bei der Geburt vergeben, nicht nachtraeglich repariert. Ein eigenes `task new` haette zwei Geburtsorte fuer einen Namen - und der Preflight saesse dann an zwei Stellen oder faehlte an einer. ## Was gebaut wurde ``` tools/wikitool new project --name "Küche renovieren" --set responsibility=haus [--resume] ``` 1. **Preflight:** Ist der Name - case-normalisiert - in `kb/` frei? Und im Tracker? 2. **Tracker-Projekt anlegen** (`_ensure_tracker_project` in `commands/new_page.py`, ueber die neuen, geteilten `chemenu.tasks.build_reader`/`build_writer`). 3. **Seite anlegen**, wie `new` es ohnehin tut. ## Ergebnis: die Retry-Frage aus "Schritt 2 fuer einen Provider ohne Schreibpfad" Der urspruengliche Text unten (aus #124s Befund) sah vor, dass ein erneuter Aufruf "ueber den Lesepfad verifiziert, bevor er fortfaehrt". In der Umsetzung zeigte sich: ein zustandsloser CLI-Prozess kann eine echte Namenskollision im Tracker nicht von "der Mensch hat gerade getan, worum genau dieses Kommando gebeten hat" unterscheiden - beides sieht am Lesepfad identisch aus (Tracker hat den Namen, `kb/` noch keine Seite), und ein automatisches "Treffer im Tracker = schon erledigt" haette die im AC-Punkt "Kollision samt Fundort" geforderte harte Ablehnung fuer den Normalfall stillschweigend aufgeweicht. **Entschieden (mit dem Betreiber, per Rueckfrage):** ein explizites `--resume`. Ohne `--resume` bleibt jeder Tracker-Treffer eine Ablehnung samt Fundort, auch bei einem Wiederholungsaufruf; mit `--resume` liest ein Tracker-Treffer als bestaetigte Fortsetzung, und `--resume` ohne einen tatsaechlich vorhandenen Tracker-Eintrag wirft dieselbe `HumanInterventionRequired`-Meldung erneut. `chemenu.errors.HumanInterventionRequired`s Dokumentation ist entsprechend nachgezogen (sie beschrieb urspruenglich ein automatisches `verify()` als den Weg fuer einen neuen Prozess). ## Die Reihenfolge ist die Fehlerbehandlung Tracker zuerst, Seite danach - und das ist kein Detail. `new` ist laut `AGENTS.md` § Tool error contract **nicht idempotent**; ein halb gelungener Lauf ueber zwei Systeme ist deshalb der gefaehrlichste Fall, den dieses Kommando hat. | Was scheitert | Zustand danach | Bewertung | |---|---|---| | Preflight | nichts angelegt | sauber | | Tracker-Anlage (inkl. `HumanInterventionRequired`, solange `--resume` nicht bestaetigt) | nichts angelegt | sauber | | Seiten-Anlage | Tracker-Projekt ohne Seite | ein Zustand, den das System bereits kennt und meldet - Pruefung 3 in #125 | Andersherum - Seite zuerst - entstuende eine `kb/`-Seite ohne Tracker-Projekt. Die meldet Pruefung 4 zwar auch, aber sie behauptet dabei ein Vorhaben, an dem niemand arbeiten kann. Die gewaehlte Reihenfolge laesst jeden Teilfehler in einem Zustand landen, fuer den der Rueckblick schon eine Meldung hat. **Eigens getestet** (Seiten-Schreibfehler erzwungen nach bereits bestaetigtem Tracker-Projekt): die Meldung nennt, dass die Tracker-Seite schon steht und nur die `kb/`-Seite fehlt, nie umgekehrt. ## Akzeptanzkriterien - [x] **Nach jedem Abbruch gilt: entweder existieren beide, oder nur das Tracker-Projekt, oder keines - nie nur die Seite.** Ein Test erzwingt einen Fehler in Schritt 3 und prueft genau das. (`test_new_project_never_leaves_only_the_page_when_the_write_fails`) - [x] Scheitert ein Schritt, **benennt die Meldung, welche der beiden Seiten existiert**, statt nur den Fehler zu melden. - [x] Ist der Name in `kb/` oder im Tracker vergeben (case-normalisiert), legt das Kommando **nichts** an und nennt die Kollision samt Fundort. (Ohne `--resume`; siehe "Ergebnis" oben fuer die praezisierte Retry-Semantik.) - [x] Ohne konfigurierten Provider legt es nur die Seite an und **sagt das ausdruecklich**. - [x] **Wirft `create_project` `HumanInterventionRequired`**, zeigt das Kommando die Anweisung ueber `needs_clearance()`/Exit 42 und legt **nichts** an; ein erneuter Aufruf mit `--resume` verifiziert ueber den Lesepfad (`find_project`), bevor er fortfaehrt, statt einer Nutzerbestaetigung allein zu glauben. - [x] `--responsibility` ist erforderlich; ein Wert ohne `layout:`-Eintrag wird abgelehnt. (Galt schon generisch ueber `types/project.schema.yaml` aus #123, hier nur nachgetestet.) - [x] Der Rest von `wikitool new` verhaelt sich unveraendert - fuer jeden anderen Typ ist das erzeugte Scaffold byte-identisch mit dem vor der Aenderung. (Volle Bestandssuite gruen, 1382 Tests.) - [x] `docs verify`, `instructions verify`, `pytest` gruen. - [x] `tools/CONTRACT.md`: die `new`-Zeile (und die eigene `new project`-Fehlervertragszeile) nennt das erweiterte Verhalten, die Nicht-Atomizitaet ueber zwei Systeme, und den `HumanInterventionRequired`/`--resume`-Ablauf. ## Abhaengigkeiten War `status/blocked` auf #123 (der Typ) und #124 (der Schreibpfad) - beide erledigt, Label entfernt. ## Verifiziert - `pytest` (tools/chemenu): 1382 gruen, hermetisch (`env -i` mit leerem `HOME`) wie unhermetisch. - `tools/wikitool docs verify` / `instructions verify`: gruen. - Version: `--minor` (Paket-Bump selbst), fortlaufend `--patch` fuer den Nachtrag - beide auf dem bereits seit #123 grenzuebertretenden Kandidaten `7.0.0-beta.5` (siehe CHANGES.md).
torben added the prio/plannedsize/Sarea/kbkind/buildstatus/blocked labels 2026-09-19 14:57:50 +00:00
torben removed the status/blocked label 2026-09-19 19:50:53 +00:00
Author
Owner

Umgesetzt und geschlossen (e4260fc, 6324024). Gegenueber dem urspruenglichen Entwurf: die
Retry-Semantik nach HumanInterventionRequired ist ein explizites --resume statt eines
automatischen Lesepfad-Abgleichs - Begruendung und Rueckfrage-Ergebnis stehen im Issue-Body
unter "Ergebnis". --responsibility brauchte keinen neuen Code (galt schon aus #123), nur einen
nachgetragenen Test. #119s Tabelle ist aktualisiert; #127 (weekly-review-Skill) ist als naechstes frei.

Umgesetzt und geschlossen (`e4260fc`, `6324024`). Gegenueber dem urspruenglichen Entwurf: die Retry-Semantik nach `HumanInterventionRequired` ist ein explizites `--resume` statt eines automatischen Lesepfad-Abgleichs - Begruendung und Rueckfrage-Ergebnis stehen im Issue-Body unter "Ergebnis". `--responsibility` brauchte keinen neuen Code (galt schon aus #123), nur einen nachgetragenen Test. #119s Tabelle ist aktualisiert; #127 (`weekly-review`-Skill) ist als naechstes frei.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: torben/chemenu#126