12 KiB
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:startdag:node:enqueuedag:node:completedag:node:faildag:run:completedag: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:startdag:node:enqueuedag:node:completedag:node:faildag:run:completedag: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:startdag:node:enqueuedag:node:completedag:node:faildag:run:completedag: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:pausedag: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() + <Suspense fallback={null}> |
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-*-bgconventions. - No row introduces hardcoded px/hex/rgba contracts; implementation must remain token-driven.
- No row proposes button restyling,
.btnmin-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.mdEngine 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/pausePOST /api/dag/runs/:id/resumePOST /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:abortalready exists in FN-4490 contract.dag:run:pauseanddag:run:resumeare 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)
-
Design tokens only
- Follow
AGENTS.mdAdding New CSS rules: no hardcoded px (except0), no raw hex, no rawrgba(...). - Use dashboard tokens (
--space-*,--radius-*,--color-*, status tokens) andcolor-mix(in srgb, var(--color) X%, transparent)for translucency.
- Follow
-
Per-component CSS files only
- New styles must live in
packages/dashboard/app/components/<Component>.css. - Import at top of
<Component>.tsx. - Do not add component-specific styles to
packages/dashboard/app/styles.css; only global token definitions belong there.
- New styles must live in
-
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.
- Future CSS regression tests must use
-
Lazy-load contract for heavy DAG surfaces
- Stage 2/3 surfaces are heavy and must use
React.lazy()+<Suspense fallback={null}>patterns inApp.tsxand/orAppModals.tsx. - Add Stage 3 top-level DAG view imports to
prefetchLazyViews()warm-up list.
- Stage 2/3 surfaces are heavy and must use
-
Theme contract
- Reuse existing status tokens:
--triage,--todo,--in-progress,--in-review,--done, plus--status-*-bgvariants. - 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.
- Reuse existing status tokens:
-
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
.btnchains with no size/touch-target changes.
-
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).
- Non-button reflow only, using
-
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.mddocs/dag/adr-0001-dag-orchestration.mddocs/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:resumeevent vocabulary and run-audit mapping guidance.