docs: Flow Debugger — component specs, CLAUDE.md, CLI README, register row 110

Component-CentralUI (new Flow Debugger page section), Component-InboundAPI (TraceAllCalls
property, always-on RouteCall row + Trace flag under Routing Behavior, new 'Flow Debugger
runs' section), Component-SiteRuntime (Instance Actor trace arm; Script Actor traced runs;
CallScript flag inheritance), Component-AuditLog (ScriptTrace channel in Scope, the
PullTraceEvents point-read note + mixed-version caveat under Reconciliation, per-channel
retention example), Component-Communication (§4 trace flag + inline events with proto field
numbers; §8 PullTraceEvents; RPC list), Component-ScriptAnalysis (REQ-SA-7 FlowShapePredictor),
CLAUDE.md UI bullet, deferred-work register row 110 (vertical-trace list toggle + console
capture), design doc status → implemented. CLI README sections landed in Tasks 3/16.
Umbrella index (../scadaproj/CLAUDE.md) checked: its ScadaBridge row records stack/wire
relationships only, unchanged by a new page — no edit.

Claude-Session: https://claude.ai/code/session_01GSLkkHKz9JrAtmJjmQK3cP
This commit is contained in:
Joseph Doherty
2026-09-06 00:38:41 -04:00
parent 66d5a67e4f
commit 0a9ef87b54
9 changed files with 60 additions and 3 deletions
+19 -2
View File
@@ -55,6 +55,10 @@ boundary:
| `Database.CachedWrite(...)` | Script | Outbound | Yes — `SiteCalls` (Site Call Audit) |
| `Notify.To(list).Send(...)` | Script | Outbound | Yes — `Notifications` (Notification Outbox) |
| `POST /api/{method}` (Inbound API) | External | Inbound (invokes a script) | No (gap) |
| `Route.To(x).Call(y)` (Inbound API → site) | Script | Central → site | Yes — `ScriptTrace.RouteCall`, **always-on** (2026-09-05) |
| Site script run / attribute write / attribute wait under a **traced** run | Script | Site-local | Yes — `ScriptTrace.ScriptRun` / `AttributeWrite` / `AttributeWait`, **gated** by the `Trace` flag (Flow Debugger Live runs, `ApiMethod.TraceAllCalls`) |
**`AuditChannel.ScriptTrace` (Flow Debugger, design `docs/plans/2026-09-05-flow-debugger-design.md` §5.1).** Trace steps ARE audit events — no parallel store. One kind is always-on (`RouteCall`, a central direct write per `Route.To().Call`, carrying the child run's id in `Extra.childExecutionId`); the three site kinds are emitted only when the run's `Trace` flag is set, ride the ordinary site `IAuditWriter` → SQLite → telemetry → central path, share the run's `ExecutionId` / `ParentExecutionId`, and are additionally returned inline on the routed reply so a Live run does not wait on the 5 s telemetry cadence. The Flow Debugger's graph (`FlowStep` / `FlowGraphBuilder`, Commons) is a central-side projection of these rows.
Out of scope — framework traffic is not audited:
@@ -348,6 +352,17 @@ non-draining (e.g., telemetry actor wedged), central issues a
`PullAuditEvents(sinceUtc, batchSize[, afterId])` and inserts-if-not-exists.
Same self-healing pattern as Site Call Audit's reconciliation of `SiteCalls`.
**`PullTraceEvents` is a point read, not a reconciliation path (2026-09-05).** The
Flow Debugger's value-change run cannot get its steps inline (the device echo
triggers the run after the write reply has returned), so central polls the site
with `PullTraceEvents(execution_ids[], since_utc, max_events)` — `ISiteAuditQueue.
ReadByExecutionIdsAsync`, capped at 64 ids / 2000 events, served whatever the row's
`ForwardState` — until the spawned `ScriptRun` settles. It moves no cursor and
retires nothing; the telemetry push and the reconciliation pull are unchanged.
**Mixed-version caveat:** a pre-2026-09-05 site ignores the `Trace` flag and has no
`PullTraceEvents`, so a run against it shows the central `RouteCall` row with no
child id and an empty Site lane — the page labels this *site not traced*.
**The pull is at-least-once (WP2.3).** Serving a row is not proof that central
received it, so rows are **not** flipped when they are served. The site flips
`ForwardState = 'Reconciled'` for everything at or before the cursor carried by
@@ -612,8 +627,10 @@ MS SQL for direct-write events). Unredacted secrets never persist.
index did not exist at all. See migration `AlignAuditLogEventIdUniqueness`.
- **Per-channel retention overrides (M5.5 T3):** `AuditLog:PerChannelRetentionDays`
is a dictionary keyed by canonical channel name (`ApiOutbound`, `DbOutbound`,
`Notification`, `ApiInbound`, `SecuredWrite` — all five `AuditChannel` values are
accepted by the validator) whose value is a retention window in days that
`Notification`, `ApiInbound`, `SecuredWrite`, `Cluster`, `ScriptTrace` — every
`AuditChannel` value is accepted by the validator; the docker rig's central nodes
set `"ScriptTrace": 30`, the validator floor, because traced runs are a debugging
aid, not a compliance record) whose value is a retention window in days that
MUST be strictly shorter than the global `RetentionDays`. After the daily
partition switch-out, the purge actor runs a bounded, batched row DELETE
(`PurgeChannelOlderThanAsync`) for each channel whose override is shorter than