feat(web): replay mode + runs drawer (NF-UI-7) #365
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!365
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/337-nfui7-replay-runs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
apps/web/src/features/flows/RunsDrawer.tsx) — bottom-docked collapsible panel mounted on the/flowsparent layout, streams recent flow runs from the mockflowsApi.listRunssurface. Columns: flow id, trigger, status badge (running / ok / error / cancelled), started-at (relative), duration. Four filters: trigger dropdown, flow-id substring, status dropdown, repo substring. Collapsed state persists tolocalStorage("flow.runs-drawer.open"), default expanded.FlowCanvas.tsx— when the URL carries?run=<runId>, the canvas loads the run viaflowsApi.getRun, fetches the flow body pinned torun.flow_versionviagetFlow(flowId, version), and paints per-node status outlines (ok green, skipped dashed/dim, error red + ⚠, timeout amber, running pulsing accent). A blue banner identifies the replayed run + version; a floating "Exit replay" pill strips the query param. Save is disabled and Ctrl+S / palette-Q are suppressed while replaying.getFlow()accepts an optionalversionarg. The mock can only produce the current body, so the response carries aversionMatchflag that flips tofalsewhenever the pinned version differs from the current version; the banner then surfaces a "body may differ" warning. Real version-pinning lands with NF-7'sGET /flows/:id/versions/:version.Inspector.tsx) — accepts an optionalrunNodeprop; the tab is only enabled when the parent canvas is in replay mode and the current selection resolves to a recordedflow_node_runsrow. Surfacesstatus,duration_ms, and JSON-formattedinput/output/error/intent.apps/web/src/fixtures/flow-runs.json) — 8 sample runs across 3 flows + 5 statuses (ok / error / cancelled / running / with-timeout), plus matching per-node trace rows. Shape mirrorsapps/server/src/infrastructure/database/db.ts::FlowRunRow+FlowNodeRunRow.Test plan
bun x turbo run typecheck— cleanbun x biome check apps/web/src— cleanRunsDrawer.test.tsx— 10 tests (rows render, all 3 filters narrow, click navigates with{run}search, collapse/expand toggle)FlowCanvas.replay.test.tsx— 9 tests (banner + version, no banner withoutrunId, body-may-differ warning, save disabled, Ctrl+S suppressed, status overlay in node data, error-node overlay, Inspector Run tab enabled + JSON surfaced, exit-pill navigates)Inspector.test.tsx(13) +FlowCanvasEditing.test.tsx(18) +FlowCanvas.test.tsx(8) +InputRefPicker.test.tsx(30) +flows.test.tsxroute (8) all pass — 125 flows tests total/flows/:flowId?run=:id, replay banner reads right, Save is disabled, Exit-replay pill clears the query paramOut of scope
flow_run_*SSE wiring.GET /flows/runs+GET /flows/runs/:idand the fixture mirrors those response shapes.Closes #337
🤖 Generated with Claude Code
48eee9de0120031dd80c20031dd80cf3d4dfe446