Jak se dodání ukazuje člověku: co UI je, jak souvisí s Cockpitem, odkud pochází každá hodnota na něm, jak zůstává rychlé a aktuální a jak se přidává obrazovka. Popisuje chování tak, jak je implementováno a testováno; kde se obojí rozchází, tento dokument je špatně a mění se ve stejném commitu jako oprava.
- Rozhodnutím je ADR 0135.
- Pravidlo, kterému UI podléhá, je
project.ui-derived-state. - Záznam funkce je
.ai/repo/features/ui.md(stabilní od 2026-10-12, kdy vlastník přijal ADR 0135). - Tvrzení, které čtenář může ověřit, je
ui-dashboard-cites-its-sources(docs/claims/ui-dashboard-cites-its-sources.md), dokázané pomocíapps/majordomus-cli/tests/ui_surface.rs. - Zadání vlastníka s referenčními obrazovkami je
campaigns/majordomus-ui-complete-opus-fable-v3-20261011/.
Produkt a jeho technická reference
Sdílený server checkoutu obsluhuje dva povrchy, které člověk čte.
| Povrch | Připojit | Co to je |
|---|---|---|
| UI | /ui | produkt: dodávka vlastními slovy projektu, hustá, propojená a klikatelná |
| Cockpit | /cockpit | jeho technická reference: vykreslený registr, jedna stránka na schopnost, objekt, graf a trasu |
UI je místo, kam je člověk poslán jako první, a není pohledem na registr: jeho navigací jsou jeho obrazovky, jeho slova jsou slova doručení. Na Cockpit odkazuje jen jako na technický pohled na to, co obrazovka četla (ADR 0135), a v rámečku:
- odkaz „technický pohled“ na každém řádku zdroje, na stránku Cockpitu pro danou schopnost;
- technický pohled na objekt, který obrazovka jmenuje a UI pro něj nemá vlastní obrazovku (dokument, test, deklarující soubor, záznam funkce nebo nasazení), na stránku Cockpitu pro tento objekt;
- položka Cockpitu mezi ostatními povrchy v liště nástrojů a vyhledávání v liště nástrojů, které je vyhledáváním Cockpitu (
/cockpit/search), dokud UI nebude mít vlastní vyhledávání.
Obě plochy jsou projekce (ADR 0012): neobsahují žádná data, skládají schopnosti přes exekutor, který volá každý transport, a tentýž proces je obsluhuje pod jednou politikou zabezpečení obsahu. UI je nativní plocha webové topologie (web.surfaces ji uvádí), deklarovaná vedle Cockpitu v apps/majordomus-cli/src/web/discover.rs.
Obrazovky
| Obrazovka | Cesta | Čte |
|---|---|---|
| Dashboard | /ui | repository.info, health.report, release.version, distribution.releases, plan.status, plan.roadmap, mesh.peers; fronta na vlastní trase |
| Příkaz | /ui/command | commands.list (jeho filtr origin tvoří záložky obrazovky), executions.list; capabilities.list pro schopnost, kterou příkaz je |
| Pracovní prostor záměrů | /ui/idd | intents.list, plan.roadmap, plan.issues, plan.waves, plan.next: jeden záměr (?intent=, jinak první, který intents.list hlásí jako executing, pak verifying, planned, declared — pravidlo se vypisuje) s jeho inspektorem, milníky, které jmenuje, v pořadí plánu rozvoje s tím, na co každý čeká, každý úkol těchto milníků nebo jmenující záměr podle vlny s jeho stavem, prioritou, blokátory a přechodem, který jeho stav povoluje; ?issue= otevře panel přechodu daného úkolu přímo na obrazovce, formulář, který vykresluje stránka úkolu v Cockpitu, zapojený jedním modulem, který načítají oba povrchy (share/cockpit/moves.js, stránkou jmenovaný jako data-moves-lib) a provedený přes plan.transition jako provádění, které odmítne přechod, jejž plán nedovoluje, a řekne proč, vlny, které tyto úkoly zabírají, s konflikty rozsahu, které je serializují, a jejich graf závislostí nad tabulkou týchž hran. Proč záměr stojí tam, kde stojí, se ptá na vlastní trase (/ui/panels/standing?intent=, intent_realization.explain, což trvá sekundy): věty, o které se jeho fáze a verdikt opírají, každé nesplněné kritérium se stavem důkazu, příkazem, který ho reprodukuje, a úkoly, které mu slouží, práce realizující záměr s proveniencí každého odkazu a jeho drift. executions.list dává každé plan.transition, které tento server spustil na úkolech záměru, nejnovější první, každé s odkazem na jeho provádění v Cockpitu. Obrazovka se načte znovu, když skončí provádění jejího serveru na /events, a říká, co ten kanál dělá (níže). Nerozhoduje žádný vlastní stav, vlnu ani členství |
| Plán rozvoje | /ui/roadmap | plan.roadmap, plan.status, intents.list; jeden milník (?milestone=) v inspektoru, s plan.issues: jeho úkoly, co může začít, jeho kritická cesta a jeho sousedé; jeden záměr (?intent=) ve svém inspektoru: jeho prohlášení, invarianty a kritéria s jejich důkazy a milníky a úkoly, které mu slouží |
| Úkoly & PR | /ui/work | plan.status, plan.issues; fronta na vlastní trase, jeden pull request (?pr=) v jejím detailu |
| Úkoly | /ui/issues | plan.issues, plan.status, plan.roadmap: každý úkol, zúžený podle ?status= (vlastní stavy plánu jako karty), ?milestone=, ?priority= a ?q=, každý vedoucí na svůj inspektor |
| PR Drain | /ui/prs | plan.issues (jeden úkol, ?issue=); integration.queue (jeden počet na dráhu, kterou počítal) a integration.events na vlastní trase (/ui/panels/drain), zúžené přes ?disposition=, ?lane= a ?q=, jeden pull request (?pr=) v inspektoru s tím, co s ním executor udělal, nedávná aktivita dráhy a její merge za den během čtrnáctidenního období, kterým stopa končí |
| Schopnosti | /ui/capabilities | repository.info, capabilities.list podle druhu; jedna schopnost (?id=) z capabilities.describe |
| Mesh | /ui/mesh | mesh.peers, mesh.events, mesh.state (živá tvrzení); jeden stroj (?node=) v inspektoru a kdo drží každou roli pravidla project.the-cooperation-model-is-the-owners-word čtené z tvrzení |
| CI/CD & releasy | /ui/delivery | distribution.releases, release.version, deploy.list, gates.model, integration.timings (medián, 90. percentil a nejdelší běh každé kontroly a otevřené heady, které čekaly nejdéle, každý vedoucí na svůj pull request) |
| Nasazení | /ui/deployments | deploy.list (co vrstva deklaruje); deploy.observed (co zaznamenal forge: kde stojí každé prostředí, každé nasazení do každého prostředí — mimo jiné GitHub Pages — a každý release, přičemž každý commit, ref, prostředí, běh a release je odkaz); delivery.report na vlastní trase |
| Důkazy | /ui/evidence | evidence.report; jedno tvrzení (?claim=) v jeho inspektoru z evidence.claim: co je rozhoduje, jeho poslední běh, co se od té doby změnilo, jak je reprodukovat a tvrzení, která jeho test také dokazuje |
| Znalosti | /ui/knowledge | knowledge_base.status, knowledge_base.candidates: kandidáti čekající na revizi, od nejnovějších a omezení s počtem toho, co zůstalo mimo, předměty, kterých se týkají, a zda deriver stále zapisuje. Příkazy revize jsou jmenovány jako text; obrazovka nic nepovyšuje ani nezamítá |
| Dokumentace | /ui/docs | objects.list (funkce, dokumenty), web.surfaces |
| Governance | /ui/governance | rules.report, každé pravidlo pojmenované a vedoucí ke svému inspektoru; jedno pravidlo (?rule=) z rules.show: co říká, jak je vynucováno, testy, které je dokazují, co chybí a pravidla kolem něj |
| Observatory | /ui/observatory a /ui/kiosk jako jeho preset | mesh.peers, mesh.events, mesh.state, plan.roadmap, distribution.releases, release.version, health.report, economics.runs, repository.info, rules.report, evidence.report, quality.report, plan.waves, distribution.status, capabilities.list: patnáct scén, každá nakreslená z toho, co její zdroje odpověděly nebo jmenovaly jako nedostupné s důvodem zdroje (Observatory) |
Navigace je SCREENS v apps/majordomus-cli/src/ui/mod.rs a nic jiného. Test ji porovnává s větvemi dispatcheru, takže obrazovka bez trasy nebo trasa bez obrazovky selže. Obrazovka z konceptu vlastníka, která zatím nemá producenta, v navigaci není: odkaz na nic je slepá ulice.
Každá obrazovka má stejný tvar:
- hero pruh s glyfem obrazovky, titulkem, sloganem a úvodem, za nimi rozsvícená značka produktu, a řada dlaždic KPI;
- mřížka panelů;
- rámec kolem obou: nahoře navigační lišta webu (níže), pod ní postranní panel obrazovek s kartou verze na konci a lišta nástrojů s hledáním, časem přečtení obrazovky a ostatními plochami (dokumentace, API, Cockpit).
Navbar pochází z webu
majordomus.dev je referencí toho, jak produkt vypadá, a lišta nahoře na každé obrazovce — i na každé stránce Cockpitu — je vlastní navbar webu (project.the-ui-wears-the-sites-navbar), nikoli lišta nakreslená podle něj: značka a verze, čtyři otázky webu jako menu, hledání, přepínač motivu, produkt, GitHub a výzva k akci.
flowchart LR nav["site/data/nav.toml<br>the declaration"] --> partial["site/templates/partials/navbar.html<br>the one renderer"] partial --> built["site/public/404.html<br>the built bar"] built -->|"scripts/ui navbar --write"| copy["apps/majordomus-cli/src/ui/navbar.html<br>compiled in"] copy --> shell["ui/shell.rs<br>every screen"] copy -->|"@source"| css["share/ui/ui.css<br>the same utilities"] sitejs["site/nav.js, site/theme.js"] -->|"scripts/cockpit-assets"| uijs["share/ui/nav.js, theme.js"]
| Co | Odkud pochází |
|---|---|
| značkování | partial webu nad site/data/nav.toml, vyříznutý ze sestaveného webu pomocí scripts/ui navbar --write do apps/majordomus-cli/src/ui/navbar.html a zkompilovaný dovnitř (ui/navbar.rs) |
| styly | utility, které ten soubor jmenuje, zkompilované do share/ui/ui.css a share/cockpit/cockpit.css ze stejných stylesheetů Tailwind, tématu Flowbite a designu jako app.css webu |
| nabídky a přepínač motivu | nav.js a theme.js webu, servírované z share/ui/ a share/cockpit/ jako bytové kopie, které scripts/cockpit-assets zapisuje a --check drží; kontrakt motivu je na <html>, kde jej čte skript webu |
| tlačítko hledání | povrchu: v UI vede / a Ctrl/Cmd+K do vyhledávání v liště nástrojů; v Cockpitu otevírá paletu |
| verze v odznaku | spustitelného souboru, kde web uvádí release, který nabízí |
| položka produktu | samotné UI, kde web vede k jeho publikovanému snímku |
| každý jiný odkaz | web na vlastní adrese |
Chcete-li lištu změnit, změňte web — deklaraci nebo partial — pak znovu sestavte a nechte kopii následovat: scripts/site-build && scripts/ui navbar --write && scripts/cockpit-assets. scripts/ui navbar, který scripts/ui audit spouští jako první v úloze ui, odmítne kopii, která není sestavenou lištou, a pak porovná lištu, kterou prohlížeč kreslí na úvodní stránce webu, s těmi, které kreslí na /ui a /cockpit: každý prvek, jeho box a vypočtené styly, v obou motivech, při každé šířce, kterou design deklaruje, se zavřenou lištou i s otevřeným menu.
Dlaždice KPI vedou na obrazovku, která je vysvětluje. Panel, jehož celek je na jiné obrazovce, říká „Zobrazit vše“. Řádek milníku vede na tento milník v plánu rozvoje, kde je řádek, na který dopadne, zvýrazněn. Řádek schopnosti otevře svůj detail (?id=), pull request fronty otevře svůj detail (?pr=) a stroj mesh — v tabulce nebo jako uzel grafu — otevře svůj inspektor (?node=); každý výběr je URL, takže přežije opětovné načtení i tlačítko Zpět prohlížeče.
Co obrazovka jmenuje, je odkaz
Každá entita, kterou obrazovka jmenuje, někam vede (I2481):
| Co je pojmenováno | Kam to vede |
|---|---|
| úkol, pull request, milník, intent, tvrzení, pravidlo, schopnost, stroj | jeho inspektor v UI |
| kontrola | jeho řádek v modelu CI, /ui/delivery#gate-<id>; kontroly, které implikuje, vedou k jejím |
| nasazení | jeho řádek v Deployments, /ui/deployments#deployment-<id> |
| nasazený commit, ref, z něhož byl nasazen, prostředí, běh, který jej nasadil, publikovaný release | stránka forge pro něj, sestavená z adresy repozitáře, kterou forge sám uvedl při pozorování (deploy.observed) |
| úkol nebo milník, který pojmenovává próza samotného milníku | jeho inspektor; próza je záznamu, vykreslená se svým značkováním (ui/prose.rs) |
| příkaz, který registr servíruje i jako schopnost | inspektor té schopnosti; oba jsou jedno, když je deklarovaná cesta schopnosti v příkazové řádce vyvoláním příkazu |
| release | záznam, který pro něj distribuce publikuje, na adrese, kterou udává distribution.releases |
| dokument, test, funkce, deklarace pravidla nebo nasazení | jeho technický pohled, stránka Cockpitu pro daný objekt |
| veřejná adresa, kterou sondovala zpráva o doručení | ta adresa |
Odkaz na technický pohled se kreslí jen tehdy, když index objekt drží: řekl to zdroj (vlastní URI pravidla, test, který důkaz našel na disku), nebo jej rozřeší objects.get. Co index nedrží, je text, takže žádný odkaz nevede na stránku, která odpovídá 404. Dva druhy názvů zůstávají textem, protože nic neodvozuje, kam vedou: commit mimo obrazovku Deployments, protože žádná schopnost, na niž se ostatní obrazovky ptají při prvním vykreslení, neuvádí adresu forge (PR Drain, který se ptá fronty, a Deployments, který se ptá na pozorované, forge odkazují), a cesta, která není objektem indexu.
Co forge zaznamenal, se čte z jednoho pozorování, které pořizuje majordomus served forge a které se uchovává vedle pozorování pull requestů, jež pořizuje majordomus prs refresh. Checkout, který se nikdy nezeptal, to řekne i s tímto příkazem, místo aby kreslil prázdné tabulky; úloha publikovaného snapshotu se zeptá před čtením, takže veřejné Deployments a PR Drain nejsou prázdné.
Seznam, který obrazovka zkrátí, to říká: „Prvních 8 z 31; dalších 23 se zde nezobrazuje“, s odkazem na obrazovku, která je ukáže všechny, pokud existuje. Případ 1091 a apps/majordomus-cli/tests/ui_links.rs čtou každou obrazovku přes skutečný server a sledují každý odkaz pod /ui i každý technický pohled, který kreslí; kdo neodpoví, v nich selže.
Detail pull requestu se čte z vlastní odpovědi fronty, takže nestojí druhé volání: co pull request je, každá kontrola s verdiktem, důkazy, z nichž byl každý verdikt přečten, proč stojí tam, kde stojí, další akce, která by ho pohnula, cesty, které píše, a faktory jeho pořadí. Číslo, které fronta nepozorovala, se označí jako nepozorované.
Odkud se hodnota bere
Každá hodnota je odečet: hodnota na ukazateli RFC 6901 do odpovědi jedné schopnosti (apps/majordomus-cli/src/ui/source.rs). Dlaždice pod svou hodnotou ukazuje svou schopnost a ukazatel. Panel končí svými zdroji. Každý zdroj je pojmenován s dobou, kterou trval, a se všemi dalšími způsoby, jak položit tutéž otázku, jak je schopnost deklaruje přes capabilities.describe:
- API: trasa, s odkazem, takže prohlížeč otevře stejnou odpověď jako JSON;
- CLI: příkaz, který člověk píše,
majordomus <path>; - MCP: nástroj, který agent volá;
- technický pohled: stránka schopnosti v Cockpitu.
Nic se nepočítá za UI:
- Seznam, který zobrazí, je seznam, který vrátila schopnost.
- Počet je číslo na ukazateli nebo délka seznamu tam.
- Ukazatel je obrázek dvou čísel napsaných vedle něj.
- Koláč kreslí počty, které jeho legenda vypisuje.
- Stavové slovo je vlastní slovo zdroje, stylované stavovým slovníkem design systému.
- Okno je vlastní zdroji. Dlaždice merge jsou označeny
throughput/window_daysfronty a graf propustnosti PR Drain počítá merge ze stopy za den přes totéž okno; když fronta okno neuvádí, dlaždice to řekne a žádný den se nepočítá. Sloupce grafu jsou jediné, co si obrazovka sčítá sama, každý z událostímerge_succeededté stopy v ten den, s počtem napsaným vedle sloupce.
Třídy, které se překrývají, například pokrytí v reportu pravidel, se uvádějí a nikdy nesčítají. Co chybí, to říká:
| Zdroj | UI ukazuje |
|---|---|
| zodpovězeno a ukazatel drží hodnotu | hodnota (zlomek zaokrouhlený na dvě místa) |
| zodpovězeno a ukazatel nic nedrží | none |
| odpověděl řádkem bez stavového slova | unknown |
| nemohl odpovědět | not answered, s důvodem |
Žádný z nich se nikdy nekreslí jako nula ani jako zdravý. Kontroly ui-integrity a cockpit-projection drží zdroje UI přesně tak, jak drží zdroje Cockpitu: scripts/ci/cockpit-projection-check prochází oba adresáře. Případy 389 a 547 dokazují, že v UI odmítne čtení indexu nebo registru a chybějící počet nakreslený jako nula.
Rychlé a aktuální
Obrazovka nečeká na své zdroje (ADR 0142, pravidlo project.no-screen-waits-for-a-source). Žádá o poslední čtení každého z nich (Context::read, capability::readings): co proces ví nyní, předáno z paměti. Handlery, git a soubory se dotýká worker za čtečkou, nikdy na cestě požadavku.
| Zdrojem bylo | Co čtenář dostane | Co se děje za nimi |
|---|---|---|
| čteno v repozitáři tak, jak je nyní | odečet, okamžitě | čteno znovu, jakmile je starší než vteřina |
| přečteno před poslední změnou repozitáře | nové čtení, pokud dorazí do 50 ms, jinak staré, označené jako zastaralé | čteno znovu, spolu s každým dalším zdrojem čteným za posledních pět minut |
| v tomto procesu nikdy nečteno | první čtení, na které se čeká | nic víc; po minutě se říká, že čeká |
Nečeká se ani na vlastní opětovné načtení repozitáře. Když se repozitář změnil, obrazovka se vykreslí z generace, kterou server má, otevře se větou „Repozitář se změnil: tato obrazovka ho ukazuje, jak byl, a čte se znovu“ a další generace se načte za ní. Odpověď přes API, MCP nebo příkazovou řádku stále čeká na generaci, kterou její volající viděl.
Odečet říká, jak stojí na svém zdrojovém řádku. Aktuální starší než pět sekund uvádí svůj věk („read 12 s ago“). Zastaralý říká „read 12 s ago, before the repository changed; reading again“ a jeho řádek nese data-catching-up. ui.js čte obrazovku s takovým řádkem znovu po 0,4 s, poté po dvojnásobku, až do 6,4 s, dokud žádný nezbývá. Zastaralá hodnota se nikdy nevykresluje jako aktuální.
První čtenář UI spustí na pozadí jeden průchod každou obrazovkou a panelem, takže obrazovka otevřená příště má své zdroje přečtené dřív, než je vyžádána. Průchod prochází SCREENS a PANELS; žádný jiný seznam zdrojů neexistuje.
Odpověď není čtení. execute, a tedy API, MCP a příkazová řádka, stále spouští handler nebo vracejí přesně to, co by vrátil. Pochybnost řeší dva přepínače:
MAJORDOMUS_CAPABILITY_CACHE=offzpůsobí, že každé čtení spustí svůj handler a počká na něj.MAJORDOMUS_READING_PATIENCE_MS=waituchová odečty a každé čtení nechá počkat na aktuální. Číslo nastaví těch 50 ms.
Zdroje, které zatím nemají čtení, se ptají najednou, každý na vlastním vlákně, takže první vykreslení stojí tolik, co nejpomalejší zdroj, ne součet všech (source::ask_all).
Zdroj příliš pomalý pro první vykreslení je panel s vlastní routou. Fronta pull requestů (integration.queue) je /ui/panels/pull-requests:
- s
?fragmenttrasa odpovídá samotným panelem aui.jsjej umístí na místo, jakmile je obrazovka vykreslena; - bez JavaScriptu je zástupka odkazem na tutéž routu.
Dokud je obrazovka viditelná, ui.js se serveru každou minutu ptá znovu, vloží nové vykreslení a aktualizuje čas v liště nástrojů. Ten čas je okamžik, kdy byla stránka vykreslena; každý řádek zdroje říká, kdy je jeho vlastní čtení starší. Je to obnovení a tak se i označuje. Proudová stránka a jeden proud změněných čtení ji nahradí v I2487.
Pracovní prostor záměrů také sleduje provádění, která jeho server spouští (I2783). Jeho obrazovka nese data-follows-executions a stránka jmenuje kanál (data-events, /events) a jediného klienta WebSocket Cockpitu (share/cockpit/socket.js, data-socket-lib). Když tam provádění skončí (dokončeno, selhalo nebo zrušeno), ui.js obrazovku znovu načte do několika sekund, jednou na dávku a nejvýš každé dvě sekundy. Totéž dělá po opětovném připojení nebo mezeře, která mohla konec minout. Za časem čtení horní lišta říká, co ten kanál dělá: executions live, reconnecting nebo offline, převzato z vlastního stavu socketu. Kanál jen signalizuje, kdy číst znovu; obrazovka stále říká jen to, na co odpovídají její zdroje. Nese jen provádění tohoto serveru, takže pohyb, který provede jiný proces, se ukáže až v další minutě.
Jak je to rychlé, se měří, nezapisuje se to zde. majordomus bench odvozuje cíl z každé obrazovky v SCREENS a každého panelu v PANELS, studený i teplý:
system.http.ui.<route>čte stránku nad připnutým kontextem.system.http.live.ui.<route>čte obrazovku nad živým pohledem, z něhož odpovídáserve, takže platí git razítko na požadavek.system.http.live.indexměří samotné toto razítko na/.- Panel se měří pouze pomocí
--profile full, protože jeho zdroj je důvodem, proč je panelem.
Cíle jsou uvedeny v generated/benchmarks.md.
Obrazovka nad svým rozpočtem shodí build (I2489). Politika měření výkonu, .ai/repo/benchmarks/rust/policy.yaml, deklaruje, že teplá obrazovka odpoví do 100 ms na p95, pro oba pohledy. majordomus bench --check drží každý rozpočet s výchozí hodnotou i bez ní a na každém hostiteli, vypíše každou omezenou obrazovku s její hodnotou a mezí a končí exitem 10, když je některá nad ní. Job ui v CI jej spouští před auditem prohlížeče:
majordomus bench system.http. --transport system --profile ci --no-write --check
Práh regrese to nedokáže: obrazovka, která byla vždy pomalá, nikdy nezregreduje, a platforma bez baseline neporovnává nic. První běh kontroly našel /ui/command na 400–660 ms, zatímco každá jiná obrazovka četla 1–21 ms. První požadavek po přesunu repozitáře zatím bench neměří (I2485).
Grafy vztahů
Vztah, který zdroj zaznamenává, se kreslí jako graf: závislosti mezi milníky (rozložené ve svém směru; uzel otevře inspektor onoho milníku), otevřené pull requesty, které na sobě závisejí (již sloučená závislost se nekreslí; ta, kterou fronta nedrží, je malý uzel vedoucí na forge), a stroje meshe, runtime, které na nich běží, a relace, které ty drží (rozložené silově, relace jako malé listy označené po výběru). Server umístí uzly a hrany na stránku (view::graph). Vendorované Cytoscape, načtené jen obrazovkou, která má graf, je vykreslí:
- v odstínech designového systému, přečtených ze stylesheetu;
- s rozvržením, které se při omezeném pohybu neanimuje;
- s uzly, které vedou tam, kde je jejich řádek.
Tabulka týchž hran zůstává pod grafem a čte ji čtenář bez JavaScriptu nebo bez knihovny. Kreslí se jen uzly, které se účastní hrany.
Observatoř
Ostatní obrazovky jsou řádky pro člověka, který přišel něco rozhodnout. Observatory je tatáž fakta jako obraz, určený pro displej, u kterého nikdo nesedí (ADR 0158). Je to jedna obrazovka a nepřidává žádnou schopnost:
| Cesta | Co to je |
|---|---|
/ui/observatory | obrazovka, uvnitř rámu aplikace |
/ui/kiosk | stejná obrazovka, projekce a skript, vyplňující okno nad rámem, pro displej ponechaný běžet |
/ui/screensaver | trvalé přesměrování na /ui/kiosk, jeho lepší název |
/ui/obsrvatory | trvalé přesměrování na /ui/observatory |
Scény tvoří jeden seznam, SCENES v apps/majordomus-cli/src/ui/observatory.rs. Každá uvádí svůj popisek, schopnosti, které vyžaduje, co znamenají její značky, obrazovku, která ukazuje tytéž skutečnosti jako řádky, jak dlouho zůstává a jaký je její charakter:
- sémantická scéna váže značky na záznamy: stroj, událost, milník, release;
- scéna ambient je dekorace, je označena jako dekorace a nepředstavuje žádný fakt.
| Scéna | Popisek | Vyžaduje | Jeho řádky |
|---|---|---|---|
mesh | Mesh Cosmos | mesh.peers | Mesh |
activity | Event River | mesh.events | Mesh |
intents | Intent Nebula | plan.roadmap | Plán rozvoje |
tokens | Spektrum tokenů | economics.runs | Důkazy |
heartbeat | Puls systému | health.report | Dashboard |
delivery | Strom dodávky | distribution.releases | CI/CD & releasy |
coop | Choreografie spolupráce | mesh.state | Mesh |
proof | Mříž důkazů | rules.report | Governance |
claims | Registr tvrzení | evidence.report | Důkazy |
surface | Atlas povrchů | quality.report | Schopnosti |
waves | Wave Front | plan.waves | Plán rozvoje |
matrix | Matice release | distribution.status | CI/CD & releasy |
registry | Registry Treemap | capabilities.list | Schopnosti |
ladder | Žebříček milníků | plan.roadmap | Plán rozvoje |
ambient | Ambient Intelligence | nic: je to dekorace | Dashboard |
Tabulka je pomůcka ke čtení; seznam v modulu je to, co čte stránka, skript a případ 3011, a stránka vypisuje requires každé scény.
Posledních sedm (proof až ladder, ADR 0160) čte, co repozitář dokazuje, a nepotřebuje žádný mesh, takže se kreslí i na veřejném webu. Počítají se, nikdy neodhadují: značka je pravidlo, druh tvrzení, naměřený počet, vlna nebo kontrola, a kde zdroj hlásí víc položek, než zobrazení pojme, scéna je seskupí a řekne, kolik jich nakreslila. Kreslí se pomocí p5 v instančním režimu na vlastní povrch, který režisér skládá na svou scénu, z share/ui/observatory-kiosk.js; p5 je připnutá knihovna, kterou scripts/cockpit-assets kopíruje do share/ui/vendor/, není commitnutá a načítá se jen při zobrazení některé z těchto scén. Checkout sestavený bez ní říká na scéně „p5 is not built here“ a stejná fakta si ponechává v tabulce pod ní.
Stránka nese celou svou projekci jako jeden dokument, observatory/v1, v atributu data-observatory své sekce: kdy byla pozorována, revizi, každý dotázaný zdroj se stavem, v jakém odpověděl (answered nebo failed, s důvodem a spotřebovaným časem) a každou scénu s jejím modelem. Pravidlo obrazovky je v tomto dokumentu:
| Zdroje scény | Scéna |
|---|---|
| zodpovězeno, s něčím ke kreslení | available, s modelem |
| odpověděla, že není co kreslit, nebo nemohla odpovědět | nedostupné: žádný model, vlastní důvod zdroje, a skript na něj nepřepíná |
Scéna se nikdy nekreslí prázdná, nikdy se zástupnými značkami a nikdy se nenahrazuje obrázkem zdraví. Událost meshe se promítá jako její identita (stream a sekvence), její druh, její uzel, její logický čas a její nástěnný čas, a nikdy jako její tělo.
Slovo stavu říká, jak byla stránka přečtena:
LIVE: čteno znovu do 90 sekund. Skript žádá o svou vlastní stránku každých 60 sekund a mezi těmito čteními sleduje žurnál meshe od kurzoru každé 3 sekundy přesobservatory.events, které odpovídá jen událostmi nad kurzorem, projektovanými přesně tak, jak je projektuje scéna. Dvakrát doručená událost je jedna značka, řeka drží nejvýše 200 a oba čtenáři ustoupí na 120 sekund, když server neodpovídá;RESYNCED: po deset sekund poté, co kurzor jmenoval hodiny, kterých žurnál nikdy nedosáhl (žurnál jiného runtime, nebo takový, který se restartoval); stránka byla ihned přečtena znovu;STALE: v rámci meze se nečte znovu;REPLAY: scéna meshe nakreslená ze záznamu repozitáře, s časem, kdy byla zaznamenána;SNAPSHOT: veřejný web, který nic nečte znovu a jmenuje svou revizi.
Bez JavaScriptu je tatáž projekce tabulkou: jeden řádek na scénu, se stavem slovy (available, decorative nebo unavailable), jejím významem nebo důvodem, tím, co vyžaduje, a odkazem na její řádky.
Volba scény čtenářem platí pět minut, poté rotace pokračuje. Nové události žurnálu přeruší rotaci ve prospěch řeky, jakmile zobrazená scéna měla 12 sekund, a nejvýše jednou za 120 sekund, takže vytížený žurnál nemůže displej obsadit; volba čtenáře se nikdy nepřerušuje. Scéna, jejíž renderer vyhodí výjimku, je v karanténě po zbytek života displeje: rotace ji přeskočí, ostatní pokračují a scéna řekne QUARANTINED s tím, co selhalo, když si ji čtenář vyžádá. Nic na obrazovce nespouští práci ani nezapisuje záznam.
Vlastní stav displeje je čitelný pro inspektor nebo běh důkazů: vlastnost observatory sekce odpovídá data() (projekce, kterou právě kreslí), quarantined() a trace() (posledních 24 voleb rotace s jejich důvody). Důkazy kontrol se berou přes ni pomocí scripts/lib/ui-observatory.mjs.
Na veřejném webu proces, který pořizuje snímek, neprovozuje žádný mesh. Tam mesh, activity a coop kreslí záznam, který repozitář nese (.ai/repo/observatory/recording.json, čtený observatory.replay), a stav říká REPLAY s časem, kdy byl zaznamenán, a not live. Scéna, kterou záznam nenese, je nedostupná a říká proč; záznam, který nelze přečíst, je selhaný zdroj, nikdy scéna. tokens je nedostupné, dokud není zaznamenán žádný běh.
Záznam je odpověď observatory.capture na serveru, který provozuje mesh, uložená tak, jak přišla, a commitnutá. Nejmenuje nic svou identitou: stroje jsou machine 1, machine 2 v pořadí, v jakém je mesh vypsal, runtimy a relace jsou pořadová čísla a událost si ponechává druh, logické hodiny a čas. Její manifest jmenuje schopnosti, ze kterých byla přečtena, okno událostí, které drží (první a poslední čas a logické hodiny), a co bylo odstraněno a proč; observatory.replay odmítne záznam s událostí, které chybí druh, hodiny nebo čas, a událost pojmenuje. Záznam je okamžik; nahrazuje se novým zachycením. Co je stále otevřené, je v Co zatím nedělá.
Bez JavaScriptu
Každá obrazovka je kompletní HTML a nabídka úzké obrazovky se otevírá zaškrtávacím políčkem a jeho popiskem. share/ui/ui.js je jediný vlastní skript UI: stahuje pomalé panely, obnovuje obrazovku, kreslí grafy, odhaluje tlačítko hledání v liště a drží postranní panel pod lištou. Nabídky lišty a přepínač motivu běží na dvou vlastních skriptech webu. Jediný inline skript je příkaz motivu, který politika povoluje podle jeho digestu, tentýž, který dodává Cockpit. Obsluhovaný test ověřuje, že UI a Cockpit nesou jednu totožnou politiku.
Aktiva a design
Soubory UI žijí v share/ui/.
| Soubor | Jak se vyrábí | Commitnuto |
|---|---|---|
ui.css | zkompilováno z share/ui/src/ui.css příkazem scripts/cockpit-assets, vedle stylopisu Cockpitu; --check selže, je-li kterýkoli zastaralý | ano |
nav.js, theme.js | zkopírováno bajt po bajtu z site/nav.js a site/theme.js pomocí scripts/cockpit-assets; --check selže, když se kterýkoli liší | ano |
favicon.svg | zapsáno z kanonické značky pomocí majordomus generate | ano |
vendor/cytoscape.min.js | zkopírováno z připnutého npm balíčku pomocí scripts/cockpit-assets; distribuce bez něj se o něj nežádá a místo toho stojí tabulka každého grafu (I2900) | ne |
Třída ui modelu CI (.ai/repo/ci/gates.yaml) vybírá kontrolu aktiv, sondu, designovou kontrolu a audit UI, kdykoli se změní soubor pod share/ui/ nebo apps/majordomus-cli/src/ui/.
Stylesheet importuje tokeny, slovník stavů, primitiva a sadu z share/design/, kde stejné soubory importují web a Cockpit. Každá barva je role, stav nebo tón; žádná není literál. Značkování pojmenovává, čím věc je, nikdy třídu utility, protože stylesheet kompiluje jen to, co je v něm napsáno — kromě lišty webu, která je značkováním webu a kompiluje se z jeho kopie. Ikony jsou ikony sady, deklarované jednou v site/data/kit/icons.toml a zkompilované do crate pomocí majordomus generate (apps/majordomus-cli/src/ui/icons.toml); test drží obojí v rovnosti.
Volby jsou adresy
To, co čtenář na obrazovce vybere, je v jejím URL: karta, hledání, řádek, závislost, úkol. Každý ovládací prvek je odkaz nebo formulář GET na tutéž obrazovku s volbou v dotazu, takže pohled lze přidat do záložek, sdílet a znovu načíst, tlačítko zpět volbu vrátí a obrazovka k použití nepotřebuje skript. Hodnota, kterou odkaz nese, se čte jako vlastní slovník zdroje, nebo se zahodí: dispozice nebo lane je slovo fronty (malá písmena, číslice, podtržítka), úkol je I a čtyři číslice, pull request je číslo; cokoli jiného se neopakuje. Na PR Drain cestují volby na trasu odloženého panelu, takže pomalá část obrazovky odpovídá na stejnou otázku jako zbytek.
Přidání obrazovky
- Přidejte modul pod
apps/majordomus-cli/src/ui/, který se ptá svých zdrojů pomocísource::ask_alla skládá komponentyviewz čtení, nikdy z vlastní hodnoty. - Přidejte ji do
SCREENSvui/mod.rss její ikonou a její větev do dispečera. - Zdroj příliš pomalý pro první vykreslení se stává trasou panelu v
PANELS, vykreslenou jako zástupný prvek sdata-panel-src. Kterýkoli seznam činí trasu cílem měření výkonu; nic jiného se neupravuje. - Vést někam: dlaždice s
kpi_to, panel spanel_to, řádek s odkazem.
Na veřejném webu: snapshot
UI je projekce, na kterou odpovídá běžící proces, a veřejný web jsou soubory. Web proto nese UI jako snímek na /ui/ (ADR 0141): vlastní odpovědi UI, přečtené jednou na commitu, který web publikuje, zapsané.
majordomus web report ui-snapshot --limit 20
Zapisuje do target/web/ui-snapshot. --limit omezuje stránky a --budget-seconds čas strávený na stránkách, na které obrazovky odkazují; výchozí hodnoty uvádí nápověda příkazu.
Příkaz sestaví totéž UI, na které směruje server, v procesu, a vyžádá si od něj každou obrazovku a panel, poté stránky, na které odkazují: po jedné stránce z každé rodiny (inspektor každého pravidla, každého tvrzení, každého úkolu), dokud není zapsáno --limit stránek nebo neuplyne --budget-seconds, podle toho, co nastane dřív. Obrazovky a panely se zapíší bez ohledu na cenu. Sám nic nevykresluje. Mění jen to, co soubor nedokáže a trasa ano:
| V UI | Ve snímku |
|---|---|
| odkaz na jinou obrazovku nebo inspektor | relativní odkaz na soubor té stránky; dotaz inspektoru je adresář (governance/_rule/<id>/) |
| odkaz na stránku za hranicí, filtr z více polí, formulář, API | stránka snapshotu o živém UI, nesoucí cestu, kterou odkaz myslel |
| odkaz na stránku Cockpitu: „technický pohled“ na zdroj nebo na objekt | ta stránka vlastního snapshotu Cockpitu na /cockpit/, pokud ji drží (ADR 0147), a stránka o živém UI, pokud ne |
odkaz na povrch, který publikace drží (/rustdoc, /openapi.json) | beze změny |
odkaz do poskytované dokumentace (/docs/…) | táž stránka publikovaného webu |
| skript čte obrazovku znovu každou minutu a sleduje provedení svého serveru | nedělá ani jedno: tělo nese data-snapshot |
pomalý panel je zástupný prvek (data-panel-src), který skript vyplní, jakmile se obrazovka vykreslí | samotný panel, již přečtený: snapshot se zeptá každé stránky s hlavičkou X-Majordomus-Snapshot a UI umístí každý panel tam, kde stál jeho zástupný prvek |
| „Read at“ v liště nástrojů | také oznámení na každé stránce: commit, čas, spustitelný soubor a odkaz na živé UI |
Snapshot ví, co UI mohlo číst tam, kde byl pořízen. Runner Pages nemá mesh, žádné zaznamenané pozorování forge ani běžící provádění, takže tyto panely čtou none, unknown nebo not answered, nikdy nulu. Snapshot není důkazem živého stavu ničeho: k tomu spusťte majordomus serve v checkoutu a otevřete /ui.
Důkazy jsou výjimka. Runner Pages záznam o testech má: artefakt evidence, který zaznamenala validace téhož commitu nebo jeho nejbližšího předka. Job snímku zavede knihu onoho běhu na místo dřív, než se čte UI. Publikace, jejíž obrazovka důkazů by stále ukazovala víc tvrzení jako nespuštěných, než kolik dovoluje deklarovaná baseline, je odmítnuta (scripts/pages published-evidence, pravidlo project.published-evidence-is-what-ci-recorded).
Adresář se sám deklaruje (surface.json) jako povrch ui-snapshot, připojený na /ui, published-only, sestavený z commitu, u kterého byl přečten. Proces servíruje UI na /ui a publikace tam drží snímek a majordomus web validate drží obojí bez kolize. snapshot.json vedle něj vypisuje každou zapsanou stránku, každou stránku ponechanou živému UI a to, co čtení ukončilo (complete, limit nebo budget). test/cases/1092_the_ui_snapshot_holds_every_screen.sh a test/cases/1093_the_ui_snapshot_links_nothing_absent.sh ho k tomu zavazují.
Cockpit se publikuje stejně, stejným exportérem (ADR 0147, COCKPIT.md). Zapisuje se po snímku UI: nejdřív přečte stránky Cockpitu, na které chtěl odkazovat snímek UI, a pak tyto odkazy vede na stránky, které napsal, takže schopnost, kterou obrazovka cituje, je stránkou, kterou čtenář může otevřít. Každý povrch se čte jednou. Drží to test/cases/2982_two_snapshots_link_what_the_other_holds.sh.
Publikovaný snapshot je držen na trunku (project.the-published-ui-is-the-trunks). Model publikace deklaruje, že ho publikace drží (deploy.snapshots v .ai/repo/ci/pages.yaml), scripts/site-deploy odmítne publikovat web bez snapshotu přečteného v HEAD a scripts/pages verify-ui se po nasazení a uvnitř kontroly pages-live ptá veřejného webu: commit surface.json, banner a název snapshot.json a každou stránku, kterou záznam uvádí. Snapshot, který se zastavil na své mezi, projde a sonda uvede, co vynechal; snapshot, který chybí, jmenuje starší commit nebo neříká, co ukončilo jeho čtení, selže. docs/GITHUB_PAGES_ARCHITECTURE.md má podrobnosti a test/cases/2983_the_published_ui_is_the_trunks.sh je drží.
První obrazovka vede jen s čísly, o kterých může čtenář snímku rozhodnout. Ten proces není server, takže health.report říká unknown pro připojené klienty a runtime mesh, a tedy pro celou zprávu. Číslo zdraví na Dashboardu je místo toho verdikt repository zprávy: nejhorší z dimenzí, které popisují repozitář, a ne proces, který ho servíruje. Panel Zdraví pod ním stále vypisuje každou dimenzi s jejím vlastním slovem. Kde není aktivní žádný runtime mesh, číslo mesh říká Mesh active: no a nepočítá žádné stroje. Sonda odmítne publikovanou první obrazovku s nerozhodnutým číslem a test/cases/1092_the_ui_snapshot_holds_every_screen.sh drží snímek ke stejnému.
Co zatím nedělá
majordomus uijako příkaz, který zajistí sdílený server a otevře tento povrch, je I2484. Dokud nepřistane, otevřete/uina adrese, kterou vypíšemajordomus serve status.- Nic v UI zatím nespouští práci: spuštění schopnosti, úkolu nebo milníku přes executor a živé sledování jeho běhu je rovina řízení provádění balíčku V4. Akce na uzlu mesh je totéž, za executorem (V5); inspektor to říká.
- Obrazovka Nastavení neexistuje: žádná schopnost nedrží nastavení čtenáře.
- Časování CI je to, jak dlouho trvaly poslední běhy otevřených pull requestů, měřeno ze zaznamenané observace forge (
integration.timings); zatím neexistuje historie běhů, takže se nekreslí žádný trend. - Milníky nenesou data, takže plán rozvoje je sekvence a graf, nikdy kalendář.
- Přehrávání Observatoře na veřejném webu je tak staré jako poslední commitnutý záznam; nic žádný nezachycuje podle plánu. Mezi čteními své stránky sleduje žurnál dotazem na události nad svým kurzorem; nic se do ní netlačí. Její kontroly a měření za nimi jsou v
.ai/repo/benchmarks/observatory/manifest.json; snímková frekvence tam je headless Chromia na stroji, který jmenuje, ne panelu.