Zdůvodnění
Kontrakt session/v1 učinil povinným každé pole odvoditelné strojem — head, branch, commits, changed_files, seznamy referencí — a jediné pole nesoucí smysl nechal volitelné. To pole je tělo: k čemu epizoda byla a jak dopadla.
Jediným producentem byl člověk píšící do majordomus session close. Životní cyklus uzavírá epizodu z koncové události poskytovatele a lib/capture.sh ji uzavírá s mj_session_close ... < /dev/null. Takže na automatické cestě — což je každá cesta — bylo tělo prázdné z konstrukce, ne z opomenutí. Dne 2026-09-11 se záznam epizody, která udělala devadesát čtyři commitů, četl celý takto:
---
schema: session/v1
...
commits: [ "a3c7102", "5314bd6", ... 94 entries ... ]
tasks: []
issues: []
...
---
a nic víc. To je stvrzenka, ne záznam. Každé pole, které validátor kontroloval, bylo přítomné, takže sekce ohlásila, že je zdravá — validátor změřil tu polovinu kontraktu, která měla producenta, a tu, která ho neměla, neměřil.
Druhá půlka téže vady: záznam nikdo necommitnul. Každý povrch, který čte záznamy relací — stránky /sessions/ webu, index v Rustu, registr, session list v jiném klonu — čte sledovaný strom. Záznam zapsaný do pracovního stromu a tam ponechaný je zapsán, zvalidován, započten jako zdravý a neviditelný všude, kde by se čtenář skutečně díval. Pět záznamů leželo nesledovaných v primárním checkoutu, zatímco doctor hlásilo sekci zeleně, a lib/session.sh to říkalo ve vlastním komentáři: „Životní cyklus zapíše záznam, když se epizoda uzavře, a nic ho necommituje, takže mezera je výchozí stav, ne nehoda.“
Mezera, kterou popisuje komentář a žádná kontrola ji neodmítá, je mezera, kterou se repozitář rozhodl ponechat.
Požadované chování
Tělo se skládá, nikdy nezůstane prázdné. session close čte autorský souhrn ze standardního vstupu jako dřív; když žádný nepřijde, složí ho ze dvou zdrojů a řekne, který je který:
- to, co si pracovník sám zapsal během epizody — jeho checkpointy, zaznamenaná rozhodnutí, otevřené otázky. Je to jediný materiál v repozitáři, který nese záměr.
- co dokládají git a ledger — commity s předměty, soubory, přesunuté úkoly plánu, jak epizoda skončila.
Tam, kde pracovník nic nezaznamenal, sekce to říká jménem a jmenuje příkaz, který by něco zaznamenal. Nevymýšlí souhrn. Vymyšlený příběh v záznamu jen pro připisování je horší než přiznaná mezera, protože čtenář je pak od sebe nerozezná.
Sekce se deklarují v policy.yaml pod session.record_sections, se stejným kontraktem, jaký mají sekce předávky: sekce tam pojmenovaná bez zapisovatele v lib/derive.sh je chyba konfigurace hlášená jménem, nikdy tiše prázdný nadpis.
Tělo je vymezeno epizodou, ne úlohou. Úloha přežije epizody, které na ní pracují. Odvození rozsahu commitů z úvodního commitu úlohy způsobilo, že první koncept této sekce tvrdil 1261 commitů a 2339 změněných souborů pro epizodu, která udělala jeden a čtyřicet devět. Záznam epizody je vymezen tímtéž start_head, které zaznamenává její vlastní front matter.
Lifecycle commituje záznam, který zapisuje. capture session --event end commituje publikovaný záznam a tři vlastnosti nejsou k diskusi:
- Commituje tuto cestu a nic jiného. Strom se skládá z
HEADplus jediné cesty záznamu v dočasném indexu, takže cokoli měl pracovník při zavření okna v indexu, zůstane v indexu a necommitnuto. - Nespouští žádný commit hook.
.githooks/pre-commitspouštídoctor, stráž worktree a kontrolu čerstvosti stránek — dohromady mnohem déle, než poskytovatel povoluje koncovému hooku, který by commit zabil v půli. Commit se proto vytváří plumbingem (read-tree/write-tree/commit-tree/update-ref), který nemá žádné hooky ke spuštění, protože neběží žádné porcelain. - Nikdy neselže. Každá cesta vrací 0. Záznam, který nešlo commitnout, je commitnutý přesně tak jako dřív a
doctorjej stále jmenuje.
Push se řídí kontraktem pushe. Záznam se pushuje jen jako fast-forward, který tato funkce sama ověřila, přes .githooks/pre-push jako každý jiný push. Ten hook se ptá majordomus finish --check — zda smí být úloha zveřejněna — a po většinu života úlohy je odpověď ne, takže se push často neodešle. To je správný výsledek a ne omezení, které by se mělo obcházet: záznam je už commitnutý a cestuje s dalším pushem pracovníka. Obejít hook by znamenalo, že tato cesta jako jediná v nástroji rozhodne, že se na ni vlastní kontrakt pushe repozitáře nevztahuje.
Chování při selhání
test/cases/63_session_records.sh uzavře epizodu bez ručně psaného shrnutí a odmítne záznam, jehož tělo je prázdné, jehož rozsah commitů je rozsah úlohy, ne epizody, nebo který close nechal necommitnutý. Sekce deklarovaná v session.record_sections bez zapisovatele skončí session close kódem 10 a jmenuje sekci.
Ověření
majordomus session close # with no stdin: the record has a body
test/cases/63_session_records.sh # the body, its scope, and the commit