Pět veličin v tomto repozitáři, které rostou samy, příkazy, které je měří, a příkazy, které je zmenšují. Chování tak, jak je implementováno a testováno; kde se tento dokument a skripty rozcházejí, dokument se mýlí a mění se ve stejném commitu. Pravidlo je project.accumulation-is-measured; kontrola je scripts/ci/backlog-check; behaviorální případy jsou test/cases/131_backlog_hygiene.sh a test/cases/276_disk_is_bounded.sh.
Zjištění, kvůli kterému to existuje
2026-09-11 operátor nahlásil jeden příznak — worktrees, procesy a větve se hromadí a nic se nenasazuje — a měření našlo čtyři oddělené veličiny najednou (pátá, disk, zaplnila svazek následující den a má níže vlastní sekci):
| Množství | Změřeno | Z toho |
|---|---|---|
| otevřené pull requesty | 16 | 15 se čistě sloučilo na jakémkoli vývojářském stroji |
| linked worktrees | 64 | 47 s nepotvrzenou prací |
| lokální větve | 111 | 91 nesloučeno do origin/master |
běžící servery majordomus | 192 | 14 opuštěných, jeden starší než den, 13 portů, ~150 MB |
Nasazovací pipeline nebyla rozbitá: gh-pages bylo o jeden commit za master a web běžel. Nic neselhávalo. Každá část fungovala tak, jak byla navržena, a výsledkem byl přesto stav bez pohybu — což je smyslem tohoto dokumentu.
Proč se pull requesty na GitHubu nemergují a nikdy nebudou
Toto úložiště commituje své odvozené artefakty a každý z nich nese otisk stromu, ze kterého byl vygenerován. Po merge tento strom není stromem žádného z rodičů, takže oba zaznamenané otisky jsou špatně a žádná textová kombinace z nich není správná — správná hodnota existuje až po spuštění generátoru. .gitattributes proto tyto cesty označí merge=derived a scripts/merge-derived je vyřeší místo konfliktu.
Vlastní merge driver je spustitelný soubor jmenovaný v git config merge.<name>.driver. Tato konfigurace je pro každý klon a nelze ji commitnout — proto existuje just derive-merge-driver. Servery GitHubu jsou klon, který ji nikdy nespustil. GitHub tedy provede prostý třícestný merge nad soubory, které každá větev přegenerovává, najde konflikty ve všech a ohlásí pull request jako CONFLICTING / DIRTY.
CONFLICTING na GitHubu není falešně pozitivní. Konflikt je skutečný pro každý klon, který nemá driver, a GitHub je vždy takový klon. Táž větev, změřená oběma způsoby:
git merge-tree --write-tree origin/master <branch> # exit 0
git -c merge.derived.driver=false merge-tree --write-tree origin/master <branch> # exit 1, 15 conflicts
Na otázku „sloučí se to“ tedy existují dvě poctivé odpovědi a která z nich se dostane k vám, závisí na tom, zda je driver nakonfigurován. Ta, na které záleží, je klon, který výsledek skutečně ponese — vývojářův stroj — a tam byla odpověď ano u patnácti z šestnácti toho dne otevřených. Tlačítko merge není pomalé ani nespolehlivé; je strukturálně nedostupné a dostupným se nestane. Přispěvatel, který na ně čeká, čeká navždy, a toto čekání je celý backlog.
Zeptejte se gitu na návratový kód, nikdy nehledejte grepem v jeho výstupu. Znění konfliktu u merge-tree není smlouva; grep, který ho mine, započítá konfliktní merge jako čistý, což je nejdražší způsob, jak může být toto měření špatně. majordomus prs používá návratový kód.
Příkazy
| Množství | Měření | Zredukovat |
|---|---|---|
| pull requesty | majordomus prs status | majordomus prs drain --refresh |
| worktrees, větve | majordomus worktree | úklid majordomus worktree, ručně u špinavých |
| opuštěné servery | scripts/reap-orphans | scripts/reap-orphans --kill |
| výstup buildu na disku | scripts/reap-orphans --targets | scripts/reap-orphans --reclaim |
| celá kontrola | scripts/ci/backlog-check | scripts/ci/backlog-check --remote |
majordomus prs
Integrace pull requestů je typovaný podsystém spustitelného souboru (docs/INTEGRATION.md, ADR 0101). majordomus prs refresh pozoruje forge a stahuje každou otevřenou hlavu; status, plan a explain klasifikují každý pull request proti aktuálnímu masteru gitem a odvozeným driverem — nikdy ne mergeable forge — offline; drain mergne další připravený, ověří, že přistál, a před čímkoli dalším znovu pozoruje, jeden merge po druhém. drain --refresh přinese master do prvního pull requestu, který ho potřebuje, když nic není připraveno, po jednom, protože merge čehokoli jiného mezitím by ho zase dostal pozadu.
Nahradilo scripts/land, které sloučilo každý čistý pull request na jednu integrační větev: dávka, jejíž regrese nikdo nedokázal přiřadit, plánovaná ze seznamu, který první merge zastaral.
Měření běží na hodinách: .github/workflows/queue.yml (model .ai/repo/ci/queue.yaml) spouští majordomus prs refresh a majordomus prs status každých třicet minut a publikuje frontu do souhrnu jobu, takže její stav je měření, nikoli něco, na co si někdo vzpomene zeptat. Nikdy nespouští drain ani cleanup --apply a jeho token nemůže zapisovat: stav je automatický, merge zůstává rozhodnutím. Token jen pro čtení nemůže přečíst ani ochranu větve, takže to report řekne (exit 10) a nic nenazve ready; job selže jen u nepoužitelného měření (exit 12). test/cases/350_the_queue_measures_itself.sh drží obě poloviny a selže, pokud workflow získá jednající příkaz nebo oprávnění k zápisu.
scripts/reap-orphans
majordomus serve nebo mcp přežije svého klienta, kdykoli klient zemře bez jeho zavření: rodič je sklizen, server je přepodřízen procesu init a drží svůj port i paměť do restartu stroje. Server, který odpovídá, není server, s nímž někdo mluví.
Relace v tomto repozitáři jsou navzájem svými nástroji, takže proces se nikdy neshoduje podle jména. pkill -f majordomus by ukončilo servery, ke kterým jsou připojeni živí peers. Proces se ukončí, jen když platí všechny čtyři podmínky, každá znovu ověřená těsně před signálem:
- je to proces majordomus
servenebomcp, podle cesty ke spustitelnému souboru; - jeho rodičem je init (
ppid 1) — relace, která ho spustila, zanikla; - má nula TCP spojení
ESTABLISHED— není připojen žádný klient; - je starší než
--min-age(výchozí 30m).
Ve výchozím stavu nanečisto; --kill provede akci. Server, který získá klienta mezi skenem a signálem, se přeskočí.
Souhlas také vybírá svůj předmět. Bez --servers/--targets zkoumá --kill samotné servery a --reclaim samotný výstup buildu; bez jakýchkoli příznaků se hlásí obojí a nic se nedotkne. Není to kosmetika. Běh --reclaim jednou vypsal tabulku živých serverů pod slovy would reap, což svádí čtenáře věřit, že souhlas, který dal pro výstup buildu, se chystá ukončit jeho server — nebo už ukončil. Souhlas pojmenovaný pro jeden předmět nikdy netabuluje předmět druhého.
Úklid, který se zastaví před svým shrnutím, říká INCOMPLETE a jmenuje, který ze dvou předmětů zkoumal a který nikdy nedosáhl. Hlavička sloupců s řádky pod sebou má tvar odpovědi a stav ukončení je jediné, co říká opak — což nikdo z terminálu nečte. 2026-09-13 běh vypsal hlavičku, jeden server a zemřel na SIGPIPE s exitem 141 z nedostatku čtenáře, který by četl svůj proud do konce; považoval se za report (project.a-verdict-states-its-subject, test/cases/318_a_partial_sweep_says_so.sh).
Výstup sestavení a podlaha pod sestavením
Dne 2026-09-12 tento stroj dosáhl nula volných bajtů na svazku o velikosti 926 GiB. Každá relace na něm zemřela ve stejné minutě — ne elegantně, ale s harnessem neschopným zapsat vlastní soubory úloh, což se každé relaci jeví jako rozbitý tooling, ne jako plný disk, a df nešlo spustit také. ~/dev/prismatic-majordomus-wt držel 180 GB, z toho ~145 GB tvořilo apps/majordomus-cli/target ve worktrees, jejichž větve už byly sloučeny. Jeden přistál před hodinami a stále držel 32 GiB. Nic v dokončení práce neodstraní adresář sestavení, který vytvořila, takže by to neudělalo nikdy nic.
Odpovídá na to tentýž reaper, s druhým subjektem a druhým souhlasem (--reclaim, nikdy ne --kill). Odstraňuje target/ a nikdy worktree: falešně pozitivní nález někoho stojí přestavbu a nemůže stát ani bajt zdroje. Adresář sestavení se získává zpět jen tehdy, když platí všechna čtyři — mergnuto do origin/master nebo pushnuto (špička je v remote-tracking refu), nikdo v tom worktree nepracuje, git status je prázdné a adresář je prokazatelně vlastním adresářem cargo uvnitř onoho worktree. Pushnuto bylo přidáno 2026-10-10, kdy forma jen pro mergnuté mohla získat zpět 3 z 31 adresářů sestavení, zatímco 270 GB leželo ve větvích pushnutých a čekajících ve frontě přistání nebo v odpojených offload stromech a dva stroje dosáhly najednou 99 %. Primární checkout je vyloučen jménem, ne predikátem, protože jeho spustitelný soubor si půjčuje každý jiný checkout.
Živost se čte ze stroje (ps a pracovní adresář každého procesu) a nikdy z nástěnky peerů: oznámení patří připojení a pracovník, který se znovu připojí, si ponechá práci, ale ztratí své místo na nástěnce — přesně okno, v němž reaper běží. Samotná mergnutost by byla katastrofa a ten případ nastal na stroji toho rána: worktree o 11,8 GB se živým peerem uvnitř se četl jako plně mergnutý, protože relace v něm pracující ještě necommitovala a jeho špička byla stále tam, kde ji merge nechal. mtime tu není nikdy predikátem (je to ten, jehož chybějící vstup se změní na extrémní hodnotu, a jednou vyčistil tři aktivní worktrees) a reaper jako celek odmítá — nezískává zpět nic, ne všechno — když nelze přečíst živost nebo origin/master.
Druhá polovina je mez, ne varování. df v doctor pomůže další osobě a nemůže pomoci té, která už uvízla. mj_rust_space_check v lib/rust_bin.sh odmítne zahájit build pod 5120MB volného místa a všechny tři cesty, které jeden spouštějí — launcher, scripts/derive, just build — se na to ptají. Dolní mez je změřena: plný cargo build --locked crate do prázdného target/ zapsal 2,45GiB a dolní mez jsou dva takové. MAJORDOMUS_MIN_FREE_MB=0 ji zruší. Mez, jejíž vlastní vstup nelze změřit, to řekne a nechá build běžet — záměrný opak úklidu, protože odmítnout každý build na stroji, jehož df je nečitelný, zastaví veškerou práci kvůli hypotetické hrozbě.
Samotná podlaha je okraj útesu: odmítne, až když nic nezbývá, čím by odmítla, a reaper je příkaz, na který si někdo musí vzpomenout. Pod horní hranicí — MAJORDOMUS_RECLAIM_BELOW_MB, výchozí 51200MB, deset buildů v jejich mediánové pracovní velikosti — proto tatáž kontrola nejdřív sama spustí scripts/reap-orphans --targets --reclaim, nejvýš jednou za deset minut na stroj, a teprve pak uplatní podlahu. Zametání se děje, protože se dějí buildy. Reaper, který chybí nebo odmítne, build nikdy neshodí. test/run.sh nastavuje hranici na 0, protože případ nesmí jednat na stroji, který měří; případ 276 zkouší reklamaci na vlastní fixture.
Odvozené stromy, které nikdy nebyly deklarovány
merge=derived pomáhá jen cestě, která je označena. scripts/generate-site-data při každém běhu maže a znovu generuje čtrnáct celých sekcí pod site/content/ — jeho řádky rm -rf "$CONTENT_ROOT/..." jsou seznam — a 2026-09-11 třináct ze čtrnácti nebylo deklarováno v .gitattributes. Deklarováno bylo jen registry.
Každá integrace tak kolidovala v guarantees/, commands/, use-cases/, why/, plan/, skills/ a dalších: obsah, který nevlastní žádná větev, který generátor přepisuje celý a který pak člověk řešil ručně, při každém merge, donekonečna. Byla to po samotném omezení forge největší mechanická příčina nahromaděné fronty a vyšla najevo tady jen proto, že ji přistání šesti pull requestů zasáhlo hned při prvním merge origin/master.
Všech čtrnáct je nyní deklarováno a scripts/ci/backlog-check čte seznam z generátoru, místo aby jej vedlo ručně — ručně vedený seznam zaostane poprvé, když se přidá sekce, a právě tak třináct vynechání zůstalo nepovšimnuto.
Proč byly servery vůbec opuštěny
majordomus serve --idle N se zastaví, když k němu nebyl N sekund připojen žádný peer, a DEFAULT_IDLE_SECONDS (900) je konstanta, se kterou se spouští sdílený server — scripts/ci/entry-converges drží tento kontrakt pro server, který serve ensure spouští, což je cesta, kterou jde člověk.
Neunikla cesta. --idle syrového serve má výchozí hodnotu 0 — běžet do zastavení a čtyři případy sady spustily server na pozadí bez něj. Případ přerušený před spuštěním úklidového trapu — zabitý běh, limit útraty, zavřený notebook — nechá ten server držet port do restartu stroje. Odtud se opuštěné servery braly a proto nyní stejný kontrakt drží pro vlastní spouštění sady scripts/ci/backlog-check, nikoli jen pro vstupní cestu. Dvě poloviny jednoho pravidla, kontrolované jen jedním směrem, jsou tu opakující se tvar.
Worktree a větve
majordomus worktree odvozuje topologii z gitu (project.worktree-topology) a označuje, které větve jsou způsobilé k úklidu. Počet způsobilých je obvykle mnohem nižší než počet těch, které vypadají zbytečně: v den uvedený výše 5 ze 111. Nula unikátních commitů není důkaz, že je větev bezpečné smazat — sloučená větev může držet nezacommitovanou a nesledovanou autorskou práci a 47 ze 64 worktrees bylo špinavých. Klasifikujte pracovní strom, nejen historii, a před odstraněním čehokoli pushněte.
Co kontrola drží
Runner CI nemá žádné worktree, žádné opuštěné servery a žádnou vlastní nevyřízenou frontu, takže backlog-check ta množství neměří. Drží pohromadě věci, jejichž absence nechala ta množství nepozorovaně narůstat: že každé množství má stále svůj příkaz, že reaper je bezpečný konstrukcí, že .gitattributes a jeho instalátor se stále shodují — deklarace kontrolovaná jen jedním směrem je způsob, jakým tato třída vad přežívá — a že žádný dokument neposílá čtenáře k tlačítku merge. --remote přidává samotné měření a selže, když je přistávatelných a stále otevřených víc než MJ_BACKLOG_MAX (výchozí 10) pull requestů.