feat(wire): attribute updates carry source_execution_id/trace; PullTraceEvents RPC + site read-by-execution-ids

Flow Debugger (design 2026-09-05 §5.3/§5.4): AttributeValueUpdate fields 7/8 stamped by
StreamRelayActor and parsed by SiteStreamGrpcClient (older frames => null/false). New
PullTraceEvents unary RPC on SiteStreamService (same PSK-gated prefix as PullAuditEvents):
a point read of the site audit SQLite by ExecutionId OR ParentExecutionId
(ISiteAuditQueue.ReadByExecutionIdsAsync, json_extract on the codec's camelCase keys, new
IX_audit_event_occurred index, 64-id / 2000-row caps) that moves no cursor and flips no
ForwardState. Central IPullTraceEventsClient/GrpcPullTraceEventsClient mirror the audit pull
client (endpoint resolution, NodeB failover, fault => empty) and register beside it.

Claude-Session: https://claude.ai/code/session_01GSLkkHKz9JrAtmJjmQK3cP
This commit is contained in:
Joseph Doherty
2026-09-05 23:52:50 -04:00
parent f15d0db0ad
commit 7e61552d82
15 changed files with 1458 additions and 80 deletions
@@ -557,7 +557,11 @@ public class SiteStreamGrpcClient : IAsyncDisposable, IDisposable
evt.AttributeChanged.AttributeName,
evt.AttributeChanged.Value,
MapQuality(evt.AttributeChanged.Quality),
evt.AttributeChanged.Timestamp.ToDateTimeOffset()),
evt.AttributeChanged.Timestamp.ToDateTimeOffset(),
// Flow Debugger (design §5.4): fields 7/8 — an older site leaves them at the
// proto3 defaults, which map to null / false.
SourceExecutionId: Guid.TryParse(evt.AttributeChanged.SourceExecutionId, out var traceSource) ? traceSource : null,
Trace: evt.AttributeChanged.Trace),
SiteStreamEvent.EventOneofCase.AlarmChanged => new AlarmStateChanged(
evt.AlarmChanged.InstanceUniqueName,
evt.AlarmChanged.AlarmName,