Das Arbeitsverzeichnis
Jedes Artefakt, das die Pipeline erzeugt: wo es liegt, was es validiert und was sich gefahrlos löschen lässt.
Das Arbeitsverzeichnis (--work) ist der Ort, an dem alles liegt, was die Pipeline
erzeugt. Eines pro dokumentiertem Repository.
<work>/
phase1/
graph.json the call graph — everything downstream reads this
functions.csv every function, flat, for grepping or a spreadsheet
graph.dot Graphviz: dot -Tsvg graph.dot -o graph.svg
dropped-calls.json calls we could NOT resolve, categorized — not hidden
scan-coverage.json files we could NOT read or fully parse — not counted as covered
phase2/
cards/<rel>.json one card per source file, mirroring the source tree
cards/_coverage.json how many files got prose, and which did not
cards/_rejected/ replies that produced no usable card (capped at 20)
skeleton.yaml the stage spine
assignment.json file → stage
organization.yaml intra-stage groups + reading order
strategy.json which strategy produced the above
phase3/
narration.json stage and system prose
registers.json cross-stage state registers
cache/ content-hash caches for prose and registers
handbook/ the rendered output, once you run `render`
run-manifest.json model, phases, timings and token usage of the last good runDrei Eigenschaften, auf die Verlass ist
Alles wird beim Lesen schema-validiert
Jedes Artefakt trägt ein version-Feld und wird beim Laden mit zod validiert. Ein
korruptes oder von Hand editiertes Artefakt schlägt laut fehl und nennt sich selbst:
handbook: error: work/myrepo/phase2/skeleton.yaml: stages.3.id: InvalidEs propagiert nie in eine spätere Phase.
Zwei bewusste Ausnahmen, beide aus Resilienz, nicht aus Nachlässigkeit:
- Karten — eine einzelne nicht parsebare Kartendatei wird übersprungen, ist aber nicht fatal. Ein einziges fremdes oder halb synchronisiertes JSON im Kartenverzeichnis würde sonst das Fortsetzen, die Phasen 2b/2c/3 und jedes Laden des Modells zum Absturz bringen.
languages-Metadaten ingraph.json— optional, weil es hier keinen Mechanismus zur Artefakt-Migration gibt und jeder Graph, der vor der Einführung der Treue-Deklarationen geschrieben wurde, weiterhin validieren muss.unparsedFilesist aus demselben Grund optional: Fehlt es, ist die Analyse älter als dieser Nachweis — es heißt nicht, dass nichts fehlgeschlagen ist.
Jeder Schreibvorgang ist atomar
In eine Temporärdatei schreiben, dann umbenennen. Ein Absturz mitten im Schreiben hinterlässt nie ein halb geschriebenes Artefakt, an dem der nächste Lauf erstickt.
Ein Lauf pro Arbeitsverzeichnis
generate und resync nehmen denselben re-entranten Verzeichnis-Lock. Ein
gleichzeitiger CLI-Lauf und ein Studio-Job auf denselben Artefakten würden ihre
Schreibvorgänge verschränken; der zweite wird stattdessen mit einer klaren Meldung
abgewiesen.
Was gefahrlos möglich ist
| Aktion | Sicher? | Anmerkung |
|---|---|---|
| Das ganze Arbeitsverzeichnis löschen | ✅ | Außerhalb wurde nichts verändert. Von Grund auf neu generieren. |
| Es in Git committen | ✅ | Alles Text. Praktisch, um nachzuvollziehen, was eine Regenerierung geändert hat. |
phase3/cache/ löschen | ✅ | Kostet beim nächsten Lauf einen komplett neuen Erzähltext. |
phase2/cards/_rejected/ löschen | ✅ | Nur Diagnostik. Wird zu Beginn eines neuen Kartendurchlaufs automatisch geleert. |
skeleton.yaml von Hand editieren | ✅ | Wird beim Lesen validiert, und --skeleton existiert genau dafür. |
graph.json von Hand editieren | ⚠️ | Es ist generiert. Stattdessen analyze erneut ausführen. |
phase2/strategy.json löschen | ⚠️ | Der nächste Lauf fällt auf file zurück, was zu den Artefakten passen kann — oder nicht. |
| Es öffentlich teilen | ⚠️ | Karten zitieren und beschreiben Ihre Quellen. Wie Quellcode behandeln. |
Von Hand lesen
Der Graph ist der interessante Teil:
# how big is this codebase, really
jq '.metadata | {files: (.scannedFiles|length), nInternalFunctions, nEdges}' phase1/graph.json
# the busiest functions — where a change is most likely to fan out
jq -r '.nodes | to_entries | map(select(.value.kind=="internal"))
| sort_by(-.value.nCallers) | .[:15]
| .[] | "\(.value.nCallers)\t\(.value.qualname)\t\(.value.file)"' phase1/graph.json
# what could not be resolved, by category
jq '.metadata.byCategory' phase1/dropped-calls.json
# which files the scan could not turn into facts, and why
jq '.metadata.byReason, .files' phase1/scan-coverage.json
# which files never got prose
jq '.missing' phase2/cards/_coverage.jsonfunctions.csv existiert aus demselben Grund — manchmal ist das schnellste Werkzeug eine
Tabellenkalkulation.
Die zwei Abdeckungsdateien beantworten verschiedene Fragen
_coverage.json beantwortet „welche Dateien konnte das Modell nicht beschreiben?“.
scan-coverage.json beantwortet die Frage darunter: „welche Dateien hat der Parser
überhaupt nie zu lesen geschafft?“ — mit einem reason von unreadable, unparsable
oder partial.
Die ersten beiden steuern keine Fakten bei und fallen deshalb auch aus scannedFiles
in graph.json heraus: Nichts Nachgelagertes schreibt eine Karte über eine Datei, die
niemand geöffnet hat, und zählt sie danach als beschrieben. partial-Dateien bleiben —
tree-sitter hat sich vom Syntaxfehler erholt, und die gefundenen Funktionen sind echt,
bloß unvollständig.
Ein leeres files-Array heißt: Jede gescannte Datei wurde sauber geparst. Das ist eine
Aussage; ein schlicht fehlendes Artefakt ist keine.
Wo sonst noch geschrieben wird
Handbooks schreibt an genau zwei Stellen außerhalb des Arbeitsverzeichnisses, beide opt-in über den ausgeführten Befehl:
<source>/.handbook-patches/— vonapplyangelegt, enthält Backups und deren Manifeste. Eine.gitignorewird automatisch hineingeschrieben, damit Backups nie in Git landen.$HOME/.handbook-studio/— Studios Repository-Registry und seine automatisch angelegten Arbeitsverzeichnisse. Mit--state-dirverschiebbar.
Die fünf Phasen
Was jede Generierungsphase erzeugt, was sie kostet, worauf sie bei einem Fehlschlag degradiert und wie sich eine einzelne Phase erneut ausführen lässt.
Analysetreue
Zwei Analyse-Tiers erzeugen identisch aussehende Ausgabe. Das ist eine Falle — deshalb deklariert jeder Adapter, was er liefern kann, und das Handbook legt es offen.