Upgrade-Lauf 5.0.0 -> 6.0.0 auf ausgelieferter Instanz: Laufbericht, Telemetrie, sieben Befunde #107

Closed
opened 2026-09-16 06:08:51 +00:00 by torben · 7 comments
Owner

Zweck

Vollstaendig getracete Durchfuehrung des dokumentierten Upgrade-Pfads (INSTALL.md § "Eine Instanz
aktualisieren", Weg Tarball) auf einer echten ausgelieferten Instanz - nicht im Ursprungs-Repo
und nicht im CI-Replay. Ziel war eine Validierungsgrundlage, gegen die derselbe Lauf auf einer
Dev-Instanz nachgestellt werden kann.

Die Telemetrie des Laufs steht verbatim im ersten Kommentar. Sieben Befunde unten; keiner hat den
Lauf zum Scheitern gebracht, vier davon kosteten jede Instanz Handarbeit, die der dokumentierte
Weg nicht vorsah.

Ausgangslage: Instanz aus dist export-Tarball, VERSION 5.0.0, kb_version 5.0.0,
63 Seiten, language: de, Harness Claude Code, sauberer Arbeitsbaum, ein Remote.

Herkunft der Befunde. 1 bis 4 stammen aus dem Lauf selbst (2026-09-15). 5 bis 7 und die
Ursachenanalyse unter Befund 1 stammen aus der Review-Sitzung vom 2026-09-16, die das
Sitzungstranskript, die drei Ergebnis-Commits und den Endzustand der Instanz gegengelesen hat.

Abgeschlossen: sechs Befunde erledigt, einer ausgelagert

Befund Stand
1 - Session-Id-Fallback zersplittert den Lauf ausgelagert nach #110. Der Anleitungsteil ist mit 504149c erledigt; was bleibt, ist eine Betreiberentscheidung und kein Bauauftrag
2 - version notes antwortete auf keiner Instanz erledigt, 0c98080, 6.1.0-beta.4
3 - dist upgrade konnte die Release-Fassung nicht uebernehmen erledigt, 72d01be, 6.1.0-beta.3
4 - Migrationsdokument nennt ein Beispiel, das das Gegenteil zeigt erledigt, 0e09cf4, 6.1.0-beta.2
5 - Rest-Abschnitt ## Authoring guidance erledigt in der Instanz (b5014d9) und im Stack (0e09cf4)
6 - Verifikationsschritt ohne festgehaltene Baseline erledigt, 0e09cf4
7 - Upgrade-Pfad ohne agentengerichtete Prozedur ausgelagert nach #108, dort erledigt: 504149c, 6.1.0-beta.1

Dieses Issue ist der Laufbericht und wird als solcher nicht weiter bearbeitet. Alle
Werkzeugaenderungen, die aus ihm Bauauftraege waren, sind gebaut; beide Befunde, die eigene
Arbeitspakete wurden, haben eigene Issues (#108 erledigt, #110 offen). Was hier bleibt und
weiterhin Wert hat, ist die Evidenz: die vollstaendige Trace im ersten Kommentar, die
Lauf-Zusammenfassung mit Zeitstempeln, und der Reproduktionsabschnitt, der pro Schritt sagt, ab
welcher Version er nicht mehr reproduziert.

Lauf-Zusammenfassung

Zeit (UTC) Schritt Ergebnis
19:45:07 version check Update 5.0.0 -> 6.0.0, Grenzuebertritt gemeldet
19:45:18 migrate status nichts offen
19:45:18 version notes Exit 1 - Befund 2
19:46:03 dist upgrade --dry-run 201 unveraendert, 8 neu, 1 lokal geaendert, 0 entfallen
19:46:31 dist upgrade Exit 1 - Befund 3
19:46:59 dist upgrade --dry-run Exit 1, Arbeitsbaum unsauber (nach Handreparatur)
~19:47 git commit der Handreparatur ausserhalb des Werkzeugs noetig - und ausserhalb von Invariante 5, siehe Befund 3
19:47:17 dist upgrade --dry-run 202 / 8 / 0 / 0
19:47:22 dist upgrade OK, 210 Dateien geschrieben
19:47:28 migrate status 1 optionales Upgrade, nichts blockiert
19:47:29 instructions sync 5 Skills publiziert
19:47:44 doctor alles OK, ein WARN (session-id)
19:47:46 docs verify Exit 1 - TOC fehlt auf types/concept.md, types/source.md
19:47:53 docs toc --apply 2 Dateien repariert - wie in den Release-Notes angekuendigt
19:47:58 docs verify / instructions verify / lint gruen
19:48:28 publish Exit 42, Mass-Update-Gate, 69 Dateien, Token 96e2563ff596
19:58:22 publish --confirm OK, Commit dcc17df, gepusht
20:02-20:06 optionale Migration 6.0.0-type-guidance-split angenommen - Befund 4, 5, 6
20:06:33 migrate done 6.0.0 --pages 0 Angebot als genommen vermerkt
20:06:43 publish OK, Commit c8c9f9b, 5 Dateien, unter der Gate-Schwelle

33 wikitool.call-Events insgesamt, ein einziger unerwarteter Exit-Code (types describe source,
Exit 1 um 20:06:09 - das war SIGPIPE durch ein | head des Aufrufers, kein Werkzeugfehler; siehe
Anmerkung unter Befund 1 und die Ursachenverkettung in Befund 6).

Nicht in der Tabelle, weil nie gelaufen: migrate verify --from <commit vor dem Tausch>,
INSTALL.md Schritt 6, erster Pruefschritt. Siehe Befund 7.


Befund 1: Session-Id-Fallback zersplittert den Lauf - Join-Key tot, Iteration-Budget-Gate faktisch abgeschaltet

Ausgelagert nach #110. Die Evidenz bleibt hier stehen, weil sie das Messergebnis dieses Laufs
ist und den Befund ueberhaupt erst tragbar macht - dasselbe Muster wie bei Befund 7. Die
Entscheidung, die Loesungsachsen und die Akzeptanzkriterien stehen in #110.

Beobachtung

Der Lauf ist eine Sitzung. Die Telemetrie kennt ihn als 21 Sitzungen:

21 session_ids: 671c1b9a-92dd-484b-b29a-bf6d29c006ff
                3835015 3835056 3835179 3835232 3835285 3835339 3835353 3835371
                3835425 3835460 3835471 3835548 3836791 3837235 3837668 3837691
                3837722 3837739 3837778 3837804

Aufgeschluesselt nach Quelle:

Quelle Session-Id-Form Events
claude-code (Hook) UUID der echten Sitzung 1 session.start, 5 prompt.submitted
wikitool (Emitter) 20 verschiedene Parent-PIDs 20 session.start, 33 wikitool.call, 1 gate.refused, 1 gate.cleared, 2 publish.commit

WIKITOOL_SESSION_ID war nicht gesetzt, der Fallback ist die Parent-PID
(chemenu/session.py). Der Harness startet pro Tool-Call eine neue Shell - also pro Aufruf
eine neue PID und damit eine neue "Sitzung".

Folge 1: EVALS.md' Join-Key haelt nicht

EVALS.md § Architecture: "Everything joins on WIKITOOL_SESSION_ID." In diesem Lauf joint
nichts: die Hook-Events tragen die UUID, die wikitool-Events tragen 20 PIDs. Es gibt keinen
gemeinsamen Schluessel.

Das ist im Scorer direkt sichtbar. eval score --session 3835548 (die Sitzung mit der
Gate-Verweigerung) meldet:

- `skip` **clearance-ended-the-turn** - No wikitool.call between a clearance request (exit 42) and the next prompt.submitted.
    - this harness cannot report prompt.submitted - cannot say

Der Harness hat prompt.submitted gemeldet - 5 mal, nur unter der UUID. Ausgerechnet die
L2-Regel, die Gate-Befolgung prueft, kann auf dem Hauptharness nie ein Urteil faellen. Das ist
kein fehlender Hook (#82), sondern ein toter Schluessel: #82 wuerde tool.pre/tool.post
ergaenzen, die dann ebenfalls unter der UUID landen und weiterhin nicht zu den
wikitool.call-Events joinen. Die beiden Issues muessen zusammen gedacht werden, sonst
verdrahtet #82 Hooks, deren Events immer noch niemand zuordnen kann.

Ausserdem scort eval score jeweils 1 bis 3 Calls statt 33, waehrend die L1-Strukturpruefung in
allen 21 Buckets identisch neu berechnet wird. Ein Lauf ist so nicht bewertbar.

Folge 2: das Iteration-Budget-Gate erreicht seine Schwelle nie

Gravierender, weil es eine der vier in Code gegossenen Sicherungen ist (AGENTS.md § Gates:
60 Calls pro Sitzung, Loop-Breaker bei 3 identischen in Folge).

tools/.wikitool_session/budget.json, Stand nach dem Lauf:

46 Session-Buckets; Counts absteigend: [9, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, ...]

Der Hoechststand ist 9 - und der stammt aus wiki-setup-nathan, einem Bucket, in dem
WIKITOOL_SESSION_ID gesetzt war. Jeder PID-Bucket kommt ueber 3 nicht hinaus. Bei 33
Calls in einem Lauf hat der Zaehler also nie mehr als 3 von 60 gesehen.

Damit ist das Gate unter diesem Harness nicht "grosszuegig", sondern strukturell
unerreichbar
- und der Loop-Breaker gleich mit: drei identische Calls in Folge landen in drei
verschiedenen Buckets. Eine Sicherung, die ausdruecklich deshalb in Code sitzt, weil ein Agent
sich an einer Prompt-Regel vorbeireden kann (docs/why-gates-are-code.md), ist hier still aus.

doctor sagt das Noetige bereits - nur als WARN und ohne die Folge zu nennen:

WARN session-id: WIKITOOL_SESSION_ID is not set - budget falls back to the parent PID
  fix: See instructions/session-setup.md

Ursache eine Ebene tiefer: instructions/session-setup.md war auf diesem Harness wirkungslos

Nachgetragen aus der Review-Sitzung. doctor verweist auf instructions/session-setup.md, und
dort stand als Schritt, woertlich:

export WIKITOOL_SESSION_ID="wiki-$(date +%s)"
tools/wikitool sync

"Run this once per working session" - genau das funktioniert auf Claude Code nicht. Der
Harness fuehrt jeden Bash-Tool-Call in einer frisch initialisierten Shell aus; das
Arbeitsverzeichnis wird uebernommen, Shell-State (Umgebungsvariablen, Funktionen) nicht. Ein
export in Aufruf N ist in Aufruf N+1 verschwunden. Die 20 verschiedenen Parent-PIDs oben sind
dieselbe Tatsache von der anderen Seite gemessen.

Das aendert die Reichweite des Befunds: eine bessere Fallback-Kette repariert den Messwert, aber
die Anleitung, die das Problem eigentlich verhindern soll, war auf dem Hauptharness ein No-op.

Erledigt mit 504149c (6.1.0-beta.1, aus #108): instructions/session-setup.md nennt jetzt
die Inline-Form pro Aufruf, sagt warum ein export nur traegt solange die Shell traegt, und gibt
den Einzeiler an, mit dem sich beantworten laesst, welcher Fall vorliegt. Der Rest dieses Befunds -
Fallback-Kette, Join-Key, WARN-Haerte - ist davon unberuehrt und in #110 offen.

Nebenbefund zur Trace-Treue

types describe source steht mit exit_code: 1 in der Trace (20:06:09). Der Aufruf war
erfolgreich; der Exit-Code entstand durch SIGPIPE, weil der Aufrufer die Ausgabe durch | head
geschickt hat. Der unmittelbar folgende identische Aufruf ohne Pipe steht mit exit_code: 0 da.
Wer die Trace als Fehlerquelle auswertet, zaehlt hier einen Werkzeugfehler, den es nicht gab.
Dasselbe | head ist die Ursache von Befund 5 - siehe Befund 6. In #110 als Nebenbefund
mitgenommen, weil er dieselbe Trace betrifft.


Befund 2: version notes scheiterte auf jeder ausgelieferten Instanz - erledigt (0c98080, 6.1.0-beta.4)

kind/defect - Doku und Realitaet widersprachen sich.

INSTALL.md § "Eine Instanz aktualisieren", Schritt 4, verbatim (Stand des Laufs):

  1. Bei einer Kompatibilitätsgrenze (dist upgrade meldet sie laut) die Release-Notes vor dem
    nächsten Schritt lesen: Breaking Change: und Migration: im Eintrag von
    tools/wikitool version notes sagen, was aufhört zu funktionieren und ob der Korpus
    umgeschrieben werden muss.

Der Aufruf auf der Instanz:

$ tools/wikitool version notes
ERROR CHANGES.md has no entry for 5.0.0 - run `wikitool version bump` before
releasing, or write the entry

Ursache

version notes liest die lokale CHANGES.md. Eine ausgelieferte Instanz bekommt dafuer den
Stub aus tools/chemenu/dist_templates/CHANGES.md - 9 Zeilen, Vorwort, null Versionseintraege.
CHANGES.md steht ausserdem in chemenu.ownership.is_upgrade_preserved, wird von dist upgrade
also bewusst nie ueberschrieben. Der Stub bleibt der Stub - dauerhaft. version notes konnte
auf einer Instanz nicht nur damals nicht funktionieren, sondern nie.

Das traf genau den Moment, fuer den der Schritt existiert: den Grenzuebertritt, an dem der
Betreiber wissen muss, was aufhoert zu funktionieren. Der Lauf kam nur weiter, weil die
Release-Notes ueber die Gitea-API gelesen wurden - ein Weg, den INSTALL.md an dieser Stelle nicht
nannte, und den eine Instanz ohne erreichbaren MCP-Server gar nicht hat.

Eine Zwischenstufe hat den Widerspruch dokumentarisch beseitigt, den Defekt aber nicht:
INSTALL.md verweist seit 504149c auf instructions/upgrade-instance.md, deren Schritt 2 die
Release-Seite aus release_url las und ausdruecklich sagte, dass version notes auf einer
Instanz nicht antwortet.

Umgesetzt: Fallback auf den Release-Feed, laut angekuendigt

Von den beiden erwogenen Wegen der erste. Ausschlaggebend war, dass
instructions/upgrade-instance.md Schritt 2 den eigenen Workaround-Absatz schon als temporaer
fuehrte ("This paragraph stops being necessary the day version notes falls back to that
feed"
): die billigere Variante haette ihn dauerhaft stehenlassen.

Die Regel, in drei Faellen:

  1. Der lokale CHANGES.md-Eintrag ist da -> er wird gedruckt. Unveraendert, und der einzige
    Fall, den das Ursprungs-Repo und CI je erreichen.
  2. Kein Eintrag und kein Release-Stamp (ein Dev-Checkout) -> die alte Fehlermeldung,
    unveraendert. Das ist der Wachhund gegen einen Netzaufruf im Ursprungs-Repo: nur eine
    ausgelieferte Instanz geht online, und release.ymls
    version notes > /tmp/release-notes.md kann den neuen Pfad damit nie betreten. Ein Test
    verdrahtet einen Fetcher, der beim Aufruf AssertionError wirft, und prueft, dass er nicht
    aufgerufen wird.
  3. Kein Eintrag, aber ein Release-Stamp (eine ausgelieferte Instanz) -> der Feed aus
    update_url wird gefragt, derselbe, den version check benutzt (WIKITOOL_UPDATE_URL und
    --url uebersteuern ihn wie dort). --offline verweigert den Aufruf und faellt auf die
    Fehlermeldung zurueck, die dann release_url aus dem Stamp nennt.

Die Notes gehen nach stdout, die Herkunft nach stderr. version notes existiert, damit der
Release-Workflow kein Markdown in der Shell parsen muss (release.yml:
version notes > /tmp/release-notes.md), also darf stdout nichts als den Eintrag tragen.

Antwortet der Feed eine andere Version als die gefragte, wird das in der stderr-Kopfzeile
benannt und die Notes werden trotzdem gedruckt. Das ist nicht der Randfall, sondern der
Hauptfall: in Schritt 2 des Upgrades steht VERSION noch auf der alten Version, waehrend die
gesuchten Notes die der neuen sind. Der Feed kennt nur /releases/latest - update_url ist die
einzige URL, die der Stamp traegt, und eine /releases/tags/<tag>-URL daraus zusammenzusetzen
waere geraten statt gelesen (Invariante 7).

Nicht erreichbarer Feed: Exit 1, mit dem Feed-Fehler und release_url aus dem Stamp. Ein
leerer body faellt genauso aus - eine leere Antwort darf nicht als "dieses Release hat nichts
zu melden" durchgehen.

Nachgezogen: instructions/upgrade-instance.md Schritt 2 (Workaround-Absatz weg, dafuer die
beiden Dinge, die man vor dem Lesen der Ausgabe wissen muss), das Vorwort derselben Datei (es
nennt keine Werkzeugluecke mehr - es waren zwei, jetzt sind es null), INSTALL.md § "Version und
Updates" an zwei Stellen (die Notes-Quelle, und die inzwischen falsche Behauptung, version check sei der einzige Befehl, der ins Netz geht), tools/CONTRACT.md in beiden Tabellen sowie
die Modul-Docstrings von version_cmd.py und version.fetch_latest, die dieselbe
Ein-Netzaufruf-Behauptung trugen.


Befund 3: dist upgrade kannte keinen Weg, die Release-Fassung einer lokal geaenderten Datei zu uebernehmen - erledigt (72d01be, 6.1.0-beta.3)

kind/defect / fehlende Faehigkeit.

Beobachtung

Der Dry-Run meldete genau eine lokal geaenderte Datei:

201 unchanged, 8 new, 1 locally changed, 0 removed from the release.
Locally modified (1):
  - kb/CONTRACT.md

Der Unterschied war reine Whitespace-Formatierung einer Markdown-Tabelle (Spaltenauffuellung,
vermutlich ein Format-on-Save), inhaltlich identisch. kb/CONTRACT.md ist dabei stackeigen:
instructions/private-instance.md fuehrt <stage>/CONTRACT.md ausdruecklich als Maschinerie, an
der "an instance never edits it".

Beide damals angebotenen Wege waren hier falsch:

  • --keep-local behielt die Drift. Der neue Stamp schreibt trotzdem die Release-Digest - die
    Datei divergierte also bei jedem kuenftigen dist upgrade erneut und wurde jedes Mal wieder
    gemeldet. Fuer eine Datei, die der Instanz gar nicht gehoert, der dauerhaft falsche Zustand.
  • "reconcile by hand" war der richtige Weg, hatte aber kein Werkzeug: Handkopie aus dem
    entpackten Tarball, dann ein Commit nur zur Herstellung der Clean-Tree-Vorbedingung des
    naechsten Kommandos. Drei Schritte, zwei davon ausserhalb des Werkzeugs. Die
    Sauberkeits-Vorbedingung und die Handreparatur standen sich dabei gegenseitig im Weg: die
    Reparatur macht den Baum unsauber, den das Kommando sauber verlangt.

Der Preis war eine Invariantenverletzung

Das schaerfste Argument fuer eine Werkzeugloesung: der Commit 7fe8353 ist ein **rohes git add

  • git commit**. AGENTS.md Invariante 5 sagt "Never call raw git commit/git push. Publish
    through tools/wikitool publish"
    und kennt keine Ausnahme fuer "ist ja nur eine Vorbedingung".
    Richtig waere tools/wikitool publish --no-push gewesen.

Bemerkenswert ist weniger der Fehlgriff als die Richtung: eine fehlende Werkzeugfaehigkeit hat den
Lauf an einer in Code gegossenen Regel vorbeigefuehrt, und nichts hat es gemeldet - kein Gate, kein
Check, kein Scorer.

Erwartungshaltung aus dem Transkript

Der Agent kuendigte um 19:46:28, vor dem Lauf ohne Flag, woertlich an: "I'll let the upgrade
take the release's version rather than pinning the local formatting"
- und rief dist upgrade
dann ohne Flag auf. Das Mentalmodell war also "Default = Release-Fassung nehmen"; der Default ist
Abbruch. Die Fehlermeldung korrigierte das nicht: sie nannte --keep-local und "reconcile by
hand", sagte aber nicht, dass es zu --keep-local kein Gegenstueck gibt. Es fehlte damit nicht
nur ein Flag, sondern auch der Satz, der die falsche Erwartung abfaengt.

Umgesetzt: --take-release <pfad>, wiederholbar

--take-release nimmt einen Pfad und ist wiederholbar (wie search --field), statt ein pauschales
Gegenstueck zu --keep-local zu sein. Der Grund ist die Asymmetrie der beiden Antworten:
--keep-local laesst alles stehen und verliert nichts, --take-release verwirft eine lokale
Aenderung. Eine Verwerfung benennt ihr Ziel - dasselbe Muster, das issue-tracking.md Schritt 1
fuer destruktive Schritte verlangt -, und der gemischte Fall (zwei geaenderte Dateien, eine davon
zurueckzusetzen) ist damit ueberhaupt erst loesbar.

  • Ein Pfad, der gar nicht in der blockierten Liste steht, ist Exit 1 mit der Liste dessen, was
    dort steht - und zwar auch im --dry-run: das ist ein Fehler im Argument, nicht ein
    Zustand des Baums, und ein still ignorierter Tippfehler haette ein erfolgreiches Upgrade
    gemeldet und die Aenderung behalten, die verworfen werden sollte. Es ist die einzige
    Verweigerung, die einen Dry-Run nicht-null macht; ein blockierter Pfad tut das weiter nicht.
  • Eine lokal geloeschte Datei ist ein gueltiges Ziel: die Release-Fassung wird wieder angelegt.
  • --take-release und --keep-local zusammen sind erlaubt und komponieren. Ohne
    --keep-local bricht ein blockierter Pfad, zu dem nichts gesagt wurde, weiter ab.
  • Nach --take-release stimmt die Datei wieder mit der Stamp-Digest ueberein, die Drift ist also
    weg und nicht nur ueberschrieben - genau der Unterschied zu --keep-local.
  • Der Dry-Run markiert jeden benannten Pfad als einen, den er aus dem Release ueberschreiben
    wuerde.

Die Fehlermeldung des Abbruchs nennt alle drei Antworten samt fertiger Kommandozeile, im Muster
des Mass-Update-Gates, das seine --confirm-Zeile ebenso zum Einsetzen ausdruckt:

ERROR 1 locally changed file(s) (listed above) would be silently overwritten.
Nothing was written, and none of these three is the default:
  - take the release's version and discard the local change:
      dist upgrade <source> --take-release kb/CONTRACT.md
  - keep every local change and upgrade around them (it is reported again
    on every future upgrade):
      dist upgrade <source> --keep-local
  - reconcile them by hand first, then re-run.

Nachgezogen: instructions/upgrade-instance.md Schritt 6 traegt statt der
Drei-Schritt-Handreparatur die Entscheidung pro Pfad und den Dry-Run, mit dem man sie vorher
sieht; Schritt 7 nimmt die Flags mit. tools/CONTRACT.md in beiden Tabellen. Bewusst nicht
geaendert: die Dirty-Tree-Vorbedingung - mit --take-release entfaellt die Handreparatur und
damit der unsaubere Baum, den sie erst erzeugte.


Befund 4: 6.0.0-type-guidance-split nennt ein Beispiel, das in der Instanz das Gegenteil zeigt - erledigt (0e09cf4)

kind/defect, Dokumentation. Betraf das mitgelieferte Migrationsdokument, nicht den Code.

4a - das benannte Beispiel war in der Instanz die unmigrierte Datei

instructions/migrations/6.0.0-type-guidance-split.md, Schritt 4, verbatim (Stand des Laufs):

  1. Delete the now-duplicated prose from the type-spec, keeping the H1, a short pointer to the
    guidance file (types/entity.md's own current text is the worked example), ## Frontmatter
    and ## Template.

Im Ursprungs-Repo stimmt das: dort ist types/entity.md die stackeigene, bereits migrierte Datei.
In einer ausgelieferten Instanz ist types/entity.md die beim Setup adoptierte Kopie - also
genau die Datei, die noch die alte, zu entfernende Prosa traegt. Wer dem Satz woertlich folgte,
schrieb den Vorher-Zustand ab.

Das gesuchte Beispiel liegt in der Instanz unter types/entity.md.template - dort steht der
Nachher-Zustand (Pointer-Absatz, guidance:-Feld in der Frontmatter), weil dist upgrade die
Templates verbatim mitliefert.

Verschaerfung aus der Review-Sitzung, gegen den Baum bestaetigt: im Ursprungs-Repo existiert
ueberhaupt keine types/*.md.template-Datei - dist export re-keyt types/<name>.md erst beim
Export zur .template (dist_cmd._owned_type_stem, _plan_types). Der Satz konnte in einer
Instanz also nicht bloss unguenstig sein, er konnte dort strukturell nie stimmen.

Umgesetzt: der Schritt (jetzt Schritt 5, nach dem neu eingezogenen Vorher-Schritt aus Befund 6)
nennt types/<name>.md.template als Beispiel und sagt den Grund dazu - types/<name>.md ist die
adoptierte Kopie und damit die Datei, die gerade geaendert wird, die .template daneben traegt den
Nachher-Zustand. Mit dem Zusatz, die .template fuer die Form zu lesen und nicht wholesale zu
kopieren: ihre ## Frontmatter und ihr ## Template sind die Stack-Defaults, nicht die der
Instanz.

4b - die Sprachfrage blieb offen, direkt nachdem 6.0.0 sie verschoben hat

Das Dokument sagte nicht, in welcher Sprache der neue Pointer-Absatz zu schreiben ist. Fuer eine
Instanz mit language: de war das nicht ableitbar, denn 6.0.0 hatte diese Grenze gerade erst neu
gezogen (Bump "Control-Plane-Sprache universell", docs/language-boundaries.md).

Umgesetzt, und dabei gegen types/type-spec.md § "Who owns a type-spec" korrigiert. Die im
urspruenglichen Befund vorgeschlagene Begruendung "ein Abschnitt, den die Instanz behaelt, ist
ihrer, also traegt er die KB-Sprache"
haelt gegen den Baum nicht: die Sprachachse ist der
Leser, nicht der Eigentuemer. Anleitungsprosa in einem Type-Spec ist Control Plane und damit
englisch, unabhaengig davon, wem die Datei gehoert - so steht es in der Tabelle in
types/type-spec.md, so steht es im Docstring von dist_cmd.instance_owned_type_stems
("Ownership, not language"), und so steht es in AGENTS.md § File naming. Das Ergebnis von
Befund 5 war trotzdem richtig, nur die Begruendung nicht: der uebrige Bullet war redundant und
gehoerte weg, nicht uebersetzt.

Das Dokument sagt jetzt entsprechend:

Teil des Type-Specs Sprache Begruendung
H1, Pointer-Absatz Englisch Anleitungsprosa an einen Agenten = Control Plane, egal wem die Datei gehoert
behaltene lokale Prosa Englisch ebenfalls Anleitungsprosa - eine vor dieser Regel in der KB-Sprache geschriebene Notiz wird uebersetzt, nicht umbenannt
## Frontmatter-Tabelle unveraendert lassen die Migration fasst Frontmatter ausdruecklich nicht an
## Template-Block + Nachsatz unveraendert lassen (hier: deutsch) Seitentext in der KB-Sprache

Die Tabelle steht im Dokument nicht als Kopie - der Schritt sagt die Antwort in zwei Saetzen
und verlinkt types/type-spec.md § "Who owns a type-spec" fuer die vollstaendige Aufteilung
(Invariante 8). Der Satz "eine englische Ueberschrift ueber einem Koerper in einer anderen
Sprache ist die halbfertige Fassung dieses Schritts"
benennt genau den Zustand, den Befund 5
produziert hat.

Dazu neu, weil es der eigentliche Mechanismus hinter Befund 5 ist: eine behaltene Notiz darf
nicht ## Authoring guidance heissen.
types describe setzt diesen Kopf selbst und inlined
darunter die Guidance-Datei, die ihren eigenen gleichnamigen Abschnitt mitbringt - ein dritter aus
dem Type-Spec-Koerper ist die Doppelung.

4c - kleinere Beobachtung zur Schrittfolge

Schritt 6 (migrate done 6.0.0 --pages 0) tut genau, was es verspricht, und die Ausgabe ist
unmissverstaendlich:

OK Recorded the optional 6.0.0-type-guidance-split. Content stays at 5.0.0 - an
offer changes a file you own, not the shape of your content.

Danach bleibt doctor bei kb-version: 5.0.0 (nothing outstanding up to 6.0.0). Das ist korrekt
und dokumentiert, sieht aber auf den ersten Blick nach einem haengengebliebenen Upgrade aus. Keine
Aenderung noetig - hier nur vermerkt, weil eine Dev-Instanz-Validierung sonst darueber stolpert.


Befund 5: Rest-Abschnitt ## Authoring guidance - repariert in der Instanz (b5014d9) und im Stack (0e09cf4)

kind/defect. Gefunden in der Review-Sitzung, live gegengeprueft und dort auch behoben. Steht
hier, weil er die Wirkung von Befund 4b und Befund 6 belegt.

5a - die Instanz (b5014d9)

Bei types/source.md wurde der Abschnitt ## Autorenanweisungen nicht geloescht, sondern zu
## Authoring guidance umbenannt, mit einem verbliebenen deutschen Bullet:

## Authoring guidance

- Der Titel beginnt mit "Source - ", gefolgt vom Namen der Quelle

Zwei Fehler in drei Zeilen:

  1. Ein dritter Kopf desselben Namens in der komponierten Ausgabe. Zwei sind der
    Normalzustand und kein Befund: types describe setzt selbst einen ## Authoring guidance-Kopf und inlined darunter die Guidance-Datei, die ihren eigenen gleichnamigen
    Abschnitt mitbringt - so sieht es bei allen vier Typen aus. source hatte danach einen
    dritten aus dem Type-Spec selbst.
  2. Englische Ueberschrift ueber deutschem Inhalt in einer instanzeigenen Datei. Die Grenze,
    an der das falsch ist, ist der Leser, nicht der Eigentuemer - siehe die Korrektur unter
    Befund 4b: Anleitungsprosa bleibt englisch, auch in einer Datei, die der Instanz gehoert.
    Richtig war hier trotzdem das Entfernen, weil der Bullet redundant zum
    title_prefix: "Source - " in der Frontmatter war, das wikitool new source ohnehin erzwingt.

entity, concept und comparison waren sauber - betroffen war nur source, der einzige der
vier Typen, dessen Prosa umfangreich genug war, dass ein Bullet uebrigblieb, den die
Stack-Guidance nicht abdeckt.

Behoben mit b5014d9: Abschnitt ersatzlos entfernt, geprueft mit dem Muster aus Befund 6 -
types describe source vor und nach der Aenderung in je eine Datei, dann diff. Der Diff
zeigt genau die vier entfernten Zeilen und sonst nichts; alle vier Typen komponieren jetzt mit
zwei Koepfen.

5b - derselbe Defekt im Stack selbst (0e09cf4)

Nachgetragen 2026-09-16, gefunden beim Nachmessen im Ursprungs-Repo. Das Kriterium unten war
gegen die Instanz nathan abgehakt, gegen den Stack nie - und dort stand derselbe Rest-Abschnitt:

$ grep -c '^## Authoring guidance' <types describe $t>
entity: 2   concept: 2   source: 3   comparison: 2

types/source.md im Ursprungs-Repo trug bis 0e09cf4 einen ## Authoring guidance-Abschnitt mit
demselben einen Bullet (hier englisch, weil c64479f ihn uebersetzt hatte; d49513b hat dann den
Rest der Prosa ausgelagert und ihn stehenlassen). Das ist kein Instanzschaden, sondern ein
Auslieferungsdefekt: die Datei wird beim Export zu types/source.md.template, jede neu
aufgesetzte Instanz haette ihn mit adoptiert
- und ihn dann bei der naechsten
guidance-Migration genau so wiedergefunden wie nathan.

Entfernt, geprueft mit demselben Vorher/Nachher-Diff: genau vier Zeilen weg, sonst nichts, alle
vier Typen bei zwei Koepfen. Inhaltlich verloren geht nichts - title_prefix steht in der
Frontmatter, in der Feldtabelle von types/type-spec.md und im Nachsatz zum ## Template-Block
von types/source.md; ausserdem verbietet types/type-spec.md § Writing Shape das Wiederholen
einer Schema-Regel im Fliesstext ausdruecklich.

Nebenbeobachtung, kein Befund: dass types describe einen ## Authoring guidance-Kopf setzt
und unmittelbar darunter eine Guidance-Datei mit eigenem H1 und eigenem gleichnamigem Abschnitt
inlined, ist eine kosmetische Doppelung im Stack selbst - gleich fuer alle vier Typen, ohne
Auswirkung auf Inhalt oder Werkzeuge.


Befund 6: Schritt 5 des Migrationsdokuments war als Verifikation unfalsifizierbar - erledigt (0e09cf4)

kind/defect, Dokumentation. Direkte Ursache von Befund 5.

instructions/migrations/6.0.0-type-guidance-split.md, Schritt 5, verlangte:

The output must read the same as it did before this migration [...] the structure (frontmatter
fields, template block) must be byte-identical.

Kein Schritt davor hielt das Vorher fest. Eine Pruefung gegen einen Zustand, den niemand
aufgeschrieben hat, ist keine Pruefung - sie faellt auf das Gedaechtnis des Ausfuehrenden zurueck,
und bei einer Ausgabe von ueber 150 Zeilen je Typ ist das keins.

Der Lauf hat entsprechend geprueft: types describe durch | head -250 und | tail -80, also in
Ausschnitten, mit dem Urteil "All four compose correctly, structurally identical to before". Der
Rest-Abschnitt aus Befund 5 liegt in der Mitte der source-Ausgabe und war in keinem der beiden
Ausschnitte. Dasselbe | head erzeugte zugleich den SIGPIPE-Exit-1, den der Nebenbefund unter
Befund 1 als Trace-Rauschen fuehrt: ein Verhalten, zwei Symptome.

Umgesetzt an beiden Stellen:

  1. Das Dokument hat einen eigenen Schritt 3 bekommen - types describe <name> vollstaendig in
    eine Datei, vor der Aenderung, mit dem Satz, dass ein head/tail genau die Mitte
    verschwinden laesst. Schritt 6 diffed dagegen und nennt zusaetzlich die Ein-Zahl-Probe
    grep -c '^## Authoring guidance': zwei ist richtig, drei heisst Rest-Abschnitt im Type-Spec.
    Die alten Schritte 3-6 sind auf 4-7 gerueckt, die Querverweise mit.
  2. instructions/migrate-corpus.md § "Writing the migration document" traegt das Muster
    generisch: ein Verifikationsschritt nennt seine eigene Baseline, und zwar in einem frueheren
    Schritt. migrate verify traegt seine im letzten Commit, ob jemand daran denkt oder nicht -
    eine Migration an der Maschinerie statt an kb/ hat gar keine, und genau dort entsteht die
    Behauptung, die sich nicht widerlegen laesst.

Nicht angefasst: instructions/upgrade-instance.md Schritt 12, der seit 504149c dasselbe in
Richtung des Ausfuehrenden sagt. Zwei Adressaten, zwei Regeln - der Autor eines
Migrationsdokuments und der Betreiber, der eines abarbeitet -, also keine zweite Kopie im Sinne
von Invariante 8.


Befund 7: der Upgrade-Pfad hatte keine agentengerichtete Prozedur - ausgelagert nach #108, dort erledigt

kind/defect, Prozess. Umgesetzt mit 504149c (6.1.0-beta.1); hier bleibt die Evidenz aus dem
Lauf stehen, weil sie die Begruendung der Loesung traegt - dasselbe Muster, mit dem Befund 1 jetzt
nach #110 gegangen ist.

Die Schrittfolge stand nur in INSTALL.md - einem Dokument fuer Menschen (AGENTS.md § File
naming: README-foermige Wurzeldateien werden "never by an agent as instruction" geladen).
Ausgefuehrt wird sie von einem Agenten. Der erste Tool-Call des Laufs listete instructions/
mit - der Agent suchte also zuerst eine Instruktion, fand keine, oeffnete
instructions/private-instance.md (der falsche Weg: Clone mit gemeinsamer History statt
Tarball-Instanz), verwarf sie und griff auf INSTALL.md zurueck.

Was im selben Lauf daraus folgte:

  • migrate verify --from <commit vor dem Tausch> wurde nie ausgefuehrt, obwohl es in
    INSTALL.md Schritt 6 der erste Pruefschritt war. Die Lauf-Tabelle oben belegt es lueckenlos.
    Der Grund ist praezise benennbar: der Lauf folgte nicht INSTALL.md, sondern dem
    Abschlussbericht von dist upgrade - und in dessen Liste kam migrate verify nicht vor.
  • Die Agent-Session wurde nie neu gestartet. Beide Reihenfolgen verlangten das, die eine am
    Ende von Schritt 6, die andere am Ende des Abschlussberichts. Die optionale Migration lief
    anschliessend unter dem 5.0.0-Kontrollplan, obwohl AGENTS.md im selben Commit +44/-3 bekommen
    hatte - und genau dort fielen Befund 4b (Sprachgrenze, neu in 6.0.0) und Befund 5 an.
  • Drei Reihenfolgen waren im Umlauf: INSTALL.md Schritt 6, der Abschlussbericht, und die
    tatsaechlich gelaufene. Dass der Lauf der zweiten folgte, machte die erste zu toter Doku -
    genau der Zustand, den Invariante 8 verbietet.

Umgesetzt: instructions/upgrade-instance.md (manual: true) ist die eine Fassung, dreizehn
Schritte, mit dem Sitzungsneustart zwischen Maschinerie-Publish und Migrationskette statt am Ende
und migrate status als Wiedereinstiegspunkt. Der Abschlussbericht von dist upgrade nennt jetzt
die Datei und das Wiedereinstiegskommando statt einer eigenen Liste, INSTALL.md nur noch die
Entscheidung davor. Details und Abgrenzung: #108.


Was der Lauf bestaetigt hat

Ausdruecklich keine Befunde - das hat gehalten:

  • Der angekuendigte Grenzuebertritt kam exakt wie beschrieben. Die Release-Notes sagten
    voraus, dass docs verify nach dem Update auf adoptierten Page-Type-Specs ohne TOC-Region
    faellt, und nannten docs toc --apply als Reparatur. Genau das trat ein
    (types/concept.md, types/source.md), und genau das reparierte es - ein Werkzeuglauf, keine
    Inhaltsmigration. Nicht identisch mit #106: dort ging es um kb/CONVENTIONS.md.template auf
    einer frischen Instanz; hier um adoptierte types/*.md auf dem Upgrade-Pfad. Der in kb/CONVENTIONS.md.template traegt keine TOC-Region: frische Instanz und CI scheitern an docs verify (#106)
    umgesetzte Fix (Templates in toc.target_files()) deckt diesen Fall nicht ab, weil die
    betroffenen Dateien bereits im Dateisatz stehen - ihnen fehlte die Region nur, weil sie vor der
    Scope-Erweiterung adoptiert wurden.
  • dist upgrade klassifiziert korrekt - 202 unveraendert / 8 neu / 0 lokal geaendert /
    0 entfallen, und die 8 neuen Dateien waren exakt die des Bumps (4 *.guidance.md,
    types/type-guidance.md(.schema.yaml), docs/language-boundaries.md, das Migrationsdokument).
  • migrate status hat richtig nicht blockiert. "Migration: none required" aus den
    Release-Notes und "Nothing outstanding" aus dem Werkzeug stimmten ueberein.
  • Das Mass-Update-Gate hat sauber gearbeitet: Exit 42 bei 69 Dateien, Token an Dateiliste und
    Inhalt gebunden, Freigabe mit demselben Token akzeptiert, gate.refused/gate.cleared beide in
    der Trace. Als Datenpunkt fuer #53: 69 Dateien bei Schwelle 10, und der zweite Publish desselben
    Laufs lag mit 5 Dateien darunter.
  • types describe komponiert nach der Migration unveraendert. Korrigiert durch Befund 5:
    fuer entity, concept und comparison stimmte es; fuer source nicht - dort stand bis
    b5014d9 (Instanz) bzw. 0e09cf4 (Stack) ein dritter ## Authoring guidance-Kopf in der
    komponierten Ausgabe. Was fuer alle vier haelt: Frontmatter-Felder und ## Template-Block sind
    byte-gleich, nur die Herkunft der Anleitungsprosa hat gewechselt.

Reproduktion auf einer Dev-Instanz

Die Reproduktion gilt gegen einen 6.0.0-Tarball - also gegen die Maschinerie, in der die
Befunde aufgetreten sind. Wie ein Lauf gegen das Ergebnis dieses Issues stattdessen ausgeht, steht
unter dem Block.

# 1. Instanz auf 5.0.0 herstellen (aus einem 5.0.0-Checkout)
tools/wikitool dist export /tmp/inst-5.0.0
cd /tmp/inst-5.0.0 && git init -q -b main
git config user.name Dev && git config user.email dev@example.invalid
# Templates adoptieren wie instructions/setup-instance.md Schritt 5/6
python3 -m venv tools/.venv && tools/.venv/bin/pip install -q -r tools/requirements.txt
tools/wikitool instructions sync && tools/wikitool index rebuild
git add -A && git commit -qm baseline

# 2. Die Drift dieses Laufs nachstellen (Befund 3)
#    kb/CONTRACT.md durch einen Markdown-Formatter schicken - Whitespace-only,
#    inhaltlich identisch - und committen.

# 3. Nicht setzen, um Befund 1 zu reproduzieren: WIKITOOL_SESSION_ID
#    Jeden wikitool-Aufruf aus einer eigenen Shell absetzen (wie ein Agent-Harness es tut).

# 4. Upgrade fahren
tools/wikitool version check                       # meldet Grenzuebertritt
tools/wikitool version notes                       # ERWARTET Exit 1  -> Befund 2
tools/wikitool dist upgrade <6.0.0-tarball> --dry-run
tools/wikitool dist upgrade <6.0.0-tarball>        # ERWARTET Exit 1  -> Befund 3
#   -> Handreparatur + Commit, dann erneut
tools/wikitool migrate status && tools/wikitool instructions sync
tools/wikitool doctor
tools/wikitool docs verify                         # ERWARTET Exit 1 auf types/*.md
tools/wikitool docs toc --apply && tools/wikitool docs verify
tools/wikitool instructions verify && tools/wikitool lint

# 5. Befund 1 messen - der einzige Teil, der weiter reproduziert (siehe #110)
python3 -c "import json;d=json.load(open('tools/.wikitool_session/budget.json'));\
print(len(d),'Buckets; max count:',max(e.get('count',0) for e in d.values()))"
tools/wikitool eval sessions                       # ERWARTET: viele Buckets, je 1-3 Events

# 6. Befund 5/6 reproduzieren: die optionale Migration fahren und vorher/nachher diffen
tools/wikitool types describe source > /tmp/source-vorher.txt
#   ... Schritte 3 und 4 des Migrationsdokuments ausfuehren ...
tools/wikitool types describe source > /tmp/source-nachher.txt
diff /tmp/source-vorher.txt /tmp/source-nachher.txt
#   ERWARTET ohne Gegenmassnahme: ein dritter "## Authoring guidance"-Kopf im Nachher
grep -c '^## Authoring guidance' /tmp/source-nachher.txt   # ERWARTET 3, korrekt sind 2
#   Gegenprobe: bei entity/concept/comparison sind es vorher wie nachher 2

Was ab dem jeweiligen Stand nicht mehr reproduziert:

Ab Schritt
6.1.0-beta.2 Schritt 6 - die Stack-Kopie ist sauber, eine frische Instanz startet bei zwei Koepfen, und das Migrationsdokument schreibt Vorher-Datei und Diff selbst vor
6.1.0-beta.3 Schritt 4, zweites ERWARTET Exit 1 - der Abbruch nennt jetzt --take-release <pfad> als dritten Weg, und der erledigt den Fall in einem Kommando statt in drei Handgriffen
6.1.0-beta.4 Schritt 4, erstes ERWARTET Exit 1 - version notes antwortet aus dem Feed

Schritt 5 reproduziert unveraendert und ist damit der Reproduktionsabschnitt, den #110 erbt.

Akzeptanzkriterien

Erledigt:

  • Befund 1, Anleitungsteil: instructions/session-setup.md nennt eine Form, die auf einem
    Harness mit Shell-pro-Tool-Call wirkt - nicht nur export einmal pro Sitzung. Erledigt in
    #108 (504149c): Inline-Form pro Aufruf, mit dem Einzeiler zum Feststellen, welcher Fall
    vorliegt.
  • Befund 2: tools/wikitool version notes liefert auf einer frisch ausgelieferten Instanz
    die Notes des installierten Release aus dem Feed - stdout traegt nur den Eintrag, die
    Herkunftszeilen gehen nach stderr, --offline verweigert den Netzaufruf, und ein
    Dev-Checkout ohne Release-Stamp betritt den Pfad nie. Erledigt mit 0c98080; die
    Stamp-Grenze ist mit einem Test abgesichert, der einen werfenden Fetcher verdrahtet und
    prueft, dass er nicht aufgerufen wird.
  • Befund 2: Ein unerreichbarer Feed ist Exit 1 mit Feed-Fehler und release_url aus dem
    Stamp - nie eine stille Antwort und nie ein Abbruch ohne die Seite, die der Mensch
    stattdessen lesen kann. Ein leerer body faellt genauso aus.
  • Befund 2: instructions/upgrade-instance.md Schritt 2 traegt den Workaround-Absatz nicht
    mehr, und INSTALL.md § "Version und Updates" sagt nicht mehr, dass der Befehl auf einer
    Instanz nicht antwortet. Das Vorwort der Instruktion nennt gar keine Werkzeugluecke mehr -
    es waren zwei, beide sind mit diesem Issue weg.
  • Befund 3: Eine lokal geaenderte stackeigene Datei laesst sich in einem Kommando auf
    die Release-Fassung zuruecksetzen (dist upgrade <source> --take-release <pfad>), ohne
    Handkopie und ohne Vorbereitungs-Commit; tools/CONTRACT.mds dist upgrade-Zeile und die
    Fehlerkontrakt-Zeile nennen den Weg. Erledigt mit 72d01be.
  • Befund 3: Ein --take-release-Pfad, der nicht blockiert ist, ist Exit 1 - auch im
    --dry-run, damit ein Tippfehler vor dem Schreiblauf auffaellt. Es bleibt die einzige
    Verweigerung, die einen Dry-Run nicht-null macht; ein blockierter Pfad tut das weiter nicht.
  • Befund 3: Die Fehlermeldung des Abbruchs nennt alle drei Antworten samt einsetzbarer
    Kommandozeile und sagt, dass keine davon der Default ist - so, dass "Default = Release
    nehmen" nicht als Erwartung stehenbleibt. Mit einem Test, der genau auf diese vier
    Bestandteile prueft.
  • Befund 4: Das Migrationsdokument verweist auf types/entity.md.template und sagt, in
    welcher Sprache der Pointer-Absatz zu schreiben ist. Erledigt mit 0e09cf4; die Sprachregel
    ist dabei gegen types/type-spec.md § "Who owns a type-spec" korrigiert worden (Leser, nicht
    Eigentuemer - siehe Befund 4b) und wird verlinkt statt kopiert.
  • Befund 5: tools/wikitool types describe source gibt in der Instanz nathan so viele
    ## Authoring guidance-Koepfe aus wie bei den anderen drei Typen (zwei), und kein Abschnitt
    dort traegt eine englische Ueberschrift ueber deutschem Inhalt. Erledigt mit b5014d9,
    geprueft per Vorher/Nachher-Diff.
  • Befund 5: Dasselbe gilt im Ursprungs-Repo, dessen types/source.md beim Export zu
    types/source.md.template wird - sonst adoptiert jede neue Instanz den Defekt erneut.
    Erledigt mit 0e09cf4, geprueft per Vorher/Nachher-Diff: vier entfernte Zeilen, alle vier
    Typen bei zwei Koepfen.
  • Befund 6: Schritt 5 des Migrationsdokuments verlangt eine festgehaltene Vorher-Ausgabe
    und einen Diff; instructions/migrate-corpus.md fuehrt dasselbe Muster fuer kuenftige
    assisted-Migrationen. Erledigt mit 0e09cf4 (neuer Schritt 3 im Dokument,
    § "Writing the migration document" in migrate-corpus.md).
  • Befund 7: abgehandelt in #108 - instructions/upgrade-instance.md (manual: true)
    existiert, dist upgrades Abschlussbericht nennt sie, INSTALL.md traegt die Schrittfolge
    nicht mehr doppelt.
  • pytest, docs verify, instructions verify ohne neue Befunde fuer alles, was dieses
    Issue gebaut hat. Stand 6.1.0-beta.4: 1290 Tests (1276 vor der letzten Sitzung, +8 fuer
    --take-release, +6 fuer den version notes-Fallback), auch gegen eine leere Maschine nach
    instructions/dev/testing-conventions.md Schritt 6 identisch gruen; docs verify mit 73
    ausgelieferten Dokumenten und 58 Referenzdateien; instructions verify mit 23 Instruktionen
    und 7 Skills. CI gruen auf 72d01be (Laeufe 298, 299), 0c98080 (300, 301) und 536093f
    (302).

Nicht erledigt, sondern nach #110 ausgelagert - dort in praezisierter Form, mit einer
zusaetzlichen Bedingung zur Bucket-Neuinterpretation, die hier fehlte:

Herkunft und Artefakte

Lauf vom 2026-09-15, Instanz 5.0.0 -> 6.0.0, Harness Claude Code, Sitzung 671c1b9a.
Ergebnis-Commits in der Instanz: 7fe8353 (Handreparatur aus Befund 3), dcc17df (Maschinerie),
c8c9f9b (optionale Migration).

Review-Sitzung vom 2026-09-16: hat Transkript, die drei Commits und den Endzustand gegengelesen
und Befund 5, 6, 7 sowie die Ursachenabschnitte unter Befund 1 und 3 ergaenzt. Befund 5 ist dabei
live gegen die Instanz geprueft, nicht aus dem Transkript abgeleitet, und in derselben Sitzung
repariert (b5014d9 in torben/nathan). Aus derselben Sitzung stammt #108, das Befund 7
abgeschlossen hat.

Erste Umsetzungssitzung vom 2026-09-16 (0e09cf4, 6.1.0-beta.2): Befund 4 und 6 umgesetzt,
dabei die Sprachbegruendung aus Befund 4b/5 gegen types/type-spec.md korrigiert und die
Stack-Haelfte von Befund 5 gefunden und behoben. Modelle: Entwurf, Versionsteil und Grenzurteile
auf Opus 5, mechanische Mitte auf Opus 5, Abschluss auf Opus 5 - der in stack-dev Schritt 3
angebotene Wechsel auf Sonnet wurde angeboten und nicht gezogen.

Zweite Umsetzungssitzung vom 2026-09-16 (72d01be = 6.1.0-beta.3, 0c98080 =
6.1.0-beta.4, 536093f = Doku-Nachzug ohne Bump): Befund 3 und 2 entschieden und gebaut, in
zwei Publishes plus einem Nachzug aus der Abschlussphase. Beide Bumps --minor mit
--impact medium - neue Faehigkeit, in beide Richtungen ein Drop-in, kein Grenzuebertritt, und
damit bleibt die Bump-Liste des Kandidaten flach, wie sie es bei vier gleichgewichtigen
Upgrade-Pfad-Aenderungen sein soll. In der Abschlussphase zusaetzlich gefunden und mitgenommen:
INSTALL.md behauptete weiter, version check sei der einzige Befehl, der ins Netz geht, und
tools/CONTRACT.md § "Future considerations (not implemented)" fuehrte noch den
MCP-Server-Wrapper und dist upgrade selbst - beide seit ihrer Umsetzung falsch und im selben
Dokument weiter oben als existierend beschrieben. Modelle: Entwurf, Versionsteil und Grenzurteile
auf Opus 5, mechanische Mitte (Code, Tests, Bumps, Pruefungen) auf Opus 5, Abschluss auf Opus 5 -
der Wechsel auf Sonnet wurde an beiden vorgesehenen Stellen angeboten und nicht gezogen.

Abschluss am 2026-09-16: Befund 1 nach #110 ausgelagert und dieses Issue geschlossen. Die
Evidenz zu Befund 1 bleibt hier - Trace, Bucket-Messung, Scorer-Ausgabe, Reproduktionsschritt 5 -,
weil sie das Messergebnis dieses Laufs ist; #110 traegt die Entscheidung, die Loesungsachsen und
praezisierte Akzeptanzkriterien. Dasselbe Muster wie bei Befund 7 und #108, an derselben Stelle
begruendet.

Nicht stale, und deshalb bewusst nicht angefasst: docs/ownership-and-templates.md. Seine
Begruendung - eine lokal geaenderte Datei sei "a decision someone takes deliberately instead of
one an upgrade takes for them"
- ist genau die Eigenschaft, die --take-release umsetzt, indem
es den Pfad benennen laesst. docs/version-model.md und docs/why-gates-are-code.md sind von
beiden Aenderungen nicht beruehrt.

Erster Kommentar traegt die vollstaendige Telemetrie des Laufs verbatim - 63 Events, aus 21
Bucket-Dateien nach ts zusammengefuehrt. Einzige Aenderung: die drei identischen 69-Pfad-Arrays
in gate.refused/gate.cleared/publish.commit sind elidiert und die Liste steht einmal darunter.
Das ist der Teil dieses Issues, den #110 als Evidenz braucht und der hier bewusst bleibt, statt
kopiert zu werden.

Das rohe Sitzungstranskript ist bewusst nicht angehaengt: die Instanz ist privat, das
Transkript traegt Seitentitel, Infrastrukturthemen und Kontaktdaten aus kb/, und dieses Repo ist
oeffentlich (instructions/private-instance.md: "the cost of a mistaken push is disclosure rather
than inconvenience"
). Die Telemetrie unten ist dagegen geprueft frei davon - sie enthaelt nur
Stack-Pfade, Kommandonamen und Exit-Codes. Wer das Transkript fuer die Dev-Instanz-Validierung
braucht, bekommt es auf Anfrage redigiert (ANSI entfernt, Instanzinhalte maskiert).

Nebenbefund aus genau dieser Redaktion, weil er chemenu.telemetry.scrub betrifft: eine
Maskierung per Regex ueber Terminalausgabe greift nicht, solange die ANSI-Sequenzen drinstehen -
ssh://git@host:PORT/... und Vorname Nachname <mail@host> waren durch eingestreute
Farbcodes aufgetrennt und ueberlebten den ersten Durchgang unmaskiert. ANSI muss vor der
Maskierung entfernt werden, nicht danach. Nicht in #110 mitgenommen - eigenstaendiger Befund an
einer anderen Stelle, und bis heute kein eigenes Issue.

## Zweck Vollstaendig getracete Durchfuehrung des dokumentierten Upgrade-Pfads (INSTALL.md § "Eine Instanz aktualisieren", Weg Tarball) auf einer **echten ausgelieferten Instanz** - nicht im Ursprungs-Repo und nicht im CI-Replay. Ziel war eine Validierungsgrundlage, gegen die derselbe Lauf auf einer Dev-Instanz nachgestellt werden kann. Die Telemetrie des Laufs steht verbatim im ersten Kommentar. Sieben Befunde unten; keiner hat den Lauf zum Scheitern gebracht, vier davon kosteten jede Instanz Handarbeit, die der dokumentierte Weg nicht vorsah. **Ausgangslage:** Instanz aus `dist export`-Tarball, `VERSION` 5.0.0, `kb_version` 5.0.0, 63 Seiten, `language: de`, Harness Claude Code, sauberer Arbeitsbaum, ein Remote. **Herkunft der Befunde.** 1 bis 4 stammen aus dem Lauf selbst (2026-09-15). 5 bis 7 und die Ursachenanalyse unter Befund 1 stammen aus der Review-Sitzung vom 2026-09-16, die das Sitzungstranskript, die drei Ergebnis-Commits und den Endzustand der Instanz gegengelesen hat. ## Abgeschlossen: sechs Befunde erledigt, einer ausgelagert | Befund | Stand | |---|---| | 1 - Session-Id-Fallback zersplittert den Lauf | **ausgelagert nach #110.** Der Anleitungsteil ist mit `504149c` erledigt; was bleibt, ist eine Betreiberentscheidung und kein Bauauftrag | | 2 - `version notes` antwortete auf keiner Instanz | erledigt, `0c98080`, `6.1.0-beta.4` | | 3 - `dist upgrade` konnte die Release-Fassung nicht uebernehmen | erledigt, `72d01be`, `6.1.0-beta.3` | | 4 - Migrationsdokument nennt ein Beispiel, das das Gegenteil zeigt | erledigt, `0e09cf4`, `6.1.0-beta.2` | | 5 - Rest-Abschnitt `## Authoring guidance` | erledigt in der Instanz (`b5014d9`) und im Stack (`0e09cf4`) | | 6 - Verifikationsschritt ohne festgehaltene Baseline | erledigt, `0e09cf4` | | 7 - Upgrade-Pfad ohne agentengerichtete Prozedur | ausgelagert nach #108, dort erledigt: `504149c`, `6.1.0-beta.1` | **Dieses Issue ist der Laufbericht und wird als solcher nicht weiter bearbeitet.** Alle Werkzeugaenderungen, die aus ihm Bauauftraege waren, sind gebaut; beide Befunde, die eigene Arbeitspakete wurden, haben eigene Issues (#108 erledigt, #110 offen). Was hier bleibt und weiterhin Wert hat, ist die Evidenz: die vollstaendige Trace im ersten Kommentar, die Lauf-Zusammenfassung mit Zeitstempeln, und der Reproduktionsabschnitt, der pro Schritt sagt, ab welcher Version er nicht mehr reproduziert. ## Lauf-Zusammenfassung | Zeit (UTC) | Schritt | Ergebnis | |---|---|---| | 19:45:07 | `version check` | Update 5.0.0 -> 6.0.0, Grenzuebertritt gemeldet | | 19:45:18 | `migrate status` | nichts offen | | 19:45:18 | `version notes` | **Exit 1** - Befund 2 | | 19:46:03 | `dist upgrade --dry-run` | 201 unveraendert, 8 neu, **1 lokal geaendert**, 0 entfallen | | 19:46:31 | `dist upgrade` | **Exit 1** - Befund 3 | | 19:46:59 | `dist upgrade --dry-run` | Exit 1, Arbeitsbaum unsauber (nach Handreparatur) | | ~19:47 | `git commit` der Handreparatur | ausserhalb des Werkzeugs noetig - und ausserhalb von Invariante 5, siehe Befund 3 | | 19:47:17 | `dist upgrade --dry-run` | 202 / 8 / **0** / 0 | | 19:47:22 | `dist upgrade` | OK, 210 Dateien geschrieben | | 19:47:28 | `migrate status` | 1 optionales Upgrade, nichts blockiert | | 19:47:29 | `instructions sync` | 5 Skills publiziert | | 19:47:44 | `doctor` | alles OK, ein WARN (`session-id`) | | 19:47:46 | `docs verify` | **Exit 1** - TOC fehlt auf `types/concept.md`, `types/source.md` | | 19:47:53 | `docs toc --apply` | 2 Dateien repariert - wie in den Release-Notes angekuendigt | | 19:47:58 | `docs verify` / `instructions verify` / `lint` | gruen | | 19:48:28 | `publish` | **Exit 42**, Mass-Update-Gate, 69 Dateien, Token `96e2563ff596` | | 19:58:22 | `publish --confirm` | OK, Commit `dcc17df`, gepusht | | 20:02-20:06 | optionale Migration `6.0.0-type-guidance-split` | angenommen - Befund 4, 5, 6 | | 20:06:33 | `migrate done 6.0.0 --pages 0` | Angebot als genommen vermerkt | | 20:06:43 | `publish` | OK, Commit `c8c9f9b`, 5 Dateien, unter der Gate-Schwelle | 33 `wikitool.call`-Events insgesamt, ein einziger unerwarteter Exit-Code (`types describe source`, Exit 1 um 20:06:09 - das war SIGPIPE durch ein `| head` des Aufrufers, kein Werkzeugfehler; siehe Anmerkung unter Befund 1 und die Ursachenverkettung in Befund 6). **Nicht in der Tabelle, weil nie gelaufen:** `migrate verify --from <commit vor dem Tausch>`, INSTALL.md Schritt 6, erster Pruefschritt. Siehe Befund 7. --- ## Befund 1: Session-Id-Fallback zersplittert den Lauf - Join-Key tot, Iteration-Budget-Gate faktisch abgeschaltet **Ausgelagert nach #110.** Die Evidenz bleibt hier stehen, weil sie das Messergebnis dieses Laufs ist und den Befund ueberhaupt erst tragbar macht - dasselbe Muster wie bei Befund 7. Die Entscheidung, die Loesungsachsen und die Akzeptanzkriterien stehen in #110. ### Beobachtung Der Lauf ist **eine** Sitzung. Die Telemetrie kennt ihn als **21 Sitzungen**: ``` 21 session_ids: 671c1b9a-92dd-484b-b29a-bf6d29c006ff 3835015 3835056 3835179 3835232 3835285 3835339 3835353 3835371 3835425 3835460 3835471 3835548 3836791 3837235 3837668 3837691 3837722 3837739 3837778 3837804 ``` Aufgeschluesselt nach Quelle: | Quelle | Session-Id-Form | Events | |---|---|---| | `claude-code` (Hook) | UUID der echten Sitzung | 1 `session.start`, 5 `prompt.submitted` | | `wikitool` (Emitter) | **20 verschiedene Parent-PIDs** | 20 `session.start`, 33 `wikitool.call`, 1 `gate.refused`, 1 `gate.cleared`, 2 `publish.commit` | `WIKITOOL_SESSION_ID` war nicht gesetzt, der Fallback ist die Parent-PID (`chemenu/session.py`). Der Harness startet **pro Tool-Call eine neue Shell** - also pro Aufruf eine neue PID und damit eine neue "Sitzung". ### Folge 1: EVALS.md' Join-Key haelt nicht `EVALS.md` § Architecture: *"Everything joins on `WIKITOOL_SESSION_ID`."* In diesem Lauf joint **nichts**: die Hook-Events tragen die UUID, die wikitool-Events tragen 20 PIDs. Es gibt keinen gemeinsamen Schluessel. Das ist im Scorer direkt sichtbar. `eval score --session 3835548` (die Sitzung mit der Gate-Verweigerung) meldet: ``` - `skip` **clearance-ended-the-turn** - No wikitool.call between a clearance request (exit 42) and the next prompt.submitted. - this harness cannot report prompt.submitted - cannot say ``` Der Harness *hat* `prompt.submitted` gemeldet - 5 mal, nur unter der UUID. Ausgerechnet die L2-Regel, die Gate-Befolgung prueft, kann auf dem Hauptharness nie ein Urteil faellen. Das ist kein fehlender Hook (#82), sondern ein toter Schluessel: #82 wuerde `tool.pre`/`tool.post` ergaenzen, die dann **ebenfalls** unter der UUID landen und weiterhin nicht zu den `wikitool.call`-Events joinen. Die beiden Issues muessen zusammen gedacht werden, sonst verdrahtet #82 Hooks, deren Events immer noch niemand zuordnen kann. Ausserdem scort `eval score` jeweils 1 bis 3 Calls statt 33, waehrend die L1-Strukturpruefung in allen 21 Buckets identisch neu berechnet wird. Ein Lauf ist so nicht bewertbar. ### Folge 2: das Iteration-Budget-Gate erreicht seine Schwelle nie Gravierender, weil es eine der vier in Code gegossenen Sicherungen ist (`AGENTS.md` § Gates: 60 Calls pro Sitzung, Loop-Breaker bei 3 identischen in Folge). `tools/.wikitool_session/budget.json`, Stand nach dem Lauf: ``` 46 Session-Buckets; Counts absteigend: [9, 3, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, ...] ``` Der Hoechststand ist **9** - und der stammt aus `wiki-setup-nathan`, einem Bucket, in dem `WIKITOOL_SESSION_ID` *gesetzt* war. Jeder PID-Bucket kommt ueber **3** nicht hinaus. Bei 33 Calls in einem Lauf hat der Zaehler also nie mehr als 3 von 60 gesehen. Damit ist das Gate unter diesem Harness nicht "grosszuegig", sondern **strukturell unerreichbar** - und der Loop-Breaker gleich mit: drei identische Calls in Folge landen in drei verschiedenen Buckets. Eine Sicherung, die ausdruecklich deshalb in Code sitzt, weil ein Agent sich an einer Prompt-Regel vorbeireden kann (`docs/why-gates-are-code.md`), ist hier still aus. `doctor` sagt das Noetige bereits - nur als WARN und ohne die Folge zu nennen: ``` WARN session-id: WIKITOOL_SESSION_ID is not set - budget falls back to the parent PID fix: See instructions/session-setup.md ``` ### Ursache eine Ebene tiefer: `instructions/session-setup.md` war auf diesem Harness wirkungslos Nachgetragen aus der Review-Sitzung. `doctor` verweist auf `instructions/session-setup.md`, und dort stand als Schritt, woertlich: ```bash export WIKITOOL_SESSION_ID="wiki-$(date +%s)" tools/wikitool sync ``` *"Run this **once per working session**"* - genau das funktioniert auf Claude Code nicht. Der Harness fuehrt jeden Bash-Tool-Call in einer frisch initialisierten Shell aus; das Arbeitsverzeichnis wird uebernommen, Shell-State (Umgebungsvariablen, Funktionen) **nicht**. Ein `export` in Aufruf N ist in Aufruf N+1 verschwunden. Die 20 verschiedenen Parent-PIDs oben sind dieselbe Tatsache von der anderen Seite gemessen. Das aendert die Reichweite des Befunds: eine bessere Fallback-Kette repariert den Messwert, aber die Anleitung, die das Problem eigentlich verhindern soll, war auf dem Hauptharness ein No-op. **Erledigt mit `504149c` (`6.1.0-beta.1`, aus #108):** `instructions/session-setup.md` nennt jetzt die Inline-Form pro Aufruf, sagt warum ein `export` nur traegt solange die Shell traegt, und gibt den Einzeiler an, mit dem sich beantworten laesst, welcher Fall vorliegt. Der Rest dieses Befunds - Fallback-Kette, Join-Key, WARN-Haerte - ist davon unberuehrt und in #110 offen. ### Nebenbefund zur Trace-Treue `types describe source` steht mit `exit_code: 1` in der Trace (20:06:09). Der Aufruf war erfolgreich; der Exit-Code entstand durch SIGPIPE, weil der Aufrufer die Ausgabe durch `| head` geschickt hat. Der unmittelbar folgende identische Aufruf ohne Pipe steht mit `exit_code: 0` da. Wer die Trace als Fehlerquelle auswertet, zaehlt hier einen Werkzeugfehler, den es nicht gab. Dasselbe `| head` ist die Ursache von Befund 5 - siehe Befund 6. In #110 als Nebenbefund mitgenommen, weil er dieselbe Trace betrifft. --- ## Befund 2: `version notes` scheiterte auf jeder ausgelieferten Instanz - **erledigt** (`0c98080`, `6.1.0-beta.4`) `kind/defect` - Doku und Realitaet widersprachen sich. INSTALL.md § "Eine Instanz aktualisieren", Schritt 4, verbatim (Stand des Laufs): > 4. Bei einer Kompatibilitätsgrenze (`dist upgrade` meldet sie laut) die Release-Notes vor dem > nächsten Schritt lesen: **Breaking Change:** und **Migration:** im Eintrag von > `tools/wikitool version notes` sagen, was aufhört zu funktionieren und ob der Korpus > umgeschrieben werden muss. Der Aufruf auf der Instanz: ``` $ tools/wikitool version notes ERROR CHANGES.md has no entry for 5.0.0 - run `wikitool version bump` before releasing, or write the entry ``` ### Ursache `version notes` liest die lokale `CHANGES.md`. Eine ausgelieferte Instanz bekommt dafuer den Stub aus `tools/chemenu/dist_templates/CHANGES.md` - 9 Zeilen, Vorwort, **null Versionseintraege**. `CHANGES.md` steht ausserdem in `chemenu.ownership.is_upgrade_preserved`, wird von `dist upgrade` also bewusst nie ueberschrieben. Der Stub bleibt der Stub - **dauerhaft**. `version notes` konnte auf einer Instanz nicht nur damals nicht funktionieren, sondern nie. Das traf genau den Moment, fuer den der Schritt existiert: den Grenzuebertritt, an dem der Betreiber wissen muss, was aufhoert zu funktionieren. Der Lauf kam nur weiter, weil die Release-Notes ueber die Gitea-API gelesen wurden - ein Weg, den INSTALL.md an dieser Stelle nicht nannte, und den eine Instanz ohne erreichbaren MCP-Server gar nicht hat. Eine Zwischenstufe hat den Widerspruch *dokumentarisch* beseitigt, den Defekt aber nicht: INSTALL.md verweist seit `504149c` auf `instructions/upgrade-instance.md`, deren Schritt 2 die Release-Seite aus `release_url` las und ausdruecklich sagte, dass `version notes` auf einer Instanz nicht antwortet. ### Umgesetzt: Fallback auf den Release-Feed, laut angekuendigt Von den beiden erwogenen Wegen der erste. Ausschlaggebend war, dass `instructions/upgrade-instance.md` Schritt 2 den eigenen Workaround-Absatz schon als temporaer fuehrte (*"This paragraph stops being necessary the day `version notes` falls back to that feed"*): die billigere Variante haette ihn dauerhaft stehenlassen. Die Regel, in drei Faellen: 1. **Der lokale `CHANGES.md`-Eintrag ist da** -> er wird gedruckt. Unveraendert, und der einzige Fall, den das Ursprungs-Repo und CI je erreichen. 2. **Kein Eintrag und kein Release-Stamp** (ein Dev-Checkout) -> die alte Fehlermeldung, unveraendert. Das ist der Wachhund gegen einen Netzaufruf im Ursprungs-Repo: nur eine *ausgelieferte* Instanz geht online, und `release.yml`s `version notes > /tmp/release-notes.md` kann den neuen Pfad damit nie betreten. Ein Test verdrahtet einen Fetcher, der beim Aufruf `AssertionError` wirft, und prueft, dass er nicht aufgerufen wird. 3. **Kein Eintrag, aber ein Release-Stamp** (eine ausgelieferte Instanz) -> der Feed aus `update_url` wird gefragt, derselbe, den `version check` benutzt (`WIKITOOL_UPDATE_URL` und `--url` uebersteuern ihn wie dort). `--offline` verweigert den Aufruf und faellt auf die Fehlermeldung zurueck, die dann `release_url` aus dem Stamp nennt. **Die Notes gehen nach stdout, die Herkunft nach stderr.** `version notes` existiert, damit der Release-Workflow kein Markdown in der Shell parsen muss (`release.yml`: `version notes > /tmp/release-notes.md`), also darf stdout nichts als den Eintrag tragen. **Antwortet der Feed eine andere Version als die gefragte**, wird das in der stderr-Kopfzeile benannt und die Notes werden trotzdem gedruckt. Das ist nicht der Randfall, sondern der Hauptfall: in Schritt 2 des Upgrades steht `VERSION` noch auf der *alten* Version, waehrend die gesuchten Notes die der neuen sind. Der Feed kennt nur `/releases/latest` - `update_url` ist die einzige URL, die der Stamp traegt, und eine `/releases/tags/<tag>`-URL daraus zusammenzusetzen waere geraten statt gelesen (Invariante 7). **Nicht erreichbarer Feed:** Exit 1, mit dem Feed-Fehler *und* `release_url` aus dem Stamp. Ein leerer `body` faellt genauso aus - eine leere Antwort darf nicht als "dieses Release hat nichts zu melden" durchgehen. Nachgezogen: `instructions/upgrade-instance.md` Schritt 2 (Workaround-Absatz weg, dafuer die beiden Dinge, die man vor dem Lesen der Ausgabe wissen muss), das Vorwort derselben Datei (es nennt keine Werkzeugluecke mehr - es waren zwei, jetzt sind es null), INSTALL.md § "Version und Updates" an zwei Stellen (die Notes-Quelle, und die inzwischen falsche Behauptung, `version check` sei der einzige Befehl, der ins Netz geht), `tools/CONTRACT.md` in beiden Tabellen sowie die Modul-Docstrings von `version_cmd.py` und `version.fetch_latest`, die dieselbe Ein-Netzaufruf-Behauptung trugen. --- ## Befund 3: `dist upgrade` kannte keinen Weg, die Release-Fassung einer lokal geaenderten Datei zu uebernehmen - **erledigt** (`72d01be`, `6.1.0-beta.3`) `kind/defect` / fehlende Faehigkeit. ### Beobachtung Der Dry-Run meldete genau eine lokal geaenderte Datei: ``` 201 unchanged, 8 new, 1 locally changed, 0 removed from the release. Locally modified (1): - kb/CONTRACT.md ``` Der Unterschied war **reine Whitespace-Formatierung** einer Markdown-Tabelle (Spaltenauffuellung, vermutlich ein Format-on-Save), inhaltlich identisch. `kb/CONTRACT.md` ist dabei stackeigen: `instructions/private-instance.md` fuehrt `<stage>/CONTRACT.md` ausdruecklich als Maschinerie, an der *"an instance never edits it"*. Beide damals angebotenen Wege waren hier falsch: - `--keep-local` **behielt** die Drift. Der neue Stamp schreibt trotzdem die Release-Digest - die Datei divergierte also bei **jedem** kuenftigen `dist upgrade` erneut und wurde jedes Mal wieder gemeldet. Fuer eine Datei, die der Instanz gar nicht gehoert, der dauerhaft falsche Zustand. - "reconcile by hand" war der richtige Weg, hatte aber kein Werkzeug: Handkopie aus dem entpackten Tarball, dann ein Commit nur zur Herstellung der Clean-Tree-Vorbedingung des naechsten Kommandos. Drei Schritte, zwei davon ausserhalb des Werkzeugs. Die Sauberkeits-Vorbedingung und die Handreparatur standen sich dabei gegenseitig im Weg: die Reparatur macht den Baum unsauber, den das Kommando sauber verlangt. ### Der Preis war eine Invariantenverletzung Das schaerfste Argument fuer eine Werkzeugloesung: der Commit `7fe8353` ist ein **rohes `git add` + `git commit`**. `AGENTS.md` Invariante 5 sagt *"Never call raw `git commit`/`git push`. Publish through `tools/wikitool publish`"* und kennt keine Ausnahme fuer "ist ja nur eine Vorbedingung". Richtig waere `tools/wikitool publish --no-push` gewesen. Bemerkenswert ist weniger der Fehlgriff als die Richtung: eine fehlende Werkzeugfaehigkeit hat den Lauf an einer in Code gegossenen Regel vorbeigefuehrt, und nichts hat es gemeldet - kein Gate, kein Check, kein Scorer. ### Erwartungshaltung aus dem Transkript Der Agent kuendigte um 19:46:28, *vor* dem Lauf ohne Flag, woertlich an: *"I'll let the upgrade take the release's version rather than pinning the local formatting"* - und rief `dist upgrade` dann ohne Flag auf. Das Mentalmodell war also "Default = Release-Fassung nehmen"; der Default ist Abbruch. Die Fehlermeldung korrigierte das nicht: sie nannte `--keep-local` und "reconcile by hand", sagte aber nicht, dass es zu `--keep-local` kein Gegenstueck gibt. Es fehlte damit nicht nur ein Flag, sondern auch der Satz, der die falsche Erwartung abfaengt. ### Umgesetzt: `--take-release <pfad>`, wiederholbar `--take-release` nimmt einen Pfad und ist wiederholbar (wie `search --field`), statt ein pauschales Gegenstueck zu `--keep-local` zu sein. Der Grund ist die Asymmetrie der beiden Antworten: `--keep-local` laesst alles stehen und verliert nichts, `--take-release` verwirft eine lokale Aenderung. Eine Verwerfung benennt ihr Ziel - dasselbe Muster, das `issue-tracking.md` Schritt 1 fuer destruktive Schritte verlangt -, und der gemischte Fall (zwei geaenderte Dateien, eine davon zurueckzusetzen) ist damit ueberhaupt erst loesbar. - Ein Pfad, der gar nicht in der blockierten Liste steht, ist **Exit 1** mit der Liste dessen, was dort steht - und zwar **auch im `--dry-run`**: das ist ein Fehler im *Argument*, nicht ein Zustand des Baums, und ein still ignorierter Tippfehler haette ein erfolgreiches Upgrade gemeldet und die Aenderung behalten, die verworfen werden sollte. Es ist die einzige Verweigerung, die einen Dry-Run nicht-null macht; ein blockierter Pfad tut das weiter nicht. - Eine lokal *geloeschte* Datei ist ein gueltiges Ziel: die Release-Fassung wird wieder angelegt. - `--take-release` und `--keep-local` zusammen sind erlaubt und komponieren. **Ohne** `--keep-local` bricht ein blockierter Pfad, zu dem nichts gesagt wurde, weiter ab. - Nach `--take-release` stimmt die Datei wieder mit der Stamp-Digest ueberein, die Drift ist also *weg* und nicht nur ueberschrieben - genau der Unterschied zu `--keep-local`. - Der Dry-Run markiert jeden benannten Pfad als einen, den er aus dem Release ueberschreiben wuerde. **Die Fehlermeldung des Abbruchs nennt alle drei Antworten samt fertiger Kommandozeile**, im Muster des Mass-Update-Gates, das seine `--confirm`-Zeile ebenso zum Einsetzen ausdruckt: ``` ERROR 1 locally changed file(s) (listed above) would be silently overwritten. Nothing was written, and none of these three is the default: - take the release's version and discard the local change: dist upgrade <source> --take-release kb/CONTRACT.md - keep every local change and upgrade around them (it is reported again on every future upgrade): dist upgrade <source> --keep-local - reconcile them by hand first, then re-run. ``` Nachgezogen: `instructions/upgrade-instance.md` Schritt 6 traegt statt der Drei-Schritt-Handreparatur die Entscheidung pro Pfad und den Dry-Run, mit dem man sie vorher sieht; Schritt 7 nimmt die Flags mit. `tools/CONTRACT.md` in beiden Tabellen. Bewusst **nicht** geaendert: die Dirty-Tree-Vorbedingung - mit `--take-release` entfaellt die Handreparatur und damit der unsaubere Baum, den sie erst erzeugte. --- ## Befund 4: `6.0.0-type-guidance-split` nennt ein Beispiel, das in der Instanz das Gegenteil zeigt - **erledigt** (`0e09cf4`) `kind/defect`, Dokumentation. Betraf das mitgelieferte Migrationsdokument, nicht den Code. ### 4a - das benannte Beispiel war in der Instanz die unmigrierte Datei `instructions/migrations/6.0.0-type-guidance-split.md`, Schritt 4, verbatim (Stand des Laufs): > 4. **Delete the now-duplicated prose from the type-spec**, keeping the H1, a short pointer to the > guidance file (`types/entity.md`'s own current text is the worked example), `## Frontmatter` > and `## Template`. Im Ursprungs-Repo stimmt das: dort ist `types/entity.md` die stackeigene, bereits migrierte Datei. In einer **ausgelieferten Instanz** ist `types/entity.md` die beim Setup adoptierte Kopie - also genau die Datei, die noch die *alte*, zu entfernende Prosa traegt. Wer dem Satz woertlich folgte, schrieb den Vorher-Zustand ab. Das gesuchte Beispiel liegt in der Instanz unter **`types/entity.md.template`** - dort steht der Nachher-Zustand (Pointer-Absatz, `guidance:`-Feld in der Frontmatter), weil `dist upgrade` die Templates verbatim mitliefert. **Verschaerfung aus der Review-Sitzung, gegen den Baum bestaetigt:** im Ursprungs-Repo existiert ueberhaupt keine `types/*.md.template`-Datei - `dist export` re-keyt `types/<name>.md` erst beim Export zur `.template` (`dist_cmd._owned_type_stem`, `_plan_types`). Der Satz konnte in einer Instanz also nicht bloss unguenstig sein, er konnte dort strukturell nie stimmen. **Umgesetzt:** der Schritt (jetzt Schritt 5, nach dem neu eingezogenen Vorher-Schritt aus Befund 6) nennt `types/<name>.md.template` als Beispiel und sagt den Grund dazu - `types/<name>.md` ist die adoptierte Kopie und damit die Datei, die gerade geaendert wird, die `.template` daneben traegt den Nachher-Zustand. Mit dem Zusatz, die `.template` fuer die *Form* zu lesen und nicht wholesale zu kopieren: ihre `## Frontmatter` und ihr `## Template` sind die Stack-Defaults, nicht die der Instanz. ### 4b - die Sprachfrage blieb offen, direkt nachdem 6.0.0 sie verschoben hat Das Dokument sagte nicht, in welcher Sprache der neue Pointer-Absatz zu schreiben ist. Fuer eine Instanz mit `language: de` war das nicht ableitbar, denn 6.0.0 hatte diese Grenze gerade erst neu gezogen (Bump "Control-Plane-Sprache universell", `docs/language-boundaries.md`). **Umgesetzt, und dabei gegen `types/type-spec.md` § "Who owns a type-spec" korrigiert.** Die im urspruenglichen Befund vorgeschlagene Begruendung *"ein Abschnitt, den die Instanz behaelt, ist ihrer, also traegt er die KB-Sprache"* haelt gegen den Baum **nicht**: die Sprachachse ist der Leser, nicht der Eigentuemer. Anleitungsprosa in einem Type-Spec ist Control Plane und damit englisch, unabhaengig davon, wem die Datei gehoert - so steht es in der Tabelle in `types/type-spec.md`, so steht es im Docstring von `dist_cmd.instance_owned_type_stems` (*"Ownership, not language"*), und so steht es in `AGENTS.md` § File naming. Das Ergebnis von Befund 5 war trotzdem richtig, nur die Begruendung nicht: der uebrige Bullet war redundant und gehoerte weg, nicht uebersetzt. Das Dokument sagt jetzt entsprechend: | Teil des Type-Specs | Sprache | Begruendung | |---|---|---| | H1, Pointer-Absatz | Englisch | Anleitungsprosa an einen Agenten = Control Plane, egal wem die Datei gehoert | | **behaltene lokale Prosa** | Englisch | ebenfalls Anleitungsprosa - eine vor dieser Regel in der KB-Sprache geschriebene Notiz wird **uebersetzt, nicht umbenannt** | | `## Frontmatter`-Tabelle | unveraendert lassen | die Migration fasst Frontmatter ausdruecklich nicht an | | `## Template`-Block + Nachsatz | unveraendert lassen (hier: deutsch) | Seitentext in der KB-Sprache | Die Tabelle steht im Dokument **nicht** als Kopie - der Schritt sagt die Antwort in zwei Saetzen und verlinkt `types/type-spec.md` § "Who owns a type-spec" fuer die vollstaendige Aufteilung (Invariante 8). Der Satz *"eine englische Ueberschrift ueber einem Koerper in einer anderen Sprache ist die halbfertige Fassung dieses Schritts"* benennt genau den Zustand, den Befund 5 produziert hat. Dazu neu, weil es der eigentliche Mechanismus hinter Befund 5 ist: **eine behaltene Notiz darf nicht `## Authoring guidance` heissen.** `types describe` setzt diesen Kopf selbst und inlined darunter die Guidance-Datei, die ihren eigenen gleichnamigen Abschnitt mitbringt - ein dritter aus dem Type-Spec-Koerper ist die Doppelung. ### 4c - kleinere Beobachtung zur Schrittfolge Schritt 6 (`migrate done 6.0.0 --pages 0`) tut genau, was es verspricht, und die Ausgabe ist unmissverstaendlich: ``` OK Recorded the optional 6.0.0-type-guidance-split. Content stays at 5.0.0 - an offer changes a file you own, not the shape of your content. ``` Danach bleibt `doctor` bei `kb-version: 5.0.0 (nothing outstanding up to 6.0.0)`. Das ist korrekt und dokumentiert, sieht aber auf den ersten Blick nach einem haengengebliebenen Upgrade aus. Keine Aenderung noetig - hier nur vermerkt, weil eine Dev-Instanz-Validierung sonst darueber stolpert. --- ## Befund 5: Rest-Abschnitt `## Authoring guidance` - **repariert in der Instanz (`b5014d9`) und im Stack (`0e09cf4`)** `kind/defect`. Gefunden in der Review-Sitzung, live gegengeprueft und dort auch behoben. Steht hier, weil er die Wirkung von Befund 4b und Befund 6 belegt. ### 5a - die Instanz (`b5014d9`) Bei `types/source.md` wurde der Abschnitt `## Autorenanweisungen` nicht geloescht, sondern zu `## Authoring guidance` **umbenannt**, mit einem verbliebenen deutschen Bullet: ```markdown ## Authoring guidance - Der Titel beginnt mit "Source - ", gefolgt vom Namen der Quelle ``` Zwei Fehler in drei Zeilen: 1. **Ein dritter Kopf desselben Namens in der komponierten Ausgabe.** Zwei sind der Normalzustand und kein Befund: `types describe` setzt selbst einen `## Authoring guidance`-Kopf und inlined darunter die Guidance-Datei, die ihren eigenen gleichnamigen Abschnitt mitbringt - so sieht es bei allen vier Typen aus. `source` hatte danach einen dritten aus dem Type-Spec selbst. 2. **Englische Ueberschrift ueber deutschem Inhalt** in einer instanzeigenen Datei. Die Grenze, an der das falsch ist, ist der *Leser*, nicht der Eigentuemer - siehe die Korrektur unter Befund 4b: Anleitungsprosa bleibt englisch, auch in einer Datei, die der Instanz gehoert. Richtig war hier trotzdem das Entfernen, weil der Bullet redundant zum `title_prefix: "Source - "` in der Frontmatter war, das `wikitool new source` ohnehin erzwingt. `entity`, `concept` und `comparison` waren sauber - betroffen war nur `source`, der einzige der vier Typen, dessen Prosa umfangreich genug war, dass ein Bullet uebrigblieb, den die Stack-Guidance nicht abdeckt. **Behoben mit `b5014d9`:** Abschnitt ersatzlos entfernt, geprueft mit dem Muster aus Befund 6 - `types describe source` vor und nach der Aenderung in je eine Datei, dann `diff`. Der Diff zeigt genau die vier entfernten Zeilen und sonst nichts; alle vier Typen komponieren jetzt mit zwei Koepfen. ### 5b - derselbe Defekt im Stack selbst (`0e09cf4`) **Nachgetragen 2026-09-16, gefunden beim Nachmessen im Ursprungs-Repo.** Das Kriterium unten war gegen die Instanz `nathan` abgehakt, gegen den Stack nie - und dort stand derselbe Rest-Abschnitt: ``` $ grep -c '^## Authoring guidance' <types describe $t> entity: 2 concept: 2 source: 3 comparison: 2 ``` `types/source.md` im Ursprungs-Repo trug bis `0e09cf4` einen `## Authoring guidance`-Abschnitt mit demselben einen Bullet (hier englisch, weil `c64479f` ihn uebersetzt hatte; `d49513b` hat dann den Rest der Prosa ausgelagert und ihn stehenlassen). Das ist kein Instanzschaden, sondern ein Auslieferungsdefekt: die Datei wird beim Export zu `types/source.md.template`, **jede neu aufgesetzte Instanz haette ihn mit adoptiert** - und ihn dann bei der naechsten `guidance`-Migration genau so wiedergefunden wie `nathan`. Entfernt, geprueft mit demselben Vorher/Nachher-Diff: genau vier Zeilen weg, sonst nichts, alle vier Typen bei zwei Koepfen. Inhaltlich verloren geht nichts - `title_prefix` steht in der Frontmatter, in der Feldtabelle von `types/type-spec.md` und im Nachsatz zum `## Template`-Block von `types/source.md`; ausserdem verbietet `types/type-spec.md` § Writing Shape das Wiederholen einer Schema-Regel im Fliesstext ausdruecklich. **Nebenbeobachtung, kein Befund:** dass `types describe` einen `## Authoring guidance`-Kopf setzt und unmittelbar darunter eine Guidance-Datei mit eigenem H1 *und* eigenem gleichnamigem Abschnitt inlined, ist eine kosmetische Doppelung im Stack selbst - gleich fuer alle vier Typen, ohne Auswirkung auf Inhalt oder Werkzeuge. --- ## Befund 6: Schritt 5 des Migrationsdokuments war als Verifikation unfalsifizierbar - **erledigt** (`0e09cf4`) `kind/defect`, Dokumentation. Direkte Ursache von Befund 5. `instructions/migrations/6.0.0-type-guidance-split.md`, Schritt 5, verlangte: > The output must read the same as it did before this migration [...] the structure (frontmatter > fields, template block) must be byte-identical. Kein Schritt davor hielt das Vorher fest. Eine Pruefung gegen einen Zustand, den niemand aufgeschrieben hat, ist keine Pruefung - sie faellt auf das Gedaechtnis des Ausfuehrenden zurueck, und bei einer Ausgabe von ueber 150 Zeilen je Typ ist das keins. Der Lauf hat entsprechend geprueft: `types describe` durch `| head -250` und `| tail -80`, also in Ausschnitten, mit dem Urteil *"All four compose correctly, structurally identical to before"*. Der Rest-Abschnitt aus Befund 5 liegt in der Mitte der `source`-Ausgabe und war in keinem der beiden Ausschnitte. Dasselbe `| head` erzeugte zugleich den SIGPIPE-Exit-1, den der Nebenbefund unter Befund 1 als Trace-Rauschen fuehrt: ein Verhalten, zwei Symptome. **Umgesetzt an beiden Stellen:** 1. **Das Dokument** hat einen eigenen Schritt 3 bekommen - `types describe <name>` vollstaendig in eine Datei, *vor* der Aenderung, mit dem Satz, dass ein `head`/`tail` genau die Mitte verschwinden laesst. Schritt 6 diffed dagegen und nennt zusaetzlich die Ein-Zahl-Probe `grep -c '^## Authoring guidance'`: zwei ist richtig, drei heisst Rest-Abschnitt im Type-Spec. Die alten Schritte 3-6 sind auf 4-7 gerueckt, die Querverweise mit. 2. **`instructions/migrate-corpus.md` § "Writing the migration document"** traegt das Muster generisch: ein Verifikationsschritt nennt seine eigene Baseline, und zwar in einem frueheren Schritt. `migrate verify` traegt seine im letzten Commit, ob jemand daran denkt oder nicht - eine Migration an der Maschinerie statt an `kb/` hat gar keine, und genau dort entsteht die Behauptung, die sich nicht widerlegen laesst. Nicht angefasst: `instructions/upgrade-instance.md` Schritt 12, der seit `504149c` dasselbe in Richtung des *Ausfuehrenden* sagt. Zwei Adressaten, zwei Regeln - der Autor eines Migrationsdokuments und der Betreiber, der eines abarbeitet -, also keine zweite Kopie im Sinne von Invariante 8. --- ## Befund 7: der Upgrade-Pfad hatte keine agentengerichtete Prozedur - **ausgelagert nach #108, dort erledigt** `kind/defect`, Prozess. Umgesetzt mit `504149c` (`6.1.0-beta.1`); hier bleibt die Evidenz aus dem Lauf stehen, weil sie die Begruendung der Loesung traegt - dasselbe Muster, mit dem Befund 1 jetzt nach #110 gegangen ist. Die Schrittfolge stand nur in INSTALL.md - einem Dokument fuer Menschen (`AGENTS.md` § File naming: README-foermige Wurzeldateien werden *"never by an agent as instruction"* geladen). Ausgefuehrt wird sie von einem Agenten. Der erste Tool-Call des Laufs listete `instructions/` mit - der Agent suchte also zuerst eine Instruktion, fand keine, oeffnete `instructions/private-instance.md` (der falsche Weg: Clone mit gemeinsamer History statt Tarball-Instanz), verwarf sie und griff auf INSTALL.md zurueck. Was im selben Lauf daraus folgte: - **`migrate verify --from <commit vor dem Tausch>` wurde nie ausgefuehrt**, obwohl es in INSTALL.md Schritt 6 der erste Pruefschritt war. Die Lauf-Tabelle oben belegt es lueckenlos. Der Grund ist praezise benennbar: der Lauf folgte nicht INSTALL.md, sondern dem Abschlussbericht von `dist upgrade` - und in dessen Liste kam `migrate verify` nicht vor. - **Die Agent-Session wurde nie neu gestartet.** Beide Reihenfolgen verlangten das, die eine am Ende von Schritt 6, die andere am Ende des Abschlussberichts. Die optionale Migration lief anschliessend unter dem 5.0.0-Kontrollplan, obwohl `AGENTS.md` im selben Commit +44/-3 bekommen hatte - und genau dort fielen Befund 4b (Sprachgrenze, neu in 6.0.0) und Befund 5 an. - **Drei Reihenfolgen waren im Umlauf**: INSTALL.md Schritt 6, der Abschlussbericht, und die tatsaechlich gelaufene. Dass der Lauf der zweiten folgte, machte die erste zu toter Doku - genau der Zustand, den Invariante 8 verbietet. Umgesetzt: `instructions/upgrade-instance.md` (`manual: true`) ist die eine Fassung, dreizehn Schritte, mit dem Sitzungsneustart zwischen Maschinerie-Publish und Migrationskette statt am Ende und `migrate status` als Wiedereinstiegspunkt. Der Abschlussbericht von `dist upgrade` nennt jetzt die Datei und das Wiedereinstiegskommando statt einer eigenen Liste, INSTALL.md nur noch die Entscheidung davor. Details und Abgrenzung: #108. --- ## Was der Lauf bestaetigt hat Ausdruecklich keine Befunde - das hat gehalten: - **Der angekuendigte Grenzuebertritt kam exakt wie beschrieben.** Die Release-Notes sagten voraus, dass `docs verify` nach dem Update auf adoptierten Page-Type-Specs ohne TOC-Region faellt, und nannten `docs toc --apply` als Reparatur. Genau das trat ein (`types/concept.md`, `types/source.md`), und genau das reparierte es - ein Werkzeuglauf, keine Inhaltsmigration. **Nicht identisch mit #106**: dort ging es um `kb/CONVENTIONS.md.template` auf einer *frischen* Instanz; hier um adoptierte `types/*.md` auf dem *Upgrade*-Pfad. Der in #106 umgesetzte Fix (Templates in `toc.target_files()`) deckt diesen Fall nicht ab, weil die betroffenen Dateien bereits im Dateisatz stehen - ihnen fehlte die Region nur, weil sie vor der Scope-Erweiterung adoptiert wurden. - **`dist upgrade` klassifiziert korrekt** - 202 unveraendert / 8 neu / 0 lokal geaendert / 0 entfallen, und die 8 neuen Dateien waren exakt die des Bumps (4 `*.guidance.md`, `types/type-guidance.md(.schema.yaml)`, `docs/language-boundaries.md`, das Migrationsdokument). - **`migrate status` hat richtig nicht blockiert.** "Migration: none required" aus den Release-Notes und "Nothing outstanding" aus dem Werkzeug stimmten ueberein. - **Das Mass-Update-Gate hat sauber gearbeitet**: Exit 42 bei 69 Dateien, Token an Dateiliste *und* Inhalt gebunden, Freigabe mit demselben Token akzeptiert, `gate.refused`/`gate.cleared` beide in der Trace. Als Datenpunkt fuer #53: 69 Dateien bei Schwelle 10, und der zweite Publish desselben Laufs lag mit 5 Dateien darunter. - ~~`types describe` komponiert nach der Migration unveraendert.~~ **Korrigiert durch Befund 5:** fuer `entity`, `concept` und `comparison` stimmte es; fuer `source` nicht - dort stand bis `b5014d9` (Instanz) bzw. `0e09cf4` (Stack) ein dritter `## Authoring guidance`-Kopf in der komponierten Ausgabe. Was fuer alle vier haelt: Frontmatter-Felder und `## Template`-Block sind byte-gleich, nur die Herkunft der Anleitungsprosa hat gewechselt. ## Reproduktion auf einer Dev-Instanz Die Reproduktion gilt **gegen einen 6.0.0-Tarball** - also gegen die Maschinerie, in der die Befunde aufgetreten sind. Wie ein Lauf gegen das Ergebnis dieses Issues stattdessen ausgeht, steht unter dem Block. ```bash # 1. Instanz auf 5.0.0 herstellen (aus einem 5.0.0-Checkout) tools/wikitool dist export /tmp/inst-5.0.0 cd /tmp/inst-5.0.0 && git init -q -b main git config user.name Dev && git config user.email dev@example.invalid # Templates adoptieren wie instructions/setup-instance.md Schritt 5/6 python3 -m venv tools/.venv && tools/.venv/bin/pip install -q -r tools/requirements.txt tools/wikitool instructions sync && tools/wikitool index rebuild git add -A && git commit -qm baseline # 2. Die Drift dieses Laufs nachstellen (Befund 3) # kb/CONTRACT.md durch einen Markdown-Formatter schicken - Whitespace-only, # inhaltlich identisch - und committen. # 3. Nicht setzen, um Befund 1 zu reproduzieren: WIKITOOL_SESSION_ID # Jeden wikitool-Aufruf aus einer eigenen Shell absetzen (wie ein Agent-Harness es tut). # 4. Upgrade fahren tools/wikitool version check # meldet Grenzuebertritt tools/wikitool version notes # ERWARTET Exit 1 -> Befund 2 tools/wikitool dist upgrade <6.0.0-tarball> --dry-run tools/wikitool dist upgrade <6.0.0-tarball> # ERWARTET Exit 1 -> Befund 3 # -> Handreparatur + Commit, dann erneut tools/wikitool migrate status && tools/wikitool instructions sync tools/wikitool doctor tools/wikitool docs verify # ERWARTET Exit 1 auf types/*.md tools/wikitool docs toc --apply && tools/wikitool docs verify tools/wikitool instructions verify && tools/wikitool lint # 5. Befund 1 messen - der einzige Teil, der weiter reproduziert (siehe #110) python3 -c "import json;d=json.load(open('tools/.wikitool_session/budget.json'));\ print(len(d),'Buckets; max count:',max(e.get('count',0) for e in d.values()))" tools/wikitool eval sessions # ERWARTET: viele Buckets, je 1-3 Events # 6. Befund 5/6 reproduzieren: die optionale Migration fahren und vorher/nachher diffen tools/wikitool types describe source > /tmp/source-vorher.txt # ... Schritte 3 und 4 des Migrationsdokuments ausfuehren ... tools/wikitool types describe source > /tmp/source-nachher.txt diff /tmp/source-vorher.txt /tmp/source-nachher.txt # ERWARTET ohne Gegenmassnahme: ein dritter "## Authoring guidance"-Kopf im Nachher grep -c '^## Authoring guidance' /tmp/source-nachher.txt # ERWARTET 3, korrekt sind 2 # Gegenprobe: bei entity/concept/comparison sind es vorher wie nachher 2 ``` **Was ab dem jeweiligen Stand nicht mehr reproduziert:** | Ab | Schritt | |---|---| | `6.1.0-beta.2` | Schritt 6 - die Stack-Kopie ist sauber, eine frische Instanz startet bei zwei Koepfen, und das Migrationsdokument schreibt Vorher-Datei und Diff selbst vor | | `6.1.0-beta.3` | Schritt 4, zweites `ERWARTET Exit 1` - der Abbruch nennt jetzt `--take-release <pfad>` als dritten Weg, und der erledigt den Fall in einem Kommando statt in drei Handgriffen | | `6.1.0-beta.4` | Schritt 4, erstes `ERWARTET Exit 1` - `version notes` antwortet aus dem Feed | **Schritt 5 reproduziert unveraendert** und ist damit der Reproduktionsabschnitt, den #110 erbt. ## Akzeptanzkriterien Erledigt: - [x] **Befund 1, Anleitungsteil:** `instructions/session-setup.md` nennt eine Form, die auf einem Harness mit Shell-pro-Tool-Call wirkt - nicht nur `export` einmal pro Sitzung. Erledigt in #108 (`504149c`): Inline-Form pro Aufruf, mit dem Einzeiler zum Feststellen, welcher Fall vorliegt. - [x] **Befund 2:** `tools/wikitool version notes` liefert auf einer frisch ausgelieferten Instanz die Notes des installierten Release aus dem Feed - stdout traegt nur den Eintrag, die Herkunftszeilen gehen nach stderr, `--offline` verweigert den Netzaufruf, und ein Dev-Checkout ohne Release-Stamp betritt den Pfad nie. Erledigt mit `0c98080`; die Stamp-Grenze ist mit einem Test abgesichert, der einen werfenden Fetcher verdrahtet und prueft, dass er nicht aufgerufen wird. - [x] **Befund 2:** Ein unerreichbarer Feed ist Exit 1 mit Feed-Fehler *und* `release_url` aus dem Stamp - nie eine stille Antwort und nie ein Abbruch ohne die Seite, die der Mensch stattdessen lesen kann. Ein leerer `body` faellt genauso aus. - [x] **Befund 2:** `instructions/upgrade-instance.md` Schritt 2 traegt den Workaround-Absatz nicht mehr, und INSTALL.md § "Version und Updates" sagt nicht mehr, dass der Befehl auf einer Instanz nicht antwortet. Das Vorwort der Instruktion nennt gar keine Werkzeugluecke mehr - es waren zwei, beide sind mit diesem Issue weg. - [x] **Befund 3:** Eine lokal geaenderte stackeigene Datei laesst sich in **einem** Kommando auf die Release-Fassung zuruecksetzen (`dist upgrade <source> --take-release <pfad>`), ohne Handkopie und ohne Vorbereitungs-Commit; `tools/CONTRACT.md`s `dist upgrade`-Zeile und die Fehlerkontrakt-Zeile nennen den Weg. Erledigt mit `72d01be`. - [x] **Befund 3:** Ein `--take-release`-Pfad, der nicht blockiert ist, ist Exit 1 - auch im `--dry-run`, damit ein Tippfehler vor dem Schreiblauf auffaellt. Es bleibt die einzige Verweigerung, die einen Dry-Run nicht-null macht; ein blockierter Pfad tut das weiter nicht. - [x] **Befund 3:** Die Fehlermeldung des Abbruchs nennt alle drei Antworten samt einsetzbarer Kommandozeile und sagt, dass keine davon der Default ist - so, dass "Default = Release nehmen" nicht als Erwartung stehenbleibt. Mit einem Test, der genau auf diese vier Bestandteile prueft. - [x] **Befund 4:** Das Migrationsdokument verweist auf `types/entity.md.template` und sagt, in welcher Sprache der Pointer-Absatz zu schreiben ist. Erledigt mit `0e09cf4`; die Sprachregel ist dabei gegen `types/type-spec.md` § "Who owns a type-spec" korrigiert worden (Leser, nicht Eigentuemer - siehe Befund 4b) und wird verlinkt statt kopiert. - [x] **Befund 5:** `tools/wikitool types describe source` gibt in der Instanz `nathan` so viele `## Authoring guidance`-Koepfe aus wie bei den anderen drei Typen (zwei), und kein Abschnitt dort traegt eine englische Ueberschrift ueber deutschem Inhalt. Erledigt mit `b5014d9`, geprueft per Vorher/Nachher-Diff. - [x] **Befund 5:** Dasselbe gilt im **Ursprungs-Repo**, dessen `types/source.md` beim Export zu `types/source.md.template` wird - sonst adoptiert jede neue Instanz den Defekt erneut. Erledigt mit `0e09cf4`, geprueft per Vorher/Nachher-Diff: vier entfernte Zeilen, alle vier Typen bei zwei Koepfen. - [x] **Befund 6:** Schritt 5 des Migrationsdokuments verlangt eine festgehaltene Vorher-Ausgabe und einen Diff; `instructions/migrate-corpus.md` fuehrt dasselbe Muster fuer kuenftige `assisted`-Migrationen. Erledigt mit `0e09cf4` (neuer Schritt 3 im Dokument, § "Writing the migration document" in `migrate-corpus.md`). - [x] **Befund 7:** abgehandelt in #108 - `instructions/upgrade-instance.md` (`manual: true`) existiert, `dist upgrade`s Abschlussbericht nennt sie, INSTALL.md traegt die Schrittfolge nicht mehr doppelt. - [x] `pytest`, `docs verify`, `instructions verify` ohne neue Befunde fuer alles, was dieses Issue gebaut hat. Stand `6.1.0-beta.4`: 1290 Tests (1276 vor der letzten Sitzung, +8 fuer `--take-release`, +6 fuer den `version notes`-Fallback), auch gegen eine leere Maschine nach `instructions/dev/testing-conventions.md` Schritt 6 identisch gruen; `docs verify` mit 73 ausgelieferten Dokumenten und 58 Referenzdateien; `instructions verify` mit 23 Instruktionen und 7 Skills. CI gruen auf `72d01be` (Laeufe 298, 299), `0c98080` (300, 301) und `536093f` (302). Nicht erledigt, sondern **nach #110 ausgelagert** - dort in praezisierter Form, mit einer zusaetzlichen Bedingung zur Bucket-Neuinterpretation, die hier fehlte: - ~~Ein Lauf auf Claude Code landet in genau einem Telemetrie-Bucket~~ -> #110 - ~~Das Iteration-Budget-Gate zaehlt ueber einen ganzen Lauf; ein Test mit 61 Aufrufen aus je eigener Shell sieht die Verweigerung~~ -> #110 - ~~Entschieden und dokumentiert, wie sich das zu #82 verhaelt~~ -> #110 ## Herkunft und Artefakte Lauf vom 2026-09-15, Instanz `5.0.0 -> 6.0.0`, Harness Claude Code, Sitzung `671c1b9a`. Ergebnis-Commits in der Instanz: `7fe8353` (Handreparatur aus Befund 3), `dcc17df` (Maschinerie), `c8c9f9b` (optionale Migration). Review-Sitzung vom 2026-09-16: hat Transkript, die drei Commits und den Endzustand gegengelesen und Befund 5, 6, 7 sowie die Ursachenabschnitte unter Befund 1 und 3 ergaenzt. Befund 5 ist dabei live gegen die Instanz geprueft, nicht aus dem Transkript abgeleitet, und in derselben Sitzung repariert (`b5014d9` in `torben/nathan`). Aus derselben Sitzung stammt #108, das Befund 7 abgeschlossen hat. Erste Umsetzungssitzung vom 2026-09-16 (`0e09cf4`, `6.1.0-beta.2`): Befund 4 und 6 umgesetzt, dabei die Sprachbegruendung aus Befund 4b/5 gegen `types/type-spec.md` korrigiert und die Stack-Haelfte von Befund 5 gefunden und behoben. Modelle: Entwurf, Versionsteil und Grenzurteile auf Opus 5, mechanische Mitte auf Opus 5, Abschluss auf Opus 5 - der in `stack-dev` Schritt 3 angebotene Wechsel auf Sonnet wurde angeboten und nicht gezogen. Zweite Umsetzungssitzung vom 2026-09-16 (`72d01be` = `6.1.0-beta.3`, `0c98080` = `6.1.0-beta.4`, `536093f` = Doku-Nachzug ohne Bump): Befund 3 und 2 entschieden und gebaut, in zwei Publishes plus einem Nachzug aus der Abschlussphase. Beide Bumps `--minor` mit `--impact medium` - neue Faehigkeit, in beide Richtungen ein Drop-in, kein Grenzuebertritt, und damit bleibt die Bump-Liste des Kandidaten flach, wie sie es bei vier gleichgewichtigen Upgrade-Pfad-Aenderungen sein soll. In der Abschlussphase zusaetzlich gefunden und mitgenommen: INSTALL.md behauptete weiter, `version check` sei der einzige Befehl, der ins Netz geht, und `tools/CONTRACT.md` § "Future considerations (not implemented)" fuehrte noch den MCP-Server-Wrapper und `dist upgrade` selbst - beide seit ihrer Umsetzung falsch und im selben Dokument weiter oben als existierend beschrieben. Modelle: Entwurf, Versionsteil und Grenzurteile auf Opus 5, mechanische Mitte (Code, Tests, Bumps, Pruefungen) auf Opus 5, Abschluss auf Opus 5 - der Wechsel auf Sonnet wurde an beiden vorgesehenen Stellen angeboten und nicht gezogen. Abschluss am 2026-09-16: Befund 1 nach **#110** ausgelagert und dieses Issue geschlossen. Die Evidenz zu Befund 1 bleibt hier - Trace, Bucket-Messung, Scorer-Ausgabe, Reproduktionsschritt 5 -, weil sie das Messergebnis dieses Laufs ist; #110 traegt die Entscheidung, die Loesungsachsen und praezisierte Akzeptanzkriterien. Dasselbe Muster wie bei Befund 7 und #108, an derselben Stelle begruendet. Nicht stale, und deshalb bewusst nicht angefasst: `docs/ownership-and-templates.md`. Seine Begruendung - eine lokal geaenderte Datei sei *"a decision someone takes deliberately instead of one an upgrade takes for them"* - ist genau die Eigenschaft, die `--take-release` umsetzt, indem es den Pfad benennen laesst. `docs/version-model.md` und `docs/why-gates-are-code.md` sind von beiden Aenderungen nicht beruehrt. **Erster Kommentar traegt die vollstaendige Telemetrie des Laufs verbatim** - 63 Events, aus 21 Bucket-Dateien nach `ts` zusammengefuehrt. Einzige Aenderung: die drei identischen 69-Pfad-Arrays in `gate.refused`/`gate.cleared`/`publish.commit` sind elidiert und die Liste steht einmal darunter. Das ist der Teil dieses Issues, den #110 als Evidenz braucht und der hier bewusst bleibt, statt kopiert zu werden. Das rohe Sitzungstranskript ist **bewusst nicht angehaengt**: die Instanz ist privat, das Transkript traegt Seitentitel, Infrastrukturthemen und Kontaktdaten aus `kb/`, und dieses Repo ist oeffentlich (`instructions/private-instance.md`: *"the cost of a mistaken push is disclosure rather than inconvenience"*). Die Telemetrie unten ist dagegen geprueft frei davon - sie enthaelt nur Stack-Pfade, Kommandonamen und Exit-Codes. Wer das Transkript fuer die Dev-Instanz-Validierung braucht, bekommt es auf Anfrage redigiert (ANSI entfernt, Instanzinhalte maskiert). Nebenbefund aus genau dieser Redaktion, weil er `chemenu.telemetry.scrub` betrifft: eine Maskierung per Regex ueber **Terminalausgabe** greift nicht, solange die ANSI-Sequenzen drinstehen - `ssh://git@host:PORT/...` und `Vorname Nachname <mail@host>` waren durch eingestreute Farbcodes aufgetrennt und ueberlebten den ersten Durchgang unmaskiert. ANSI muss vor der Maskierung entfernt werden, nicht danach. Nicht in #110 mitgenommen - eigenstaendiger Befund an einer anderen Stelle, und bis heute kein eigenes Issue.
torben added the prio/plannedsize/Marea/distributionarea/processkind/defect labels 2026-09-16 06:08:51 +00:00
Author
Owner

Telemetrie des Laufs - verbatim

63 Events, zusammengefuehrt aus den 21 Bucket-Dateien unter reports/telemetry/<session>/trace.jsonl
(Filter: -newermt "2026-09-15 21:40" lokal = 19:40 UTC), sortiert nach ts. Unveraendert bis auf
eine Sache: die drei identischen 69-Pfad-Arrays in gate.refused, gate.cleared und dem ersten
publish.commit sind durch <<69 Pfade - elidiert, Liste einmal unten>> ersetzt; die Liste steht
darunter. Ausserdem sind bei prompt.submitted die Felder transcript_path und cwd entfernt
(lokale Pfade, kein Informationswert hier) - prompt, prompt_sha256 und prompt_length stehen
unveraendert da.

Dass dieselbe Datei 21 session_id-Werte traegt, ist Befund 1 und kein Artefakt der Zusammenfuehrung.

{"v": 1, "ts": "2026-09-15T19:44:52.158756+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3834977, "seq": 1, "source": "claude-code", "event": "session.start", "attrs": {"harness": "claude-code", "completeness": ["session.start", "session.end", "prompt.submitted", "tool.pre", "tool.post", "tool.error", "turn.end", "instructions.loaded", "subagent.start", "subagent.stop", "compaction"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:44:52.158880+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3834977, "seq": 2, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 46, "prompt_sha256": "2ebc776efd9cfeee7a54967b07dafb002bfc5193d2595f282d92850c07907851", "prompt": "aktualisiere den stack auf die letzte version."}}
{"v": 1, "ts": "2026-09-15T19:45:07.753037+00:00", "session_id": "3835015", "pid": 3835017, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:45:07.753149+00:00", "session_id": "3835015", "pid": 3835017, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "version", "args": ["check"], "exit_code": 0, "duration_ms": 104.1}}
{"v": 1, "ts": "2026-09-15T19:45:18.625842+00:00", "session_id": "3835056", "pid": 3835058, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:45:18.625930+00:00", "session_id": "3835056", "pid": 3835058, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["status"], "exit_code": 0, "duration_ms": 255.0}}
{"v": 1, "ts": "2026-09-15T19:45:18.937497+00:00", "session_id": "3835056", "pid": 3835063, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "version", "args": ["notes"], "exit_code": 1, "duration_ms": 33.7}}
{"v": 1, "ts": "2026-09-15T19:46:03.354028+00:00", "session_id": "3835179", "pid": 3835181, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:46:03.354109+00:00", "session_id": "3835179", "pid": 3835181, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz", "--dry-run"], "exit_code": 0, "duration_ms": 129.8}}
{"v": 1, "ts": "2026-09-15T19:46:31.306797+00:00", "session_id": "3835232", "pid": 3835234, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:46:31.306874+00:00", "session_id": "3835232", "pid": 3835234, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz"], "exit_code": 1, "duration_ms": 130.2}}
{"v": 1, "ts": "2026-09-15T19:46:59.478952+00:00", "session_id": "3835285", "pid": 3835287, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:46:59.479019+00:00", "session_id": "3835285", "pid": 3835287, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz", "--dry-run"], "exit_code": 1, "duration_ms": 44.8}}
{"v": 1, "ts": "2026-09-15T19:47:17.147609+00:00", "session_id": "3835339", "pid": 3835341, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:47:17.147690+00:00", "session_id": "3835339", "pid": 3835341, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz", "--dry-run"], "exit_code": 0, "duration_ms": 130.4}}
{"v": 1, "ts": "2026-09-15T19:47:22.989307+00:00", "session_id": "3835353", "pid": 3835355, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:47:22.989389+00:00", "session_id": "3835353", "pid": 3835355, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz"], "exit_code": 0, "duration_ms": 172.5}}
{"v": 1, "ts": "2026-09-15T19:47:28.789436+00:00", "session_id": "3835371", "pid": 3835373, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:47:28.789523+00:00", "session_id": "3835371", "pid": 3835373, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["status"], "exit_code": 0, "duration_ms": 57.1}}
{"v": 1, "ts": "2026-09-15T19:47:29.110458+00:00", "session_id": "3835371", "pid": 3835377, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "instructions", "args": ["sync"], "exit_code": 0, "duration_ms": 39.5}}
{"v": 1, "ts": "2026-09-15T19:47:44.434440+00:00", "session_id": "3835425", "pid": 3835427, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:47:44.434529+00:00", "session_id": "3835425", "pid": 3835427, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "doctor", "args": [], "exit_code": 0, "duration_ms": 92.7}}
{"v": 1, "ts": "2026-09-15T19:47:46.370777+00:00", "session_id": "3835425", "pid": 3835437, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["verify"], "exit_code": 1, "duration_ms": 1644.6}}
{"v": 1, "ts": "2026-09-15T19:47:53.978922+00:00", "session_id": "3835460", "pid": 3835462, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:47:53.979000+00:00", "session_id": "3835460", "pid": 3835462, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["toc", "--apply"], "exit_code": 0, "duration_ms": 86.0}}
{"v": 1, "ts": "2026-09-15T19:47:58.835954+00:00", "session_id": "3835471", "pid": 3835473, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:47:58.836043+00:00", "session_id": "3835471", "pid": 3835473, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["verify"], "exit_code": 0, "duration_ms": 414.3}}
{"v": 1, "ts": "2026-09-15T19:47:59.216332+00:00", "session_id": "3835471", "pid": 3835482, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "instructions", "args": ["verify"], "exit_code": 0, "duration_ms": 97.5}}
{"v": 1, "ts": "2026-09-15T19:48:00.112259+00:00", "session_id": "3835471", "pid": 3835485, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "lint", "args": [], "exit_code": 0, "duration_ms": 614.3}}
{"v": 1, "ts": "2026-09-15T19:48:28.408424+00:00", "session_id": "3835548", "pid": 3835550, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:48:28.408499+00:00", "session_id": "3835548", "pid": 3835550, "seq": 2, "source": "wikitool", "event": "gate.refused", "attrs": {"gate": "mass-update", "reason": "needs-clearance", "token": "96e2563ff596", "presented_token": null, "changed": 69, "counted": 69, "threshold": 10, "files": "<<69 Pfade - elidiert, Liste einmal unten>>"}}
{"v": 1, "ts": "2026-09-15T19:48:28.429958+00:00", "session_id": "3835548", "pid": 3835550, "seq": 3, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "publish", "args": ["--message", "stack: upgrade machinery 5.0.0 -> 6.0.0"], "exit_code": 42, "duration_ms": 416.9}}
{"v": 1, "ts": "2026-09-15T19:58:14.796703+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3836779, "seq": 1, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 8, "prompt_sha256": "2687f86ed6784b8a5fca36e6c468e12aa44dc3c7e8137e3160d1a95079bdcd02", "prompt": "approved"}}
{"v": 1, "ts": "2026-09-15T19:58:21.785485+00:00", "session_id": "3836791", "pid": 3836793, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T19:58:21.785560+00:00", "session_id": "3836791", "pid": 3836793, "seq": 2, "source": "wikitool", "event": "gate.cleared", "attrs": {"gate": "mass-update", "token": "96e2563ff596", "counted": 69, "threshold": 10, "files": "<<69 Pfade - elidiert, Liste einmal unten>>"}}
{"v": 1, "ts": "2026-09-15T19:58:22.573729+00:00", "session_id": "3836791", "pid": 3836793, "seq": 3, "source": "wikitool", "event": "publish.commit", "attrs": {"summary": "stack: upgrade machinery 5.0.0 -> 6.0.0", "files": "<<69 Pfade - elidiert, Liste einmal unten>>", "changed": 69, "counted": 69, "paths": [], "pushed": true, "remote": "origin", "branch": "main"}}
{"v": 1, "ts": "2026-09-15T19:58:22.586659+00:00", "session_id": "3836791", "pid": 3836793, "seq": 4, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "publish", "args": ["--confirm", "96e2563ff596", "--message", "stack: upgrade machinery 5.0.0 -> 6.0.0"], "exit_code": 0, "duration_ms": 1181.8}}
{"v": 1, "ts": "2026-09-15T20:01:51.551944+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3837219, "seq": 1, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 10, "prompt_sha256": "137b05c8fcd27c223b7682bd736980295e97ce5cc370b27120884115e8a0b887", "prompt": "make it so"}}
{"v": 1, "ts": "2026-09-15T20:02:01.986725+00:00", "session_id": "3837235", "pid": 3837237, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T20:02:01.986800+00:00", "session_id": "3837235", "pid": 3837237, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["list"], "exit_code": 0, "duration_ms": 32.8}}
{"v": 1, "ts": "2026-09-15T20:06:01.055001+00:00", "session_id": "3837668", "pid": 3837671, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T20:06:01.055085+00:00", "session_id": "3837668", "pid": 3837671, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["toc", "--apply"], "exit_code": 0, "duration_ms": 89.2}}
{"v": 1, "ts": "2026-09-15T20:06:01.755430+00:00", "session_id": "3837668", "pid": 3837674, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["verify"], "exit_code": 0, "duration_ms": 415.2}}
{"v": 1, "ts": "2026-09-15T20:06:08.439953+00:00", "session_id": "3837691", "pid": 3837693, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T20:06:08.440078+00:00", "session_id": "3837691", "pid": 3837693, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "entity"], "exit_code": 0, "duration_ms": 41.1}}
{"v": 1, "ts": "2026-09-15T20:06:08.756049+00:00", "session_id": "3837691", "pid": 3837696, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "concept"], "exit_code": 0, "duration_ms": 40.3}}
{"v": 1, "ts": "2026-09-15T20:06:09.086658+00:00", "session_id": "3837691", "pid": 3837703, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "source"], "exit_code": 1, "duration_ms": 41.4}}
{"v": 1, "ts": "2026-09-15T20:06:16.367533+00:00", "session_id": "3837722", "pid": 3837724, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T20:06:16.367641+00:00", "session_id": "3837722", "pid": 3837724, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "source"], "exit_code": 0, "duration_ms": 42.5}}
{"v": 1, "ts": "2026-09-15T20:06:16.686072+00:00", "session_id": "3837722", "pid": 3837728, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "comparison"], "exit_code": 0, "duration_ms": 38.6}}
{"v": 1, "ts": "2026-09-15T20:06:24.306079+00:00", "session_id": "3837739", "pid": 3837741, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T20:06:24.306152+00:00", "session_id": "3837739", "pid": 3837741, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["verify"], "exit_code": 0, "duration_ms": 403.3}}
{"v": 1, "ts": "2026-09-15T20:06:24.686788+00:00", "session_id": "3837739", "pid": 3837749, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "instructions", "args": ["verify"], "exit_code": 0, "duration_ms": 93.4}}
{"v": 1, "ts": "2026-09-15T20:06:25.049867+00:00", "session_id": "3837739", "pid": 3837752, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "doctor", "args": [], "exit_code": 0, "duration_ms": 65.5}}
{"v": 1, "ts": "2026-09-15T20:06:25.397424+00:00", "session_id": "3837739", "pid": 3837764, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["status"], "exit_code": 0, "duration_ms": 56.9}}
{"v": 1, "ts": "2026-09-15T20:06:33.119504+00:00", "session_id": "3837778", "pid": 3837780, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T20:06:33.119572+00:00", "session_id": "3837778", "pid": 3837780, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["done", "6.0.0", "--pages", "0"], "exit_code": 0, "duration_ms": 36.2}}
{"v": 1, "ts": "2026-09-15T20:06:33.448615+00:00", "session_id": "3837778", "pid": 3837783, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["status"], "exit_code": 0, "duration_ms": 54.4}}
{"v": 1, "ts": "2026-09-15T20:06:43.228331+00:00", "session_id": "3837804", "pid": 3837806, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}}
{"v": 1, "ts": "2026-09-15T20:06:43.228414+00:00", "session_id": "3837804", "pid": 3837806, "seq": 2, "source": "wikitool", "event": "publish.commit", "attrs": {"summary": "types: take offered 6.0.0-type-guidance-split migration\n\nLink entity/concept/source/comparison to their new stack-owned\ntypes/<name>.guidance.md so they receive future authoring-prose\nimprovements again. Frontmatter and Template blocks untouched.", "files": [".wikitool-kb.json", "types/comparison.md", "types/concept.md", "types/entity.md", "types/source.md"], "changed": 5, "counted": 5, "paths": [], "pushed": true, "remote": "origin", "branch": "main"}}
{"v": 1, "ts": "2026-09-15T20:06:43.234283+00:00", "session_id": "3837804", "pid": 3837806, "seq": 3, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "publish", "args": ["--message", "types: take offered 6.0.0-type-guidance-split migration\n\nLink entity/concept/source/comparison to their new stack-owned\ntypes/<name>.guidance.md so they receive future authoring-prose\nimprovements again. Frontmatter and Template blocks untouched."], "exit_code": 0, "duration_ms": 970.4}}
{"v": 1, "ts": "2026-09-15T20:23:49.966805+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3839739, "seq": 1, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 41, "prompt_sha256": "08a258dc7245e17391c89d8c434d03e57ef1211886559173a18957e3d29e7f66", "prompt": "Can you access Torben/chemenu @gitea-mcp?"}}
{"v": 1, "ts": "2026-09-15T20:26:52.076905+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3840230, "seq": 1, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 393, "prompt_sha256": "fcf32a5b6942cb94a800ac558ccaafdaa4fd39332e63870ef46075084ba210f4", "prompt": "Do a full analysis and runtime data collection of this upgrade run. Include stack specific tracing and if somehow possible, take the raw session transcript as well. Create an issue in the chemenu repo collecting this telemetry as verbatim as possible, rely on file attachments if possible. \nGoal is to use your analysis to validate the upgrade procedure on a dev instance of the chemenu stack."}}

Die elidierte 69-Pfad-Liste

Identisch in gate.refused, gate.cleared und dem ersten publish.commit - das ist der
Commit dcc17df:

.wikitool-release.json
AGENTS.md
ENVIRONMENT.md.template
README.md
SOUL.md.template
USER.md.template
VERSION
docs/language-boundaries.md
docs/ownership-and-templates.md
docs/version-model.md
instructions/CONTRACT.md
instructions/gates.md
instructions/migrations/6.0.0-type-guidance-split.md
instructions/session-setup.md
instructions/setup-instance.md
instructions/wiki-ingest/SKILL.md
instructions/wiki-lint/SKILL.md
instructions/wiki-manage/SKILL.md
instructions/wiki-query/SKILL.md
instructions/wiki-status/SKILL.md
kb/CONVENTIONS.md.template
kb/concepts/COLLECTION.md.template
kb/sources/COLLECTION.md.template
tools/CONTRACT.md
tools/README.md
tools/chemenu/api.py
tools/chemenu/commands/dist_cmd.py
tools/chemenu/commands/docs_verify.py
tools/chemenu/commands/git_publish.py
tools/chemenu/commands/instructions_cmd.py
tools/chemenu/commands/run_budget.py
tools/chemenu/commands/search.py
tools/chemenu/commands/types_cmd.py
tools/chemenu/commands/version_cmd.py
tools/chemenu/mcp/server.py
tools/chemenu/search/service.py
tools/chemenu/search/types.py
tools/chemenu/tests/test_api.py
tools/chemenu/tests/test_dist_cmd.py
tools/chemenu/tests/test_dist_upgrade.py
tools/chemenu/tests/test_docs_verify.py
tools/chemenu/tests/test_git_publish.py
tools/chemenu/tests/test_instructions_cmd.py
tools/chemenu/tests/test_mcp_server.py
tools/chemenu/tests/test_run_budget.py
tools/chemenu/tests/test_search.py
tools/chemenu/tests/test_toc.py
tools/chemenu/tests/test_type_resolver.py
tools/chemenu/tests/test_types_cmd.py
tools/chemenu/tests/test_version_cmd.py
tools/chemenu/toc.py
tools/chemenu/type_resolver.py
tools/chemenu/types_core.py
tools/chemenu/version.py
types/comparison.guidance.md
types/comparison.md.template
types/concept.guidance.md
types/concept.md
types/concept.md.template
types/entity.guidance.md
types/entity.md.template
types/lint-report.md
types/source.guidance.md
types/source.md
types/source.md.template
types/type-guidance.md
types/type-guidance.schema.yaml
types/type-spec.md
types/type-spec.schema.yaml

Abgeleitete Kennzahlen

Event-Histogramm ueber die 63 Zeilen:

  33  wikitool.call
  21  session.start
   5  prompt.submitted
   2  publish.commit
   1  gate.refused
   1  gate.cleared

Laufzeiten, soweit auffaellig: docs verify kalt 1644.6 ms, danach 403-415 ms (dreimal gemessen).
publish --confirm 1181.8 ms inklusive Push, der zweite Publish 970.4 ms. Alles andere unter
300 ms.

budget.state taucht in der ganzen Trace nicht auf, obwohl das Event im
completeness-Feld jedes session.start als meldbar gefuehrt wird - passt zu Befund 1, Folge 2:
ein Zaehler, der nie in die Naehe seiner Schwelle kommt, hat auch nichts zu melden.

## Telemetrie des Laufs - verbatim 63 Events, zusammengefuehrt aus den 21 Bucket-Dateien unter `reports/telemetry/<session>/trace.jsonl` (Filter: `-newermt "2026-09-15 21:40"` lokal = 19:40 UTC), sortiert nach `ts`. Unveraendert bis auf **eine** Sache: die drei identischen 69-Pfad-Arrays in `gate.refused`, `gate.cleared` und dem ersten `publish.commit` sind durch `<<69 Pfade - elidiert, Liste einmal unten>>` ersetzt; die Liste steht darunter. Ausserdem sind bei `prompt.submitted` die Felder `transcript_path` und `cwd` entfernt (lokale Pfade, kein Informationswert hier) - `prompt`, `prompt_sha256` und `prompt_length` stehen unveraendert da. Dass dieselbe Datei 21 `session_id`-Werte traegt, ist Befund 1 und kein Artefakt der Zusammenfuehrung. ```jsonl {"v": 1, "ts": "2026-09-15T19:44:52.158756+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3834977, "seq": 1, "source": "claude-code", "event": "session.start", "attrs": {"harness": "claude-code", "completeness": ["session.start", "session.end", "prompt.submitted", "tool.pre", "tool.post", "tool.error", "turn.end", "instructions.loaded", "subagent.start", "subagent.stop", "compaction"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:44:52.158880+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3834977, "seq": 2, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 46, "prompt_sha256": "2ebc776efd9cfeee7a54967b07dafb002bfc5193d2595f282d92850c07907851", "prompt": "aktualisiere den stack auf die letzte version."}} {"v": 1, "ts": "2026-09-15T19:45:07.753037+00:00", "session_id": "3835015", "pid": 3835017, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:45:07.753149+00:00", "session_id": "3835015", "pid": 3835017, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "version", "args": ["check"], "exit_code": 0, "duration_ms": 104.1}} {"v": 1, "ts": "2026-09-15T19:45:18.625842+00:00", "session_id": "3835056", "pid": 3835058, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:45:18.625930+00:00", "session_id": "3835056", "pid": 3835058, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["status"], "exit_code": 0, "duration_ms": 255.0}} {"v": 1, "ts": "2026-09-15T19:45:18.937497+00:00", "session_id": "3835056", "pid": 3835063, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "version", "args": ["notes"], "exit_code": 1, "duration_ms": 33.7}} {"v": 1, "ts": "2026-09-15T19:46:03.354028+00:00", "session_id": "3835179", "pid": 3835181, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:46:03.354109+00:00", "session_id": "3835179", "pid": 3835181, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz", "--dry-run"], "exit_code": 0, "duration_ms": 129.8}} {"v": 1, "ts": "2026-09-15T19:46:31.306797+00:00", "session_id": "3835232", "pid": 3835234, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:46:31.306874+00:00", "session_id": "3835232", "pid": 3835234, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz"], "exit_code": 1, "duration_ms": 130.2}} {"v": 1, "ts": "2026-09-15T19:46:59.478952+00:00", "session_id": "3835285", "pid": 3835287, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:46:59.479019+00:00", "session_id": "3835285", "pid": 3835287, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz", "--dry-run"], "exit_code": 1, "duration_ms": 44.8}} {"v": 1, "ts": "2026-09-15T19:47:17.147609+00:00", "session_id": "3835339", "pid": 3835341, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:47:17.147690+00:00", "session_id": "3835339", "pid": 3835341, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz", "--dry-run"], "exit_code": 0, "duration_ms": 130.4}} {"v": 1, "ts": "2026-09-15T19:47:22.989307+00:00", "session_id": "3835353", "pid": 3835355, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:47:22.989389+00:00", "session_id": "3835353", "pid": 3835355, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "dist", "args": ["upgrade", "/home/torben/.claude/jobs/8af88af0/tmp/chemenu-stack-6.0.0.tar.gz"], "exit_code": 0, "duration_ms": 172.5}} {"v": 1, "ts": "2026-09-15T19:47:28.789436+00:00", "session_id": "3835371", "pid": 3835373, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:47:28.789523+00:00", "session_id": "3835371", "pid": 3835373, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["status"], "exit_code": 0, "duration_ms": 57.1}} {"v": 1, "ts": "2026-09-15T19:47:29.110458+00:00", "session_id": "3835371", "pid": 3835377, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "instructions", "args": ["sync"], "exit_code": 0, "duration_ms": 39.5}} {"v": 1, "ts": "2026-09-15T19:47:44.434440+00:00", "session_id": "3835425", "pid": 3835427, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:47:44.434529+00:00", "session_id": "3835425", "pid": 3835427, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "doctor", "args": [], "exit_code": 0, "duration_ms": 92.7}} {"v": 1, "ts": "2026-09-15T19:47:46.370777+00:00", "session_id": "3835425", "pid": 3835437, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["verify"], "exit_code": 1, "duration_ms": 1644.6}} {"v": 1, "ts": "2026-09-15T19:47:53.978922+00:00", "session_id": "3835460", "pid": 3835462, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:47:53.979000+00:00", "session_id": "3835460", "pid": 3835462, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["toc", "--apply"], "exit_code": 0, "duration_ms": 86.0}} {"v": 1, "ts": "2026-09-15T19:47:58.835954+00:00", "session_id": "3835471", "pid": 3835473, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:47:58.836043+00:00", "session_id": "3835471", "pid": 3835473, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["verify"], "exit_code": 0, "duration_ms": 414.3}} {"v": 1, "ts": "2026-09-15T19:47:59.216332+00:00", "session_id": "3835471", "pid": 3835482, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "instructions", "args": ["verify"], "exit_code": 0, "duration_ms": 97.5}} {"v": 1, "ts": "2026-09-15T19:48:00.112259+00:00", "session_id": "3835471", "pid": 3835485, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "lint", "args": [], "exit_code": 0, "duration_ms": 614.3}} {"v": 1, "ts": "2026-09-15T19:48:28.408424+00:00", "session_id": "3835548", "pid": 3835550, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:48:28.408499+00:00", "session_id": "3835548", "pid": 3835550, "seq": 2, "source": "wikitool", "event": "gate.refused", "attrs": {"gate": "mass-update", "reason": "needs-clearance", "token": "96e2563ff596", "presented_token": null, "changed": 69, "counted": 69, "threshold": 10, "files": "<<69 Pfade - elidiert, Liste einmal unten>>"}} {"v": 1, "ts": "2026-09-15T19:48:28.429958+00:00", "session_id": "3835548", "pid": 3835550, "seq": 3, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "publish", "args": ["--message", "stack: upgrade machinery 5.0.0 -> 6.0.0"], "exit_code": 42, "duration_ms": 416.9}} {"v": 1, "ts": "2026-09-15T19:58:14.796703+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3836779, "seq": 1, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 8, "prompt_sha256": "2687f86ed6784b8a5fca36e6c468e12aa44dc3c7e8137e3160d1a95079bdcd02", "prompt": "approved"}} {"v": 1, "ts": "2026-09-15T19:58:21.785485+00:00", "session_id": "3836791", "pid": 3836793, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T19:58:21.785560+00:00", "session_id": "3836791", "pid": 3836793, "seq": 2, "source": "wikitool", "event": "gate.cleared", "attrs": {"gate": "mass-update", "token": "96e2563ff596", "counted": 69, "threshold": 10, "files": "<<69 Pfade - elidiert, Liste einmal unten>>"}} {"v": 1, "ts": "2026-09-15T19:58:22.573729+00:00", "session_id": "3836791", "pid": 3836793, "seq": 3, "source": "wikitool", "event": "publish.commit", "attrs": {"summary": "stack: upgrade machinery 5.0.0 -> 6.0.0", "files": "<<69 Pfade - elidiert, Liste einmal unten>>", "changed": 69, "counted": 69, "paths": [], "pushed": true, "remote": "origin", "branch": "main"}} {"v": 1, "ts": "2026-09-15T19:58:22.586659+00:00", "session_id": "3836791", "pid": 3836793, "seq": 4, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "publish", "args": ["--confirm", "96e2563ff596", "--message", "stack: upgrade machinery 5.0.0 -> 6.0.0"], "exit_code": 0, "duration_ms": 1181.8}} {"v": 1, "ts": "2026-09-15T20:01:51.551944+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3837219, "seq": 1, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 10, "prompt_sha256": "137b05c8fcd27c223b7682bd736980295e97ce5cc370b27120884115e8a0b887", "prompt": "make it so"}} {"v": 1, "ts": "2026-09-15T20:02:01.986725+00:00", "session_id": "3837235", "pid": 3837237, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T20:02:01.986800+00:00", "session_id": "3837235", "pid": 3837237, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["list"], "exit_code": 0, "duration_ms": 32.8}} {"v": 1, "ts": "2026-09-15T20:06:01.055001+00:00", "session_id": "3837668", "pid": 3837671, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T20:06:01.055085+00:00", "session_id": "3837668", "pid": 3837671, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["toc", "--apply"], "exit_code": 0, "duration_ms": 89.2}} {"v": 1, "ts": "2026-09-15T20:06:01.755430+00:00", "session_id": "3837668", "pid": 3837674, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["verify"], "exit_code": 0, "duration_ms": 415.2}} {"v": 1, "ts": "2026-09-15T20:06:08.439953+00:00", "session_id": "3837691", "pid": 3837693, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T20:06:08.440078+00:00", "session_id": "3837691", "pid": 3837693, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "entity"], "exit_code": 0, "duration_ms": 41.1}} {"v": 1, "ts": "2026-09-15T20:06:08.756049+00:00", "session_id": "3837691", "pid": 3837696, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "concept"], "exit_code": 0, "duration_ms": 40.3}} {"v": 1, "ts": "2026-09-15T20:06:09.086658+00:00", "session_id": "3837691", "pid": 3837703, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "source"], "exit_code": 1, "duration_ms": 41.4}} {"v": 1, "ts": "2026-09-15T20:06:16.367533+00:00", "session_id": "3837722", "pid": 3837724, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T20:06:16.367641+00:00", "session_id": "3837722", "pid": 3837724, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "source"], "exit_code": 0, "duration_ms": 42.5}} {"v": 1, "ts": "2026-09-15T20:06:16.686072+00:00", "session_id": "3837722", "pid": 3837728, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "types", "args": ["describe", "comparison"], "exit_code": 0, "duration_ms": 38.6}} {"v": 1, "ts": "2026-09-15T20:06:24.306079+00:00", "session_id": "3837739", "pid": 3837741, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T20:06:24.306152+00:00", "session_id": "3837739", "pid": 3837741, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "docs", "args": ["verify"], "exit_code": 0, "duration_ms": 403.3}} {"v": 1, "ts": "2026-09-15T20:06:24.686788+00:00", "session_id": "3837739", "pid": 3837749, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "instructions", "args": ["verify"], "exit_code": 0, "duration_ms": 93.4}} {"v": 1, "ts": "2026-09-15T20:06:25.049867+00:00", "session_id": "3837739", "pid": 3837752, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "doctor", "args": [], "exit_code": 0, "duration_ms": 65.5}} {"v": 1, "ts": "2026-09-15T20:06:25.397424+00:00", "session_id": "3837739", "pid": 3837764, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["status"], "exit_code": 0, "duration_ms": 56.9}} {"v": 1, "ts": "2026-09-15T20:06:33.119504+00:00", "session_id": "3837778", "pid": 3837780, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T20:06:33.119572+00:00", "session_id": "3837778", "pid": 3837780, "seq": 2, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["done", "6.0.0", "--pages", "0"], "exit_code": 0, "duration_ms": 36.2}} {"v": 1, "ts": "2026-09-15T20:06:33.448615+00:00", "session_id": "3837778", "pid": 3837783, "seq": 1, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "migrate", "args": ["status"], "exit_code": 0, "duration_ms": 54.4}} {"v": 1, "ts": "2026-09-15T20:06:43.228331+00:00", "session_id": "3837804", "pid": 3837806, "seq": 1, "source": "wikitool", "event": "session.start", "attrs": {"harness": "wikitool", "completeness": ["wikitool.call", "gate.refused", "page.written", "publish.commit", "budget.state", "gate.cleared"], "synthesized": true}} {"v": 1, "ts": "2026-09-15T20:06:43.228414+00:00", "session_id": "3837804", "pid": 3837806, "seq": 2, "source": "wikitool", "event": "publish.commit", "attrs": {"summary": "types: take offered 6.0.0-type-guidance-split migration\n\nLink entity/concept/source/comparison to their new stack-owned\ntypes/<name>.guidance.md so they receive future authoring-prose\nimprovements again. Frontmatter and Template blocks untouched.", "files": [".wikitool-kb.json", "types/comparison.md", "types/concept.md", "types/entity.md", "types/source.md"], "changed": 5, "counted": 5, "paths": [], "pushed": true, "remote": "origin", "branch": "main"}} {"v": 1, "ts": "2026-09-15T20:06:43.234283+00:00", "session_id": "3837804", "pid": 3837806, "seq": 3, "source": "wikitool", "event": "wikitool.call", "attrs": {"command": "publish", "args": ["--message", "types: take offered 6.0.0-type-guidance-split migration\n\nLink entity/concept/source/comparison to their new stack-owned\ntypes/<name>.guidance.md so they receive future authoring-prose\nimprovements again. Frontmatter and Template blocks untouched."], "exit_code": 0, "duration_ms": 970.4}} {"v": 1, "ts": "2026-09-15T20:23:49.966805+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3839739, "seq": 1, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 41, "prompt_sha256": "08a258dc7245e17391c89d8c434d03e57ef1211886559173a18957e3d29e7f66", "prompt": "Can you access Torben/chemenu @gitea-mcp?"}} {"v": 1, "ts": "2026-09-15T20:26:52.076905+00:00", "session_id": "671c1b9a-92dd-484b-b29a-bf6d29c006ff", "pid": 3840230, "seq": 1, "source": "claude-code", "event": "prompt.submitted", "attrs": {"harness_event": "UserPromptSubmit", "prompt_length": 393, "prompt_sha256": "fcf32a5b6942cb94a800ac558ccaafdaa4fd39332e63870ef46075084ba210f4", "prompt": "Do a full analysis and runtime data collection of this upgrade run. Include stack specific tracing and if somehow possible, take the raw session transcript as well. Create an issue in the chemenu repo collecting this telemetry as verbatim as possible, rely on file attachments if possible. \nGoal is to use your analysis to validate the upgrade procedure on a dev instance of the chemenu stack."}} ``` ### Die elidierte 69-Pfad-Liste Identisch in `gate.refused`, `gate.cleared` und dem ersten `publish.commit` - das ist der Commit `dcc17df`: ``` .wikitool-release.json AGENTS.md ENVIRONMENT.md.template README.md SOUL.md.template USER.md.template VERSION docs/language-boundaries.md docs/ownership-and-templates.md docs/version-model.md instructions/CONTRACT.md instructions/gates.md instructions/migrations/6.0.0-type-guidance-split.md instructions/session-setup.md instructions/setup-instance.md instructions/wiki-ingest/SKILL.md instructions/wiki-lint/SKILL.md instructions/wiki-manage/SKILL.md instructions/wiki-query/SKILL.md instructions/wiki-status/SKILL.md kb/CONVENTIONS.md.template kb/concepts/COLLECTION.md.template kb/sources/COLLECTION.md.template tools/CONTRACT.md tools/README.md tools/chemenu/api.py tools/chemenu/commands/dist_cmd.py tools/chemenu/commands/docs_verify.py tools/chemenu/commands/git_publish.py tools/chemenu/commands/instructions_cmd.py tools/chemenu/commands/run_budget.py tools/chemenu/commands/search.py tools/chemenu/commands/types_cmd.py tools/chemenu/commands/version_cmd.py tools/chemenu/mcp/server.py tools/chemenu/search/service.py tools/chemenu/search/types.py tools/chemenu/tests/test_api.py tools/chemenu/tests/test_dist_cmd.py tools/chemenu/tests/test_dist_upgrade.py tools/chemenu/tests/test_docs_verify.py tools/chemenu/tests/test_git_publish.py tools/chemenu/tests/test_instructions_cmd.py tools/chemenu/tests/test_mcp_server.py tools/chemenu/tests/test_run_budget.py tools/chemenu/tests/test_search.py tools/chemenu/tests/test_toc.py tools/chemenu/tests/test_type_resolver.py tools/chemenu/tests/test_types_cmd.py tools/chemenu/tests/test_version_cmd.py tools/chemenu/toc.py tools/chemenu/type_resolver.py tools/chemenu/types_core.py tools/chemenu/version.py types/comparison.guidance.md types/comparison.md.template types/concept.guidance.md types/concept.md types/concept.md.template types/entity.guidance.md types/entity.md.template types/lint-report.md types/source.guidance.md types/source.md types/source.md.template types/type-guidance.md types/type-guidance.schema.yaml types/type-spec.md types/type-spec.schema.yaml ``` ### Abgeleitete Kennzahlen Event-Histogramm ueber die 63 Zeilen: ``` 33 wikitool.call 21 session.start 5 prompt.submitted 2 publish.commit 1 gate.refused 1 gate.cleared ``` Laufzeiten, soweit auffaellig: `docs verify` kalt 1644.6 ms, danach 403-415 ms (dreimal gemessen). `publish --confirm` 1181.8 ms inklusive Push, der zweite Publish 970.4 ms. Alles andere unter 300 ms. `budget.state` taucht in der ganzen Trace **nicht** auf, obwohl das Event im `completeness`-Feld jedes `session.start` als meldbar gefuehrt wird - passt zu Befund 1, Folge 2: ein Zaehler, der nie in die Naehe seiner Schwelle kommt, hat auch nichts zu melden.
torben changed title from Upgrade-Lauf 5.0.0 -> 6.0.0 auf ausgelieferter Instanz: Laufbericht, Telemetrie, vier Befunde to Upgrade-Lauf 5.0.0 -> 6.0.0 auf ausgelieferter Instanz: Laufbericht, Telemetrie, sieben Befunde 2026-09-16 11:57:15 +00:00
Author
Owner

Changelog: Review-Sitzung vom 2026-09-16 gegen Transkript, die drei Ergebnis-Commits und den Endzustand der Instanz. Neu: Befund 5 (Rest-Abschnitt ## Authoring guidance in types/source.md, doppelter Kopf in types describe source - live gegengeprueft), Befund 6 (Schritt 5 des Migrationsdokuments prueft gegen ein Vorher, das niemand festhaelt - direkte Ursache von Befund 5), Befund 7 (Upgrade-Pfad ohne agentengerichtete Prozedur; migrate verify nie gelaufen, Session nie neu gestartet, drei konkurrierende Reihenfolgen). Befund 1 hat einen Ursachenabschnitt bekommen: instructions/session-setup.md schreibt export ... einmal pro Sitzung, was auf einem Harness mit Shell-pro-Tool-Call wirkungslos ist. Befund 3 hat die Erwartungshaltung aus dem Transkript, Befund 4a die Verschaerfung, dass es im Ursprungs-Repo gar keine types/*.md.template gibt.

Korrigiert: die Zeile unter "Was der Lauf bestaetigt hat", types describe komponiere unveraendert - das gilt fuer drei der vier Typen, nicht fuer source. Akzeptanzkriterien um vier Punkte erweitert, Reproduktionsabschnitt um Schritt 6 (Diff-Gegentest). Befund 7 ist als Bauauftrag nach #108 ausgelagert. Titel und size/ nachgezogen: vier -> sieben Befunde, size/M -> size/L, weil daraus jetzt mehrere Arbeitspakete werden statt eines.

**Changelog:** Review-Sitzung vom 2026-09-16 gegen Transkript, die drei Ergebnis-Commits und den Endzustand der Instanz. Neu: Befund 5 (Rest-Abschnitt `## Authoring guidance` in `types/source.md`, doppelter Kopf in `types describe source` - live gegengeprueft), Befund 6 (Schritt 5 des Migrationsdokuments prueft gegen ein Vorher, das niemand festhaelt - direkte Ursache von Befund 5), Befund 7 (Upgrade-Pfad ohne agentengerichtete Prozedur; `migrate verify` nie gelaufen, Session nie neu gestartet, drei konkurrierende Reihenfolgen). Befund 1 hat einen Ursachenabschnitt bekommen: `instructions/session-setup.md` schreibt `export ... ` einmal pro Sitzung, was auf einem Harness mit Shell-pro-Tool-Call wirkungslos ist. Befund 3 hat die Erwartungshaltung aus dem Transkript, Befund 4a die Verschaerfung, dass es im Ursprungs-Repo gar keine `types/*.md.template` gibt. Korrigiert: die Zeile unter "Was der Lauf bestaetigt hat", `types describe` komponiere unveraendert - das gilt fuer drei der vier Typen, nicht fuer `source`. Akzeptanzkriterien um vier Punkte erweitert, Reproduktionsabschnitt um Schritt 6 (Diff-Gegentest). Befund 7 ist als Bauauftrag nach #108 ausgelagert. Titel und `size/` nachgezogen: vier -> sieben Befunde, `size/M` -> `size/L`, weil daraus jetzt mehrere Arbeitspakete werden statt eines.
torben added size/L and removed size/M labels 2026-09-16 11:57:39 +00:00
Author
Owner

Changelog: Befund 5 ist repariert (b5014d9 in torben/nathan) und das Kriterium abgehakt. Dabei eine Zahl in Befund 5 korrigiert: zwei ## Authoring guidance-Koepfe sind der Normalzustand - types describe setzt selbst einen und inlined darunter die Guidance-Datei mit ihrem eigenen gleichnamigen Abschnitt, bei allen vier Typen. source hatte einen dritten aus dem Type-Spec. Der Reproduktionsabschnitt nennt jetzt 3 statt 2 als Erwartungswert und die Gegenprobe an den anderen drei Typen. Befund 6 traegt die Gegenprobe: die Reparatur lief mit Vorher-Datei und Diff, und genau deshalb war das Ergebnis belastbar. "Stand"-Absatz oben auf drei erledigte Punkte aktualisiert.

**Changelog:** Befund 5 ist repariert (`b5014d9` in `torben/nathan`) und das Kriterium abgehakt. Dabei **eine Zahl in Befund 5 korrigiert**: zwei `## Authoring guidance`-Koepfe sind der Normalzustand - `types describe` setzt selbst einen und inlined darunter die Guidance-Datei mit ihrem eigenen gleichnamigen Abschnitt, bei allen vier Typen. `source` hatte einen **dritten** aus dem Type-Spec. Der Reproduktionsabschnitt nennt jetzt 3 statt 2 als Erwartungswert und die Gegenprobe an den anderen drei Typen. Befund 6 traegt die Gegenprobe: die Reparatur lief mit Vorher-Datei und Diff, und genau deshalb war das Ergebnis belastbar. "Stand"-Absatz oben auf drei erledigte Punkte aktualisiert.
Author
Owner

Changelog: Befund 4 und 6 umgesetzt und abgehakt (0e09cf4, 6.1.0-beta.2). Das Migrationsdokument hat einen eigenen Vorher-Schritt bekommen (alte Schritte 3-6 sind auf 4-7 gerueckt), verweist auf types/<name>.md.template statt types/<name>.md und nennt die Sprache des Pointer-Absatzes; instructions/migrate-corpus.md § "Writing the migration document" traegt das Baseline-Muster jetzt generisch.

Eine Begruendung korrigiert: die Sprachbegruendung unter Befund 4b/5 - "ein Abschnitt, den die Instanz behaelt, ist ihrer, also traegt er die KB-Sprache" - haelt gegen den Baum nicht. Die Sprachachse ist der Leser, nicht der Eigentuemer: types/type-spec.md § "Who owns a type-spec", AGENTS.md § File naming und der Docstring von dist_cmd.instance_owned_type_stems ("Ownership, not language") sagen uebereinstimmend, dass Anleitungsprosa in einem Type-Spec englisch bleibt, auch in einer instanzeigenen Datei. Das Ergebnis von Befund 5 war trotzdem richtig, nur der Weg dorthin - der Bullet war redundant und gehoerte weg, nicht uebersetzt. Das Dokument sagt das jetzt so und verlinkt die Tabelle, statt sie ein drittes Mal zu kopieren.

Neuer Teilbefund 5b, gefunden beim Nachmessen: types/source.md trug im Ursprungs-Repo denselben Rest-Abschnitt wie die Instanz - types describe source gab hier 3 ## Authoring guidance-Koepfe aus, die anderen drei Typen 2. Das Kriterium zu Befund 5 war gegen nathan abgehakt, gegen den Stack nie. Da die Datei beim Export zu types/source.md.template wird, haette jede neu aufgesetzte Instanz den Defekt adoptiert. Entfernt in 0e09cf4, geprueft mit genau dem Vorher/Nachher-Diff, den Befund 6 jetzt vorschreibt. Befund 5 ist dadurch in 5a (Instanz) und 5b (Stack) geteilt, mit einem zweiten Kriterium.

Ausserdem: "Stand"-Absatz auf fuenf erledigte Punkte, Schritt 6 des Reproduktionsabschnitts um den Hinweis ergaenzt, dass er gegen einen 6.0.0-Tarball gilt und ab 6.1.0-beta.2 nicht mehr reproduziert. Nicht geaendert: Befund 1, 2 und 3 - die drei offenen sind jetzt ausschliesslich Werkzeugaenderungen. Labels bleiben (size/L traegt weiter, Befund 1 allein ist es).

Bewusst nicht angefasst: instructions/upgrade-instance.md Schritt 12. Dessen Absatz richtet sich an den Ausfuehrenden einer Migration, der neue Satz in migrate-corpus.md an den Autor eines Migrationsdokuments - zwei Adressaten, keine zweite Kopie im Sinne von Invariante 8.

Verifiziert: lokal 1276 Tests, docs verify und instructions verify gruen; CI auf 0e09cf4 gruen in den Laeufen 296 und 297. Kein Release ausgeloest - release.yml reagiert nur auf ein suffixfreies VERSION, und 6.1.0-beta.2 traegt eines.

**Changelog:** Befund 4 und 6 umgesetzt und abgehakt (`0e09cf4`, `6.1.0-beta.2`). Das Migrationsdokument hat einen eigenen Vorher-Schritt bekommen (alte Schritte 3-6 sind auf 4-7 gerueckt), verweist auf `types/<name>.md.template` statt `types/<name>.md` und nennt die Sprache des Pointer-Absatzes; `instructions/migrate-corpus.md` § "Writing the migration document" traegt das Baseline-Muster jetzt generisch. **Eine Begruendung korrigiert:** die Sprachbegruendung unter Befund 4b/5 - *"ein Abschnitt, den die Instanz behaelt, ist ihrer, also traegt er die KB-Sprache"* - haelt gegen den Baum nicht. Die Sprachachse ist der **Leser**, nicht der Eigentuemer: `types/type-spec.md` § "Who owns a type-spec", `AGENTS.md` § File naming und der Docstring von `dist_cmd.instance_owned_type_stems` (*"Ownership, not language"*) sagen uebereinstimmend, dass Anleitungsprosa in einem Type-Spec englisch bleibt, auch in einer instanzeigenen Datei. Das Ergebnis von Befund 5 war trotzdem richtig, nur der Weg dorthin - der Bullet war redundant und gehoerte weg, nicht uebersetzt. Das Dokument sagt das jetzt so und verlinkt die Tabelle, statt sie ein drittes Mal zu kopieren. **Neuer Teilbefund 5b, gefunden beim Nachmessen:** `types/source.md` trug **im Ursprungs-Repo** denselben Rest-Abschnitt wie die Instanz - `types describe source` gab hier 3 `## Authoring guidance`-Koepfe aus, die anderen drei Typen 2. Das Kriterium zu Befund 5 war gegen `nathan` abgehakt, gegen den Stack nie. Da die Datei beim Export zu `types/source.md.template` wird, haette jede neu aufgesetzte Instanz den Defekt adoptiert. Entfernt in `0e09cf4`, geprueft mit genau dem Vorher/Nachher-Diff, den Befund 6 jetzt vorschreibt. Befund 5 ist dadurch in 5a (Instanz) und 5b (Stack) geteilt, mit einem zweiten Kriterium. Ausserdem: "Stand"-Absatz auf fuenf erledigte Punkte, Schritt 6 des Reproduktionsabschnitts um den Hinweis ergaenzt, dass er gegen einen 6.0.0-Tarball gilt und ab `6.1.0-beta.2` nicht mehr reproduziert. Nicht geaendert: Befund 1, 2 und 3 - die drei offenen sind jetzt ausschliesslich Werkzeugaenderungen. Labels bleiben (`size/L` traegt weiter, Befund 1 allein ist es). Bewusst nicht angefasst: `instructions/upgrade-instance.md` Schritt 12. Dessen Absatz richtet sich an den Ausfuehrenden einer Migration, der neue Satz in `migrate-corpus.md` an den Autor eines Migrationsdokuments - zwei Adressaten, keine zweite Kopie im Sinne von Invariante 8. **Verifiziert:** lokal 1276 Tests, `docs verify` und `instructions verify` gruen; CI auf `0e09cf4` gruen in den Laeufen [296](https://gitea.nehmer.net/torben/chemenu/actions/runs/296) und [297](https://gitea.nehmer.net/torben/chemenu/actions/runs/297). Kein Release ausgeloest - `release.yml` reagiert nur auf ein suffixfreies `VERSION`, und `6.1.0-beta.2` traegt eines.
Author
Owner

Changelog: Befund 2 und 3 sind entschieden; die beiden § Loesungsvorschlag-Abschnitte sind durch § Entschieden ersetzt und tragen jetzt die Regel statt der Alternativen.

Befund 2: von den beiden Wegen der erste - version notes faellt auf den Feed aus update_url zurueck, statt nur zu sagen, wo die Notes stehen. Ausschlaggebend war, dass instructions/upgrade-instance.md Schritt 2 den eigenen Workaround-Absatz schon als temporaer fuehrt ("This paragraph stops being necessary the day version notes falls back to that feed"). Drei Praezisierungen, die im Vorschlag nicht standen und die die Kollision mit version.pys "the one place in wikitool that talks to a remote host" aufloesen: der Fallback greift nur bei vorhandenem Release-Stamp, ein Dev-Checkout betritt ihn also nie und release.ymls version notes > /tmp/release-notes.md kann keinen Netzaufruf ausloesen; die Notes gehen nach stdout, die Herkunftszeilen nach stderr, damit der Redirect weiter nur den Eintrag traegt; --offline verweigert den Aufruf. Der Feed kennt nur /releases/latest, also wird eine abweichende Version benannt statt eine /releases/tags/<tag>-URL zu raten - der Hauptfall ist ohnehin, dass VERSION in Schritt 2 noch die alte ist.

Befund 3: --take-release nimmt einen Pfad und ist wiederholbar, statt ein pauschales Gegenstueck zu --keep-local zu sein. Die beiden Antworten sind nicht symmetrisch: --keep-local verliert nichts, --take-release verwirft eine lokale Aenderung, und eine Verwerfung benennt ihr Ziel (Schritt 1 dieser Instruktion). Der gemischte Fall wird damit ueberhaupt erst loesbar, beide Flags zusammen komponieren, ein nicht blockierter Pfad ist Exit 1 auch im --dry-run, und die Abbruchmeldung nennt alle drei Antworten samt einsetzbarer Kommandozeile im Muster des Mass-Update-Gates.

Akzeptanzkriterien zu 2 und 3 auf die entschiedene Form nachgezogen: aus zwei sind sechs geworden, jedes mit einer pruefbaren Eigenschaft statt einer Aktivitaet. Reproduktionsabschnitt um den Hinweis ergaenzt, wie Schritt 4 nach dieser Sitzung ausgeht. Befund 1 unberuehrt - laut eigenem Abschnitt eine Betreiberentscheidung, gegen #82 zusammen zu entscheiden und nicht Teil dieser Sitzung. Labels bleiben.

**Changelog:** Befund 2 und 3 sind entschieden; die beiden § Loesungsvorschlag-Abschnitte sind durch § Entschieden ersetzt und tragen jetzt die Regel statt der Alternativen. **Befund 2:** von den beiden Wegen der erste - `version notes` faellt auf den Feed aus `update_url` zurueck, statt nur zu sagen, wo die Notes stehen. Ausschlaggebend war, dass `instructions/upgrade-instance.md` Schritt 2 den eigenen Workaround-Absatz schon als temporaer fuehrt (*"This paragraph stops being necessary the day `version notes` falls back to that feed"*). Drei Praezisierungen, die im Vorschlag nicht standen und die die Kollision mit `version.py`s *"the one place in `wikitool` that talks to a remote host"* aufloesen: der Fallback greift **nur bei vorhandenem Release-Stamp**, ein Dev-Checkout betritt ihn also nie und `release.yml`s `version notes > /tmp/release-notes.md` kann keinen Netzaufruf ausloesen; die Notes gehen nach stdout, die Herkunftszeilen nach stderr, damit der Redirect weiter nur den Eintrag traegt; `--offline` verweigert den Aufruf. Der Feed kennt nur `/releases/latest`, also wird eine abweichende Version benannt statt eine `/releases/tags/<tag>`-URL zu raten - der Hauptfall ist ohnehin, dass `VERSION` in Schritt 2 noch die alte ist. **Befund 3:** `--take-release` nimmt einen **Pfad** und ist wiederholbar, statt ein pauschales Gegenstueck zu `--keep-local` zu sein. Die beiden Antworten sind nicht symmetrisch: `--keep-local` verliert nichts, `--take-release` verwirft eine lokale Aenderung, und eine Verwerfung benennt ihr Ziel (Schritt 1 dieser Instruktion). Der gemischte Fall wird damit ueberhaupt erst loesbar, beide Flags zusammen komponieren, ein nicht blockierter Pfad ist Exit 1 auch im `--dry-run`, und die Abbruchmeldung nennt alle drei Antworten samt einsetzbarer Kommandozeile im Muster des Mass-Update-Gates. Akzeptanzkriterien zu 2 und 3 auf die entschiedene Form nachgezogen: aus zwei sind sechs geworden, jedes mit einer pruefbaren Eigenschaft statt einer Aktivitaet. Reproduktionsabschnitt um den Hinweis ergaenzt, wie Schritt 4 nach dieser Sitzung ausgeht. Befund 1 unberuehrt - laut eigenem Abschnitt eine Betreiberentscheidung, gegen #82 zusammen zu entscheiden und nicht Teil dieser Sitzung. Labels bleiben.
torben added kind/decision and removed kind/defect labels 2026-09-16 16:02:24 +00:00
Author
Owner

Changelog: Befund 2 und 3 gebaut und abgehakt - 72d01be (6.1.0-beta.3, --take-release) und 0c98080 (6.1.0-beta.4, version notes-Fallback), plus 536093f als Doku-Nachzug ohne Bump. Beide § Entschieden sind zu § Umgesetzt geworden und tragen jetzt, was tatsaechlich geschrieben wurde statt was geschrieben werden sollte; die Praesensformulierungen ueber die beiden Defekte sind auf Vergangenheit umgestellt.

Damit ist Befund 1 der einzige offene. Der "Stand"-Absatz ist durch eine Tabelle ueber alle sieben ersetzt, Befund 1 traegt oben und unten den Vermerk, dass er es ist, sein § Loesungsrichtung heisst jetzt § Zu entscheiden, und der Reproduktionsabschnitt sagt pro Schritt, ab welcher Version er nicht mehr reproduziert - Schritt 5 (Befund 1) ist der einzige, der unveraendert gilt. Akzeptanzkriterien in "offen" und "erledigt" geteilt: 3 offen, 12 abgehakt.

Label nachgezogen: kind/defect -> kind/decision. Was bleibt, ist keine Umsetzung mehr, sondern eine Betreiberentscheidung gegen #82. size/L und prio/planned bleiben - Befund 1 allein traegt beides.

Nicht geschlossen, und ein Vorschlag dazu steht im Koerper: Befund 1 als eigenes Issue auslagern und dieses schliessen, so wie Befund 7 nach #108 gegangen ist. Bewusst nicht einseitig getan, weil die Labels des neuen Issues Antworten auf Fragen sind, die erst die Entscheidung gegen #82 beantwortet.

Verifiziert: 1290 Tests (1276 vorher, +8 fuer --take-release, +6 fuer den Feed-Fallback), auch gegen eine leere Maschine nach testing-conventions.md Schritt 6 identisch gruen; docs verify mit 73 ausgelieferten Dokumenten und 58 Referenzdateien, instructions verify mit 23 Instruktionen und 7 Skills. CI gruen auf allen drei Commits: 298/299, 300/301, 302. Kein Release ausgeloest - release.yml reagiert nur auf ein suffixfreies VERSION.

In der Abschlussphase zusaetzlich gefunden und in 536093f mitgenommen, weil beides Behauptungen ueber die geaenderten Flaechen waren: INSTALL.md fuehrte weiter version check als einzigen Befehl, der ins Netz geht, und tools/CONTRACT.md § "Future considerations (not implemented)" listete noch den MCP-Server-Wrapper und dist upgrade selbst - beide seit ihrer Umsetzung falsch und im selben Dokument weiter oben als existierend beschrieben. docs/ownership-and-templates.md dagegen geprueft und bewusst nicht angefasst: seine Begruendung, eine lokal geaenderte Datei solle "a decision someone takes deliberately" sein, ist genau die Eigenschaft, die --take-release umsetzt.

**Changelog:** Befund 2 und 3 gebaut und abgehakt - `72d01be` (`6.1.0-beta.3`, `--take-release`) und `0c98080` (`6.1.0-beta.4`, `version notes`-Fallback), plus `536093f` als Doku-Nachzug ohne Bump. Beide § Entschieden sind zu § Umgesetzt geworden und tragen jetzt, was tatsaechlich geschrieben wurde statt was geschrieben werden sollte; die Praesensformulierungen ueber die beiden Defekte sind auf Vergangenheit umgestellt. **Damit ist Befund 1 der einzige offene.** Der "Stand"-Absatz ist durch eine Tabelle ueber alle sieben ersetzt, Befund 1 traegt oben und unten den Vermerk, dass er es ist, sein § Loesungsrichtung heisst jetzt § Zu entscheiden, und der Reproduktionsabschnitt sagt pro Schritt, ab welcher Version er nicht mehr reproduziert - Schritt 5 (Befund 1) ist der einzige, der unveraendert gilt. Akzeptanzkriterien in "offen" und "erledigt" geteilt: 3 offen, 12 abgehakt. **Label nachgezogen:** `kind/defect` -> `kind/decision`. Was bleibt, ist keine Umsetzung mehr, sondern eine Betreiberentscheidung gegen #82. `size/L` und `prio/planned` bleiben - Befund 1 allein traegt beides. **Nicht geschlossen, und ein Vorschlag dazu** steht im Koerper: Befund 1 als eigenes Issue auslagern und dieses schliessen, so wie Befund 7 nach #108 gegangen ist. Bewusst nicht einseitig getan, weil die Labels des neuen Issues Antworten auf Fragen sind, die erst die Entscheidung gegen #82 beantwortet. **Verifiziert:** 1290 Tests (1276 vorher, +8 fuer `--take-release`, +6 fuer den Feed-Fallback), auch gegen eine leere Maschine nach `testing-conventions.md` Schritt 6 identisch gruen; `docs verify` mit 73 ausgelieferten Dokumenten und 58 Referenzdateien, `instructions verify` mit 23 Instruktionen und 7 Skills. CI gruen auf allen drei Commits: [298](https://gitea.nehmer.net/torben/chemenu/actions/runs/298)/[299](https://gitea.nehmer.net/torben/chemenu/actions/runs/299), [300](https://gitea.nehmer.net/torben/chemenu/actions/runs/300)/[301](https://gitea.nehmer.net/torben/chemenu/actions/runs/301), [302](https://gitea.nehmer.net/torben/chemenu/actions/runs/302). Kein Release ausgeloest - `release.yml` reagiert nur auf ein suffixfreies `VERSION`. **In der Abschlussphase zusaetzlich gefunden** und in `536093f` mitgenommen, weil beides Behauptungen ueber die geaenderten Flaechen waren: INSTALL.md fuehrte weiter `version check` als einzigen Befehl, der ins Netz geht, und `tools/CONTRACT.md` § "Future considerations (not implemented)" listete noch den MCP-Server-Wrapper und `dist upgrade` selbst - beide seit ihrer Umsetzung falsch und im selben Dokument weiter oben als existierend beschrieben. `docs/ownership-and-templates.md` dagegen geprueft und bewusst nicht angefasst: seine Begruendung, eine lokal geaenderte Datei solle *"a decision someone takes deliberately"* sein, ist genau die Eigenschaft, die `--take-release` umsetzt.
Author
Owner

Changelog: Befund 1 nach #110 ausgelagert, dieses Issue geschlossen. Damit ist es kein offenes Arbeitspaket mehr, sondern der Laufbericht zum getraceten 5.0.0-auf-6.0.0-Upgrade - sechs Befunde erledigt, einer in #108 und einer in #110 zu eigenen Paketen geworden.

Was sich im Koerper geaendert hat: die Stand-Tabelle sagt jetzt pro Befund "erledigt" oder "ausgelagert nach #NNN"; Befund 1 traegt oben den Auslagerungsvermerk und behaelt seine Evidenz - Trace, Bucket-Messung, Scorer-Ausgabe -, weil die das Messergebnis dieses Laufs ist und #110 sie braucht, statt sie kopiert zu bekommen. Sein § Zu entscheiden ist weg, die Loesungsachsen stehen in #110. Die drei Akzeptanzkriterien zu Befund 1 sind gestrichen mit Ziel, nicht abgehakt, und die Kriterienliste ist auf "Erledigt" (13) plus "ausgelagert" (3) umgestellt. Befund 7 nennt jetzt explizit dasselbe Muster - Evidenz bleibt, Arbeit geht -, weil #110 sich darauf beruft. Reproduktionsschritt 5 ist als der einzige markiert, der unveraendert reproduziert, und als der, den #110 erbt.

Verweis in beide Richtungen: #110 nennt dieses Issue als Herkunft, verweist fuer die 63-Event-Trace auf den ersten Kommentar hier, und haelt fest, dass die Abhaengigkeit zu #82 in diese Richtung laeuft - #82 braucht eine Antwort aus #110, nicht umgekehrt, weil tool.pre/tool.post ohne gemeinsamen Schluessel ebenfalls unter der Harness-UUID landen.

#110 hat dabei ein Kriterium bekommen, das hier fehlte: dass nach einer Aenderung der Schluesselbildung kein bestehender Bucket in budget.json still neu interpretiert wird - kein geerbter Count fuer eine neue Sitzung, kein alter Count gegen eine neue angerechnet. budget.json ist eine maschinengelesene Datei, und "die Form einer maschinengelesenen Datei" steht im Grenzuebertritt-Katalog von instructions/dev/version-parts.md; der Versionsteil ist dort als vor dem ersten Commit zu beantworten vermerkt, nicht zu raten.

Labels von #110: area/process (wie #82, sein Geschwister), kind/decision, prio/planned, size/L - alle vier uebernommen aus dem Urteil, das hier zuletzt fuer Befund 1 allein galt. Kein status/blocked: #110 ist eigenstaendig bearbeitbar, die Abhaengigkeit laeuft in die andere Richtung.

**Changelog:** Befund 1 nach **#110** ausgelagert, dieses Issue geschlossen. Damit ist es kein offenes Arbeitspaket mehr, sondern der Laufbericht zum getraceten 5.0.0-auf-6.0.0-Upgrade - sechs Befunde erledigt, einer in #108 und einer in #110 zu eigenen Paketen geworden. **Was sich im Koerper geaendert hat:** die Stand-Tabelle sagt jetzt pro Befund "erledigt" oder "ausgelagert nach #NNN"; Befund 1 traegt oben den Auslagerungsvermerk und behaelt seine Evidenz - Trace, Bucket-Messung, Scorer-Ausgabe -, weil die das Messergebnis dieses Laufs ist und #110 sie braucht, statt sie kopiert zu bekommen. Sein § Zu entscheiden ist weg, die Loesungsachsen stehen in #110. Die drei Akzeptanzkriterien zu Befund 1 sind **gestrichen mit Ziel**, nicht abgehakt, und die Kriterienliste ist auf "Erledigt" (13) plus "ausgelagert" (3) umgestellt. Befund 7 nennt jetzt explizit dasselbe Muster - Evidenz bleibt, Arbeit geht -, weil #110 sich darauf beruft. Reproduktionsschritt 5 ist als der einzige markiert, der unveraendert reproduziert, und als der, den #110 erbt. **Verweis in beide Richtungen:** #110 nennt dieses Issue als Herkunft, verweist fuer die 63-Event-Trace auf den ersten Kommentar hier, und haelt fest, dass die Abhaengigkeit zu #82 in diese Richtung laeuft - #82 braucht eine Antwort aus #110, nicht umgekehrt, weil `tool.pre`/`tool.post` ohne gemeinsamen Schluessel ebenfalls unter der Harness-UUID landen. **#110 hat dabei ein Kriterium bekommen, das hier fehlte:** dass nach einer Aenderung der Schluesselbildung **kein bestehender Bucket in `budget.json` still neu interpretiert** wird - kein geerbter Count fuer eine neue Sitzung, kein alter Count gegen eine neue angerechnet. `budget.json` ist eine maschinengelesene Datei, und "die Form einer maschinengelesenen Datei" steht im Grenzuebertritt-Katalog von `instructions/dev/version-parts.md`; der Versionsteil ist dort als vor dem ersten Commit zu beantworten vermerkt, nicht zu raten. Labels von #110: `area/process` (wie #82, sein Geschwister), `kind/decision`, `prio/planned`, `size/L` - alle vier uebernommen aus dem Urteil, das hier zuletzt fuer Befund 1 allein galt. Kein `status/blocked`: #110 ist eigenstaendig bearbeitbar, die Abhaengigkeit laeuft in die andere Richtung.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: torben/chemenu#107