Skip to content

2026-05-10 — Phase-aware governance UI (TASKSET 3)

status: published
mr: MR-7, MR-10

The petrova.host dashboard previously showed governance signals (CI, needs-human, audit) but had no way to visualise the phase progression of each consumer repo across the fleet. The only phase surface was the flat “Recent transitions” table on the repo detail page, which lacked structure and required manual interpretation.

TASKSET 3 closes this gap as the third step in the governance-completeness plan (after TASKSET 1: derived needs-human/ci-status signals and TASKSET 2: full MR audit coverage).

Ship a petrova.phases.list MCP tool backed by a new PhasesSource that aggregates two existing data stores:

  1. state/<slug>.yamlcurrent_phase + gate_open (real-time sweeper output)
  2. state/transitions/<slug>.jsonl — historical phase events (written newest-first by petrova sweep-state)

The tool returns a PhasesFleet shape: per-repo PhaseEntry[] each containing a sorted PhaseRecord[], plus the union of all phase numbers seen across the fleet.

The dashboard surfaces this via two new/extended views:

  • /console/phases — fleet × phase grid. Rows = repos, columns = all phase numbers seen fleet-wide. Each cell shows ✓ (closed, links to decision doc), ◆ (open), or · (not started). A “current” column and a gate indicator sit beside the slug.
  • /console/repo/[slug] — “Phase timeline” block replaces the flat transitions table. Phases shown newest-first (highest number first) with status badge, closed/opened date, and a clickable decision-doc link when the URL can be constructed from {repo_url}/blob/main/docs/decisions/{at}-{note}.md.

“phases” is added as a nav entry in Shell.astro between “acts” and “governance”.

  • Re-using transitions.recent directly in the dashboard — discarded because the raw JSONL order is newest-first and non-sequential (kahn-hq has Phase-11 before Phase-8), making it unsuitable for a grid without server-side aggregation.
  • Adding a phases field to state YAML via the sweeper — would add sweep latency and require a schema bump and a sweeper code path. The source data already exists in the transitions JSONL; aggregating at query time is cheaper and keeps the sweeper focused on ephemeral signals.
  • positive: operators can see at a glance which repos are lagging behind on phase closure; decision doc links are one click away from the grid.
  • positive: the petrova.phases.list tool is available to MCP consumers (e.g. Claude Code) for phase-aware automation.
  • neutral: PhasesSource is not cached; fleet-wide queries scan all transition files on each request. Acceptable for the current fleet size (<10 repos); a cache layer can be added in a later taskset if needed.
  • constraint: decision-doc URLs are constructed heuristically from {at}-{note}.md; if a doc was committed under a different filename the link will 404. This is the same pattern used by the existing transitions tool.
  • TASKSET 1 decision: 2026-05-10-derived-needs-human-and-ci-status.md
  • TASKSET 2 decision: 2026-05-10-governance-audit-completeness.md
  • host/src/sources/phases.ts (new)
  • host/src/tools/phases.ts (new)
  • dashboard/src/pages/console/phases.astro (new)