Skip to content

The Cockpit is published as a snapshot by the exporter that reads the UI, and two snapshots link only the pages each holds

The Cockpit is published as a snapshot by the exporter that reads the UI, and two snapshots link only the pages each holds

majordomus://adr/adr-0147proposed architectureinterfacecockpituipages

it references

  • put_in_force .ai/repo/ci/pages.yaml (file)
  • put_in_force apps/majordomus-cli/src/cockpit/mod.rs (file)
  • put_in_force apps/majordomus-cli/src/web/report/snapshot.rs (file)
  • put_in_force adr-0012
  • put_in_force adr-0135
  • put_in_force adr-0141
  • put_in_force docs/COCKPIT.md (document)
  • put_in_force docs/MAJORDOMUS_UI.md (document)
  • put_in_force test/cases/2981_the_cockpit_snapshot_holds_its_routes.sh (test)
  • put_in_force test/cases/2982_two_snapshots_link_what_the_other_holds.sh (test)

referenced by

Nothing in the layer names it. Backlinks are derived, so an empty list is an answer rather than an omission.

Context

The owner's mission of 2026-10-12, "Unified Product Experience", names three surfaces of one product: the landing page, /ui and /cockpit. Its acceptance asks that the public /cockpit be verified, and that the three be navigable from one another.

  • The UI is published at /ui since ADR 0141: a snapshot read at one commit.
  • https://majordomus.dev/cockpit/ answered the site's own not-found page. Nothing asked.
  • Every page of the UI names its sources with a link to the capability's page in the Cockpit (ADR 0135). In the UI's snapshot each of those links led to a page saying that only a running process answers it. On a real repository that was 187 links on sixteen screens. The surface a reader is sent to first led nowhere for its own evidence.
  • The exporter of ADR 0141 was written for the UI: its mount, its assets, its screens and its script were named in the code.

Decision

One exporter reads both surfaces, and a third one would be a constant.

  1. A subject. What differs between the UI's snapshot and the Cockpit's is a value (web::report::snapshot::Subject): the identity, the producer, the served surface, the mount, the assets, the query key that asks for a part of a page, whether a page keeps its scripts, and the routes a publication never holds. The exporter takes a subject, the surface's own handler and the pages to read first. UI and COCKPIT are the two there are.
  2. majordomus web report cockpit-snapshot reads the Cockpit in-process and writes target/web/cockpit-snapshot, declared as a surface of every publication at /cockpit and of no process. It reads, in order: every static route; every Cockpit page the UI's snapshot wanted to link to; then, one page per family in turn, what those link to, until the page bound or the time budget.
  3. No script. The Cockpit's scripts open sockets, poll and post to the process. A snapshot of it carries none of them. Every page of the Cockpit is complete HTML before a script runs, so nothing is lost but what could not have worked.
  4. One page is withheld. /cockpit/continuity reads .ai/local/: the open episodes and handovers of one checkout, which name a disk. The subject withholds it. It is never read, whatever links to it, and a link to it leads to the page about the live Cockpit. A test found that seeding alone did not hold this: the navigation links the page from every other one.
  5. Two snapshots link by the pages each holds. A snapshot is bounded, so its mount being published says nothing about one page of it. A link into another snapshot's surface leads to that page when the other snapshot's own record lists it, and to the live page when it does not. The snapshot written second corrects the files of the first: the links the first led to its live page, because the second did not exist yet, are led to the pages the second wrote. Each surface is read once.
  6. The publication model declares both (deploy.snapshots in .ai/repo/ci/pages.yaml). The deploy places each at the mount the topology gives it, scripts/pages verify-ui --surface cockpit asks the public site for it after a deploy, and the pages-live gate holds every declared snapshot to the published commit.

Consequences

  • /cockpit/ on the public site is the Cockpit of the published commit, said to be a snapshot on every page, with the commit, the time and the executable that read it.
  • A capability the UI cites is a page a reader can open on the public site. On this repository 169 of the 187 links lead to a Cockpit page; the rest are a form and pages past the bound.
  • The Cockpit's snapshot is bounded far below the registry: a page per capability and per object would be thousands of files. What the bound leaves out is listed in its snapshot.json and leads to the live page.
  • A snapshot shows the machine that rendered it where a page is about a machine: peers, worktrees and health are a CI runner's. They are published as read. Only the page that reads .ai/local/ is withheld.
  • The Cockpit does not link to the UI yet, in either direction of a publication. One link contract for the site, the UI and the Cockpit is I2496.
  • ADR 0141 stands as written. Its exporter is this one; its command, its directory and its declaration are unchanged.

Alternatives refused

  • A page at /cockpit/ that says the Cockpit runs with your server. Honest, and it would have closed the 404. It would also have left the UI's evidence links leading nowhere, which is the defect a reader meets.
  • A second exporter for the Cockpit. The first one already held every rule a publication needs: relative links, the live page, the stamp, the bound. A copy would drift from it.
  • Reading the UI twice, once to learn what it links to and once to link it. The UI's snapshot costs minutes on CI; correcting its files after the Cockpit is written costs a pass over them.

Status

Proposed by session p12 on 2026-10-12, for the owner's Unified Product Experience mission, with the split agreed with p9. Acceptance is the owner's act.

Where this comes from

canonical file
.ai/repo/adrs/0147-the-cockpit-is-published-as-a-snapshot-by-the-exporter-that-reads-the-ui.md
identity
adr-0147
also served as
MCP resource majordomus://adr/adr-0147 · majordomus entity show adr/adr-0147 · GET /api/v1/entity?uri=majordomus://adr/adr-0147
in the Cockpit
/cockpit/objects/adr/adr-0147

This page is generated from the file above by scripts/generate-site-data; editing the page changes nothing, editing the file changes every surface. The relations above are edges of docs/generated/graph.json, which the executable writes from the same index.

Searches the titles and descriptions of every page this site publishes.