feat(central-ui): Flow Debugger page (predict, live run, replay, step detail) + nav entry

/deployment/flow-debugger (RequireDeployment): entry toggle (inbound method | value-change
trigger), method picker or Site → Instance → Attribute pickers (site-scope filtered), Live |
Replay mode, inputs form generated from the method's ParameterDefinitions via
InboundApiSchema (values coerced by declared type into the request JsonElement), status
strip (state chip, run #, start, total, steps/boundaries/writes, root ExecutionId link to
the Execution Chain page), the FlowGraphView with −/Fit/+ zoom, and FlowStepDetail (tabs
Input · Output · Writes · Timing, 'Where this ran' column, Open in Debug View when the
instance is known, Audit rows (n) → /audit/log?executionId=). State machine Idle →
Predicted → Running → Completed | Failed | TimedOut; STANDBY_NODE renders as an inline
warning alert with the server message verbatim; ?methodId= / ?instanceId=&attribute= /
?executionId= drill-ins (the last replays on first render); last entry + inputs persisted
per method in localStorage; 'site not traced' label when a run's route call came back with
no child execution and no Site-lane steps. NavMenu: Deployment → Flow Debugger.

Claude-Session: https://claude.ai/code/session_01GSLkkHKz9JrAtmJjmQK3cP
This commit is contained in:
Joseph Doherty
2026-09-06 00:31:55 -04:00
parent ba15a38327
commit 254118a467
6 changed files with 1242 additions and 0 deletions
@@ -0,0 +1,71 @@
/* Flow Debugger page — toolbar / status strip / flow / detail (design 2026-09-05 §4). */
.fd-status {
display: flex;
flex-wrap: wrap;
gap: 0.5rem 1.25rem;
align-items: center;
font-size: 0.85rem;
padding: 0.4rem 0.75rem;
border: 1px solid var(--rule);
border-radius: 4px;
background: var(--bs-body-bg, #fff);
}
.fd-status .fd-label {
color: var(--ink-faint);
font-size: 0.65rem;
letter-spacing: 0.06em;
text-transform: uppercase;
margin-right: 0.3rem;
}
.fd-status .fd-mono { font-family: var(--mono); }
.fd-chip {
display: inline-block;
padding: 0.1rem 0.5rem;
border-radius: 999px;
border: 1px solid var(--rule-strong);
font-size: 0.75rem;
font-weight: 600;
}
.fd-chip.idle { color: var(--ink-soft); }
.fd-chip.predicted { color: var(--accent); border-color: var(--accent); border-style: dashed; }
.fd-chip.running { color: var(--accent); border-color: var(--accent); }
.fd-chip.completed { color: var(--ok); border-color: var(--ok); }
.fd-chip.failed { color: var(--bs-danger, #c0392b); border-color: var(--bs-danger, #c0392b); }
.fd-chip.timed-out { color: var(--warn); border-color: var(--warn); }
.fd-flow-tools {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.4rem;
}
.fd-inputs .form-control-sm { font-family: var(--mono); }
::deep .fsd-eyebrow {
color: var(--ink-faint);
font-size: 0.65rem;
letter-spacing: 0.06em;
text-transform: uppercase;
}
::deep .fsd-pane {
border: 1px solid var(--rule);
border-top: none;
padding: 0.6rem 0.75rem;
min-height: 6rem;
}
::deep .fsd-json {
font-family: var(--mono);
font-size: 0.75rem;
margin: 0;
white-space: pre-wrap;
word-break: break-word;
max-height: 18rem;
overflow: auto;
}