Tento dokument vysvětluje, co model znamená. Neobsahuje žádné aktuální údaje: co je právě teď pravda, vypisuje majordomus plan status a vykresluje se na plánu rozvoje webu ze stejných dat. Chcete-li vědět, kolik úkolů je připraveno, spusťte příkaz.
majordomus start dohlíží na jednu úlohu. Tato vrstva dohlíží na to, k čemu úloha patří.
Problém
Záznam úlohy říká, co dělá jedna relace. Neříká, proč ta práce existuje, na čem závisí, co by prokázalo, že je hotová, ani co se má udělat po ní. Tato znalost žila v konverzaci a konverzace nepřežije relaci, přepnutí poskytovatele ani předávku člověku.
Následují tři selhání. Práce se vybírá z paměti, ne z pořadí závislostí, takže se něco začne dřív než to, co to potřebuje. „Hotovo“ se tvrdí místo aby se ukázalo. A plán existuje na několika místech najednou — v chatu, v odstavci README, v ručně kresleném diagramu, v milníku na GitHubu — které se rozejdou, jakmile se jedno z nich změní.
Dva záznamy
Milník je spustitelná specifikace výsledku. Ne složka na tikety: popis problému, výsledek, který ho ukončí, současný a požadovaný stav, co je v rozsahu a co záměrně ne, kritéria, jejichž splněním se výsledek stane pravdou, validace, která ho prokáže, a důkazy potřebné k jeho přijetí. Jeden soubor pod .ai/repo/project/milestones/.
Úkol je ohraničená smlouva o provedení. Nese dost na to, aby ho mohl provést pracovník bez historie konverzace: cíl, proč existuje, současný a požadovaný stav, cesty, kterých se smí dotknout, na čem závisí, akceptační kritéria, ověřovací příkazy a důkazy, které jeho dokončení vyžaduje. Jeden soubor pod .ai/repo/project/issues/.
Oba jsou ručně psané YAML ve stejné omezené podmnožině, kterou používá politika, a oba se kontrolují proti allowlistu: klíč, který nikdo nečte, je chyba, ne komentář.
Úkol pojmenovává svůj milník. Milník své úkoly nevypisuje. Jeden směr znamená, že se oba nikdy nemohou neshodnout, které úkoly patří ke kterému výsledku.
Status se odvozuje
Žádný ze záznamů nemá pole status. Jeho zápis je neznámý klíč a validace selže.
Úkol zaznamenává, co se s ním stalo — started_at, verified_at, completed_at, cancelled a jeho evidence — a stav z toho vyplývá:
| status | kdy |
|---|---|
CANCELLED | cancelled: true |
DONE | completed_at je nastaveno a každý token evidence_required má důkaz |
VERIFY | implementace je prohlášena za dokončenou a důkazy zatím nestačí |
ACTIVE | started_at je nastaveno a nic dalšího se nezaznamenává |
BLOCKED | závislost není DONE |
READY | nic z uvedeného neplatí |
Razítko se počítá jen tehdy, když ho zapsal přechod. majordomus plan start|verify|done (a schopnost plan.transition) zapisují razítko spolu s jeho pečetí — started_event, verified_event, completed_event: SHA-256 události, úkolu a razítka — a připojují událost plan_* do ledgeru checkoutu. Ledger se nikdy nesleduje, takže pečeť je ta část události, kterou klon umí ověřit. Razítko bez pečeti nehýbe žádným stavem a je selháním stamp_without_event kontroly plan validate; razítka zaznamenaná před existencí pečetí jsou jmenována v unsealed_stamps každého záznamu, seznamu, který se jen zkracuje (project.no-plan-stamp-without-its-event, ADR 0097). done je odmítnuto, pokud úkol není ACTIVE nebo VERIFY.
Stav milníku vyplývá z jeho úkolů a jeho vlastních důkazů:
| status | kdy |
|---|---|
PLANNED | nemá žádné úkoly, nebo se žádný z nich nepohnul |
ACTIVE | alespoň jeden úkol je aktivní, ověřuje se nebo je hotov |
BLOCKED | je nedokončený a žádný úkol není připraven |
VERIFY | každý úkol, který není zrušen, je hotov a vlastní důkazy milníku nejsou úplné |
DONE | i tyto důkazy jsou úplné |
Milník nikdy není DONE jen proto, že počet uzavřených úkolů dosáhl součtu. Poslední krok je vlastní přijetí milníku a je podmíněn důkazy jako každý jiný krok.
Ani milník nemá verzi. Který release ho nesl, se odvozuje, nikdy nepíše: jeho released_in je první záznam release, jehož commit obsahuje merge jeho posledního přijatého úkolu, a unreleased, dokud je otevřený (ROADMAP.md, ADR 0166). Záznam, který nese version, je odmítnut.
Aktivní milník se odvozuje stejně: milník s nejnižším pořadím, který je ACTIVE, nebo jinak s nejnižším pořadím, který není dokončen. Nic ho nedeklaruje.
Graf
depends_on je seznam id úkolů. Graf, který tvoří, se validuje, nepovažuje se za důvěryhodný. Každé z těchto zjištění je samostatné a jmenuje úkol, který jej způsobil:
- závislost na úkolu, který neexistuje
- úkol, který závisí sám na sobě
- tatáž závislost jmenovaná dvakrát
- úkol jmenující milník, který neexistuje
- cyklus, s pojmenovaným každým úkolem uvězněným v něm nebo za ním
- úkol, který je
ACTIVE,VERIFYneboDONE, zatímco závislost neníDONE - úkol bez akceptačních kritérií nebo bez ověřovacího příkazu — zástupný
Selhávající zjištění způsobí, že majordomus plan validate a majordomus doctor skončí nenulově. majordomus watch hlásí tytéž porušení jako drift. Rozpracovaná práce se hlásí a nikdy neblokuje: úkol, který je prostě nedokončený, není selháním ničeho.
Vlny provádění
Vlna je vrstva grafu. Vlna nula je každý úkol bez závislostí; úkol leží o vrstvu za svou nejhlubší závislostí. Vlny se počítají při každém čtení a nikde neukládají, takže prováděcí plán nemůže zastarat — změna jedné hrany okamžitě posune každou vlnu, která na ní závisí, na každém povrchu.
Sdílení vlny je nutné k tomu, aby dva úkoly běžely souběžně. Nestačí. Pokud se jejich deklarované cesty scope překrývají — jedna se rovná druhé, leží uvnitř ní nebo ji obsahuje — překryv se ohlásí a úkoly se serializují. Směr je záměrný: falešná serializace stojí čas, falešná paralelnost stojí konflikt objevený až po dokončení práce.
Důkazy
Úkol deklaruje evidence_required jako seznam tokenů. majordomus plan evidence připojí jeden kus důkazu k jednomu tokenu a odmítne token, který úkol nedeklaruje. Odmítne také bez příkazu nebo artefaktu — vyprávění není důkaz.
majordomus plan done odmítne, dokud je kterýkoli token nepokryt. Úkol, jehož completed_at je nastaveno, ale jehož důkazy jsou neúplné, odvodí VERIFY, nikdy DONE. Důkazy žijí ve vlastním souboru úkolu, vedle smlouvy, kterou splňují, s commitem, při němž byly zaznamenány.
Co to nedělá: nespouští příkaz znovu. Nástroj zaznamenává, co pracovník říká, že příkaz vytvořil. Hash commitu uložený vedle je to, co činí nepravdivý záznam později ověřitelným.
K čemu práce je: záměry, pokrytí a dva plánovací záznamy
Nad milníky sedí záměr (ADR 0070): co se musí stát pravdou, invarianty, které musí zůstat pravdou, a kritéria uspokojení, která o tom rozhodují, každé s důkazem, který rozhoduje. Záměr jmenuje milníky, které ho realizují. Neukládá žádný stav: jeho stupeň sleduje plán a jeho uspokojení sleduje kniha důkazů.
Vedle fáze nese každý povrch verdikt záměru (ADR 0107), který odvozují samotná kritéria a plán se ho nikdy nedotkne: satisfied, když je splněno každé kritérium, unsatisfied, když není splněno kritérium test nebo claim — druh, který lze rozhodnout ledgerem nebo spojením tvrzení — a unknown, když jsou nesplněna jen kritéria command nebo deployment, nebo žádné není deklarováno. Jeho reasons jmenují každé nesplněné kritérium s druhem a stavem jeho důkazu. Fáze si ponechává svůj význam, takže satisfied stále vyžaduje každý milník DONE; verdikt může číst satisfied, zatímco je milník otevřený, a nic, co dokončená úloha udělá, jej nepohne.
Kritérium je splněno jen důkazem, který je aktuální, a aktuální je vlastní posouzení modulu důkazů na pracovním stromě (evidence::freshness, čtené přes evidence::current), tentýž, který dělají přehled tvrzení a stránky důkazů: úspěšný běh, jehož commit je v této historii, který měřil strom odpovídající jeho commitu, jehož test se stále hashuje na to, co běželo, a od něhož se nic, co kritérium pojmenovává, nezměnilo — u testu jeho zdroj a zdroj a implementace každého tvrzení, které tento test dokazuje; u tvrzení to, co tvrzení pojmenovává. Změna, kterou kritérium nepojmenovává, včetně změny knihy důkazů samotné, ho nechává splněné. Test, který nedokazuje žádné tvrzení pojmenovávající implementaci, nepojmenovává žádný testovaný kód, takže pro něj je každá změna od běhu kromě knihy tou, kterou nic nevylučuje: takové kritérium je splněno jen během na vlastním commitu checkoutu. Aby kritérium zůstalo splněno napříč nesouvisející prací, pojmenujte jeho test v tvrzení docs/CLAIMS.yaml, které pojmenovává implementaci. Úspěch zaznamenaný na špinavém stromě nebo takový, jehož vstupy se pohnuly, je stale; selhaný běh je failing; obojí kritérium, které bylo splněno, zruší a zaznamenání aktuálního úspěchu ho splní znovu. Každé kritérium nese proof, verdikt modulu důkazů za jeho stavem, takže splněné kritérium stále říká, zda je proven v této revizi, nebo spoléhá na inputs_unchanged.
To spojuje záměr s milníky a důkazy. Co spojuje kritérium s prací, která ho má učinit pravdivým, je serves na úkolu (ADR 0073):
serves:
- intent-planning#criteria-are-covered
Odkaz se píše na úkolu, který vzniká po záměru, takže přeplánování nikdy neupravuje záměr. Plán nese serves jako data a neodvozuje z nich žádný nález; posuzuje záměrový engine a majordomus intent coverage to vypíše:
CRITERION STRENGTH ISSUES
intent-planning#criteria-are-covered covered I1901
Kritérium je covered, když mu slouží živý úkol, který vyžaduje důkazy, weak, když každý sloužící úkol žádné nevyžaduje, observed, když zaznamenaná mezera viděla, že už je pravdivé, a uncovered, když nic v plánu to pravdivým neučiní. Každý úkol také odpovídá, proč existuje: intent, když slouží kritériu, maintenance, když jeho milník nejmenuje žádný intent — legitimní provozní práce, takto označená a nikdy jí nepřiřazený vymyšlený intent — nebo unexplained, když jeho milník realizuje intent a on neslouží ničemu.
majordomus intent validate odmítne (exit 10):
| zjištění | co to znamená |
|---|---|
criterion_uncovered | záměr má práci a toto kritérium z ní nemá nic |
issue_without_purpose | úkol leží pod milníkem záměru a ničemu neslouží |
serves_outside_milestone | úkol slouží kritériu záměru, který nejmenuje jeho milník |
serves_unknown_intent, serves_unknown_criterion, malformed_serves | odkaz ukazuje na nic |
a varuje u intent_not_planned (žádný živý úkol pod žádným jmenovaným milníkem — kde začíná každý záměr), criterion_weakly_covered, duplicate_work a milestone_contributes_nothing.
Mezera a kritika
Plánování vychází ze dvou záznamů, ne z promptu, aby to, co pracovník pozoroval, a to, co recenze našla, přežily relaci, která je vytvořila.
Mezera, jedna na záměr pod .ai/repo/project/gaps/, uvádí pozorování učiněná na commitu observed_at, každé se svým zdrojem, a odpovídá na každé kritérium záměru hodnotou satisfied, missing, conflicting nebo unknown s odkazem na pozorování za ní. Mezera, která kritérium vynechá, je odmítnuta; unknown se musí napsat, ne vynechat, a nikdy se nečte jako splněno. Kritérium pozorované jako satisfied se svými pozorováními nežádá o plánovanou práci — čte se observed — a přitom je splněno jen důkazy.
Kritika, jedna na záměr pod .ai/repo/project/critiques/, je protivnický průchod plánem: nálezy zařazené podle položené otázky — missed_requirement, unproven_assumption, insufficient_work, unnecessary_work, regression_risk, surface_missing, delivery_verification — každý blocking nebo ne, a každý vyřešený open, planned do úkolu, který záměru slouží, nebo rejected s důvodem. Zamítnutí, které nikdo nepřečte, není řešení.
Práce je po zahájení držena u review svého plánu: úkol, který slouží záměru ACTIVE, VERIFY nebo DONE, zatímco záměr nemá kritiku, je executing_without_critique a zatímco je otevřeno blokující zjištění, executing_with_open_blocker. Obojí jsou selhání intent validate a kontroly intent-check. Zda je odmítnut samotný start, je volba politiky (intent.binding, pod Vazbou níže): kde je required, úkol se nikdy nestane ACTIVE.
Majordomus tyto záznamy posuzuje, nepíše je. Pozorování a kritiku provádí člověk nebo worker — Claude, Codex, Gemini — a repozitář výsledek odmítne, pokud nedrží pohromadě. Nic zde neodvozuje plán z intentu automaticky.
Preflight: smí tato práce pokračovat a čeho se musí držet
majordomus intent preflight --issue <id> (nebo --path <p>, opakované) je jediné spojení, které relace nebo přechod spotřebuje před zahájením práce; schopnost intents.preflight odpovídá toutéž hodnotou přes HTTP i MCP. Úkol se sleduje přes kritéria, která deklaruje v serves — nikdy jen přes jeho milník — a jeho spojení se posuzují podle pokrytí, které hlásí intent validate, takže se nemohou rozcházet v tom, které spojení je rozbité. Verdikt je jeden ze tří:
| verdikt | kdy | ukončení |
|---|---|---|
serves | každý článek drží a každý obsluhovaný intent má kritiku bez otevřeného blokujícího zjištění | 0 |
maintenance | úkol neslouží ničemu pod milníkem, který žádný živý záměr nepojmenovává, pokud to validace dovoluje | 0 |
refused | kterákoli příčina níže | 10 |
| příčina | co to znamená |
|---|---|
unknown_issue | uvedený úkol není v plánu |
no_issue_covers_paths | rozsah žádného otevřeného úkolu nepokrývá žádnou z cest |
issue_serves_nothing | milník úkolu realizuje živý záměr a úkol neslouží žádnému z jeho kritérií |
serves_another_intent | slouží kritériu záměru, který nejmenuje svůj milník |
serves_unknown_criterion | slouží intentu nebo kritériu, které neexistuje, nebo chybně utvořenému odkazu |
intent_not_critiqued | záměr, kterému slouží, nemá kritiku |
open_blocking_finding | kritika intentu, jemuž slouží, má blokující nález, který je stále open |
S cestami se posoudí každý otevřený úkol, jehož rozsah jednu pokrývá, a vypíše se s vlastním verdiktem; odpověď je nejhorší z nich, takže jeden obsloužený úkol nikdy neručí za jiný, který neslouží ničemu. Obsloužená práce vedle údržby odpovídá serves.
Odpověď nese záměry, kterým práce slouží, a žádné jiné: každý s jeho zněním, obsluhovanými kritérii s živým stavem jejich důkazů, jeho invarianty, non-goals a správou, jeho kritikou s ještě otevřenými blokujícími zjištěními a jeho zaznamenanou mezerou omezenou na obsluhovaná kritéria.
Vazba: čemu úloha slouží, ptáme se před jejím začátkem
Preflight je otázka. Vazba je to, kdo se jí ptá (ADR 0111): majordomus start, majordomus context, majordomus handover a majordomus plan start se každý ptá schopnosti intents.binding — majordomus-cli intent binding, GET /api/v1/intents/binding, majordomus_intent_binding — a sám nerozhoduje o ničem. Úloha jmenuje práci, kterou provádí:
| úloha zahájená pomocí | je vázáno |
|---|---|
--issue <id> | kritéria, kterým tento úkol slouží |
--intent <id> | otevřené úkoly sloužící tomuto záměru |
--exempt <class> --because "<reason>" | nic: třída, kterou politika deklaruje v intent.exemptions, a proč |
| samotný rozsah | otevřené úkoly, jejichž rozsah pokrývá cestu, když se politika vůbec ptá |
Stav je bound, maintenance (úkoly leží pod milníky, které nejmenuje žádný živý záměr), exempt nebo refused. Odmítnutí nese jednu z příčin preflightu, nebo takovou, kterou najde jen vazba:
| příčina | co to znamená |
|---|---|
nothing_named | nebyl zadán žádný úkol, záměr, cesta ani výjimka |
unknown_intent, intent_retired | uvedený záměr neexistuje, nebo je zrušen či nahrazen |
intent_has_no_open_work | žádný otevřený úkol neslouží jmenovanému záměru |
issue_outside_intent | pojmenovaný úkol neslouží žádnému kritériu vedle pojmenovaného záměru |
ambiguous_intent | samotné cesty dosáhly více než jednoho záměru; jmenujte úkol |
unknown_exemption, exemption_without_reason, exemption_names_work | třída není deklarována, nebyl uveden důvod, nebo byla udělena výjimka vedle pojmenované práce |
Co odmítnutí stojí, je intent.binding politiky:
| hodnota | start | plan start |
|---|---|---|
chybí nebo off | ptá se jen při zadání --issue, --intent nebo --exempt; odmítnutá nebo nečitelná odpověď na tu otázku nezačíná | beze změny |
advisory | vždy se ptá; odmítnutá vazba se ohlásí a úloha začne | beze změny |
required | odmítnutá nebo nečitelná vazba nenastartuje | úkol, jehož vazba je odmítnuta, se nestane ACTIVE, v obou enginech |
Vazba, kterou nelze přečíst — žádný sestavený spustitelný soubor, žádné jq — je neznámá a neznámé není nikdy úspěch tam, kde byla odpověď vyžadována.
Záznam úlohy a předávka uchovávají to, co worker jmenoval, a dva piny, a nic ze samotného záměru: plan_revision se posune, když se upraví tvrzení záměru, invarianty, non-goals nebo kritéria, odkaz nebo kritika; evidence_standing se posune, když kritérium, které je obsluhováno, změní stav důkazů. majordomus context vypisuje sekci INTENT čtenou z vazby při každém volání a majordomus handover --resolve vypisuje Intent: unchanged, evidence_moved, plan_changed nebo unknown. Úkol, který úloha jmenovala, je odkaz declared v realizaci níže.
Realizace: kdo ji činí pravdivou a zda s ní realita souhlasí
Záměr patří projektu, ne relaci, která na něm pracuje. Která práce jej realizuje, se proto nikdy nezapisuje do úlohy, relace ani předávky; spojuje se při každém čtení ze záznamů, které lifecycle už vede (ADR 0075): úlohy účetní knihy, každá se všemi epizodami, které na ní pracovaly, poskytovatelem každé epizody a předávkami mezi nimi; uzavřené záznamy relací; a claimy na nástěnce peerů.
majordomus intent realization # every intent, its unmet criteria, the work realising it
majordomus intent realization --intent <id> # one intent and the work linked to it
majordomus intent explain <id> # why it stands where it stands, sentence by sentence
Každá vazba od práce k úkolu říká, jak je známa, a spojení si pro každý úkol ponechá tu nejsilnější:
| provenance | jak byl link přečten |
|---|---|
declared | tvrzení nebo vlastní slova úlohy citují úkol |
observed | přechod plánu v epizodě práce, nebo issues uzavřeného záznamu relace |
derived | název větve nese id úkolu |
inferred | jen když neexistuje nic silnějšího: rozsah otevřeného úkolu se překrývá s prací |
Takže úloha, kterou epizoda Claude Code zahájí a předá a epizoda Codexu obnoví, je jedna jednotka práce se dvěma epizodami a oběma poskytovateli a záměr, jemuž slouží, uvádí oba. Řádek ledgeru session.started epizody pojmenovává jejího poskytovatele, takže řada přežije konec epizody.
Uzavřená práce nepřebíjí důkazy. Když je každý milník záměru DONE a poslední zaznamenaný běh kritéria selhává nebo je zastaralý (už není aktuální, viz výše), realizace hlásí closed_work_contradicted se jménem kritéria a končí s exit 10; spouští ji kontrola intent-realization. Záměr, který byl splněn a regreduje, skončí přesně tam: jeho fáze spadne zpět na verifying a nic o záměru se k tomu nemuselo zapsat. closed_work_unproven (každý milník DONE, kritérium nikdy nedoloženo) a criterion_closed_unmet (každý úkol sloužící kritériu DONE, kritérium nesplněno) jsou varování, stejně jako živá práce, která neslouží žádnému záměru (work_serves_no_intent). Kde se fáze a verdikt rozcházejí, jmenují to dvě další varování jednou na záměr: evidence_ahead_of_plan (verdikt je satisfied, zatímco fáze je planned nebo executing) a closed_work_not_satisfied (každý milník DONE, verdikt unsatisfied nebo unknown, s kritérii, která ho drží zpátky).
V Cockpitu /cockpit/intents vypíše každý záměr s jeho fází a prací, která jej realizuje, a /cockpit/intents/<id> ukáže jeden: každé kritérium se stavem důkazu, navázané na objekt testu, který jmenuje, a na úkoly, které mu slouží, a každou jednotku práce s provenancí jejího odkazu. Obě stránky vykreslují schopnosti výše a samy o ničem nerozhodují.
test/cases/388_an_intent_is_realised_across_providers_and_held_to_reality.sh je smyčka od začátku do konce: deklarována, realizována přes dva poskytovatele a předávku, uzavřena, zatímco jeden případ selhává, opravena, splněna, znovu rozbita a opravena — se souborem intentu bajt po bajtu totožným po celou dobu.
Co záměry zatím nedělají
Každé z nich je tvrzení planned v CLAIMS.yaml a domovská stránka je odtud vypisuje:
intent-closes-github-milestones— projekce GitHub uzavírá milník jen z jeho odvozeného stavu plánu a žádný intent nečte.intent-command-deployment-evidence— kritérium rozhodnutécommandnebodeploymentse vyřeší a čte senot_derivable; ledger zaznamenává jen běhy testů a tvrzení, takže takové kritérium není nikdy splněno.
Dohledatelnost: co úkol realizovalo a co úkol realizoval
Model sahá sám jen po větev: složka cesty větve rovná id úkolu (feature/I1305-traceability → I1305) je jediná hrana, kterou topologie už čte a pre-commit pojistka už vynucuje. Vše nad ní — commity, pull requesty — je odvozeno při každém čtení a nikde neuloženo. Žádný kanonický záznam pod .ai/repo/project/ neuvádí větev, commit, pull request ani běh kontroly a žádný nesmí: git a GitHub tato fakta už drží a záznam, který jedno opakuje, je druhá pravda, jež začne hnít ve chvíli, kdy se přepíše historie.
Dva systémy drží dvě poloviny a hranice mezi nimi je táž, kterou respektuje scripts/github-sync — spustitelný soubor, bin/, lib/, share/ a test/ nevolají síť a test/cases/08_no_forbidden_constructs.sh to dokazuje:
| polovina | zdroj | kde žije |
|---|---|---|
| větve a commity | git for-each-ref, git log | modul schopností trace Rust programu |
| pull requesty | GitHub API, přes gh | scripts/traceability |
flowchart LR
issue["issue"]
subgraph git["derived from git"]
branch["branch"] -->|contains| commit["commit"]
end
subgraph github["derived from GitHub"]
pr["pull request"]
end
issue -->|names| branch
pr -->|"head branch of"| branch
milestone["milestone"] -->|"the one edge git does not hold:<br>the canonical issue record declares it"| issue
Commity větve jsou commity, které drží a trunk nikoli: měřeno proti trunku, dokud je větev otevřená, a proti prvnímu rodiči merge commitu, který ji přinesl, jakmile je sloučena. Čteno zpětně, commit patří k úkolu, jehož větve ho drží.
Tři odpovědi jsou stavy, ne selhání, a každá se hlásí jménem, nikdy se tiše nezahodí:
- absorbed — větev se dostala do trunku bez vlastního merge commitu (fast-forward nebo rebase na něj). Její commity se od commitů trunku nedají rozlišit, takže se žádné nenárokují a trasování říká, že je neúplné.
- unattributed — commit nedrží žádná větev jmenující úkol a head větev žádného pull requestu žádnou nejmenuje. Je to buď práce commitnutá bez smlouvy o provádění, nebo větev smazaná po svém sloučení, a odpověď to říká, místo aby mezi nimi volila. Práce bez smlouvy je přesně to, co report sledovatelnosti existuje zviditelnit; vynechat ji by report zmařilo.
- nejednoznačné — větve jmenující dva různé úkoly drží stejný commit. Hrana jména větve nemůže rozhodnout, a tak nerozhoduje.
scripts/traceability every issue, and the trunk commits nothing accounts for
scripts/traceability --issue I1305 its branches, its commits and its pull requests
scripts/traceability --commit <rev> the issue and milestone it served, or unattributed
scripts/traceability --pull 42 the same, from the pull request's side
scripts/traceability --no-github the git half alone: no token, no network
scripts/traceability --strict exit 10 when something has no contract; the shape of a gate
Polovina s gitem je majordomus_trace_issue, majordomus_trace_commit a majordomus_traceability na MCP a /api/v1/trace, /api/v1/trace/issue, /api/v1/trace/commit na HTTP; skript je jejich klient, nikoli druhá implementace. MJ_GH_FIXTURE_PULLS čte pull requesty ze souboru ve tvaru, který vytváří živé čtení, takže spojení lze dokázat bez sítě a bez tokenu — stejný šev používá scripts/github-sync a zkouší jej test/cases/98_traceability.sh.
Doručení: jak daleko práce došla
Stav úkolu je razítko; jeho dodání je fakt o objektech, které ho realizovaly. majordomus plan delivery [<id>] [--at <rev>] [--json] odpovídá u každého úkolu na nejvzdálenější prokázanou fázi, s objektem, který ji prokázal, a kdy byl pozorován (ADR 0166). Nic se neukládá a nic z toho nezapisuje razítko: merge není akceptace.
| fáze | dokázáno v |
|---|---|
none | nic z přečteného úkol nejmenuje |
branch | větev, jejíž složka cesty je id úkolu (pravidlo I1405) nebo slug úkolu |
pr_open | otevřený pull request v zaznamenaném pozorování forge, jehož titul nebo head větev ho jmenuje |
merged | nejnovější commit v historii trunku, který jej jmenuje: sloučení podle názvu pull requestu nebo větve, nebo commit podle předmětu (type(scope): description (I2740)); nikdy tělo, které stejně ochotně zmiňuje sousední úkoly |
released | první záznam releasu (.ai/repo/releases/v*.yaml), jehož commit obsahuje tento merge |
deployed | publikované latest.json jmenuje tento release nebo pozdější |
Živá odpověď čte trunk, který tento klon zná (remote-tracking trunk, pokud lokální není napřed), každou větev, pozorování forge, které majordomus prs refresh zaznamenal, záznamy release a latest.json commitu, který naposledy úspěšně publikoval nasazení Pages (zaznamenává ho majordomus served forge). Release pocházejí ze záznamů, nikdy z tagů: záznam jmenuje commit, který vydal, a je souborem stromu, zatímco tag je ref, který se může objevit kterýkoli den.
Commitnutá odvozená data jsou funkcí samotného commitu, jinak by každý tag, push, pull request a nasazení rozsvítilo scripts/generate-site-data --check červeně na každé otevřené větvi. Proto --at <rev> čte jen merge tohoto commitu a záznamy vydání stromu: dokazuje merged a released a větve, forge a publikaci hlásí jako nepřečtené. scripts/generate-site-data zapíše tuto odpověď do site/data/generated/delivery.json na HEAD a reprodukuje ji pod --check na commitu, který soubor jmenuje. Živé fáze (branch, pr_open, deployed) dosahují CLI, HTTP, MCP a UI; jejich dovedení na publikovaný web při buildu Pages, jako je tomu u snapshotu UI, je ponecháno plánovacím povrchům (I2743, I2744).
Zdroj, který se nečetl, se hlásí jako nepřečtený s důvodem, nikdy jako žádný. Úkol, který by nepřečtený zdroj mohl posunout dál, není settled a jmenuje tento zdroj v unread. Stejná odpověď je GET /api/v1/plan/delivery a nástroj MCP majordomus_plan_delivery.
Pull request mergovaný uvnitř kombinovaného topu se dostane do trunku přes octopus merge, který jej jmenuje jen v próze, a jeho název patří forge, ne gitu. majordomus served forge proto v pozorování deploymentu zaznamenává i nejnovější mergované pull requesty (až 1000, po stránkách po 100) a živá odpověď počítá název mergovaného pull requestu, když je jeho merge commit nebo head v přečtené historii (via: forge_title). Tak se ukáže, že #1097 realizoval I2653, který jeho commity jmenují jen v těle. Zdrojem je merged_titles; u commitu je nepřečtený, takže commitnutá data zůstávají funkcí historie commitu.
Kde je práce nyní
now příkazu plan.roadmap je první otevřený milník v pořadí plánu, ať na něm někdo pracuje, či ne. plan.flight (GET /api/v1/plan/flight, MCP majordomus_plan_flight) odpovídá místo toho, kde se práce odehrává, živě při každém volání (ADR 0166, rozhodnutí 4):
- now je každý otevřený milník s otevřeným úkolem, na kterém probíhá práce: otevřený pull request, který jej jmenuje (
pr_open), živý claim mesh vytvořený pro něj nebo deklarovaný stavACTIVE. Každý přichází s těmito úkoly, důvodem, proč jsou rozpracované, jejich deklarovaným stavem vedle odvozené fáze a objekty, které to dokazují, s odkazem na forge, kde je má; - next je první otevřený milník v pořadí plánu, který není now a jehož nedokončené předpoklady jsou všechny now;
- Nejnovější release je nejvyšší stabilní verze mezi záznamy releasů, tagy
v*klonu a publikovanýmlatest.json. Každý zdroj je hlášen jako přečtený nebo nepřečtený aexecutable_taggedříká, zda je vlastní verze odpovídajícího spustitelného souboru otagována. Záznam, který se mergne po svém tagu, už nezpůsobí, že obrazovka ukazuje starší release, než je ten, který ji vykreslil.
/ui/roadmap ji čte a ?milestone=<id> se na ni ptá u každého úkolu daného milníku. Mesh běží v serveru; jinde se jeho tvrzení hlásí jako nepřečtená.
Drift: kde si razítka protiřečí s prací
Odvozování nikdy nezapisuje razítko, takže se obojí může rozcházet. majordomus plan drift [<id>] [--at <rev>] [--gate head|trunk] [--json] jmenuje každý rozpor s objekty, které jej prokazují (ADR 0166, rozhodnutí 2):
| třída | deklarováno | dodáno |
|---|---|---|
merged_not_recorded | READY, BLOCKED nebo ACTIVE | uvádí ho sloučení (pull request, merge commit, release) a neuvádí ho žádný otevřený pull request |
active_without_work | ACTIVE, začalo před oknem | žádná větev, pull request, sloučení ani živý claim v meshi ji nejmenuje |
done_without_trace | HOTOVO | žádný merge ho nejmenuje; jen upozornění, protože existují úkoly pouze pro záznam |
Každé zjištění nese svůj věk, zda je za oknem, zdroje, které nebyly přečteny a mohly ho rozpustit (unread; zjištění s nepřečteným forge je stále zjištění a není settled), a příkaz, který ho rozhodne: majordomus plan verify|done <id>.
.ai/repo/ci/plan.yaml deklaruje drift.window (sekundy) a drift.enforcement (advisory nebo blocking). Kontrola plan-drift (scripts/ci/plan-drift-check, každý plán) se při pushi do výchozí větve ptá na plan drift --gate trunk a všude jinde na --gate head:
- na hlavě je každé
merged_not_recordedPENDING; - na trunku je ten, který byl sloučen dříve, než je okno, ODMÍTNUT s uvedením příkazu, který to urovná, a mladší je PENDING;
active_without_workje NOTE adone_without_traceADVISORY: ani jedno neodmítá;- chybějící nebo nečitelné okno odmítne (exit 12);
- odmítnutí shazují kontrolu (exit 10) pod
blockinga podadvisoryse hlásí s exit 0. Kontrola přistává jako poradní, aby nezčervenila trunk kvůli driftu, který předchází; I2748 ten drift vyřeší a učiní ji blokující.
Táž odpověď je GET /api/v1/plan/drift a nástroj MCP majordomus_plan_drift. test/cases/3101_merged_work_unrecorded_is_drift.sh dokládá třídy, okno a kontrolu, přičemž šest mutací kódu ji shodí.
Projekce
Kanonické soubory jsou jediným zdrojem. Vše ostatní z nich generuje jediný engine — lib/project.awk, načítaný přes lib/project.sh — takže žádné dva povrchy nemohou mít různý názor na to, co je připraveno:
| povrch | jak |
|---|---|
| příkazová řádka | majordomus plan |
| DAG v Mermaidu | majordomus plan graph |
| Milníky a úkoly na GitHubu | scripts/github-sync, prokázáno jako aktuální pomocí scripts/ci/github-check |
| stránky plánu rozvoje, milníků, úkolů a DAG webu | scripts/generate-site-data |
| dokumentace | tento soubor vysvětluje sémantiku; čísla jsou generovaná |
GitHub je projekce a místo k diskusi, nikdy zdroj. Kanonická změna aktualizuje generovanou oblast těla úkolu; člověk, který tuto oblast upraví, je hlášen jako drift a nepřepisuje se; komentáře člověka a jakýkoli text mimo oblast se nikdy nedotknou. Nic se nečte zpět: zavření úkolu na GitHubu ho zde nedokončí.
Záznam se na GitHubu najde podle identity, kterou nese ve svém těle, zapsané vedle hashe jako <!-- majordomus:record I0001 -->. Číslo na GitHubu přiděluje GitHub a název upravuje člověk, takže ani jedno nemůže být klíčem: párování podle názvu znamená, že přejmenování osiří záznam a další --apply vytvoří druhý pro práci, která už existuje.
Každý nález o těle je jeden ze šesti stavů, ze dvou nezávislých otázek — přepsal člověk oblast od chvíle, kdy byla zveřejněna, a pohnul se od té doby kanonický záznam?
| state | význam | --apply |
|---|---|---|
insync | neporušeno a aktuální | nic |
behind | neporušeno, kanonický záznam se posunul | přepisuje |
edited | oblast přepsal člověk | odmítne bez --force |
conflict | člověk jej přepsal a záznam se pohnul | odmítne bez --force |
adopt | bez značky identity; tentokrát přiřazeno podle názvu | napíše jeden |
missing | žádný protějšek na GitHubu | vytváří |
a u vzdáleného záznamu místo kanonického unmanaged: úkol, který si nárokuje kanonické id, jež tento repozitář nemá.
Aplikace je důsledek landingu; shoda je kontrola. Každý push do výchozí větve spustí .github/workflows/github.yml, který spustí --check, pak --apply, když je něco dlužno, a pak kontrolu (project.the-projection-is-applied-at-landing@1); --apply člověka z trunku je záložní cesta, když ten běh selže. scripts/ci/github-check čte remote při každé změně, která může pohnout kteroukoli stranou, prvních šest stavů rovnou odmítne a ratchetuje missing a adopt proti .ai/repo/ci/github-drift-baseline.txt, které smí klesat a nikdy nesmí stoupat. Existuje proto, že detektor byl napsán, nikdy nevolán, a projekce za pět dnů zchátrala na desetinu modelu, zatímco každý build byl zelený (project.github-projection-gated@1).
Head se posuzuje podle toho, co mění. GitHub ukazuje plán trunku a nic jiného, takže záznam, který pull request upravuje, je tam behind, dokud se pull request nesloučí a přistání ho neaplikuje. Kontrola hlásí čtyři stavy, které aplikace zapisuje (behind, state, milestone, closed), jako PENDING místo jejich odmítnutí, u záznamů, které head změnil od svého merge base, a na trunku u záznamů změněných v přistání mladším než apply.window v .ai/repo/ci/github.yaml. Po uplynutí tohoto okna je trunk odmítnut a odmítnutí pojmenuje scripts/github-sync --apply. Záznam se počítá jako změněný, když se liší jeho soubor nebo jeho vykreslení, protože uzavření jednoho úkolu pohne stavem každého úkolu, který na něj čekal. Drift záznamu, který head nezměnil, se odmítá jako dříve.
Síťová volání žijí v scripts/github-sync, mimo nástroj. bin/, lib/, share/ a test/ neobsahují žádného síťového klienta a test/cases/08_no_forbidden_constructs.sh to dokazuje.
Práce s modelem
majordomus plan status # where the outcome stands
majordomus plan next # the one issue to take now
majordomus plan show I0007 # the whole contract, no chat history needed
majordomus plan start I0007 # refused unless it is READY
# ... execute, inside the scope the issue declares ...
majordomus plan verify I0007 # implementation complete, evidence pending
majordomus plan evidence I0007 --covers doctrine_test --type test \
--command "bash test/run.sh 44_model_doctrine" --result "1 passed"
majordomus plan done I0007 # refused while a required token is uncovered
majordomus plan next # recomputed, not chosen
Pracovník bere úkol, který mu graf nabízí. Vybrat něco jiného chce důvod: je to blokátor, neplatí kvůli tomu předpoklad, na kterém milník stojí, nebo člověk změnil priority.
Přeplánování
Plán se bude měnit. Přidat úkol, odebrat jeden, rozdělit jeden, sloučit dva, přesunout hranu, zúžit rozsah, změnit validaci — to vše je úprava kanonických souborů a vše se znovu ověří při dalším čtení. Dvě omezení přežijí každou úpravu: graf zůstává acyklický a rozlišitelný a už zaznamenané důkazy se nemažou kvůli úhlednějšímu příběhu.
Přeplánování není volitelné, když úkol objeví závislost, kterou nikdo nepředpověděl, kritérium přijetí se ukáže jako netestovatelné, implementační cesta je vyvrácena nebo se úkol stane zbytečným. Nechat graf popisovat plán, který realita opustila, je přesně to selhání, kterému tato vrstva má zabránit.
Co bylo odmítnuto
Pole status s validací. Dva zdroje pravdy a pravidlo, jak je smířit. Správný může být jen graf, takže jen on se ukládá.
Milník, který vypisuje své úkoly. Druhá hrana v opačném směru, která se může s první rozcházet.
Samostatné úložiště důkazů. Kontrakt a důkaz, že byl splněn, patří do jednoho záznamu; jejich rozdělení umožňuje číst jedno bez druhého.
Mapovací soubor z kanonického id na číslo na GitHubu. Stav, který je třeba udržovat v souladu se dvěma systémy. Úkol nese své id ve značce uvnitř své generované oblasti, milník jako předponu názvu a párování je porovnání řetězců.
Odhady, velocity, burndown. Žádné z nich nemění, co má pracovník dělat dál, což je jediná otázka, na kterou tato vrstva odpovídá.
PLANNED jako status úkolu. Znamenal by vždy jen READY nebo BLOCKED s jiným slovem.
Viz také
docs/DOGFOODING.md— proč toto úložiště používá model samo na sobědocs/SCHEMAS.md— pole každého souborudocs/CLI.md—majordomus plan, podpříkaz po podpříkazudocs/DOCTRINE.md— jak se vynucujímajordomus.project-integrityamajordomus.dag-integrity