Session-Id-Fallback zersplittert einen Lauf: Telemetrie-Join-Key tot, Iteration-Budget-Gate strukturell unerreichbar #110

Closed
opened 2026-09-16 16:18:43 +00:00 by torben · 3 comments
Owner

Ergebnis

Umgesetzt und publiziert am 2026-09-16, 6.1.0-beta.5 (--minor, --impact high).

  • e4e2332 - die Aenderung selbst (15 Dateien, +610/-44), nach Freigabe des Mass-Update-Gates.
  • 4284f10 - Nachzug in docs/why-gates-are-code.md (kein Bump: docs/ liegt nicht im
    Pfad-Scope des CI-Version-Gates).

Der Befund ist geschlossen: eine Sitzung auf Claude Code laeuft jetzt in einem Bucket, und das
Iteration-Budget-Gate zaehlt ueber einen ganzen Lauf. Der Beleg steht unter § Verifiziert.

Was der Befund war

chemenu.session fiel ohne gesetztes WIKITOOL_SESSION_ID auf os.getppid() zurueck. Auf Claude
Code - jeder Bash-Tool-Call in einer frisch initialisierten Shell - war das eine neue "Sitzung" pro
Aufruf. Gemessen in #107: ein Lauf mit 33 wikitool-Aufrufen erschien als 21 Telemetrie-Buckets;
der hoechste PID-Bucket kam auf 3 von 60 moeglichen Aufrufen. Zwei Folgen, beide behoben:

  1. Der Join-Key hielt nicht. Hook-Events trugen die Harness-UUID, wikitool-Events die
    wechselnde PID. EVALS.mds Satz "Everything joins on WIKITOOL_SESSION_ID" war auf dem
    Hauptharness falsch, und die L2-Regel clearance-ended-the-turn meldete "cannot say", obwohl
    der Harness prompt.submitted fuenfmal gemeldet hatte.
  2. Das Iteration-Budget-Gate war strukturell unerreichbar, und der Loop-Breaker mit ihm - drei
    identische Aufrufe landeten in drei Buckets.

Entscheidungen (getroffen 2026-09-16, umgesetzt wie beschlossen)

  1. Fallback-Kette WIKITOOL_SESSION_ID → Registry belegter Harness-Variablen → getppid().
    Umgesetzt in chemenu/session.py als HARNESS_ENV_VARS mit einem verifizierten Eintrag,
    CLAUDE_CODE_SESSION_ID → claude-code. Der Wert wird unveraendert Schluessel - kein
    Praefix, keine Normalisierung ausser dem bestehenden session_slug() fuer Verzeichnisnamen,
    weil genau diese Gleichheit den Join mit den Hook-Events herstellt. Verworfen blieben: eine
    Sitzungsdatei im Checkout und eine Branch/Worktree-Kette.
  2. doctor ist dreiwertig, die Herkunft steht in Trace und Status. Kein zusaetzlicher
    Meldepunkt in publish - verworfen als Rauschen.
  3. Limit bleibt 60, Loop-Window 3. Nicht vorsorglich angehoben: das haette das Gate an einer
    Zahl kalibriert, fuer die es weiterhin keine Messung gibt. Die erste Sitzung, die es reisst,
    ist die Messung - dann als eigenes Issue.
  4. Der SIGPIPE-Nebenbefund wurde hier mitgemacht.
  5. Versionsteil --minor. Gegen instructions/dev/version-parts.md geprueft: vorwaerts ein
    Drop-in (die Kette faellt weiterhin auf getppid() zurueck, budget.json wird unveraendert
    weitergelesen, Eintraege ohne Herkunftsfeld behalten ihren Count), rueckwaerts ebenso (die alte
    Fassung liest count/recent/last_seen und ignoriert das zusaetzliche Feld). Kein
    Kommando-, Flag- oder Variablen-Rename; WIKITOOL_SESSION_ID behaelt Namen und Vorrang. Der
    Vorbehalt aus der Planung - Praefix oder Pflichtfeld waere ein Grenzuebertritt - ist geprueft
    und traf nicht zu.

Was gebaut wurde

  1. chemenu/session.py - die dreistufige Kette, session_id_source() nennt im Harness-Fall
    die Variable und den Harness (CLAUDE_CODE_SESSION_ID (claude-code)). Der Modulkopf haelt
    fest, dass ein Registry-Eintrag nur nach Messung gegen eine echte Sitzung aufgenommen wird.
  2. commands/run_budget.py - _entry_for(): jeder Eintrag traegt seine Herkunft; dieselbe
    Id-Zeichenkette unter anderer Herkunft beginnt einen neuen Zaehler statt einen fremden zu
    erben. Eintraege ohne das Feld (vor der Aenderung geschrieben) behalten ihren Count.
  3. commands/doctor.py - check_session_id() dreiwertig: OK bei expliziter Variable, OK
    mit Nennung des Harness bei einer Registry-Variablen, WARN nur noch beim PID-Fallback.
  4. telemetry/writer.py - der session.start-Event der wikitool-Quelle traegt
    session_origin. Nur diese Quelle, weil nur sie ihre Id ueber die Kette aufloest; jede andere
    bekommt die Id aus ihrer eigenen Hook-Payload gereicht.
  5. cli.py (SIGPIPE) - gemessen, was die Planung offen gelassen hatte: Click faengt
    BrokenPipeError selbst ab (core.py, except OSError ... errno.EPIPE) und erzwingt
    sys.exit(1); ununterscheidbar von einem echten Fehlschlag, und deshalb nachtraeglich nicht
    mehr korrigierbar. _BrokenPipeSwallow sitzt jetzt vor Click auf stdout/stderr und
    schluckt den EPIPE-Schreibfehler, bevor Click ihn sieht; der Aufruf endet mit seinem echten
    Exit-Code und der Trace-Eintrag traegt stdout_truncated: true. _pacify_real_fd() haengt den
    echten Deskriptor danach an /dev/null, sonst meldet CPythons eigener Flush beim
    Interpreter-Ende "Exception ignored while flushing sys.stdout" und der Prozess endet mit 120.
  6. Tests - tests/test_cli.py ist neu (9 Tests); conftest.pys _WIKITOOL_ENV zieht die
    Registry-Variablen aus HARNESS_ENV_VARS, weil diese Suite in Claude Code laeuft und sonst
    jeder Fallback-Test die echte Sitzungs-Id eingesammelt haette. Die beiden Gate-Tests laufen
    ueber echte Subprozesse, weil os.getppid() innerhalb eines Testprozesses konstant ist.
  7. Doku-Nachzug - EVALS.md (Join-Satz, session_id-Feldzeile, plus die Feststellung, dass
    ein beobachtender Tool-Hook ohne gemeinsamen Schluessel nichts loest - ohne Issue-Nummer, das
    Dokument wird ausgeliefert), instructions/session-setup.md, INSTALL.md, tools/CONTRACT.md
    (doctor-Zeile und Budget-Abschnitt), docs/why-gates-are-code.md.
  8. version bump --minor --impact high samt Changeset-Prosa in CHANGES.md.

Akzeptanzkriterien

  • Ein Lauf auf Claude Code landet in genau einem Telemetrie-Bucket. Belegt an der echten
    Sitzung 30d734d5-7f75-4890-b17e-1ce930f381fc: drei wikitool-Aufrufe aus drei
    verschiedenen Shells
    (Shell-PIDs 4035563, 4035575 und die des Publish) stehen in
    einem Bucket in budget.json (count: 3, source: CLAUDE_CODE_SESSION_ID (claude-code)) und in einem Trace-Verzeichnis. Vor der Aenderung waeren das drei
    Buckets mit je 1 gewesen. Siehe § Verifiziert fuer die Einschraenkung auf der Hook-Seite.
  • EVALS.mds Join-Satz ist ersetzt. Er beschreibt jetzt die Kette und die Bedingung,
    unter der ein Harness einen Registry-Eintrag bekommt; die session_id-Feldzeile stimmt mit
    session_id_source() ueberein.
  • Das Gate zaehlt ueber einen ganzen Lauf. test_the_iteration_budget_gate_trips_across_separate_shells
    setzt 61 Aufrufe aus je eigenem Subprozess ab, nur ueber die Harness-Variable - der 61. wird
    verweigert. test_the_loop_breaker_trips_across_separate_shells analog fuer drei identische
    Aufrufe. Beide Tests waeren vor dieser Aenderung gruen und blind gewesen.
  • Kein bestehender Bucket wird still neu interpretiert. Drei Tests in
    test_run_budget.py: ein Bucket ohne Herkunftsfeld behaelt seinen Count (Altbestand), einer
    mit abweichender Herkunft beginnt bei 0, einer mit gleicher Herkunft zaehlt weiter.
  • doctor dreiwertig, Herkunft in budget status und im session.start-Event. Live
    geprueft: ohne WIKITOOL_SESSION_ID meldet doctor OK session-id: scoped by harness variable CLAUDE_CODE_SESSION_ID (claude-code) und budget status nennt dieselbe Herkunft.
  • Ein durch eine geschlossene Pipe abgebrochener Aufruf steht nicht als Fehler in der
    Trace.
    Vorher/nachher am selben Kommando gemessen: types describe source | head -1
    stand mit exit_code: 1 in der Trace, jetzt mit exit_code: 0 und stdout_truncated: true, ohne die Meldung des CPython-Flushs und mit Prozess-Exit 0 statt 120. Ein echter
    Fehlschlag (new entity --name "") steht weiterhin mit exit_code: 1 und ohne das Flag.
  • Das Verhaeltnis zum Hook-Issue ist dokumentiert. In EVALS.md als Sachaussage ohne
    Nummer, und als Kommentar an #82.
  • --minor gebumpt, Changeset geschrieben, Vorbehalt geprueft (siehe Entscheidung 5).
  • pytest, docs verify, instructions verify ohne neue Befunde - siehe § Verifiziert.

Verifiziert

  • pytest: 1309 Tests gruen (19 neu: 9 in test_cli.py, 5 in test_run_budget.py, 5 in
    test_telemetry_emit.py).
  • docs verify: OK - 56 Kommandos dokumentiert, keine Issue-Referenzen in 73 ausgelieferten
    Dokumenten, TOCs aktuell, CHANGES.md nennt 6.1.0-beta.5.
  • instructions verify: OK - 23 Instruktionen, 7 Skills, 14 publizierte Kopien deckungsgleich.
  • CI: Laeufe 303 und 304 zu e4e2332 - beide success, inklusive Version-Gate und des
    vollstaendigen setup-instance.md-Replays gegen einen frischen dist export. Lauf 305 zu
    4284f10 (nur docs/) lief zum Zeitpunkt des Schliessens noch.
  • Live auf dieser Instanz gemessen, mit und ohne gesetzte Variable: doctor, budget status,
    budget.json, Trace-Inhalt.

Einschraenkung, die zum Nachweis oben gehoert: das Trace-Verzeichnis dieser Sitzung enthaelt
nur noch die wikitool-Events. Die Umsetzungssitzung hat es bei einer Aufraeumaktion zwischen
zwei Pruefschritten selbst geloescht (rm -rf reports/telemetry/$CLAUDE_CODE_SESSION_ID) und damit
die beiden Hook-Events dieser Sitzung mitgenommen - gitignorierte, abgeleitete Daten, aber eben
auch der Beleg. Die Gleichheit der Schluessel ist trotzdem belegt: dieselbe Datei wurde zu Beginn
derselben Sitzung gelesen und trug dort "session_id":"30d734d5-7f75-4890-b17e-1ce930f381fc" in
session.start und prompt.submitted aus der Quelle claude-code - also genau den Wert, unter
dem die wikitool-Events jetzt stehen. Eine Trace, die beide Seiten in einem Schnappschuss zeigt,
entsteht bei der naechsten Prompt-Abgabe dieser oder jeder folgenden Sitzung von selbst.

Bewusst nicht gemacht

  • kb/concepts/workflows/Iteration and Cost Limits.md nicht nachgezogen. Die Seite nennt
    weiter nur WIKITOOL_SESSION_ID und die PID als Fallback. Eine kb/-Seite braucht eine Quelle
    (Invariante 3), und fuer diese Aenderung existiert keine in raw/; eine zu schreiben ist
    Inhaltsarbeit nach den kb/-Regeln und nicht Teil dieses Werkpakets. Wer den naechsten
    Stack-Lauf ohnehin als Quelle ablegt, zieht sie dabei mit.
  • Das Limit nicht angehoben (Entscheidung 3).
  • Kein beobachtender Tool-Hook verdrahtet - das ist #82 und bleibt dort; dieses Issue hat nur
    die Reihenfolge geklaert.

Herkunft

Befund 1 aus #107 - dem getraceten Upgrade-Lauf 5.0.0 auf 6.0.0 auf einer echten
ausgelieferten Instanz, 2026-09-15, Harness Claude Code, Sitzung 671c1b9a. Sechs der sieben
Befunde waren dort erledigt; dieser war der einzige, der eine Betreiberentscheidung brauchte.
Ausgelagert am 2026-09-16, entschieden und umgesetzt am selben Tag.

Die Evidenz des urspruenglichen Befunds bleibt in #107: die 63-Event-Trace verbatim im ersten
Kommentar, die Bucket-Messung und die Scorer-Ausgabe im Befund-1-Abschnitt, und der
Reproduktionsabschnitt, dessen Schritt 5 genau diesen Befund nachstellt - er reproduziert nach
e4e2332 nicht mehr.

Modelle dieser Sitzung (kein mechanischer Check deckt eine dieser drei Phasen ab): Entwurf,
Versionsteil und Grenzurteil auf Opus 5; Code, Tests und Bump ebenfalls auf Opus 5 (der Wechsel
auf Sonnet wurde angeboten und nicht genommen); Abschlussphase auf Opus 5.

## Ergebnis **Umgesetzt und publiziert am 2026-09-16**, `6.1.0-beta.5` (`--minor`, `--impact high`). - `e4e2332` - die Aenderung selbst (15 Dateien, +610/-44), nach Freigabe des Mass-Update-Gates. - `4284f10` - Nachzug in `docs/why-gates-are-code.md` (kein Bump: `docs/` liegt nicht im Pfad-Scope des CI-Version-Gates). Der Befund ist geschlossen: eine Sitzung auf Claude Code laeuft jetzt in **einem** Bucket, und das Iteration-Budget-Gate zaehlt ueber einen ganzen Lauf. Der Beleg steht unter § Verifiziert. ## Was der Befund war `chemenu.session` fiel ohne gesetztes `WIKITOOL_SESSION_ID` auf `os.getppid()` zurueck. Auf Claude Code - jeder Bash-Tool-Call in einer frisch initialisierten Shell - war das eine neue "Sitzung" pro Aufruf. Gemessen in #107: ein Lauf mit 33 `wikitool`-Aufrufen erschien als 21 Telemetrie-Buckets; der hoechste PID-Bucket kam auf 3 von 60 moeglichen Aufrufen. Zwei Folgen, beide behoben: 1. **Der Join-Key hielt nicht.** Hook-Events trugen die Harness-UUID, `wikitool`-Events die wechselnde PID. `EVALS.md`s Satz *"Everything joins on `WIKITOOL_SESSION_ID`"* war auf dem Hauptharness falsch, und die L2-Regel `clearance-ended-the-turn` meldete "cannot say", obwohl der Harness `prompt.submitted` fuenfmal gemeldet hatte. 2. **Das Iteration-Budget-Gate war strukturell unerreichbar**, und der Loop-Breaker mit ihm - drei identische Aufrufe landeten in drei Buckets. ## Entscheidungen (getroffen 2026-09-16, umgesetzt wie beschlossen) 1. **Fallback-Kette `WIKITOOL_SESSION_ID` → Registry belegter Harness-Variablen → `getppid()`.** Umgesetzt in `chemenu/session.py` als `HARNESS_ENV_VARS` mit einem verifizierten Eintrag, `CLAUDE_CODE_SESSION_ID` → `claude-code`. Der Wert wird **unveraendert** Schluessel - kein Praefix, keine Normalisierung ausser dem bestehenden `session_slug()` fuer Verzeichnisnamen, weil genau diese Gleichheit den Join mit den Hook-Events herstellt. Verworfen blieben: eine Sitzungsdatei im Checkout und eine Branch/Worktree-Kette. 2. **`doctor` ist dreiwertig**, die Herkunft steht in Trace und Status. Kein zusaetzlicher Meldepunkt in `publish` - verworfen als Rauschen. 3. **Limit bleibt 60, Loop-Window 3.** Nicht vorsorglich angehoben: das haette das Gate an einer Zahl kalibriert, fuer die es weiterhin keine Messung gibt. Die erste Sitzung, die es reisst, ist die Messung - dann als eigenes Issue. 4. **Der SIGPIPE-Nebenbefund wurde hier mitgemacht.** 5. **Versionsteil `--minor`.** Gegen `instructions/dev/version-parts.md` geprueft: vorwaerts ein Drop-in (die Kette faellt weiterhin auf `getppid()` zurueck, `budget.json` wird unveraendert weitergelesen, Eintraege ohne Herkunftsfeld behalten ihren Count), rueckwaerts ebenso (die alte Fassung liest `count`/`recent`/`last_seen` und ignoriert das zusaetzliche Feld). Kein Kommando-, Flag- oder Variablen-Rename; `WIKITOOL_SESSION_ID` behaelt Namen und Vorrang. Der Vorbehalt aus der Planung - Praefix oder Pflichtfeld waere ein Grenzuebertritt - ist geprueft und traf nicht zu. ## Was gebaut wurde 1. **`chemenu/session.py`** - die dreistufige Kette, `session_id_source()` nennt im Harness-Fall die Variable und den Harness (`CLAUDE_CODE_SESSION_ID (claude-code)`). Der Modulkopf haelt fest, dass ein Registry-Eintrag nur nach Messung gegen eine echte Sitzung aufgenommen wird. 2. **`commands/run_budget.py`** - `_entry_for()`: jeder Eintrag traegt seine Herkunft; dieselbe Id-Zeichenkette unter anderer Herkunft beginnt einen neuen Zaehler statt einen fremden zu erben. Eintraege ohne das Feld (vor der Aenderung geschrieben) behalten ihren Count. 3. **`commands/doctor.py`** - `check_session_id()` dreiwertig: `OK` bei expliziter Variable, `OK` mit Nennung des Harness bei einer Registry-Variablen, `WARN` nur noch beim PID-Fallback. 4. **`telemetry/writer.py`** - der `session.start`-Event der `wikitool`-Quelle traegt `session_origin`. Nur diese Quelle, weil nur sie ihre Id ueber die Kette aufloest; jede andere bekommt die Id aus ihrer eigenen Hook-Payload gereicht. 5. **`cli.py` (SIGPIPE)** - gemessen, was die Planung offen gelassen hatte: Click faengt `BrokenPipeError` selbst ab (`core.py`, `except OSError ... errno.EPIPE`) und erzwingt `sys.exit(1)`; ununterscheidbar von einem echten Fehlschlag, und deshalb nachtraeglich nicht mehr korrigierbar. `_BrokenPipeSwallow` sitzt jetzt **vor** Click auf `stdout`/`stderr` und schluckt den EPIPE-Schreibfehler, bevor Click ihn sieht; der Aufruf endet mit seinem echten Exit-Code und der Trace-Eintrag traegt `stdout_truncated: true`. `_pacify_real_fd()` haengt den echten Deskriptor danach an `/dev/null`, sonst meldet CPythons eigener Flush beim Interpreter-Ende "Exception ignored while flushing sys.stdout" und der Prozess endet mit 120. 6. **Tests** - `tests/test_cli.py` ist neu (9 Tests); `conftest.py`s `_WIKITOOL_ENV` zieht die Registry-Variablen aus `HARNESS_ENV_VARS`, weil diese Suite **in** Claude Code laeuft und sonst jeder Fallback-Test die echte Sitzungs-Id eingesammelt haette. Die beiden Gate-Tests laufen ueber echte Subprozesse, weil `os.getppid()` innerhalb eines Testprozesses konstant ist. 7. **Doku-Nachzug** - `EVALS.md` (Join-Satz, `session_id`-Feldzeile, plus die Feststellung, dass ein beobachtender Tool-Hook ohne gemeinsamen Schluessel nichts loest - ohne Issue-Nummer, das Dokument wird ausgeliefert), `instructions/session-setup.md`, `INSTALL.md`, `tools/CONTRACT.md` (`doctor`-Zeile und Budget-Abschnitt), `docs/why-gates-are-code.md`. 8. **`version bump --minor --impact high`** samt Changeset-Prosa in `CHANGES.md`. ## Akzeptanzkriterien - [x] **Ein Lauf auf Claude Code landet in genau einem Telemetrie-Bucket.** Belegt an der echten Sitzung `30d734d5-7f75-4890-b17e-1ce930f381fc`: drei `wikitool`-Aufrufe aus **drei verschiedenen Shells** (Shell-PIDs 4035563, 4035575 und die des Publish) stehen in **einem** Bucket in `budget.json` (`count: 3`, `source: CLAUDE_CODE_SESSION_ID (claude-code)`) und in **einem** Trace-Verzeichnis. Vor der Aenderung waeren das drei Buckets mit je 1 gewesen. Siehe § Verifiziert fuer die Einschraenkung auf der Hook-Seite. - [x] **`EVALS.md`s Join-Satz ist ersetzt.** Er beschreibt jetzt die Kette und die Bedingung, unter der ein Harness einen Registry-Eintrag bekommt; die `session_id`-Feldzeile stimmt mit `session_id_source()` ueberein. - [x] **Das Gate zaehlt ueber einen ganzen Lauf.** `test_the_iteration_budget_gate_trips_across_separate_shells` setzt 61 Aufrufe aus je eigenem Subprozess ab, nur ueber die Harness-Variable - der 61. wird verweigert. `test_the_loop_breaker_trips_across_separate_shells` analog fuer drei identische Aufrufe. Beide Tests waeren vor dieser Aenderung gruen und blind gewesen. - [x] **Kein bestehender Bucket wird still neu interpretiert.** Drei Tests in `test_run_budget.py`: ein Bucket ohne Herkunftsfeld behaelt seinen Count (Altbestand), einer mit abweichender Herkunft beginnt bei 0, einer mit gleicher Herkunft zaehlt weiter. - [x] **`doctor` dreiwertig, Herkunft in `budget status` und im `session.start`-Event.** Live geprueft: ohne `WIKITOOL_SESSION_ID` meldet `doctor` `OK session-id: scoped by harness variable CLAUDE_CODE_SESSION_ID (claude-code)` und `budget status` nennt dieselbe Herkunft. - [x] **Ein durch eine geschlossene Pipe abgebrochener Aufruf steht nicht als Fehler in der Trace.** Vorher/nachher am selben Kommando gemessen: `types describe source | head -1` stand mit `exit_code: 1` in der Trace, jetzt mit `exit_code: 0` und `stdout_truncated: true`, ohne die Meldung des CPython-Flushs und mit Prozess-Exit 0 statt 120. Ein echter Fehlschlag (`new entity --name ""`) steht weiterhin mit `exit_code: 1` und ohne das Flag. - [x] **Das Verhaeltnis zum Hook-Issue ist dokumentiert.** In `EVALS.md` als Sachaussage ohne Nummer, und als Kommentar an #82. - [x] **`--minor` gebumpt, Changeset geschrieben, Vorbehalt geprueft** (siehe Entscheidung 5). - [x] **`pytest`, `docs verify`, `instructions verify` ohne neue Befunde** - siehe § Verifiziert. ## Verifiziert - `pytest`: 1309 Tests gruen (19 neu: 9 in `test_cli.py`, 5 in `test_run_budget.py`, 5 in `test_telemetry_emit.py`). - `docs verify`: OK - 56 Kommandos dokumentiert, keine Issue-Referenzen in 73 ausgelieferten Dokumenten, TOCs aktuell, `CHANGES.md` nennt `6.1.0-beta.5`. - `instructions verify`: OK - 23 Instruktionen, 7 Skills, 14 publizierte Kopien deckungsgleich. - CI: Laeufe **303 und 304** zu `e4e2332` - beide `success`, inklusive Version-Gate und des vollstaendigen `setup-instance.md`-Replays gegen einen frischen `dist export`. Lauf **305** zu `4284f10` (nur `docs/`) lief zum Zeitpunkt des Schliessens noch. - Live auf dieser Instanz gemessen, mit und ohne gesetzte Variable: `doctor`, `budget status`, `budget.json`, Trace-Inhalt. **Einschraenkung, die zum Nachweis oben gehoert:** das Trace-Verzeichnis dieser Sitzung enthaelt nur noch die `wikitool`-Events. Die Umsetzungssitzung hat es bei einer Aufraeumaktion zwischen zwei Pruefschritten selbst geloescht (`rm -rf reports/telemetry/$CLAUDE_CODE_SESSION_ID`) und damit die beiden Hook-Events dieser Sitzung mitgenommen - gitignorierte, abgeleitete Daten, aber eben auch der Beleg. Die Gleichheit der Schluessel ist trotzdem belegt: dieselbe Datei wurde zu Beginn derselben Sitzung gelesen und trug dort `"session_id":"30d734d5-7f75-4890-b17e-1ce930f381fc"` in `session.start` und `prompt.submitted` aus der Quelle `claude-code` - also genau den Wert, unter dem die `wikitool`-Events jetzt stehen. Eine Trace, die beide Seiten in einem Schnappschuss zeigt, entsteht bei der naechsten Prompt-Abgabe dieser oder jeder folgenden Sitzung von selbst. ## Bewusst nicht gemacht - **`kb/concepts/workflows/Iteration and Cost Limits.md` nicht nachgezogen.** Die Seite nennt weiter nur `WIKITOOL_SESSION_ID` und die PID als Fallback. Eine `kb/`-Seite braucht eine Quelle (Invariante 3), und fuer diese Aenderung existiert keine in `raw/`; eine zu schreiben ist Inhaltsarbeit nach den `kb/`-Regeln und nicht Teil dieses Werkpakets. Wer den naechsten Stack-Lauf ohnehin als Quelle ablegt, zieht sie dabei mit. - **Das Limit nicht angehoben** (Entscheidung 3). - **Kein beobachtender Tool-Hook verdrahtet** - das ist #82 und bleibt dort; dieses Issue hat nur die Reihenfolge geklaert. ## Herkunft Befund 1 aus **#107** - dem getraceten Upgrade-Lauf 5.0.0 auf 6.0.0 auf einer echten ausgelieferten Instanz, 2026-09-15, Harness Claude Code, Sitzung `671c1b9a`. Sechs der sieben Befunde waren dort erledigt; dieser war der einzige, der eine Betreiberentscheidung brauchte. Ausgelagert am 2026-09-16, entschieden und umgesetzt am selben Tag. **Die Evidenz des urspruenglichen Befunds bleibt in #107**: die 63-Event-Trace verbatim im ersten Kommentar, die Bucket-Messung und die Scorer-Ausgabe im Befund-1-Abschnitt, und der Reproduktionsabschnitt, dessen Schritt 5 genau diesen Befund nachstellt - er reproduziert nach `e4e2332` nicht mehr. **Modelle dieser Sitzung** (kein mechanischer Check deckt eine dieser drei Phasen ab): Entwurf, Versionsteil und Grenzurteil auf Opus 5; Code, Tests und Bump ebenfalls auf Opus 5 (der Wechsel auf Sonnet wurde angeboten und nicht genommen); Abschlussphase auf Opus 5.
torben added the prio/plannedsize/Larea/processkind/decision labels 2026-09-16 16:18:43 +00:00
torben added size/Mkind/build and removed size/Lkind/decision labels 2026-09-16 16:56:44 +00:00
Author
Owner

Changelog: Vorbereitungssitzung 2026-09-16 (Claude Code). Abschnitt "Zu entscheiden" ist durch "Entscheidungen" ersetzt - alle vier Achsen sind vom Betreiber entschieden: Fallback-Kette WIKITOOL_SESSION_ID → Registry belegter Harness-Variablen → getppid() (Wert unveraendert als Schluessel, kein Praefix); doctor wird dreiwertig statt eines zusaetzlichen Melde-/Gate-Punkts in publish; Limit bleibt 60; der SIGPIPE-Nebenbefund wird hier mitgemacht statt ausgelagert. Neu: eine Messung aus dieser Sitzung, die zeigt, dass CLAUDE_CODE_SESSION_ID ueber Bash-Calls hinweg stabil ist (die Shell-PID dagegen nicht) und exakt die Id ist, die der UserPromptSubmit-Hook in die Trace schreibt - darauf steht Entscheidung 1. Neu ausgearbeitet: "Zu bauen" (8 Punkte inkl. Tests und Doku-Pull-Through), "Zur Bauzeit zu pruefen" (Subagenten, Retention, Vorrang expliziter Ids) und der Versionsteil - --minor, gegen instructions/dev/version-parts.md als Drop-in in beide Richtungen geprueft, mit benanntem Vorbehalt. Akzeptanzkriterien praezisiert (Bucket-Schutz als Test statt als Argument ueber Schluesselraeume; SIGPIPE- und Meldungs-Kriterium ergaenzt). Labels: kind/decision → kind/build, size/L → size/M, weil die offenen Designfragen beantwortet sind und der Schnitt jetzt bei mehreren Dateien mit eigenem Testaufwand liegt.

**Changelog:** Vorbereitungssitzung 2026-09-16 (Claude Code). Abschnitt "Zu entscheiden" ist durch "Entscheidungen" ersetzt - alle vier Achsen sind vom Betreiber entschieden: Fallback-Kette `WIKITOOL_SESSION_ID` → Registry belegter Harness-Variablen → `getppid()` (Wert unveraendert als Schluessel, kein Praefix); `doctor` wird dreiwertig statt eines zusaetzlichen Melde-/Gate-Punkts in `publish`; Limit bleibt 60; der SIGPIPE-Nebenbefund wird hier mitgemacht statt ausgelagert. Neu: eine Messung aus dieser Sitzung, die zeigt, dass `CLAUDE_CODE_SESSION_ID` ueber Bash-Calls hinweg stabil ist (die Shell-PID dagegen nicht) und **exakt** die Id ist, die der `UserPromptSubmit`-Hook in die Trace schreibt - darauf steht Entscheidung 1. Neu ausgearbeitet: "Zu bauen" (8 Punkte inkl. Tests und Doku-Pull-Through), "Zur Bauzeit zu pruefen" (Subagenten, Retention, Vorrang expliziter Ids) und der Versionsteil - `--minor`, gegen `instructions/dev/version-parts.md` als Drop-in in beide Richtungen geprueft, mit benanntem Vorbehalt. Akzeptanzkriterien praezisiert (Bucket-Schutz als Test statt als Argument ueber Schluesselraeume; SIGPIPE- und Meldungs-Kriterium ergaenzt). Labels: `kind/decision` → `kind/build`, `size/L` → `size/M`, weil die offenen Designfragen beantwortet sind und der Schnitt jetzt bei mehreren Dateien mit eigenem Testaufwand liegt.
Author
Owner

Changelog: Geschlossen. Koerper auf den Endzustand umgeschrieben: "Zu bauen" und "Zur Bauzeit zu pruefen" sind durch "Was gebaut wurde" ersetzt (alle acht Punkte umgesetzt), alle neun Akzeptanzkriterien abgehakt und je mit ihrem Beleg statt mit einer Zusage, "Verifiziert" nennt pytest/docs verify/instructions verify und die CI-Laeufe 303/304 (beide success). Neu im Koerper, weil es beim Bauen erst entstand: die SIGPIPE-Ursache ist gemessen (Click faengt EPIPE selbst ab und erzwingt sys.exit(1) - deshalb sitzt der Wrapper jetzt vor Click, nicht dahinter), und der Nachzug in docs/why-gates-are-code.md (4284f10) kam dazu, weil dieser Befund die Begruendung der Seite tatsaechlich bewegt: ein Gate in Code muss auch erreichbar sein, und eines, das nie ausloest, sieht aus wie eines, das niemand brauchte. Ebenfalls neu und bewusst so stehen gelassen: die Einschraenkung zum Bucket-Nachweis - die Umsetzungssitzung hat das Trace-Verzeichnis dieser Sitzung beim Aufraeumen selbst geloescht und damit die Hook-Events mitgenommen; was daraus noch belegbar ist und was nicht, steht im Koerper statt geglaettet zu werden. Abschnitt "Bewusst nicht gemacht" haelt drei Auslassungen fest (kb-Seite mangels Quelle, Limit unveraendert, Hook-Verdrahtung bleibt #82). Labels unveraendert area/process kind/build prio/planned size/M.

**Changelog:** Geschlossen. Koerper auf den Endzustand umgeschrieben: "Zu bauen" und "Zur Bauzeit zu pruefen" sind durch "Was gebaut wurde" ersetzt (alle acht Punkte umgesetzt), alle neun Akzeptanzkriterien abgehakt und je mit ihrem Beleg statt mit einer Zusage, "Verifiziert" nennt pytest/docs verify/instructions verify und die CI-Laeufe 303/304 (beide `success`). Neu im Koerper, weil es beim Bauen erst entstand: die SIGPIPE-Ursache ist gemessen (Click faengt EPIPE selbst ab und erzwingt `sys.exit(1)` - deshalb sitzt der Wrapper jetzt vor Click, nicht dahinter), und der Nachzug in `docs/why-gates-are-code.md` (`4284f10`) kam dazu, weil dieser Befund die Begruendung der Seite tatsaechlich bewegt: ein Gate in Code muss auch erreichbar sein, und eines, das nie ausloest, sieht aus wie eines, das niemand brauchte. Ebenfalls neu und bewusst so stehen gelassen: die Einschraenkung zum Bucket-Nachweis - die Umsetzungssitzung hat das Trace-Verzeichnis dieser Sitzung beim Aufraeumen selbst geloescht und damit die Hook-Events mitgenommen; was daraus noch belegbar ist und was nicht, steht im Koerper statt geglaettet zu werden. Abschnitt "Bewusst nicht gemacht" haelt drei Auslassungen fest (kb-Seite mangels Quelle, Limit unveraendert, Hook-Verdrahtung bleibt #82). Labels unveraendert `area/process kind/build prio/planned size/M`.
Author
Owner

Nachtrag zu § Verifiziert: CI-Lauf 305 (4284f10, der docs/-Nachzug) ist inzwischen ebenfalls success. Damit sind alle drei Laeufe zu diesem Werkpaket gruen - 303 und 304 zu e4e2332, 305 zu 4284f10.

Nachtrag zu § Verifiziert: CI-Lauf **305** (`4284f10`, der `docs/`-Nachzug) ist inzwischen ebenfalls `success`. Damit sind alle drei Laeufe zu diesem Werkpaket gruen - 303 und 304 zu `e4e2332`, 305 zu `4284f10`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: torben/chemenu#110