# Milestone C: DAG dashboard surfacing plan Related tasks: **FN-4487**, **FN-4471**, **FN-4490**, **FN-4491**, **FN-4492**. ## Constraints & Governance > "Do not file, plan, or implement tasks that adjust button mobile-responsiveness, touch-target sizing, or mobile reflow of header/action button rows anywhere in the dashboard (TaskCard, SettingsModal, ChatView, MissionManager, AgentsView, FAB, etc.). **Keep buttons as they are.**" > "Reliability mechanism changes are currently under freeze pending FN-4359 governance hardening; treat new reliability-layer behavior changes as blocked unless explicitly approved in task scope." This document is planning-only. No runtime behavior, scheduler/executor/merger code, dashboard routes, API endpoints, or schema changes are made here. ## UX Progression (debug → operator) ### Stage 1 — Debug surface **Audience:** Fusion developers debugging prototype orchestration. **Ship:** Read-only structured-log view for `[dag-coordinator]` events, filterable by `runId`, mirroring `AgentLogViewer` / `ActivityFeed` interaction patterns. **Operator questions answered:** - Did this DAG run start and finish/abort? - Which node was enqueued/completed/failed most recently? - What failure reason code was emitted for the failing node/run? **Events consumed from FN-4490 contract:** - `dag:run:start` - `dag:node:enqueue` - `dag:node:complete` - `dag:node:fail` - `dag:run:complete` - `dag:run:abort` ### Stage 2 — Run inspector **Audience:** Power users monitoring multi-task DAG runs. **Ship:** Per-run detail inspector with node table, dependency/blocked context, and task deep-links into `TaskDetailModal`; read-only. **Operator questions answered:** - Which DAG node failed and why? - Which nodes are complete vs still pending/in-progress? - Which Fusion task corresponds to each node and where do I inspect logs/details? **Events consumed from FN-4490 contract:** - `dag:run:start` - `dag:node:enqueue` - `dag:node:complete` - `dag:node:fail` - `dag:run:complete` - `dag:run:abort` ### Stage 3 — Operator surface **Audience:** End-users orchestrating DAG runs. **Ship:** Top-level run list, per-run graph visualization (nodes + edges), run-state summary, and pause/resume/cancel controls. **Operator questions answered:** - Is this run still making progress or stalled? - Which branch/path of the graph failed and what is downstream impact? - Can I safely pause/resume/cancel without violating task ownership or merge safety? **Events consumed from FN-4490 contract:** - `dag:run:start` - `dag:node:enqueue` - `dag:node:complete` - `dag:node:fail` - `dag:run:complete` - `dag:run:abort` #### Events to add in FN-4490 follow-up Stage 3 controls need explicit pause/resume observability. FN-4490 currently defines only `dag:run:abort` (not pause/resume), so add: - `dag:run:pause` - `dag:run:resume` These are follow-up requirements and are not introduced as implemented behavior in this task. ## Views & Controls | Surface name | Stage | Mount point | Data source (proposed) | Reused components/classes | New tokens required | Lazy-load decision | Mobile reflow plan | |---|---:|---|---|---|---|---|---| | `DagRunDebugFeed` | 1 | `DagRunDetailModal` in `packages/dashboard/app/components/AppModals.tsx` | `GET /api/dag/runs/:id/events` backed by `DagCoordinator` run-event stream | `AgentLogViewer`, `ActivityFeed`, `.card`, `.input` | none | Modal code-split with existing `AppModals.tsx` lazy modal pattern; no eager heavy bundle | Only non-button layout wrapping at `@media (max-width: 768px)`; control buttons unchanged per Buttons Frozen | | `DagRunDetailModal` | 2 | New modal wired in `AppModals.tsx` | `GET /api/dag/runs/:id` + `GET /api/dag/runs/:id/nodes` from `DagCoordinator` read model | `.modal`, `.modal-lg`, `.card`, `.card-status-badge--{status}`, `.input`, `TaskDetailModal` deep-link behavior | none | Lazy modal import via `React.lazy()` + `` | Non-button table/graph stacking only; no `.btn` size/reflow edits | | `DagNodeDetailPanel` | 2 | Child panel inside `DagRunDetailModal` | `GET /api/dag/runs/:id/nodes/:nodeId` from `DagCoordinator` | `.card`, `.card-meta`, `.card-status-badge--{status}`, `linkifyFilePaths`, `FileBrowserContext` | none | Bundled with `DagRunDetailModal` chunk (no separate eager load) | Non-button typography/spacing adjustments only in component CSS mobile block | | `DagRunsView` | 3 | New top-level view in `packages/dashboard/app/App.tsx` nav/view registry | `GET /api/dag/runs` from `DagCoordinator` run list read model | `.card`, `.card-header`, `.card-id`, `.card-status-badge--{status}`, `.input`, `.btn`, `.btn-sm`, `.btn-warning`, `.btn-danger` | none | Required heavy-view lazy load: `React.lazy()` + `prefetchLazyViews()` warm-up registration | Card/grid/list non-button layout reflow only; action-button row unchanged per Buttons Frozen | | `DagRunGraphPanel` | 3 | Section within `DagRunDetailModal` (opened from `DagRunsView`) | `GET /api/dag/runs/:id/graph` from `DagCoordinator` graph projection | `.card`, status tokens (`--triage`, `--todo`, `--in-progress`, `--in-review`, `--done`), `ConfirmDialog` for destructive control confirmation handoff | `--dag-graph-edge` (semantic), `--dag-graph-node-shadow` (semantic), `--dag-graph-active-ring` (semantic) | Included in Stage 3 lazy chunks (`DagRunsView`/`DagRunDetailModal`) and prefetched with other heavy views | Graph canvas/layout may reflow on mobile; button classes remain existing `.btn` chain with no touch-target inflation | Notes: - Stage mapping is complete across all Stage 1–3 surfaces. - All status visuals reuse existing semantic status tokens and `--status-*-bg` conventions. - No row introduces hardcoded px/hex/rgba contracts; implementation must remain token-driven. - No row proposes button restyling, `.btn` min-height overrides, or mobile button-row reflow. ## Run Control Contract ### Pause Pause means: stop enqueuing new DAG nodes for the run while allowing currently in-flight Fusion tasks to finish through their existing executor lease + merge path. Pause does **not** cancel running tasks mid-flight and does not mutate checkout ownership. This preserves `AGENTS.md` checkout-leasing conflict semantics (409 ownership contention) and avoids violating merger file-scope protections (file-scope invariant remains authoritative). ### Resume Resume means: re-enable node enqueueing for a paused run. Any node whose dependencies are now satisfied becomes eligible through the existing scheduler path defined by the FN-4490 ADR (`DagCoordinator` as upstream readiness producer into normal queueing/dispatch), with no direct scheduler-internal bypass. ### Cancel Cancel means: stop future enqueueing, mark run aborted, and finalize run state with `dag:run:abort`. In-flight tasks may finish/fail naturally, but their outcomes do not trigger downstream nodes after cancellation. Cancel explicitly does **not**: - issue task moves (including `moveTask(in-progress → todo)`), - cancel executor sessions mid-flight, - bypass merger/workflow gates, - alter user-initiated cancel contracts in `AGENTS.md` Engine Process Rules. ### UI affordance contract - Controls are single buttons using existing classes only: `.btn`, `.btn-sm`, `.btn-warning`, `.btn-danger`. - Cancel is destructive and must be confirmation-gated via `ConfirmDialog`. - No new button styling, no button mobile reflow, and no touch-target inflation for these controls (Buttons Frozen directive applies). ### Proposed API surface (planning only) - `POST /api/dag/runs/:id/pause` - `POST /api/dag/runs/:id/resume` - `POST /api/dag/runs/:id/cancel` Success response shape (proposed): `{ ok: true, runId, state }`. Illegal state transition: `409` (mirrors existing 409 conflict semantics). Schema details, persistence model, and endpoint implementation are out-of-scope for FN-4492 and should be handled in FN-4491 / downstream Milestone C implementation. ### Observability + run-audit tie-in - Control actions must emit DAG lifecycle events and run-audit mutations. - `dag:run:abort` already exists in FN-4490 contract. - `dag:run:pause` and `dag:run:resume` are required follow-up additions to FN-4490 vocabulary before implementation. - Run-audit should record state transitions in database-domain audit entries per existing run-audit model. ### Explicit out-of-scope control behaviors - No force-kill of running tasks - No rollback of already-merged commits - No automatic retry/replay of cancelled runs - No cross-mesh fan-out cancellation ## Compliance Contract (binding for Milestone C implementation) 1. **Design tokens only** - Follow `AGENTS.md` Adding New CSS rules: no hardcoded px (except `0`), no raw hex, no raw `rgba(...)`. - Use dashboard tokens (`--space-*`, `--radius-*`, `--color-*`, status tokens) and `color-mix(in srgb, var(--color) X%, transparent)` for translucency. 2. **Per-component CSS files only** - New styles must live in `packages/dashboard/app/components/.css`. - Import at top of `.tsx`. - Do not add component-specific styles to `packages/dashboard/app/styles.css`; only global token definitions belong there. 3. **CSS tests must use fixture helpers** - Future CSS regression tests must use `packages/dashboard/app/test/cssFixture.ts` (`loadAllAppCss`, `loadAllAppCssBaseOnly`). - Direct `readFileSync('../styles.css')` assertions are disallowed by lint policy. 4. **Lazy-load contract for heavy DAG surfaces** - Stage 2/3 surfaces are heavy and must use `React.lazy()` + `` patterns in `App.tsx` and/or `AppModals.tsx`. - Add Stage 3 top-level DAG view imports to `prefetchLazyViews()` warm-up list. 5. **Theme contract** - Reuse existing status tokens: `--triage`, `--todo`, `--in-progress`, `--in-review`, `--done`, plus `--status-*-bg` variants. - Proposed new tokens in this plan are all **semantic tokens** (`--dag-graph-edge`, `--dag-graph-node-shadow`, `--dag-graph-active-ring`) and therefore require dark/light definitions only. - If implementation later needs **base tokens**, those must be added to dark/light plus all 54 theme blocks. 6. **Buttons Frozen (verbatim directive + protected files)** - "Do not file, plan, or implement tasks that adjust button mobile-responsiveness, touch-target sizing, or mobile reflow of header/action button rows anywhere in the dashboard (TaskCard, SettingsModal, ChatView, MissionManager, AgentsView, FAB, etc.). **Keep buttons as they are.**" - Implementers must not open `SettingsModal.css`, `TaskCard.css`, `ChatView.css`, or similar mobile media blocks to alter `.btn`, `.modal-close`, `.settings-header-actions`, `.card-*` button rules. - Pause/resume/cancel controls must use existing `.btn` chains with no size/touch-target changes. 7. **Mobile responsive scope** - Non-button reflow only, using `@media (max-width: 768px)` blocks placed at bottom of the component CSS file. - Touch-target convention for non-button interactive surfaces applies (e.g., graph-node tap surfaces may be primary controls; secondary chip controls remain compact). 8. **No reliability-layer behavior changes** - Milestone C implementation must not modify scheduler, executor, self-healing, restart-recovery, or merger behavior while FN-4359 freeze remains active. ## Cross-links and follow-up execution - FN-4487 mission proposal: task **FN-4487** (proposal lineage for Milestones A/B/C). - FN-4471 scoping recommendation: task **FN-4471** (upstream framing and constraints). - FN-4490 architecture inputs consumed by this plan: - `docs/dag/requirements-matrix.md` - `docs/dag/adr-0001-dag-orchestration.md` - `docs/dag/failure-observability-contract.md` - FN-4491 scaffold dependency for downstream implementation: task **FN-4491**. Follow-up tasks created from this planning pass: - **FN-4503** (depends on FN-4491, FN-4492): Milestone C implementation task for DAG dashboard surfacing. - **FN-4504** (depends on FN-4490, FN-4492): add `dag:run:pause` + `dag:run:resume` event vocabulary and run-audit mapping guidance.