Skip to content

A dashboard is a projection of capabilities, and every card names the answer it was read from

A dashboard is a projection of capabilities, and every card names the answer it was read from

majordomus://adr/adr-0088proposed architectureinterfacecapabilitiescockpit

it references

  • put_in_force apps/majordomus-cli/src/capability/builtin/dashboard.rs (file)
  • put_in_force apps/majordomus-cli/src/cockpit/pages.rs (file)
  • put_in_force adr-0012
  • put_in_force adr-0087
  • put_in_force docs/COCKPIT.md (document)
  • put_in_force project.interfaces-are-projections@1
  • put_in_force test/cases/534_the_overview_answers_four_questions.sh (test)
  • put_in_force apps/majordomus-cli/tests/dashboard.rs (test)

referenced by

88. A dashboard is a projection of capabilities, and every card names the answer it was read from

Context

The owner asked for a Dashboard Suite: not a set of pages but a routable, data-driven view of the canonical state that a reader walks from an overview to a diagnosis, from the diagnosis to the evidence, and from the evidence to the command that acts on it. The facts such a suite shows already exist. health.report decides whether this process is healthy, release.version what the tree declares and what the commits imply, plan.status and plan.next where the plan stands, worktree.status whether a checkout is where it belongs, continuity.state what refuses completion, peers.list who else claims the same paths. Each is a capability, served over MCP, HTTP, the command line and the Cockpit from one declaration (ADR 0004, ADR 0012).

A dashboard is the classic place where those facts are copied. A number that a panel computes for itself — a count of failing checks filtered out of a list, a "blocked" total summed from a table — is a second derivation of something a capability already decides, and the day the two disagree neither is wrong in its own terms. The Cockpit already refuses the structural form of that (a page may not read the index: gate cockpit-projection), but nothing refused a page that asked the right capability and then did its own arithmetic on the answer, or showed one fact in two places from two different reads.

Decision

  • The Dashboard Suite is a module of capabilities, and a page of it is one capability. The first is dashboard.overview (MCP majordomus_dashboard_overview, GET /api/v1/dashboard/overview, majordomus dashboard overview). It answers four questions — is it healthy, what changed, what is broken, what needs action — and it has no datastore, no cache of its own and no state: each source is asked once per answer, through Context::execute, the call every other surface makes.

  • Every card is a typed answer that names its source. A DashboardCard carries its value, the source's verdict (ok, warn, fail, unknown — the HealthStatus vocabulary), a line of detail, the Cockpit route a reader drills into for the evidence, the command that acts on it when one does, and a DashboardSource: the capability, the input it was asked with, an RFC 6901 pointer into its answer and a measure. The measure is exact — the value at the pointer, null when there is none — or count — the number at the pointer, or the length of the list or map there, and 0 when the source left it out, which is how the sources serialise an empty list or a zero tally. Neither is arithmetic on the source's behalf.

  • Status words are the sources' verdicts, never thresholds. fail where a source says something refuses, warn where it names something worth looking at, ok otherwise, and unknown — never ok — when a source could not answer, with its error as the detail.

  • The consistency test is the enforcement. apps/majordomus-cli/tests/dashboard.rs asks the overview, then for every card asks source.capability with source.input over that capability's own route and asserts that reading source.pointer with source.measure gives card.value; a source that did not answer must leave the card unknown and empty. It names no card, so a card added tomorrow is held to it without an edit. It also asserts that the Cockpit's overview page carries each card's value (as data-value, the JSON the route answered) and links to its route. test/cases/534_the_overview_answers_four_questions.sh holds the same contract through the built executable: the command line's JSON against each source's own answer.

  • The Cockpit renders the capability, first. The overview page opens with a "Four questions" section laid out from dashboard.overview through the executor; the rest of the page is kept.

  • Overview first; the other pages after their models. Quality, Governance, Delivery and Mesh follow as further capabilities of the module. Quality waits for the evidence model of ADR 0087, so that its cards read a subject-indexed judgement rather than inventing one.

Alternatives rejected

  • A client-side dashboard application. It would fetch the same routes and hold the arithmetic in JavaScript, where no gate of this repository reads it, and it would reintroduce the second model of the registry that ADR 0012 rejected for the Cockpit.
  • A dashboard datastore (a snapshot table, a metrics file, a cache of card values). It is a copy with a refresh schedule, and every reader then has to ask whether the copy is current — the question the capabilities already answer by being asked.
  • Per-page hand-computed numbers. Faster to write and exactly the defect this decision exists to refuse: a number without a source pointer cannot be checked, and one computed twice drifts on the first edit that forgets one of them.
  • Quality first. The most asked-for page, and the one whose facts are still being modelled (ADR 0087). Building it first would fix a shape the evidence model has not settled.

Consequences

A fact on a dashboard now has an address: the capability, the input and the pointer it was read from, and a reader can ask that source directly and must get the same value. The price is that every card is a declaration in dashboard.rs with a judge function, and a source whose output changes shape changes the card — which the consistency test and the unit test that executes every card against a synthetic repository both report at once.

The overview costs what its sources cost. worktree.status walks the worktree topology and is the slowest of them on a machine with many linked worktrees; peers.list is asked for this checkout's board alone (checkouts: this) so that the overview never probes sibling servers. The expensive and refusing capabilities — delivery.report, release.analysis, evidence.* — are refused as sources by a unit test in the module.

What is not decided here: whether a card may ever combine two sources. The contract as stated allows one source per card; a fact that needs two is a capability of its own first.

Where this comes from

canonical file
.ai/repo/adrs/0088-a-dashboard-is-a-projection-of-capabilities-and-every-card-names-its-source.md
identity
adr-0088
also served as
MCP resource majordomus://adr/adr-0088 · majordomus entity show adr/adr-0088 · GET /api/v1/entity?uri=majordomus://adr/adr-0088
in the Cockpit
/cockpit/objects/adr/adr-0088

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.