API & Dashboard — Domain Plan
Audience: the project maintainer — technical, time-pressed, wants signal over ritual.
Status: durable domain plan (throughline). Unlike the release-scoped
docs/plans/working notes that follow the distil-then-retire lifecycle, this document is one of the standing domain throughlines meant to persist across releases. It is the index and the "why" for the application/mission-data API and the dashboard/UX surface; the release milestones and epics it references are the "what ships when." Where a release plan and this plan disagree on scope of the domain, this plan is the canonical map; where they disagree on what ships in a given tag, the milestone roadmap and the owning epic win. Keep this plan factual and current; do not let it accrete release-scoped tracking that belongs in an epic.
1. Purpose & scope
Purpose. Give the application/mission-data API and the dashboard a single durable home that states the invariants the surface must hold, groups the domain's lasting sub-areas, and points at the epics and design records that carry the work. Before this plan, this surface had no standalone throughline. This plan makes the throughline explicit and becomes the domain's index. It is a sibling to the Doctrine & Charter Domain Plan, the Packs Extraction Domain Plan, and (until its 2026-09-06 retirement, Convergence #3881) the SaaS & Hosted Sync domain plan.
In scope — the application surface. "API & dashboard" here means the data surface the project's own consumers read mission state from, and the UX that renders it:
- The application / mission-data API (#645, Epic: Stable Application API Surface) —
the stable, versioned surface that exposes mission and work-package state (the status
projection reduced from
status.events.jsonl— see status-model) to the dashboard and any external application consumer, so consumers bind to a documented data contract, not to internal reducers or on-disk file shapes. - The dashboard / UX (#650) — the mission dashboard that renders that data: the WP-lane board, the mission and work-package views, and the localhost daemon surface. Direction (2026-10-01): the CLI-bundled dashboard is deleted first (#5530, operator decision 2026-10-01), ahead of the read API; the Mission Status Read API (#5528), reader re-pointing (#5532) and route rehoming (#5533) continue afterwards as the replacement read path. A replacement UI is built in its own repository and consumes the Mission Status Read API (ADR 2026-10-01-2, Accepted 2026-10-12). Direction (2026-10-12): that read API is the open-core producer surface (internally "Build Kitty") — the stable entry point to ledger and event data the free CLI exposes — and its backend is now GA-gating. The replacement UI and any multiplayer surface are the consumer side ("Multiplayer Mode," Team Kitty), consuming the producer API across its public contract (see §3.1, §6).
- Terminology fidelity in the UI (#650) — the dashboard renders the Mission canon
end to end; the historical
Feature-labelled UI drift is retired (see §3.3). This is a drift-elimination goal, not new vocabulary.
Explicit boundary / non-goal (FR-004) — the two things called "API".
This plan owns the application/mission-data API + dashboard. It is NOT the doctrine & charter Python import surface. There are two distinct surfaces the corpus calls an "API," and conflating them is the load-bearing miscategorisation this boundary exists to prevent:
- The application/mission-data API — THIS plan (#645). The data surface: mission and WP state, the reduced status projection, consumed by the dashboard and external application consumers over a documented data contract.
- The doctrine & charter public import surface — Doctrine & Charter Domain Plan §3.6 ("Stable public API surface for doctrine & charter"), design-spike #3179. A different API: the Python import / single- entry-point surface for the doctrine modules — the
runtime → charter → doctrinelayering where the runtime reaches doctrine through the charter proxy, never directly (doctrine/__init__.pydeclares 3 public names while ~79 files reach past it across ~30 submodule paths, with no architectural test pinning the public surface). That is a code-import boundary enforced by a layer test — not a data API consumed by a UI.The shared-epic subtlety. §3.6 records that #3179 reconciles its epic home to #645 because it is a direct instance of #645's single-entry-point pattern (the #645/#460 service-extraction → typed-contract → architectural-test sequence). #645 is therefore a shared epic with two facets: (a) the application/mission-data API surface + dashboard slice — this plan's — and (b) the doctrine-module Python import surface slice — §3.6's. The seam: the importable Python entry-point for the doctrine modules is §3.6's and is not restated here; the application data contract the dashboard consumes is this plan's and is not restated there. Cross-reference §3.6 when a change touches both — do not duplicate it.
Why a durable domain plan and not a release plan. The surface is governed by standing
invariants — an application consumer binds to a documented, versioned data contract, never
to internal reducers or file shapes; the dashboard never asserts UI behaviour it cannot
prove (frontend can fail silently); and the UI speaks the Mission canon, never re-drifting
to a Feature label. Those invariants outlive any one tag; the experience-shaped delivery
(deferred to the 4.x line, see §5) churns beneath them.
2. Where API/dashboard planning lives today (honest inventory)
There has been no standalone API/dashboard throughline before this document. The surface was distributed across two surfaces:
- Status model architecture — the append-only
status.events.jsonlevent log and itsreduce()projection that any mission-data API must expose. It is the data source of record, not an API/dashboard plan. - The epics themselves — #645 (Epic: Stable Application API Surface) and #650
(dashboard/UX, including the
Feature-label drift retirement). Issue-tracker groupings with scope bullets, not written plans. Experience-shaped delivery was deferred to 3.3.x by the 3.2.x milestone roadmap; 3.3.x was retired on 2026-08-23 without shipping. #645 is now on the 4.x Work milestone and #650 in Product backlog (checked 2026-09-30), and the 4.0.0 Milestone Roadmap (Theme 3), as re-anchored 2026-10-12, makes the mission-status API backend GA-gating (the open-core producer surface) and #645 GA-gating as the charter-extraction precondition.
This plan now becomes the domain's index. It ties #645 and #650 together under one set of invariants and surfaces the gaps they leave open (§4), and it draws the boundary with the doctrine-charter public-import surface (§1, §3.6-cross-ref) that shares the word "API" and, now, the #645 epic home.
3. Standing concerns — the durable spine
The domain divides into three lasting sub-areas. Each states the invariant it must hold (the durable "why"), then lists the currently open work (the release-scoped "what," which turns over across versions).
3.1 The application/mission-data API contract
Invariant. External application consumers and the dashboard bind to one documented, versioned data contract for mission and work-package state — never to internal reducers, event-log internals, or on-disk file shapes. The contract exposes the reduced status projection as its stable surface; internal churn behind it is not externally visible.
Design of record. Epic #645 (Stable Application API Surface), whose
service-extraction → typed-contract → architectural-test single-entry-point pattern
(the #645/#460 precedent) is the shape of the contract; the
status model projection as the data
source the contract exposes. ADR 2026-10-01-2 (Accepted 2026-10-12) names the contract the
Mission Status Read API and frames it as the open-core producer surface, not a hosted
Team Kitty surface. It has two granularities: an overview built from meta.json and the
event ledger, and a detail view with each WP's authored and resolved state and its
assignment. It is read-only and independent of drain. The CLI's own read path is an in-process
Python module in the specify_cli layer behind one read seam; the external form is a
read-only Java service (services/mission-status-api/) that is to start in-repo as a modular
component and be extracted as needed as an open-core surface — never into a Team Kitty repo
(direction/target state: the service directory does not exist yet; contracts/mission-status/
and the conformance fixtures already ship and stay canonical beside the Python reducer, ADR
Amendment 2026-10-12). The backend is now GA-gating (roadmap, Theme 3).
Open work. Enumerate and version the mission-data contract (the #645 application-data
facet — distinct from the #3179 doctrine-import facet §3.6 owns), then pin it with a
contract test so a consumer can rely on it across versions. Then fold the existing readers
into it (#5532): agent tasks status --json and the orchestrator-api
mission-state and list-ready reads (the former dashboard --json reader was deleted
with the dashboard, #5530, before this step). Land a gate against bypassing it (ADR D-5).
3.2 The dashboard / UX surface
Invariant. The dashboard renders mission and WP state truthfully and never asserts a UI behaviour it cannot prove — a frontend can fail silently (a caught 404 shows a fallback), so dashboard behaviour is verified by a browser-level regression, not inferred from an API response. The localhost daemon surface stays loopback-only.
Design of record. Epic #650 (dashboard/UX); the browser-level UI regression discipline recorded in the repository guidelines (the WP-modal Playwright guard is the standing example — API responses do not prove the UI works).
Open work. The experience-shaped dashboard delivery deferred beyond 4.0.0 (§5): the
WP-lane board, mission/WP views, and their browser-verified regressions. These now land
in the replacement UI's own repository, which consumes the read API. In this repository
the order changed (operator decision 2026-10-01): src/specify_cli/dashboard/ and
spec-kitty dashboard are deleted first (#5530), without a deprecation release; the
read API (#5528), reader re-pointing (#5532) and rehoming each former route (#5533)
follow as the replacement read path (ADR D-1, D-8). The localhost daemon invariant lapsed
with the deletion.
3.3 Terminology fidelity in the UI (retiring the Feature drift)
Invariant. The dashboard speaks the Mission canon end to end. The historical
Feature-labelled UI drift — a legacy label that leaked into the dashboard against the
Terminology Canon — is retired, and the UI never re-introduces a Feature label for
a Mission-domain object.
Design of record. Epic #650 carries this as an explicit goal: kill the legacy
Feature-labelled UI drift in favour of the Mission canon. The Terminology Canon (Mission,
never "feature") is the standard the retirement restores; here it is a
reviewer-verified fidelity concern, since the terminology guard does not scan the UI
label surface.
Open work. Complete the #650 label-retirement sweep so no dashboard view renders the
legacy Feature label, and keep it retired as the dashboard delivery lands in the 4.x line.
4. Known gaps
- The #645 two-facet split is unreconciled in the tracker. #645 now hosts both the application-data API facet (this plan, §3.1) and the doctrine-module import surface facet (doctrine-charter §3.6, #3179 reparented under #645). Without a facet split in the epic, a PO cannot tell which slice is the data contract and which is the Python import surface. §1's boundary statement is the reconciling map; the tracker should mirror it.
- The mission-data contract is unenumerated. The §3.1 invariant asserts a versioned
data contract, but no contract or contract test exists yet — the dashboard binds to the
projection directly today. This is the domain's key structural gap, gated behind #645.
The orchestrator-api reads use the wall-clock reducer,
reduce(). The dashboard uses the Lamport reducer,materialize_snapshot(). So two read surfaces can disagree today. - Dashboard delivery is deferred, its invariants are not. The experience-shaped delivery is a post-4.0.0 concern (§5), but the invariants (contract-bound consumers, browser-proven UI, Mission-canon labels) are in force now and must not regress as the surface is built.
- Artifact and governance views have no home outside the dashboard. The dashboard also serves mission artifacts (research, contracts, checklists, dossier) and governance views (charter, lint, glossary). They are not mission status. The dashboard is now deleted first (#5530), so these views have no read surface until each is rehomed in its own context (#5533; #954, #955 and a follow-up), as the ADR's route table lists.
5. Release-scoped view (the "what ships when")
This plan tracks the why (the API/dashboard invariants and sub-areas); the epics track
the what-ships-when. The table below is a snapshot for orientation, not a schedule.
Verify live state via gh issue view <n> --repo spec-kitty/spec-kitty before acting.
| Work | Sub-area (§3) | Owning epic | Milestone (epic, checked 2026-09-30) |
|---|---|---|---|
| Enumerate + version the mission-data API contract | Data API contract (3.1) | #645 (application-data facet) | 4.x Work |
| Mission Status Read API (overview + detail) and folding the existing readers into it | Data API contract (3.1) | #645 (#956, #957, #2789) | 4.x Work |
| Remove the CLI-bundled dashboard (deleted first; read API, re-pointing and rehoming follow) | Dashboard/UX (3.2) | #645 / #650 (#5530; then #5528, #5532, #5533) | 4.x Work |
| Dashboard WP-lane board + mission/WP views | Dashboard/UX (3.2) | #650 | Product backlog |
Retire the legacy Feature-labelled UI drift |
Terminology fidelity (3.3) | #650 | Product backlog |
Read the WHY in §3; the epic tracks the WHAT-ships-when. The Feature-label row is the
drift being killed — not a live UI label.
6. Cross-references
Sibling domain throughlines (the durable spine of docs/plans/):
- Doctrine & charter — Doctrine & Charter Domain Plan.
Its §3.6 (Stable public API surface for doctrine & charter) is the non-goal
boundary for this plan (§1): §3.6 owns the doctrine/charter Python import / single-
entry-point surface (#3179), a different API from this plan's application/mission-
data surface — even though #3179 now shares the #645 epic home as a separate facet.
(At this plan's commit the doctrine-charter plan still lives at
docs/plans/doctrine-charter-domain-plan.md; the domains/ migration WP moves it and repoints these links.) - Packs extraction — Packs Extraction Domain Plan.
- SaaS & hosted sync — domain plan retired 2026-09-06 (Convergence #3881). The former
in-process sync projection no longer exists: hosted/team rendering is server-side in the
authoritative upstream repos, and this repo's dashboard data surface is consumed locally,
with hosted status delivered via
zeitgeist_client(ephemeral by design). See the convergence-retirement ADR.
Design of record:
- Status model architecture — the
status.events.jsonlevent log andreduce()projection the mission-data API exposes. - ADR 2026-10-01-2 — the Mission Status Read API and the removal of the CLI-bundled dashboard (Accepted 2026-10-12: the open-core producer surface; the service is to start in-repo and be extracted when frozen).
- 4.0.0 Milestone Roadmap — the active cycle; Theme 3 makes the mission-status API backend GA-gating (2026-10-12 re-anchor).
- 3.2.x milestone roadmap — superseded, prior cycle. Recorded the original deferral of experience-shaped (UX/dashboard) work to the retired 3.3.x milestone.
Epics: #645 (Stable Application API Surface — application-data facet here; the #3179
doctrine-import facet is doctrine-charter §3.6), #650 (dashboard/UX + Feature-drift
retirement).
Plans index: docs/plans/index.md.