…b-pages + UI endpoints)
Completes the §P4 acceptance UI scope that was deferred in commit
0594b1d. Adds the full Vue Dashboard + Ops sub-pages with live SSE
stream + auto-reconnect, unit DAG with detail drawer, PRD/SDD diff
panel, feedback modal, and 4 ops views (Bugs / Loops / Changelog /
Progress).
Vue surface (≈1480 lines):
- web/src/views/DevLoopDashboard.vue (~110 lines)
* 4-region grid: status header / loop bar / units DAG / live stream /
PRD diff. Polls /state every 2.5s; opens feedback modal & unit
drawer; mounts Sign Off / Abandon controls.
- web/src/views/DevLoopOps.vue (~50 lines) — tab container.
- web/src/components/devloop/DashboardHeader.vue
* Status badge (7 states color-coded), NEW REQUIREMENT button,
Sign Off / Abandon buttons (disabled per FSM), Ops nav link.
- web/src/components/devloop/LoopStatusBar.vue
* 4-phase pipeline (Docs → L1 → L2 → Ship), highlights active phase.
- web/src/components/devloop/UnitsDAG.vue
* SVG DAG rendered from topological waves; per-unit status color;
click → emits select → opens UnitDrawer.
- web/src/components/devloop/UnitDrawer.vue
* Slide-in panel showing unit metadata + last 3 runs + result
summary + coder.log tail (last 1KB).
- web/src/components/devloop/LiveAgentStream.vue
* EventSource subscriber listening to project.status,
unit.state, integration.result, triage.result, sdd.updated,
prd.updated, human_intervention_needed, etc. Manual 5s reconnect
on disconnect (browser's built-in Last-Event-ID is honored).
- web/src/components/devloop/PrdDiffPanel.vue
* Reads changelog.ndjson, renders prd_rev / sdd_rev entries with
trigger labels.
- web/src/components/devloop/FeedbackModal.vue
* POSTs /feedback with PM incremental — shows rev bump on success.
- web/src/components/devloop/ops/BuglistView.vue
* Filterable bug table; status badges; severity / category columns.
- web/src/components/devloop/ops/LoopLogView.vue
* Timeline grouped by L1 (unit.*) / L2 (integration/triage/sdd/l2_*) /
L3 (project.status/shipped/prd.updated/human_intervention) /
System (rest). Free-text substring filter.
- web/src/components/devloop/ops/ChangelogView.vue
* Tabular prd_rev/sdd_rev entries with by/trigger/summary columns.
- web/src/components/devloop/ops/ProgressView.vue
* 6 metric cards (status, PRD rev, SDD rev, units passed bar,
L2 rounds bar, open bugs) + per-unit breakdown table.
Router:
- web/src/router/index.js — adds:
* /devloop/:pid → DevLoopDashboard
* /devloop/:pid/ops/:tab(bugs|loops|changelog|progress) → DevLoopOps
Backend UI-supporting endpoints (server/routes/devloop.js):
- GET /api/devloop/projects/:pid/timeline?limit=N
Reads timeline.ndjson, returns last N events reversed.
- GET /api/devloop/projects/:pid/changelog
Returns full changelog.ndjson entries reversed.
- GET /api/devloop/projects/:pid/units/:unitId
Returns { unit, runs (last 3 result.json), coder_log_tail }.
404 on unknown unit.
Tests (+5 cases):
- server/tests/devloop/routes.test.js — new P5 UI endpoints block:
* timeline / changelog / units happy-paths
* 404 on unknown unit and unknown pid
Acceptance:
- scripts/phase5-verify.js — 7 steps:
① Vue build artifacts (DevLoopDashboard.js + DevLoopOps.js chunks)
② POST /projects → state returns status + units
③ GET /timeline returns events
④ GET /changelog returns entries
⑤ GET /units/todo-be returns unit + runs
⑥ GET /bugs returns bug list
⑦ SSE /stream delivers ≥1 event after a triggering feedback POST
Vue build:
- npm run web:build → DevLoopDashboard chunk 15.63 kB,
DevLoopOps chunk 9.09 kB, both with co-loaded CSS bundles.
Results — all 7 phase gates green:
- phase0-verify: 8/8
- phase0-test-call: 7/7
- phase1-verify: 7/7
- phase2-verify: 6/6
- phase3-verify: 9/9
- phase4-verify: 9/9
- phase5-verify: 7/7
- vitest devloop+acp-core: 218/218 (was 213 → +5)
Specs: docs/prd/newfunction/_spec/plan-migration.md · P4 L3 + UI
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>