Přeskočit na obsah

Tato stránka byla automaticky přeložena z angličtiny, jediného jazyka, ve kterém se tento web píše. Číst originál.

Cockpit

Cockpit: registr vykreslený jako stránky pro člověka, čím je projekcí a ne dashboardem, modely grafu a zdraví, vrstva prohlížeče a co se děje bez ní, bezpečnostní rozhodnutí, pipeline assetů

Vykresleno z docs/COCKPIT.md — stejný Markdown, jaký ukazuje GitHub.

majordomus serve a majordomus mcp navážou jeden sdílený server na repozitář. Tento server už odpovídá strojům: nástroje a zdroje MCP, trasy HTTP pod /api/v1/, dokument OpenAPI a nad ním Swagger UI. Cockpit je tentýž server odpovídající člověku, na /cockpit.

Je to projekce v tom smyslu, jaký toto slovo má v tomto repozitáři: jedna další věc odvozená z kanonických deklarací schopností a z indexu, která nedrží žádný vlastní model, katalog ani verdikt. Rozhodnutí je ADR 12; pravidla, kterými je vázána, jsou project.interfaces-are-projections, project.rust-canonical-declaration, project.rust-benchmark-coverage a project.rust-hot-path. Chování tak, jak je implementováno a testováno; kde se tento dokument a spustitelný soubor rozcházejí, je špatně dokument a mění se ve stejném commitu.

flowchart TD
  decl["ONE CANONICAL DECLARATION<br>capability! { id, title, description, input,<br>output, stability, exposure, tags, cache?, handler }"]
  reg["CAPABILITY REGISTRY<br>+ every declarative object of the layer"]
  proj["DERIVED PROJECTIONS"]
  decl --> reg --> proj
  proj --> mcp["MCP"]
  proj --> http["HTTP"]
  proj --> openapi["OpenAPI"] --> swagger["Swagger UI"]
  proj --> cli["CLI"]
  proj --> bench["benchmark targets"]
  proj --> generated["docs/generated/*"]
  proj --> registry["the website's /registry/ pages"]
  proj --> cockpit["THE COCKPIT<br>pages, navigation, search,<br>palette, runner, graphs"]

Jak se tam dostat

majordomus serve                 # or `majordomus mcp`, which binds the same shared server

Server loguje URL, které navázal. Otevřete jej: prohlížeč je přesměrován na /cockpit a klient, který nežádá HTML, dostane JSON index, který dostával vždy. Obojí je na stejném portu; není druhý proces ani druhý příkaz.

Aby to fungovalo, není třeba nic sestavovat. Pokud share/cockpit/ nemá zkompilovaný stylesheet, stránky se přesto vykreslí, řeknou to a zůstanou plně použitelné.

Co na ní je

CestaCo ukazujeOdvozeno z
/cockpitnejprve čtyři otázky (je zdravý, co se změnilo, co je rozbité, co vyžaduje akci), poté identita repozitáře, stav gitu, stav indexu, spočítaný registr, každá diagnostika, shrnutí zdravídashboard.overview, repository.info, health.report
/cockpit/capabilitieskaždá schopnost, filtrovaná podle modulu, druhu, zdroje nebo texturegistr
/cockpit/capabilities/<id>jeden deskriptor celý: schémata, projekce, politika cache a měření výkonu, původ, příklady a formulář, který ho spustídeskriptor a jeho BenchmarkCases
/cockpit/commandskaždý příkaz, který tento repozitář nabízí, od kteréhokoli programu, který jej nabízí, a kam se každý promítácommands.list
/cockpit/executionsco tento proces spustil a co běží, s počty vedle; sleduje živý kanál a aktualizuje se sámexecutions.list
/cockpit/executions/<id>jedno provádění: jeho stav, kroky, průběh, diagnostika, živý výstup, výstup nebo chyba a vstup tak, jak byl uložen; stabilní URL, ze kterého se znovunačtení obnovíexecutions.get, executions.events
/cockpit/objectsdeklarativní objekty vrstvy, podle druhuobjects.list
/cockpit/objects/<kind>index jednoho druhu na vlastní adrese druhuentity.kinds, objects.list
/cockpit/objects/<kind>/<slug>jedna entita: co to je a kde ji veřejný web publikuje, co lze říct o artefaktech, které jmenuje, odkazy, které deklaruje, a odkazy, které se na ni vyřeší, povrchy, které za ni odpovídají, její front matter a soubor tak, jak jeentity.show
/cockpit/object?uri=adresa, kterou objekt měl, než dostal vlastní; stále se rozřeší, takže žádný publikovaný odkaz nepřestane fungovatobjects.get
/cockpit/directoriessmlouvy adresářů vrstvy: hierarchie, co každý adresář dluží, a pro jeden adresář jeho místní smlouva vedle řetězce, který se skutečně uplatňujedirectories.list
/cockpit/graphskaždý graf, který tento spustitelný soubor odvozujegraph.list
/cockpit/graphs/<id>jeden graf: kresba, slovníky a každý uzel a hrana jako tabulkygraph.get
/cockpit/graphs/topologygraf registru ve třech rozměrech — volitelnégraph.get (registry)
/cockpit/continuityco drží životní cyklus tohoto checkoutu a co dělá podsystém kolem něj: otevřená epizoda, o které je briefing, aktivní úloha, záznamy, které se zde rozlišují, se svými štítky, blokátory, ostatní stroje — toto zařízení, úložiště vůči svému remote a předávky publikované jinými zařízeními, které lze zde obnovit — pak každá otevřená epizoda úložiště, tento proces vůči repozitáři, obnova, poskytovatelé a sledované záznamycontinuity.state, continuity.status, lifecycle.episodes, lifecycle.runtime, lifecycle.recovery, lifecycle.providers, lifecycle.closed
/cockpit/intentskaždý záměr s jeho odvozenou fází, kritéria s aktuálními důkazy, práce a poskytovatelé, kteří jej realizují, a nálezy — mezi nimi uzavřená práce, které důkazy odporujíintent_realization.work
/cockpit/intents/<id>jeden záměr: jak daleko je od něj realita, každé kritérium se stavem důkazu, odkaz na objekt testu, který jmenuje, úkoly, které mu slouží, a příkaz, který jej reprodukuje; milníky; každá úloha, záznam relace a claim peera, který jej realizuje, s provenancí svého odkazu, poskytovateli a předávkami; a proč stojí tam, kde stojíintent_realization.explain
/cockpit/planmilníky v odvozeném pořadí s tím, který je aktuální, a tím po něm, úkol, který plán vydá jako další, a každý úkol filtrovaný podle milníku, stavu nebo vlnyplan.roadmap, plan.next, plan.issues
/cockpit/plan/milestones/<id>jeden milník jako graf práce: jeho výsledek, každý úkol s připraveností a vlnou, rozdělení, kritické blokátory, co smí běžet současně a každé zjištěnídevtask.milestone
/cockpit/plan/issues/<id>jeden úkol jako úloha: jeho intent, kritéria přijetí a rozsah, jeho připravenost a co jej blokuje, jeho větve a relace, externí úkol, se kterým se synchronizuje, každá hodnota s tím, odkud pochází — a tahy, které plan.transition dělá, každý spuštěný jako provádění a každý s příkazem, který jej provededevtask.issue, plan.transition, executions.start, executions.get
/cockpit/healthjedna kontrola na dimenzi, každá s enginem, který o ní rozhodl, a příkazem, který ji reprodukujehealth.report
/cockpit/qualityvlastní veřejný povrch crate tak, jak jej drží pravidla, každé číslo a nález z jednoho provedeníquality.report
/cockpit/artifactsco generátor zapisuje: každý dokument s kódováními, ve kterých je commitnut, každý soubor s jeho kontraktem a stavem vůči pracovní kopiiartifacts.list
/cockpit/releaseco udělala veřejná smlouva od posledního release a nejmenší verze, kterou dovolujerelease.analysis
/cockpit/designdesign systém tak, jak jej nese tento spustitelný soubor: každá role s hodnotou pro světlý i tmavý režim, stavy, typografická škála, hodnoty rozvržení a smlouva o motivudesign.system, design.tokens
/cockpit/meshobjevené uzly runtime tohoto procesu, poskytovatelé, kteří je zaslechli, a důvod, proč mesh běží nebo neběžímesh.status, mesh.nodes
/cockpit/monitorvše, co se děje kolem repozitáře, jako jeden živý seznam, nejnovější první: relace meshe, claimy, předávky a review, výsledky executoru a pull requesty a běhy GitHubu, s tím, co jmenuje čtenáře (?for=) první, sbaleným a započteným šumem a stavem každého zdroje (ADR 0133)monitor.stream
/cockpit/modelsdodavatelé a modely, které share/models.yaml deklaruje, s přítomností přihlašovacích údajů každého dodavatele (nikdy hodnota) a jejich směrovánímodels.list
/cockpit/apikaždá HTTP trasa, kterou registr promítá, a trasy samotné projekceregistr
/cockpit/mcpprojekce MCP: verze serveru a protokolu, transporty s aktuálně připojenými relacemi, obsluhované metody a co obsluhováno není, nástroje, které zapisují do repozitáře, každý nástroj s jeho efektem (zúženo přes ?effect=), konfigurace klientů a kde která zde stojí a kde je dosažitelná každá spustitelná schopnost (příkazová řádka, HTTP, nástroj MCP, zdroj MCP)mcp.projection, capabilities.projections
/cockpit/searchschopnosti a objekty odpovídající jednomu dotazuregistr, objects.search
/cockpit/worktreestopologie větev–worktree: kontejner, trunk, každý worktree se svým postavením, necommitnutou prací a diagnostikou, každá větev bez worktree, plán migrace s příkazem, který jej aplikuje; sám se znovu načte při změně topologieworktree.topology, worktree.migration_plan
/cockpit/peerskaždý worker tohoto repozitáře z nástěnky každého checkoutu, dvojice, jejichž nárokovaný rozsah se protíná, a checkouty, jejichž nástěnku nešlo přečístpeers.list
/cockpit/integrationfronta integrace pull requestů a její executor; když není nic pozorováno, řekne to a stále se vykreslíintegration.queue
/cockpit/trainstrainy naskládaných pull requestů, nakreslené jako interaktivní graf ve stylu Neo4j Browser (master jako kotva, články barevně podle dispozice, šipky STACKED_ON / DEPENDS_ON, panel vlastností, filtry, hledání, přizpůsobení a zoom, ovládání klávesnicí) a vypsané jako jedna tabulka na train, která nepotřebuje JavaScript; polluje svou trasu jednou za minutu (ADR 0138)integration.trains
/cockpit/reasoningvolitelní poradci a nejistoty a závěry otevřené úlohy; bez poradce jen lokální revizní cestareasoning.advisors, reasoning.status
/cockpit/economicsekonomika tokenů, změřenáeconomics.summary
/cockpit/activityčítače a fáze tohoto procesu a jejich průběžný grafperf.counters
/cockpit/assets/<file>stylopis, skripty, vendorované knihovnyshare/cockpit/

Tato tabulka se kontroluje proti dispatcheru, neuchovává se vedle něj. Každá prostá route, kterou cockpit::STATIC_ROUTES jmenuje, má zde řádek a žádný řádek nejmenuje prostou route, na kterou dispatcher neodpovídá; jinak cockpit::tests::the_documented_route_table_is_the_dispatchers build shodí. Úprava popisu řádku je zdarma. Přidání nebo odebrání route začíná v STATIC_ROUTES vedle match dispatcheru a navigační oblast, do které patří, v nav::areas() kontroluje every_area_has_a_route_and_every_route_its_area.

Každá trasa je deep link: filtry jsou query parametry, obnovení stránky nic neztratí a stránku lze někomu poslat.

Ani druh, ani entita v posledních třech řádcích se v routeru nejmenuje. Adresa objektu se odvozuje z jeho druhu a identity — majordomus://rule/project.x@1 se stane /cockpit/objects/rule/project-x-1 — takže soubor přidaný pod .ai/ dostane řádek v indexu, stránku a své místo ve zpětných odkazech každé další stránky bez jediné úpravy v Cockpitu. Dvě identity jednoho druhu, které se zredukují na jednu adresu, by byly kolizí, nikoli rozhodnutím o přednosti; majordomus entity kinds každou ohlásí a scripts/ci/entity-check odmítne strom, dokud nějaká existuje. Pravidlem je project.entities-are-routable.

Stránka entity také jmenuje veřejnou dokumentační stránku objektu — „Published at https://majordomus.dev/adrs/adr-0056/“ — nebo důvod, proč jeho druh není publikován. Stránka neodvozuje žádnou adresu: vykresluje pole documentation z entity.show, které čte site/data/publication.toml a base_url webu v době požadavku, tutéž deklaraci, z níž scripts/generate-site-data píše stránky webu. Repozitář bez takové deklarace nemá žádnou veřejnou stránku, kterou by jmenoval, a stránka to říká.

Jak se čte výpis celé vrstvy

Dva výpisy, které drží všechno — devět set schopností, devět set objektů — se čtou po stránkách a vstupuje se do nich po částech:

  • Stránka je padesát řádků. ?page= říká, která; číslo za koncem je poslední stránka a nikdy chyba. Ovládací prvek pod tabulkou říká, které řádky se zobrazují, a nabízí první stránku, poslední, sousedy této a mezeru pro zbytek.
  • Nad tabulkou jsou vlastní části výpisu — moduly registru na /cockpit/capabilities, vlastní druhy výpisu na /cockpit/objects — každá s tím, kolik jich drží při platných filtrech. Jsou to stejné katalogy, které ukazuje postranní panel, umístěné tam, kde je výpis: sada devíti set řádků se vstupuje přes svůj modul nebo druh, ne rolováním.
  • Odkaz nikdy neztratí filtr a nikdy si nenechá číslo stránky. Stránkování nese každý filtr s sebou; výběr části začne tuto část na její první stránce.

Stránka grafu stránkuje své dvě tabulky stejně, každou vlastním parametrem: ?nodes= pro tabulku uzlů a ?edges= pro tabulku hran, padesát řádků na stránku, takže stránkování jedné tabulky nikdy nepohne druhou a odkaz nese obě pozice. Každý uzel a každá hrana je stále na nějaké stránce jako text a pager každé z těch stránek dosáhne jen svými odkazy, bez skriptu; důvod je níže pod „Proč jsou tabulky pod grafem stránkovány“. Manifest artefaktů nestránkuje nic: je vypsán celý, protože čtenář, který kontroluje, zda je v něm cesta, ji musí najít vlastním vyhledáváním prohlížeče.

Jediná stránka, která je o tomto stroji

Každá jiná stránka je o repozitáři: tatáž odpověď v každém klonu a bezpečná k publikaci. /cockpit/continuity ne. Čte .ai/local/ — otevřené epizody, vyřešenou předávku, blokátory tohoto checkoutu — a ty záznamy jmenují tento disk. Proto je Cockpit vázán na loopback rozhraní a proto tato stránka nemá protějšek na webu (ADR 0014).

Na veřejném webu: snapshot

Zveřejněný web nese Cockpit na /cockpit/ jako snímek (ADR 0147): vlastní stránky Cockpitu, přečtené jednou na zveřejněném commitu a zapsané jako soubory exportérem, který zveřejňuje UI (ADR 0141).

majordomus web report cockpit-snapshot

Zapisuje do target/web/cockpit-snapshot. Postupně čte každou statickou trasu, poté každou stránku Cockpit, na kterou chtěl snímek UI odkazovat, poté po jedné stránce z každé rodiny, na co ty odkazují, dokud není --limit stránek nebo --budget-seconds. Co se liší od Cockpitu, který obsluhuje proces:

V CockpituVe snímku
odkaz na jinou stránku Cockpiturelativní odkaz na soubor té stránky
odkaz na stránku za mezí, hledání, formulář, runnerstránka snapshotu o živém Cockpitu, nesoucí cestu, kterou odkaz myslel
odkaz do UIta stránka snímku UI, když ji drží, jinak živá stránka
skripty: runner, paleta, živá provedení, dotazovací panelyžádné: žádná stránka nenese skript a každá je úplná i bez něj
/cockpit/continuitynení ve snapshotu a žádný odkaz na ni nevede: je to jediná stránka o stroji

Každá stránka říká, že je snímek, s commitem, časem a spustitelným souborem, který ji přečetl. Stránka, která se týká stroje a není zadržena (peery, worktree, zdraví), ukazuje runner, který ji vykreslil. Pro Cockpit vlastního checkoutu spusťte majordomus serve.

Adresář se deklaruje (surface.json) jako povrch cockpit-snapshot, připojený na /cockpit, published-only. snapshot.json vedle něj uvádí každou zapsanou stránku a každou stránku ponechanou živému Cockpitu. Drží ho test/cases/2981_the_cockpit_snapshot_holds_its_routes.sh.

Je to také stránka, která musí odpovídat dvěma různým čtenářům, a říká, který je který.

Worker se ptá z čeho navazuji? To je continuity.state: jedna epizoda — ta, na kterou se session-current.yaml přeloží — jedna předávka, jeden checkpoint, každý s popiskem divergence, který říká, nakolik mu věřit, a otázky, které odmítají dokončení. (ADR 0052 přidává vedle divergence popisek čerstvosti, protože advanced je pravdivé tvrzení o topologii gitu a o stáří neříká nic.)

Operátor se ptá funguje tento subsystém? To je skupina lifecycle.* a existuje proto, že odpověď workera je strukturálně slepá k otázce operátora. Ukazatel je symlink, který přesměruje nejnovější startovní událost; 2026-09-11 měl tento repozitář v jednom checkoutu pět otevřených epizod a každý povrch uměl jmenovat jednu. Proto stránka nese pod vlastními kartami briefingu:

KartaCo ukazujeSchopnost
Každá otevřená epizodajeden řádek na otevřenou epizodu: její postavení (current, open, foreign, stranded), poskytovatel, který ji otevřel, větev, kdy se otevřela, poslední řádek knihy jí označený a úlohy, kterých se dotklalifecycle.episodes
Tento proces proti repozitářicommit, při kterém byl sestaven servírovaný index, proti commitu, který git hlásí při volání, a zda se shodujílifecycle.runtime
Obnovaepizody, které se nedokážou uzavřít samy, a příkaz, který každou uvolní, dočasné soubory, které zabitý close nechal v sledované sekci relací, rozložení ukazatele a aritmetika zahájených proti uzavřenýmlifecycle.recovery
Poskytovatelépodle poskytovatele: události životního cyklu, které jeho adaptér deklaruje, zda umí archivovat prompty, jeho konfigurace klienta a položky vynucování, které tento repozitář zapojuje na jeho hooklifecycle.providers
Uzavřené epizodykolik sledovaných záznamů existuje, kolik se na této větvi uzavřelo a nejnovějších dvacet, každý s odkazem na stránku svého objektulifecycle.closed

Tři pravidla, která tato stránka dodržuje, a důvod každého.

Zde se nepočítá žádná hodnota. Každé číslo, slovo a odznak výše přichází z odpovědi schopnosti; stránka rozhoduje o barvách a o ničem jiném. Cockpit, který by si sám zjišťoval, zda epizoda uvízla, by byl druhým modelem relace a první věc, kterou dva modely relace udělají, je, že se neshodnou.

Žádný prompt se nikdy nevykresluje. Archiv promptů je jediná část lokální poloviny, která je konverzací, a žádná karta na této stránce ji nečte. Co worker napsal, není provozní stav, a povrch, který by to ukázal, by byl přepisem s lepším formátováním.

Stránka je fotografie a nepolluje. Stránky provádění sledují WebSocket, protože provádění vysílá události; úložiště relací ne, a prohlížeč, který by se každých pět sekund ptal, zda je epizoda ještě otevřená, by celý den odpovídal „ano“. Obnovení stránky je refresh, Cache-Control: no-cache ho činí poctivým a jedna sekce, kterou se nepodaří přečíst, se vykreslí jako selhaná karta, ne jako mrtvá stránka — sekce, která nejspíš selže, je úložiště, do něhož ještě nikdo nezapsal, a skrýt za ní zbylých pět by byl špatný obchod.

Co z toho dělá projekci a ne dashboard

Každá stránka se ptá schopnosti. Stránka volá Context::execute, což je volání, které dělá MCP a routes HTTP. Počítá se ve stejných počitadlech výkonu, odpovídá ze stejné cache a podléhá stejné validaci. tests/cockpit.rs ověřuje, že obsloužení každé stránky nepohne žádným počitadlem, které se smí hýbat jen při startu.

Jeden zápis, který se nejdřív ptá. Každá schopnost, kterou stránka zasáhne, je dotaz nebo příkaz měnící jen paměť tohoto procesu, kromě plan.transition, který označí jedno pole záznamu úkolu a připojí jednu událost knihy. Stránka úkolu ho nabízí jako tři tlačítka, která jsou vypnutá, dokud se nenačte plan.js, před odesláním se ptají, spouštějí přesun jako provedení — takže má identitu a vlastní stránku — a poté ukazují stav, který schopnost odvodila ze záznamu, ne ten, který pojmenovalo tlačítko. Zda je přesun legální, rozhoduje schopnost: stránka ukazuje její odmítnutí tak, jak přišlo.

Žádná stránka nečte index. Druhá polovina věty výše, která byla jen dokumentací, dokud ji scripts/ci/cockpit-projection-check (kontrola cockpit-projection, ADR 0012) nezačalo odmítat: vrstva zobrazení, která sahá do indexu, protože je ve stejném procesu, čte repozitář mimo executor, mimo cache, mimo čítače a mimo validaci, a v den, kdy se rozejde se schopností, žádná odpověď není ve svých termínech špatná. Kontrola greppuje vlastní soubory Cockpitu včetně testovacích modulů a test/cases/389_cockpit_projection.sh ji pouští proti stromům fixtures. Počet objektů a katalog druhů pocházejí z repository.info, výpis z objects.list, jeden objekt z objects.get.

Neznámé se nikdy nekreslí jako zdravé. ADR 0089 (project.ui-derived-state) rozšiřuje stejný checker. Jeho kontrola --ui-integrity (ui-integrity) zamítá čtyři věci:

  • přímé čtení ctx.registry, ctx.product nebo ctx.why mimo komentovaný povolený seznam navigace;
  • kontrola zdraví, které se HealthStatus::Ok předá jako literál;
  • #[default] na zdravé variantě enumu;
  • chybějící počet vykreslený jako nula v pages.rs.

Web, který je správný tak, jak je napsán, to zdůvodní v komentáři // ui-integrity: <reason>. Nálezy, které master už obsahuje, jsou ratchet v .ai/repo/ui-integrity-baseline.txt a test/cases/547_the_ui_says_only_what_is_derived.sh vloží každé porušení do fixture stromu.

Nic v něm není seznam. Katalogy postranního panelu jsou moduly registru, druhy, které hlásí repository.info, a odvozovací tabulka grafu. Průzkumník schopností je filtrovaný registr. Paleta čte /api/v1/capabilities, /api/v1/graphs a /api/v1/objects a vyjímá vlastní stránky Cockpitu z navigace, kterou server už vykreslil.

Runner je obecný. Formulář schopnosti se generuje z jejího vstupního schématu: ovládací prvek následuje typ JSON (řetězec, celé číslo, číslo, boolean, výčet nebo textarea JSON pro cokoli strukturovaného), popis je vlastní doc komentář vlastnosti a povinnost je ze schématu. Odeslání pošle požadavek, který vlastní vazba schopnosti očekává — řetězec dotazu pro GET, tělo JSON pro POST — na skutečnou trasu schopnosti. Není žádný endpoint runneru, žádná proxy a žádná druhá validace.

Příklady jsou případy měření výkonu. Vstupy zobrazené na stránce schopnosti a tlačítka „načíst do runneru“ jsou BenchmarkCases, tytéž vstupy, které spouští měření výkonu a které ukazuje dokument OpenAPI.

Behaviorální tvrzení je jeden test: tests/cockpit.rs::a_capability_the_repository_adds_reaches_every_cockpit_surface zapíše pravidlo do jednorázového repozitáře a ověří, že se dostane do výpisu schopností, na vlastní stránku, do průzkumníka objektů, do vyhledávání a do výpisu, který čte paleta — bez jediného řádku Cockpitu napsaného pro něj.

Čtyři otázky: dashboard, který je projekcí

Přehled se otevírá Overview z Dashboard Suite (ADR 0088): čtyři otázky — je to zdravé, co se změnilo, co je rozbité, co vyžaduje akci — na které odpovídá dashboard.overview, což je běžná schopnost (GET /api/v1/dashboard/overview, MCP majordomus_dashboard_overview, majordomus dashboard overview). Nemá žádná vlastní data. Každá karta je jeden fakt přečtený z odpovědi jiné schopnosti — health.report, release.version, plan.status, worktree.status, plan.next, continuity.state a peers.list pro nástěnku tohoto checkoutu — a nese tuto schopnost, vstup, s nímž byla dotázána, ukazatel RFC 6901, z něhož byla její hodnota čtena, a míru (exact, nebo count pro délku seznamu, který zdroj při prázdnosti vynechává), vedle vlastního verdiktu zdroje, stránky, do které se dá vrtat, a příkazu, který na to působí. Zdroj, který nemůže odpovědět, dělá své karty unknown, nikdy ok.

Stránka zapisuje hodnotu každé karty jako data-value — JSON, kterým route odpověděla — takže se stránka a route porovnávají bajt po bajtu. tests/dashboard.rs je kontrola: každému zdroji karty položí otázku této karty přes route samotného zdroje, přečte ukazatel a selže, když se hodnota karty liší; žádnou kartu nejmenuje, takže další karta je jí podrobena bez úprav. test/cases/534_the_overview_answers_four_questions.sh drží stejný kontrakt přes sestavený spustitelný soubor.

Grafy

Grafy jsou kanonické v Rustu (src/graph.rs): Graph je id, jeho slova, slovník druhů uzlů a druhů hran, které říkají, co každý tvar znamená, seřazené uzly a hrany a metadata, která čtenář potřebuje před kreslením — počty, zda je výsledek acyklický a zda se odvození zastavilo na limitu uzlů.

GrafCo ukazujeOdvozeno z
registrymoduly, schopnosti, které skládají, soubor, ve kterém byl každý deklarován, a projekce MCP / HTTP / CLIregistr
layerkaždý adresář, v němž byl objeven objekt, vnořeně, s druhy, které obsahujepůvod objektu
ruleskaždé pravidlo a pravidla, na nichž deklaruje závislostfront matter depends_on
adrskaždé rozhodnutí, co nahrazuje, a pravidla, tvrzení, soubory a testy, které uvedlo v platnostfront matter ADR
use-caseskaždý případ užití a příkazy, doktríny a tvrzení, které pojmenováváfront matter případu užití

Přidání jedné je funkce a jeden řádek v graph::DERIVATIONS. Pak se objeví v graph.list, na /api/v1/graph, jako odpověď nástroje MCP, v navigaci Cockpitu, na vlastní stránce a jako případ měření výkonu — protože GraphInput::benchmark_cases je graph::ids().

Invarianty, které drží sady property a unit testů: id uzlů jsou jedinečná, žádná hrana neodkazuje na uzel, který graf nedrží, a stejný strom a spustitelný soubor vytvoří stejné bajty (žádné hodiny, žádná absolutní cesta, žádné pořadí objevení).

Kreslicí knihovna je konzument. Překlad do tvaru prvků Cytoscape je jedna funkce v share/cockpit/graph.js; projekce do Mermaid, Graphviz nebo terminálu by nepřestavěla žádnou sémantiku.

O čem kresba rozhoduje

Prohlížeč volí rozvržení podle změřeného tvaru grafu, ne jedno jméno pro každý graf. Každý graf používal breadthfirst, které dává jednu úroveň prohledávání do šířky na jeden řádek; složený graf má 1442 uzlů a jedna úroveň držela téměř všechny, takže cy.fit() oddálilo, dokud se ten řádek nevešel do rámu, a kresba byla vodorovná čára vysoká asi jeden pixel. measure() odvozuje počet uzlů, hustotu hran, hloubku prohledávání do šířky a — číslo, které to diagnostikuje — nejširší úroveň; choose() vybírá mezi rozvrženími, která cytoscape dodává:

KdyRozloženíProč
24 uzlů nebo méněcirclevšechno se vejde na jeden kruh v čitelné velikosti; fyzika nad dvacet uzlů jen kolísá
3+ úrovně, nejširší úroveň ≤ 48, hustota < 2breadthfirstjediné vestavěné rozložení, které ukazuje směr; ochrana je nejširší úroveň, protože za ní je breadthfirst přímka
400 uzlů nebo méněcoseforce-directed: jediný vestavěný, který dává cluster k sobě, takže komunity jsou vidět
až 900 uzlů, špičaté stupněconcentric podle stupněřazení místo iterace, takže je okamžité; huby ve středu. Jen když jsou stupně špičaté: při plochém rozdělení skončí každý uzel v jednom prstenci
většígrid, podle druhu a pak stupnězměřeno: concentric nad 1452 uzly dalo disk široký 19000 px, takže fit() narazilo na minZoom a uzel se vykreslil pod pixel. Při 480 čtverečních pixelech na uzel není žádné uspořádání zároveň strukturální a čitelné, takže každý uzel dostane buňku, druhy tvoří pásy a ke struktuře se dojde filtrem a výběrem

Žádné rozšíření rozvržení není vendorováno a žádné by nemělo být: share/cockpit/vendor/ drží samotné cytoscape.min.js a politika zabezpečení obsahu Cockpitu nejmenuje žádný vzdálený původ.

Vše ostatní, co kresba ukazuje, je odvozeno stejně. Průměr uzlu je jeho stupeň, odmocněný. Barva druhu uzlu je --mj-series-<n> z share/design/tokens.yaml — osm rolí, které nenesou žádný význam, zvolených pro oddělení — a která z nich druh dostane, je hash FNV-1a vlastního jména druhu, takže druh má stejnou barvu v každém grafu a zůstane jí, i když je deklarován třicátý pátý druh. Osm barev a 34 druhů znamená, že druhy sdílejí barvu, a to je cena za stabilitu: alternativa — seřadit druhy a rozdávat barvy podle pořadí — přesouvá barvu každého druhu ve dni, kdy se jeden přidá. Legenda jmenuje, které druhy sdílejí, a filtr je rozliší.

Cytoscape neumí číst oklch, což je to, čím je paleta deklarace. Když ji dostane, zaloguje, že vlastnost je neplatná, a vrátí se k černé, a každý token, který tento soubor četl, tak končil. Token se proto vykreslí na plátno o jednom pixelu a jeho kanály se přečtou zpět a knihovna dostane [r, g, b], které přijme. Nikde se neskládá žádný barevný řetězec: je to aritmetika na hranici knihovny a hodnota je stále hodnotou deklarace. Popisky jsou deklarovaný krok meta a nad 80 uzlů se objevují jen tehdy, když čtenář přiblížil dost na to, aby je přečetl, kromě dvanácti nejvytíženějších, které jsou pojmenovány vždy. Druh hrany se maluje na hranách vybraného nebo najetého uzlu, nikdy na všech najednou. Legenda vedle kresby je i filtrem: vzorek a počet na druh a klik, který druh vyřadí.

Nic z toho není barva, velikost ani počet zapsaný v JavaScriptu a scripts/ci/design-check čte share/cockpit/graph.js jako každý jiný first-party povrch — dříve soubor vyjímalo podle cesty, a právě to umožnilo, aby odstín spočítaný ve skriptu platil rok.

Proč jsou tabulky pod grafem stránkované

Stránka grafu vypisuje každý uzel a každou hranu, padesát řádků najednou. Tabulka uzlů se stránkuje podle ?nodes= a tabulka hran podle ?edges=; každá drží svou pozici v URL, číslo za koncem je poslední stránka a ovládací prvek pod každou tabulkou říká, které řádky ukazuje.

Tabulky nejsou pohodlí vedle kresby; jsou stránkou. Kresba potřebuje JavaScript, knihovnu o 400 kB a canvas a stránka to říká vlastní prózou: „všechno, co ukazuje, je v seznamech níže, což dostane čtenář bez JavaScriptu, crawler a čtečka obrazovky“. Ta věta bývala důvodem, proč se tabulky vypisovaly celé. Přestalo to být únosné: vcelku byla composed jedním dokumentem o více než megabajtu a tisících řádků tabulek — stránkou, kterou nikdo nemohl procházet ani prohledávat a kterou žádný přístupnostní engine nedočetl v limitu své návštěvy. Dokument takové velikosti nebyl čitelný ani pro člověka, pro něhož byl kontrakt napsán.

Stránkování drží větu pravdivou, protože se nic neodebírá. Každý uzel a každá hrana je právě na jedné stránce své tabulky jako text a pager jsou obyčejné odkazy: první stránka, poslední, sousedé zobrazené stránky a předchozí a další, takže čtenář bez JavaScriptu dosáhne každé stránky sledováním odkazů a crawler dělá totéž. Kresba je nezměněna a stále ukazuje celý graf; čte hromadný formát, nikoli tabulky. apps/majordomus-cli/tests/cockpit.rs prochází tabulky grafu registru stránku po stránce přes vlastní odkazy pageru a vyžaduje, aby se objevil každý uzel a hrana, a tamní průchod stránkami vykresluje /cockpit/graphs/composed, největší z nich.

Hromadný formát je odkazován ze stránky: /api/v1/graph?id=<id>. Čtenář, který chce celý graf v jedné odpovědi, aby v něm hledal nebo ho zpracoval, vezme ten.

test/cases/190_graph_drawing.sh spouští choose() a measure() nad syntetickými tvary bez prohlížeče; scripts/lib/cockpit-probe.mjs se přes frame.mjGraph.extent() ptá běžícího rendereru, jak velkou část rámu kresba zabírá, a selže pod desetinou v obou směrech — pro registry a znovu pro největší existující graf, který jako jediný kdy tuto vadu měl. Aserce, kterou nahrazuje, počítala prvky canvas a cytoscape jich vyrobí tři nad jednopixelovou čárou.

Zdraví

health.report hlásí jednu kontrolu na dimenzi. Každá kontrola nese kdo o ní rozhodl a co ji reprodukuje, protože zdravotní report, který rozhoduje sám, je čtvrtý názor:

KontrolaRozhoduje
vrstva tak, jak byla přečtenavlastní diagnostika indexu
registr schopnostíbuilder registru, který odmítne build při duplicitním nebo poškozeném vystavení
deklarovaný rozsahdeklarace rozsahu, pod kterou byl index sestaven
správa verzígit, dotázaný jednou při startu
pokrytí měřenímpokrytí projekce měření — to samé, které čte bench coverage --check
commitnuté projekcestejné vykreslení, které zapisuje majordomus generate, porovnané s tím, co je commitnuto
sdílený serverrozhodnutí, které činí server.status, z lease tohoto checkoutu a jedné sondy serveru, který jmenuje
připojení klientinástěnka peerů v paměti tohoto procesu

Kontrola serveru hlásí, kde stojí sdílený server tohoto checkoutu — absent, starting, ready, outdated nebo stale — s jeho adresou, verzí, kterou servíruje, a důvodem, když odpověď není ready. absent a starting jsou ok: checkout, který nikdo neobsluhuje, není nezdravý, a lease, který se stále váže, se vyřeší během bind grace. outdated a stale jsou warn s důvodem jako nálezem: server odpovídající z kódu, který tento strom už nemá, a lease pojmenovávající adresu, na které nikdo neodpovídá, má každý někoho, kdo je má vyčistit, a ani jeden nebrání tomuto procesu servírovat. Je to čtvrté ze čtyř čtení „připraveno“ tohoto crate a jediné, které patří do reportu o zdraví; docs/MCP.md pojmenovává všechna čtyři a k čemu je každé.

Záměrně nevykresluje znovu každou commitnutou projekci při každém volání: to by přestavovalo kanonický stav při každém požadavku. Porovnává jediný artefakt odvozený jen z kódu (docs/generated/registry.json) a jako úplnou odpověď jmenuje majordomus generate --check.

Není to ani majordomus doctor. Doctor shellového nástroje rozhoduje, zda je Majordomus zapojen do tohoto repozitáře; tyto kontroly rozhodují, zda je v pořádku to, co tento proces obsluhuje. Různé subjekty, a server v Rustu nespouští žádný shell.

Vrstva prohlížeče

Progressive enhancement v přísném smyslu. Každá stránka je úplný HTML dřív, než se spustí jakýkoli skript; stránky grafů nesou každý uzel a hranu jako tabulky a volitelné pohledy říkají, kde jsou tytéž fakty jako text.

SouborCo přidáváPotřebuje
cockpit.jsjedna komponenta Alpine (motiv, stav palety), sdílené helperyvendor/alpine.csp.min.js
palette.jspaleta příkazů (Ctrl/Cmd + K), položky z registru—
runner.jsgenerický runner schopností—
plan.jspohyby na stránce úkolu: po potvrzení spustí plan.transition jako provedení, sleduje ho omezeným pollingem, ukáže stav, který odpověděl, nebo odmítnutí tak, jak přišlo, a znovu načte stránku—
graph.jspohled Cytoscape: posun, zoom, přizpůsobení, hledání, zaměření na okolí, zásuvka s detailyvendor/cytoscape.min.js
topology.jsgraf registru ve třech dimenzíchvendor/three.module.min.js
activity.jsprůběžný graf čítačů provádění a cachevendor/p5.min.js

Pokud vendorovaná knihovna chybí, rámec to řekne a stránka dál funguje. Žádná z nich není na kritické cestě, každá se stahuje jen na stránce, která ji používá, a ty dvě vizuální respektují prefers-reduced-motion, pozastaví se, když je karta skrytá, a uvolní, co alokovaly.

Proč tu vůbec je Three.js: graf registru je vrstevnatý — moduly skládají schopnosti, schopnosti se deklarují v souborech a promítají se do tří rozhraní — a plochá kresba musí volit mezi zobrazením vrstev a zobrazením rozvětvení. Jedna rovina na vrstvu ukáže obojí. Proč tu je p5: čítače už jsou tabulkou a tabulka neukáže, zda se na provedení, která právě přicházejí, odpovídá z cache. Oba jsou volitelné pohledy na data, která stránka také vypisuje.

Bezpečnost

  • Escapování konstrukcí. Markup je strom hodnot El; jediná cesta, jak se text dostane do výstupu, je metoda, která jej escapuje. Neexistuje řetězcová šablona a testy vykreslují pravidlo, jehož titulek je tag script.
  • Přísná politika zabezpečení obsahu. default-src 'none'; script-src 'self' 'sha256-…' — žádné unsafe-inline, žádné unsafe-eval, žádný vzdálený původ, frame-ancestors 'none'. Jediný inline skript je bootstrap motivu před vykreslením, povolený otiskem svých vlastních bajtů, vypočteným ze samotné konstanty, takže se obojí nemůže rozejít. Proto je vendorován CSP build Alpine a proto každý atribut x- pojmenovává vlastnost nebo metodu, a ne výraz.
  • Ochrana proti mutacím z prohlížeče. Požadavek nesoucí hlavičku Origin přišel ze stránky v prohlížeči. Pro cokoli kromě GET a HEAD musí být tento origin vlastní origin tohoto serveru; jinak se před spuštěním handleru odmítne s 403. Klient, který není prohlížeč, žádnou Origin neposílá a není dotčen. Čtení jsou už uzavřena: tento server neposílá žádné hlavičky CORS, takže stránka z jiného originu nemůže odpověď přečíst. Není tu žádná relace ani cookie, takže není žádný token k přidání — token vázaný na nic nic nebrání.
  • Žádná změna stavu přes GET. Vlastní routy Cockpitu odpovídají pouze GET; příkaz je POST na vlastní routu a runner jej tak označí.
  • Práce s cestami. Název assetu je odmítnut dřív, než se dotkne souborového systému, pokud obsahuje cokoli kromě [A-Za-z0-9._-/], prázdný segment, . nebo ..; vyřešená cesta se pak zkontroluje, že leží uvnitř adresáře assetů, což zavírá dveře, které by otevřel symlink. Poskytuje se jen uzavřená množina textových typů médií.
  • Ve výchozím stavu loopback. serve se váže na 127.0.0.1; navázání na cokoli jiného zaloguje, co to znamená.
  • Co zapisuje, je deklarováno. Runner dosáhne na každou schopnost, včetně příkazů, jejichž deklarovaný účinek je repository_mutation. Karta Run z tohoto účinku odvozuje své varování, takže příkaz, který zapisuje sledované soubory, to řekne dřív, než je odeslán, vždy jako POST z původu stránky. Každá jiná schopnost buď čte, nebo mění jen paměť tohoto procesu.

Assety

share/cockpit/ je místo, kde tento nástroj drží soubory Cockpitu, tak jako share/kinds.yaml a share/schemas/ jsou místa, kde drží své druhy. Čtou se z disku jednou a poskytují se z paměti s digestem svých bajtů v URL — takže změněný soubor je změněné URL a verzovaný asset se odpovídá immutable na rok.

Neměnná je jen přesná verze, kterou stránka vydává; jakékoli jiné v (prázdné, prefix, zastaralé) a žádné v vůbec se odpovídá no-cache. Každá odpověď nese otisk jako své ETag a If-None-Match, který stále platí, je 304 Not Modified bez těla. Každá URL assetu, kterou stránka načítá, nese svůj otisk: relativní importy modulu skriptu se při čtení přepisují na URL s otisky toho, co importují, takže otisk modulu zahrnuje jeho importy a každý importér jmenuje jednu URL; knihovny, které skripty načítají za běhu, dostávají své z data-vendor těla stránky (cockpit::VENDOR); favicon se opatřuje otiskem jako stylesheet. Teplá navigace proto stahuje jen stránku.

scripts/cockpit-assets            # compile the stylesheet, vendor the pinned libraries
scripts/cockpit-assets --check    # fail if the committed stylesheet differs from its source
SouborPotvrzeno?Proč
cockpit.cssanogenerovaný artefakt, kompilovaný z src/cockpit.css pomocí Tailwindu a motivu Flowbite nad sdílenými designovými styly; kontrolován na drift
src/cockpit.cssanozdroj: co má jen Cockpit (shell, paleta, runner, log, plátna), jedna sémantická třída na komponentu, nad tokeny a primitivy, které importuje z share/design/
favicon.svganogenerovaná kopie kanonické značky share/design/brand/logo-mark.svg, zapsaná pomocí majordomus generate design
*.jsanopsáno ručně, bez kroku sestavení — ale nav.js a theme.js, bajtové kopie těch z webu, zapisované a kontrolované příkazem scripts/cockpit-assets: lišta nahoře každé stránky je lištou webu, stejně jako jeho skripty (MAJORDOMUS_UI.md)
vendor/alpine.csp.min.jsanointerakce na tom závisí a má 70 kB
vendor/{cytoscape,three.module,three.core,p5}.min.jsne~2 MB, líně, volitelné, každá stránka je úplná i bez nich

V Rustu, který vykresluje stránky, nejsou žádné utility třídy a jediný markup, který je má, není markupem Cockpitu: lišta nahoře na každé stránce je vlastní lištou majordomus.dev, zkompilovaná ze sestaveného webu a do stylesheetu zkompilovaná z té kopie (project.the-ui-wears-the-sites-navbar). Vše, co jmenuje vlastní markup Cockpitu, je definováno v src/cockpit.css nebo ve sdíleném share/design/primitives.css jako složení utilit Tailwindu nad design tokeny, což drží design čitelný a činí zkompilovaný stylesheet funkcí jen těchto souborů a připnutých verzí — díky čemuž je --check přesné. V Cockpitu se nerozhoduje o žádné barvě, velikosti, barvě stavu, klíči motivu ani značce: každá pochází z share/design/tokens.yaml přes generované sheety, tytéž, které importuje publikovaný web, a scripts/ci/design-check druhé rozhodnutí odmítne. Stránka Design (/cockpit/design) vykresluje deklaraci, s níž byl spustitelný soubor sestaven, a říká, zda s ní načtený stylesheet souhlasí. Viz DESIGN_SYSTEM.md.

Node je závislost pro build. Spustitelný soubor v Rustu tyto soubory servíruje z disku a netuší, že byly postaveny.

Výkon

Stránky jsou cíle měření výkonu, deklarované vedle GET / a GET /docs, takže je bench coverage --check počítá a základní linie na nich může regredovat: system.http.cockpit_overview, system.http.cockpit_capabilities, system.http.cockpit_graph.

Jaká jsou čísla na kterémkoli stroji, se měří a nikdy se zde nepíše — důkazy žijí pod .ai/repo/benchmarks/rust/ a docs/generated/benchmarks.md. Co je zaručeno, je strukturální: žádná stránka nepřestavuje kanonický stav, asset se čte z disku jednou za proces, graf cachuje executor a nestahuje se žádná knihovna, kterou stránka nepoužívá.

Přidání do něj

Schopnost. Napište blok capability! a spusťte majordomus generate. Objeví se ve výpisu Cockpitu, na vlastní stránce s generovaným formulářem, ve vyhledávání, v paletě, v grafu registru a jako cíl měření. V src/cockpit/ se nic neupravuje.

Graf. Napište odvození a přidejte jeden řádek do graph::DERIVATIONS. Objeví se v graph.list, na /api/v1/graph, v navigaci, na stránce a jako případ měření výkonu.

Stránka. To je jediná věc, která je úpravou Cockpitu, protože stránka je vlastní tvar Cockpitu: funkce v pages.rs vracející Page a jedna větev v Cockpit::route. Stránka, která potřebuje skript, ho pojmenuje pomocí .script("name.js"), a právě to drží grafovou knihovnu mimo úvodní stránku.

Komponenta. Jedna třída v share/cockpit/src/cockpit.css a jedna funkce v view.rs. Nikdy utilitní třída v Rustu.

Testování

apps/majordomus-cli/tests/cockpit.rs spustí skutečný server na skutečném socketu proti jednorázovému repozitáři:

  • každá stránka vykreslí úplné HTML se shellem a bezpečnostními hlavičkami,
  • schopnost přidaná do repozitáře se dostane na každý povrch Cockpitu,
  • forma runneru se generuje ze vstupního schématu,
  • stránka grafu vypíše každý uzel a hranu dříve, než se načte jakákoli knihovna,
  • stránka zdraví ukazuje verdikty, ke kterým enginy dospěly,
  • aktiva jsou neměnná podle svého přesného otisku, každé URL, které stránka vydá, ho nese, revalidace, která platí, je 304 a žádný průchod neunikne z adresáře,
  • požadavek měnící stav z jiného originu je odmítnut a čtení ne,
  • index odpovídá klientovi JSON a prohlížeč odkáže na Cockpit,
  • obsah repozitáře se na stránku dostává jako text a nikdy jako značkování,
  • servírování každé stránky nic kanonického nepřestavuje,
  • stránky plánu ukazují stavy, které schopnosti plánu odpověděly, a krok učiněný ze stránky úkolu — přímo nebo jako provedení — změní záznam a pak stránku (tests/cockpit_plan.rs).

Unit testy v src/cockpit/ pokrývají escapování (oba kontexty), void elementy, mapování stavových slov na třídy, cache assetů a zamítnutí cest, digest CSP a to, že navigace je registrem, a ne seznamem.

Co záměrně nedělá

Čtyři věci, které se od řídicí roviny očekávají, záměrně vynechané. Každá je rozhodnutí, a ne mezera, a každá uvádí, co by se muselo změnit nejdřív.

Žádný streaming pro streaming. Tato sekce dříve tvrdila, že neexistuje vůbec žádný živý transport, a uváděla důvod: proud kvůli aktualizaci čítače bez pollingu je podstatné jméno přidané do jádra pro pohodlí, což optional-complexity existuje, aby odmítlo. Říkala také, co by obchod změnilo — „až dorazí něco skutečně dlouho běžícího, proud bude stát za vlastní rozhodnutí a typovaná obálka událostí patří do toho rozhodnutí, ne před něj“.

To se stalo a je to ADR 22: schopnost, která čte každý soubor vrstvy, trvá dost dlouho na to, aby se vyplatilo ji sledovat místo čekání, takže provedení má identitu, typované události a živý kanál na GET /events (EXECUTIONS.md). Co se nezměnilo, je kompromis, který odstavec chránil. Stránka aktivity stále dotazuje periodicky, protože čítače jsou pohodlí; žádná schopnost se nestala streamem, protože čtvrtý druh byl navržen a zahozen; a živý kanál nese události provedení a nic jiného. Stránka, která chce, aby číslo tikalo, má stejnou odpověď jako dřív.

Žádné rozřešení precedence pravidel. „Jaké instrukce platí na této cestě?“ je otázka, na kterou je Cockpit správným místem k odpovědi a špatným místem k rozhodnutí. Shellový nástroj vlastní rozřešení kontextu (majordomus context resolve) a druhá implementace v Rustu by byla druhým názorem na precedenci — přesně ten drift, proti kterému je tu každé pravidlo psáno. Cockpit místo toho ukazuje vstupy: každé pravidlo jako objekt, graf závislostí pravidel a adresářové smlouvy jako objekty druhu context. Samotné rozřešení čeká na jeden engine, který mohou volat oba nástroje.

Stránka health není majordomus doctor. Doctor rozhoduje, zda je Majordomus zapojen do tohoto repozitáře — hooky, projekce, retence, stav. health.report rozhoduje, zda je v pořádku to, co tento proces obsluhuje. Různé předměty s různými stroji a server v Rustu nespouští žádný shell, takže neexistuje třetí věc, která by spouštěla obojí. Kdo chce obojí, spustí obojí; každý z nich jmenuje území toho druhého.

Cesta zápisu je deklarována, ne nepřítomna. Většina schopností, které Cockpit dosáhne, jsou dotazy nebo příkazy, které mění paměť tohoto procesu; spuštění provádění a jeho zrušení jsou dvě z nich. Ty, které zapisují do repozitáře, deklarují efekt repository_mutation ve své politice provádění a právě tu čte varování na kartě Run. ADR 12 vyžaduje, aby taková schopnost byla vlastním rozhodnutím, a unit test v builtin jejich množinu připíná, takže nová se ukáže v diffu.

V prohlížeči

scripts/cockpit-probe měří Cockpit proti běžícímu serveru. Nic v něm nevypisuje routu: oblasti se procházejí z vlastní navigace shellu — kterou server vykreslil z registru, indexu a odvození grafů — a pak jedna routa na schopnost, graf a objekt pochází z /api/v1/capabilities, /api/v1/graphs a /api/v1/objects. Schopnost, druh nebo graf přidaný do backendu se sonduje poprvé, když existuje.

just cockpit-probe                      # both sweeps
just cockpit-probe --quick              # the status sweep in full, one of each family in the browser
just cockpit-probe --status             # the status sweep alone; no browser needed
COCKPIT_PROBE_URL=http://127.0.0.1:8741 scripts/cockpit-probe    # a server that is already running

Dva průchody, protože odpovídají na různé otázky za různou cenu:

SweepPřesTvrdí
statuskaždá odvozená trasa200, text/html a bezpečnostní hlavičky na shellu
prohlížečkaždá oblast plus vzorek z každé generované rodiny, při 390, 1024 a 1600 pxshell, aplikovaný stylesheet, žádné horizontální přetékání, žádná chyba konzole, žádný neúspěšný požadavek

Sweep prohlížečem je ta část, ke které stavový kód nedosáhne:

  • Alpine se spustil pod politikou bez unsafe-eval — což je celý důvod, proč je build CSP vendorován, a kontrola, která zachytí regresi na build z CDN.
  • Paleta příkazů se otevře na Ctrl/Cmd+K, naplní se položkami, které dodal registr, filtruje a naviguje tam, kam vybraná položka říká.
  • Přepínač tématu — ten webu, v liště webu — převrací kořenovou třídu a volba přežije opětovné načtení.
  • Odkaz pro přeskočení je první zastávka tabulátoru a ukazuje na #main.
  • Runner se generuje ze schématu (povinný řetězec, omezené celé číslo, zpřístupnění vlastních měřicích případů schopnosti) a jeho odeslání volá skutečnou trasu schopnosti a vykreslí odpověď — ověřeno proti požadavku, který prohlížeč skutečně poslal, ne proti náhledu.
  • Graf se kreslí nad týmiž uzly, které stránka vypisuje, nebo řekne proč nemůže.
  • frame-ancestors 'none' platí: jiný origin nemůže Cockpit vložit do rámu.
  • JavaScript vypnutý: každá vzorkovaná trasa stále nese svou navigaci a svůj obsah.

Sonda měří server, který jmenuje lease repozitáře, protože jeden server na repozitář je pravidlo, podle kterého tento nástroj žije. Když lease drží editor se spustitelným souborem starším než Cockpit, sonda to řekne a jmenuje, co dělat, místo aby tiše spustila druhý server.

Co už zachytila, což je argument pro její existenci: CSP build Alpine, který bere palette.open jako výraz, jejž nevyhodnotí — a nechal přes celou stránku modální backdrop nad každým kliknutím na stránce, která v markupu vypadala správně; CDN build, který se spustil dřív, než byla komponenta registrována; horní lišta o osm pixelů širší než viewport 390 px na každé stránce; a obal tabulky se záporným okrajem, který udělal dokument širší než viewport.

Playwright řídí již nainstalovaný Chrome (channel: 'chrome'), takže se nic nestahuje a CI znovu používá prohlížeč, který už instaluje sonda webu. Chybějící Chrome, chybějící Playwright nebo chybějící Node je SKIP prohlížečového průchodu, nikoli selhání — stavový průchod stále běží přes každou trasu.

Jeden důsledek jednorázového čtení assetů: změněný stylesheet nebo skript vyžaduje restart serveru, než je sonda uvidí. Je to záměr — asset se čte z disku jednou za proces — a proto sonda hlásí digest, který byl servírován.

Tvrzení, která tento dokument definuje

Každý odkazuje na vlastní stránku s implementací, testem a místy použití.

Prohledává názvy a popisy všech stránek, které tento web publikuje.