diff --git a/docs/plans/2026-09-05-flow-debugger-design.md b/docs/plans/2026-09-05-flow-debugger-design.md
index a1c1ab35..1ab66902 100644
--- a/docs/plans/2026-09-05-flow-debugger-design.md
+++ b/docs/plans/2026-09-05-flow-debugger-design.md
@@ -170,7 +170,11 @@ attaches the list to the `ScriptCallResult` → `RouteToCallResponse` when `Trac
collector applies `IAuditRedactor` inside `Add`, so the inline record is the same filtered event
the writer persists, and it caps at `MaxTraceEventsPerRun` (500) **or** 1 MB of summed
`DetailsJson` (`DefaultMaxBytes`), whichever comes first; beyond either bound it keeps the earlier
-events, sets `Truncated`, and the audit rows remain complete (arch-review F1). A site on an older build ignores
+events, sets `Truncated`, and the audit rows remain complete (arch-review F1). The site collector's
+`Truncated`/`LogsTruncated` ride back on `ScriptCallResult` → `RouteToCallResponse`
+(`RouteToCallResponseDto` fields 8/9, Gitea #54) and `FlowDebugRunner` ORs them into
+`FlowDebugRunResult` on both the script entry and (through `RouteHelper.WithTraceSink`'s truncation
+sink) the method entry, so a short site lane is labelled truncated. A site on an older build ignores
`Trace`, returns no `TraceEvents`, and the UI labels its lane `site not traced (older build)`.
`FlowStep` is a **central-side projection** (`Commons/Types/Debugging/FlowStepProjector`)
computed from `AuditEvent` + `AuditDetails`; nothing serializes it.
diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/InboundApi/RouteToInstanceRequest.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/InboundApi/RouteToInstanceRequest.cs
index bea0483b..359fc4d6 100644
--- a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/InboundApi/RouteToInstanceRequest.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/InboundApi/RouteToInstanceRequest.cs
@@ -29,6 +29,8 @@ public record RouteToCallRequest(
///
/// Flow Debugger — the routed site run's ExecutionId (design 2026-09-05 §5.4); null from a site that predates the field.
/// Flow Debugger — the site's ScriptTrace audit events for a traced run, in emission order (design 2026-09-05 §5.4); null when untraced or from an older site.
+/// Flow Debugger (Gitea #54) — the site's inline collector dropped step rows, so is short. False when untraced or from an older site.
+/// Flow Debugger (Gitea #54) — the site's inline collector dropped log-line rows. False when untraced or from an older site.
public record RouteToCallResponse(
string CorrelationId,
bool Success,
@@ -36,7 +38,9 @@ public record RouteToCallResponse(
string? ErrorMessage,
DateTimeOffset Timestamp,
Guid? ChildExecutionId = null,
- IReadOnlyList? TraceEvents = null);
+ IReadOnlyList? TraceEvents = null,
+ bool Truncated = false,
+ bool LogsTruncated = false);
///
/// Request to read attribute(s) from a remote instance.
diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/ScriptExecution/ScriptCallResult.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/ScriptExecution/ScriptCallResult.cs
index d506c357..d5ca4092 100644
--- a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/ScriptExecution/ScriptCallResult.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/ScriptExecution/ScriptCallResult.cs
@@ -4,10 +4,14 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Messages.ScriptExecution;
/// Flow Debugger — the run's own ExecutionId (design 2026-09-05 §5.4). Additive; null from callers that predate the field.
/// Flow Debugger — the run's ScriptTrace audit events in emission order when traced (design 2026-09-05 §5.4); null otherwise.
+/// Flow Debugger (Gitea #54) — the site's inline trace collector dropped a step row (event cap or byte budget), so is short. The audit rows are complete; Replay shows everything. Additive; false when untraced.
+/// Flow Debugger (Gitea #54) — the site's collector dropped low-priority log-line rows to keep room for the step rows. Additive; false when untraced.
public record ScriptCallResult(
string CorrelationId,
bool Success,
object? ReturnValue,
string? ErrorMessage,
Guid? ExecutionId = null,
- IReadOnlyList? TraceEvents = null);
+ IReadOnlyList? TraceEvents = null,
+ bool Truncated = false,
+ bool LogsTruncated = false);
diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs
index cc832a25..ca03f534 100644
--- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs
@@ -2649,7 +2649,10 @@ public static class SiteCommandDtoMapper
ErrorMessage = OrEmpty(response.ErrorMessage),
Timestamp = Ts(response.Timestamp),
// Flow Debugger (design 2026-09-05 §5.4): additive fields 6/7.
- ChildExecutionId = GuidToWire(response.ChildExecutionId)
+ ChildExecutionId = GuidToWire(response.ChildExecutionId),
+ // Gitea #54: additive fields 8/9 — the site collector's truncation flags.
+ Truncated = response.Truncated,
+ LogsTruncated = response.LogsTruncated
};
if (response.TraceEvents is { Count: > 0 } traceEvents)
{
@@ -2677,7 +2680,9 @@ public static class SiteCommandDtoMapper
GuidFromWire(dto.ChildExecutionId),
// An untraced run — or an older site that never sets the field — sends no
// events, which maps to null so the UI can label the lane "site not traced".
- dto.TraceEvents.Count == 0 ? null : dto.TraceEvents.Select(AuditEventDtoMapper.FromDto).ToList());
+ dto.TraceEvents.Count == 0 ? null : dto.TraceEvents.Select(AuditEventDtoMapper.FromDto).ToList(),
+ dto.Truncated,
+ dto.LogsTruncated);
}
/// Projects a onto the wire.
diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto b/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto
index 585f0070..8cb3bdcf 100644
--- a/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto
+++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto
@@ -810,6 +810,10 @@ message RouteToCallResponseDto {
// Flow Debugger (design §5.4): the site's ScriptTrace audit events for a traced run,
// in emission order. Empty from an untraced run or an older site (mapper => null).
repeated sitestream.AuditEventDto trace_events = 7;
+ // Flow Debugger (Gitea #54): the site's inline trace collector dropped step rows (truncated)
+ // or log-line rows (logs_truncated). proto3 default false from an untraced run or older site.
+ bool truncated = 8;
+ bool logs_truncated = 9;
}
message RouteToGetAttributesRequestDto {
diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs
index 8c371b69..cc64edeb 100644
--- a/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs
@@ -388,132 +388,133 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
"KAkSEwoLc2NyaXB0X25hbWUYAyABKAkSPQoKcGFyYW1ldGVycxgEIAEoCzIp",
"LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkxvb3NlVmFsdWVNYXASLQoJ",
"dGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIb",
- "ChNwYXJlbnRfZXhlY3V0aW9uX2lkGAYgASgJEg0KBXRyYWNlGAcgASgIIpIC",
+ "ChNwYXJlbnRfZXhlY3V0aW9uX2lkGAYgASgJEg0KBXRyYWNlGAcgASgIIr0C",
"ChZSb3V0ZVRvQ2FsbFJlc3BvbnNlRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEg",
"ASgJEg8KB3N1Y2Nlc3MYAiABKAgSPAoMcmV0dXJuX3ZhbHVlGAMgASgLMiYu",
"c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZRIVCg1lcnJv",
"cl9tZXNzYWdlGAQgASgJEi0KCXRpbWVzdGFtcBgFIAEoCzIaLmdvb2dsZS5w",
"cm90b2J1Zi5UaW1lc3RhbXASGgoSY2hpbGRfZXhlY3V0aW9uX2lkGAYgASgJ",
"Ei8KDHRyYWNlX2V2ZW50cxgHIAMoCzIZLnNpdGVzdHJlYW0uQXVkaXRFdmVu",
- "dER0byK7AQoeUm91dGVUb0dldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvEhYKDmNv",
- "cnJlbGF0aW9uX2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAIg",
- "ASgJEhcKD2F0dHJpYnV0ZV9uYW1lcxgDIAMoCRItCgl0aW1lc3RhbXAYBCAB",
+ "dER0bxIRCgl0cnVuY2F0ZWQYCCABKAgSFgoObG9nc190cnVuY2F0ZWQYCSAB",
+ "KAgiuwEKHlJvdXRlVG9HZXRBdHRyaWJ1dGVzUmVxdWVzdER0bxIWCg5jb3Jy",
+ "ZWxhdGlvbl9pZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgCIAEo",
+ "CRIXCg9hdHRyaWJ1dGVfbmFtZXMYAyADKAkSLQoJdGltZXN0YW1wGAQgASgL",
+ "MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhlY3V0",
+ "aW9uX2lkGAUgASgJIssBCh9Sb3V0ZVRvR2V0QXR0cmlidXRlc1Jlc3BvbnNl",
+ "RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEjkKBnZhbHVlcxgCIAEoCzIp",
+ "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkxvb3NlVmFsdWVNYXASDwoH",
+ "c3VjY2VzcxgDIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAQgASgJEi0KCXRpbWVz",
+ "dGFtcBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAi1AIKHlJv",
+ "dXRlVG9TZXRBdHRyaWJ1dGVzUmVxdWVzdER0bxIWCg5jb3JyZWxhdGlvbl9p",
+ "ZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgCIAEoCRJpChBhdHRy",
+ "aWJ1dGVfdmFsdWVzGAMgAygLMk8uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu",
+ "djEuUm91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvLkF0dHJpYnV0ZVZh",
+ "bHVlc0VudHJ5Ei0KCXRpbWVzdGFtcBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1",
+ "Zi5UaW1lc3RhbXASGwoTcGFyZW50X2V4ZWN1dGlvbl9pZBgFIAEoCRINCgV0",
+ "cmFjZRgGIAEoCBo2ChRBdHRyaWJ1dGVWYWx1ZXNFbnRyeRILCgNrZXkYASAB",
+ "KAkSDQoFdmFsdWUYAiABKAk6AjgBIpABCh9Sb3V0ZVRvU2V0QXR0cmlidXRl",
+ "c1Jlc3BvbnNlRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3N1Y2Nl",
+ "c3MYAiABKAgSFQoNZXJyb3JfbWVzc2FnZRgDIAEoCRItCgl0aW1lc3RhbXAY",
+ "BCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIsMCCiFSb3V0ZVRv",
+ "V2FpdEZvckF0dHJpYnV0ZVJlcXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQY",
+ "ASABKAkSHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYAiABKAkSFgoOYXR0cmli",
+ "dXRlX25hbWUYAyABKAkSOgoUdGFyZ2V0X3ZhbHVlX2VuY29kZWQYBCABKAsy",
+ "HC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUSKgoHdGltZW91dBgFIAEo",
+ "CzIZLmdvb2dsZS5wcm90b2J1Zi5EdXJhdGlvbhItCgl0aW1lc3RhbXAYBiAB",
"KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKE3BhcmVudF9leGVj",
- "dXRpb25faWQYBSABKAkiywEKH1JvdXRlVG9HZXRBdHRyaWJ1dGVzUmVzcG9u",
- "c2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSOQoGdmFsdWVzGAIgASgL",
- "Mikuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZU1hcBIP",
- "CgdzdWNjZXNzGAMgASgIEhUKDWVycm9yX21lc3NhZ2UYBCABKAkSLQoJdGlt",
- "ZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCLUAgoe",
- "Um91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9u",
- "X2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAIgASgJEmkKEGF0",
- "dHJpYnV0ZV92YWx1ZXMYAyADKAsyTy5zY2FkYWJyaWRnZS5zaXRlY29tbWFu",
- "ZC52MS5Sb3V0ZVRvU2V0QXR0cmlidXRlc1JlcXVlc3REdG8uQXR0cmlidXRl",
- "VmFsdWVzRW50cnkSLQoJdGltZXN0YW1wGAQgASgLMhouZ29vZ2xlLnByb3Rv",
- "YnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhlY3V0aW9uX2lkGAUgASgJEg0K",
- "BXRyYWNlGAYgASgIGjYKFEF0dHJpYnV0ZVZhbHVlc0VudHJ5EgsKA2tleRgB",
- "IAEoCRINCgV2YWx1ZRgCIAEoCToCOAEikAEKH1JvdXRlVG9TZXRBdHRyaWJ1",
- "dGVzUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3Vj",
- "Y2VzcxgCIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMgASgJEi0KCXRpbWVzdGFt",
- "cBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiwwIKIVJvdXRl",
- "VG9XYWl0Rm9yQXR0cmlidXRlUmVxdWVzdER0bxIWCg5jb3JyZWxhdGlvbl9p",
- "ZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgCIAEoCRIWCg5hdHRy",
- "aWJ1dGVfbmFtZRgDIAEoCRI6ChR0YXJnZXRfdmFsdWVfZW5jb2RlZBgEIAEo",
- "CzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdWYWx1ZRIqCgd0aW1lb3V0GAUg",
- "ASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEi0KCXRpbWVzdGFtcBgG",
- "IAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGwoTcGFyZW50X2V4",
- "ZWN1dGlvbl9pZBgHIAEoCRIcChRyZXF1aXJlX2dvb2RfcXVhbGl0eRgIIAEo",
- "CCL/AQoiUm91dGVUb1dhaXRGb3JBdHRyaWJ1dGVSZXNwb25zZUR0bxIWCg5j",
- "b3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdtYXRjaGVkGAIgASgIEjUKBXZhbHVl",
- "GAMgASgLMiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1",
- "ZRIPCgdxdWFsaXR5GAQgASgJEhEKCXRpbWVkX291dBgFIAEoCBIPCgdzdWNj",
- "ZXNzGAYgASgIEhUKDWVycm9yX21lc3NhZ2UYByABKAkSLQoJdGltZXN0YW1w",
- "GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKJAwoMUm91dGVS",
- "ZXF1ZXN0EkoKDXJvdXRlX3RvX2NhbGwYASABKAsyMS5zY2FkYWJyaWRnZS5z",
- "aXRlY29tbWFuZC52MS5Sb3V0ZVRvQ2FsbFJlcXVlc3REdG9IABJdChdyb3V0",
- "ZV90b19nZXRfYXR0cmlidXRlcxgCIAEoCzI6LnNjYWRhYnJpZGdlLnNpdGVj",
- "b21tYW5kLnYxLlJvdXRlVG9HZXRBdHRyaWJ1dGVzUmVxdWVzdER0b0gAEl0K",
- "F3JvdXRlX3RvX3NldF9hdHRyaWJ1dGVzGAMgASgLMjouc2NhZGFicmlkZ2Uu",
- "c2l0ZWNvbW1hbmQudjEuUm91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRv",
- "SAASZAobcm91dGVfdG9fd2FpdF9mb3JfYXR0cmlidXRlGAQgASgLMj0uc2Nh",
- "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb1dhaXRGb3JBdHRyaWJ1",
- "dGVSZXF1ZXN0RHRvSABCCQoHY29tbWFuZCKJAwoKUm91dGVSZXBseRJLCg1y",
- "b3V0ZV90b19jYWxsGAEgASgLMjIuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu",
- "djEuUm91dGVUb0NhbGxSZXNwb25zZUR0b0gAEl4KF3JvdXRlX3RvX2dldF9h",
- "dHRyaWJ1dGVzGAIgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu",
- "Um91dGVUb0dldEF0dHJpYnV0ZXNSZXNwb25zZUR0b0gAEl4KF3JvdXRlX3Rv",
- "X3NldF9hdHRyaWJ1dGVzGAMgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h",
- "bmQudjEuUm91dGVUb1NldEF0dHJpYnV0ZXNSZXNwb25zZUR0b0gAEmUKG3Jv",
- "dXRlX3RvX3dhaXRfZm9yX2F0dHJpYnV0ZRgEIAEoCzI+LnNjYWRhYnJpZGdl",
- "LnNpdGVjb21tYW5kLnYxLlJvdXRlVG9XYWl0Rm9yQXR0cmlidXRlUmVzcG9u",
- "c2VEdG9IAEIHCgVyZXBseSJBChZUcmlnZ2VyU2l0ZUZhaWxvdmVyRHRvEhYK",
- "DmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkibQoSU2l0",
- "ZUZhaWxvdmVyQWNrRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhAKCGFj",
- "Y2VwdGVkGAIgASgIEhYKDnRhcmdldF9hZGRyZXNzGAMgASgJEhUKDWVycm9y",
- "X21lc3NhZ2UYBCABKAkqywEKE0RlcGxveW1lbnRTdGF0dXNEdG8SJQohREVQ",
- "TE9ZTUVOVF9TVEFUVVNfRFRPX1VOU1BFQ0lGSUVEEAASIQodREVQTE9ZTUVO",
- "VF9TVEFUVVNfRFRPX1BFTkRJTkcQARIlCiFERVBMT1lNRU5UX1NUQVRVU19E",
- "VE9fSU5fUFJPR1JFU1MQAhIhCh1ERVBMT1lNRU5UX1NUQVRVU19EVE9fU1VD",
- "Q0VTUxADEiAKHERFUExPWU1FTlRfU1RBVFVTX0RUT19GQUlMRUQQBCrEAQoS",
- "QnJvd3NlTm9kZUNsYXNzRHRvEiUKIUJST1dTRV9OT0RFX0NMQVNTX0RUT19V",
- "TlNQRUNJRklFRBAAEiAKHEJST1dTRV9OT0RFX0NMQVNTX0RUT19PQkpFQ1QQ",
- "ARIiCh5CUk9XU0VfTk9ERV9DTEFTU19EVE9fVkFSSUFCTEUQAhIgChxCUk9X",
- "U0VfTk9ERV9DTEFTU19EVE9fTUVUSE9EEAMSHwobQlJPV1NFX05PREVfQ0xB",
- "U1NfRFRPX09USEVSEAQqoQIKFEJyb3dzZUZhaWx1cmVLaW5kRHRvEicKI0JS",
- "T1dTRV9GQUlMVVJFX0tJTkRfRFRPX1VOU1BFQ0lGSUVEEAASMAosQlJPV1NF",
- "X0ZBSUxVUkVfS0lORF9EVE9fQ09OTkVDVElPTl9OT1RfRk9VTkQQARI0CjBC",
- "Uk9XU0VfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNUSU9OX05PVF9DT05ORUNU",
- "RUQQAhIpCiVCUk9XU0VfRkFJTFVSRV9LSU5EX0RUT19OT1RfQlJPV1NBQkxF",
- "EAMSIwofQlJPV1NFX0ZBSUxVUkVfS0lORF9EVE9fVElNRU9VVBAEEigKJEJS",
- "T1dTRV9GQUlMVVJFX0tJTkRfRFRPX1NFUlZFUl9FUlJPUhAFKqoCChtSZWFk",
- "VGFnVmFsdWVzRmFpbHVyZUtpbmREdG8SMAosUkVBRF9UQUdfVkFMVUVTX0ZB",
- "SUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQABI5CjVSRUFEX1RBR19WQUxV",
- "RVNfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNUSU9OX05PVF9GT1VORBABEj0K",
- "OVJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJTkRfRFRPX0NPTk5FQ1RJT05f",
- "Tk9UX0NPTk5FQ1RFRBACEiwKKFJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJ",
- "TkRfRFRPX1RJTUVPVVQQAxIxCi1SRUFEX1RBR19WQUxVRVNfRkFJTFVSRV9L",
- "SU5EX0RUT19TRVJWRVJfRVJST1IQBCqTAgoUVmVyaWZ5RmFpbHVyZUtpbmRE",
- "dG8SJwojVkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQABIn",
- "CiNWRVJJRllfRkFJTFVSRV9LSU5EX0RUT19VTlJFQUNIQUJMRRABEicKI1ZF",
- "UklGWV9GQUlMVVJFX0tJTkRfRFRPX0FVVEhfRkFJTEVEEAISMQotVkVSSUZZ",
- "X0ZBSUxVUkVfS0lORF9EVE9fVU5UUlVTVEVEX0NFUlRJRklDQVRFEAMSIwof",
- "VkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVElNRU9VVBAEEigKJFZFUklGWV9G",
- "QUlMVVJFX0tJTkRfRFRPX1NFUlZFUl9FUlJPUhAFKuUBChpTdG9yZUFuZEZv",
- "cndhcmRDYXRlZ29yeUR0bxIuCipTVE9SRV9BTkRfRk9SV0FSRF9DQVRFR09S",
- "WV9EVE9fVU5TUEVDSUZJRUQQABIyCi5TVE9SRV9BTkRfRk9SV0FSRF9DQVRF",
- "R09SWV9EVE9fRVhURVJOQUxfU1lTVEVNEAESLworU1RPUkVfQU5EX0ZPUldB",
- "UkRfQ0FURUdPUllfRFRPX05PVElGSUNBVElPThACEjIKLlNUT1JFX0FORF9G",
- "T1JXQVJEX0NBVEVHT1JZX0RUT19DQUNIRURfREJfV1JJVEUQAypoCg1BbGFy",
- "bVN0YXRlRHRvEh8KG0FMQVJNX1NUQVRFX0RUT19VTlNQRUNJRklFRBAAEhoK",
- "FkFMQVJNX1NUQVRFX0RUT19BQ1RJVkUQARIaChZBTEFSTV9TVEFURV9EVE9f",
- "Tk9STUFMEAIquQEKDUFsYXJtTGV2ZWxEdG8SHwobQUxBUk1fTEVWRUxfRFRP",
- "X1VOU1BFQ0lGSUVEEAASGAoUQUxBUk1fTEVWRUxfRFRPX05PTkUQARIXChNB",
- "TEFSTV9MRVZFTF9EVE9fTE9XEAISGwoXQUxBUk1fTEVWRUxfRFRPX0xPV19M",
- "T1cQAxIYChRBTEFSTV9MRVZFTF9EVE9fSElHSBAEEh0KGUFMQVJNX0xFVkVM",
- "X0RUT19ISUdIX0hJR0gQBSqSAQoMQWxhcm1LaW5kRHRvEh4KGkFMQVJNX0tJ",
- "TkRfRFRPX1VOU1BFQ0lGSUVEEAASGwoXQUxBUk1fS0lORF9EVE9fQ09NUFVU",
- "RUQQARIgChxBTEFSTV9LSU5EX0RUT19OQVRJVkVfT1BDX1VBEAISIwofQUxB",
- "Uk1fS0lORF9EVE9fTkFUSVZFX01YX0FDQ0VTUxADKugBChNBbGFybVNoZWx2",
- "ZVN0YXRlRHRvEiYKIkFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVU5TUEVDSUZJ",
- "RUQQABIkCiBBTEFSTV9TSEVMVkVfU1RBVEVfRFRPX1VOU0hFTFZFRBABEisK",
- "J0FMQVJNX1NIRUxWRV9TVEFURV9EVE9fT05FX1NIT1RfU0hFTFZFRBACEigK",
- "JEFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVElNRURfU0hFTFZFRBADEiwKKEFM",
- "QVJNX1NIRUxWRV9TVEFURV9EVE9fUEVSTUFORU5UX1NIRUxWRUQQBDKEBQoS",
- "U2l0ZUNvbW1hbmRTZXJ2aWNlEmwKEEV4ZWN1dGVMaWZlY3ljbGUSLC5zY2Fk",
- "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5MaWZlY3ljbGVSZXF1ZXN0Giouc2Nh",
- "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTGlmZWN5Y2xlUmVwbHkSYAoMRXhl",
- "Y3V0ZU9wY1VhEiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuT3BjVWFS",
- "ZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuT3BjVWFSZXBs",
- "eRJgCgxFeGVjdXRlUXVlcnkSKC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52",
- "MS5RdWVyeVJlcXVlc3QaJi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5R",
- "dWVyeVJlcGx5EmMKDUV4ZWN1dGVQYXJrZWQSKS5zY2FkYWJyaWRnZS5zaXRl",
- "Y29tbWFuZC52MS5QYXJrZWRSZXF1ZXN0Gicuc2NhZGFicmlkZ2Uuc2l0ZWNv",
- "bW1hbmQudjEuUGFya2VkUmVwbHkSYAoMRXhlY3V0ZVJvdXRlEiguc2NhZGFi",
- "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVSZXF1ZXN0GiYuc2NhZGFicmlk",
- "Z2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVSZXBseRJ1Cg9UcmlnZ2VyRmFpbG92",
- "ZXISMi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5UcmlnZ2VyU2l0ZUZh",
- "aWxvdmVyRHRvGi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuU2l0ZUZh",
- "aWxvdmVyQWNrRHRvQiuqAihaQi5NT00uV1cuU2NhZGFCcmlkZ2UuQ29tbXVu",
- "aWNhdGlvbi5HcnBjYgZwcm90bzM="));
+ "dXRpb25faWQYByABKAkSHAoUcmVxdWlyZV9nb29kX3F1YWxpdHkYCCABKAgi",
+ "/wEKIlJvdXRlVG9XYWl0Rm9yQXR0cmlidXRlUmVzcG9uc2VEdG8SFgoOY29y",
+ "cmVsYXRpb25faWQYASABKAkSDwoHbWF0Y2hlZBgCIAEoCBI1CgV2YWx1ZRgD",
+ "IAEoCzImLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkxvb3NlVmFsdWUS",
+ "DwoHcXVhbGl0eRgEIAEoCRIRCgl0aW1lZF9vdXQYBSABKAgSDwoHc3VjY2Vz",
+ "cxgGIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAcgASgJEi0KCXRpbWVzdGFtcBgI",
+ "IAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiiQMKDFJvdXRlUmVx",
+ "dWVzdBJKCg1yb3V0ZV90b19jYWxsGAEgASgLMjEuc2NhZGFicmlkZ2Uuc2l0",
+ "ZWNvbW1hbmQudjEuUm91dGVUb0NhbGxSZXF1ZXN0RHRvSAASXQoXcm91dGVf",
+ "dG9fZ2V0X2F0dHJpYnV0ZXMYAiABKAsyOi5zY2FkYWJyaWRnZS5zaXRlY29t",
+ "bWFuZC52MS5Sb3V0ZVRvR2V0QXR0cmlidXRlc1JlcXVlc3REdG9IABJdChdy",
+ "b3V0ZV90b19zZXRfYXR0cmlidXRlcxgDIAEoCzI6LnNjYWRhYnJpZGdlLnNp",
+ "dGVjb21tYW5kLnYxLlJvdXRlVG9TZXRBdHRyaWJ1dGVzUmVxdWVzdER0b0gA",
+ "EmQKG3JvdXRlX3RvX3dhaXRfZm9yX2F0dHJpYnV0ZRgEIAEoCzI9LnNjYWRh",
+ "YnJpZGdlLnNpdGVjb21tYW5kLnYxLlJvdXRlVG9XYWl0Rm9yQXR0cmlidXRl",
+ "UmVxdWVzdER0b0gAQgkKB2NvbW1hbmQiiQMKClJvdXRlUmVwbHkSSwoNcm91",
+ "dGVfdG9fY2FsbBgBIAEoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYx",
+ "LlJvdXRlVG9DYWxsUmVzcG9uc2VEdG9IABJeChdyb3V0ZV90b19nZXRfYXR0",
+ "cmlidXRlcxgCIAEoCzI7LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJv",
+ "dXRlVG9HZXRBdHRyaWJ1dGVzUmVzcG9uc2VEdG9IABJeChdyb3V0ZV90b19z",
+ "ZXRfYXR0cmlidXRlcxgDIAEoCzI7LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k",
+ "LnYxLlJvdXRlVG9TZXRBdHRyaWJ1dGVzUmVzcG9uc2VEdG9IABJlChtyb3V0",
+ "ZV90b193YWl0X2Zvcl9hdHRyaWJ1dGUYBCABKAsyPi5zY2FkYWJyaWRnZS5z",
+ "aXRlY29tbWFuZC52MS5Sb3V0ZVRvV2FpdEZvckF0dHJpYnV0ZVJlc3BvbnNl",
+ "RHRvSABCBwoFcmVwbHkiQQoWVHJpZ2dlclNpdGVGYWlsb3ZlckR0bxIWCg5j",
+ "b3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdzaXRlX2lkGAIgASgJIm0KElNpdGVG",
+ "YWlsb3ZlckFja0R0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIQCghhY2Nl",
+ "cHRlZBgCIAEoCBIWCg50YXJnZXRfYWRkcmVzcxgDIAEoCRIVCg1lcnJvcl9t",
+ "ZXNzYWdlGAQgASgJKssBChNEZXBsb3ltZW50U3RhdHVzRHRvEiUKIURFUExP",
+ "WU1FTlRfU1RBVFVTX0RUT19VTlNQRUNJRklFRBAAEiEKHURFUExPWU1FTlRf",
+ "U1RBVFVTX0RUT19QRU5ESU5HEAESJQohREVQTE9ZTUVOVF9TVEFUVVNfRFRP",
+ "X0lOX1BST0dSRVNTEAISIQodREVQTE9ZTUVOVF9TVEFUVVNfRFRPX1NVQ0NF",
+ "U1MQAxIgChxERVBMT1lNRU5UX1NUQVRVU19EVE9fRkFJTEVEEAQqxAEKEkJy",
+ "b3dzZU5vZGVDbGFzc0R0bxIlCiFCUk9XU0VfTk9ERV9DTEFTU19EVE9fVU5T",
+ "UEVDSUZJRUQQABIgChxCUk9XU0VfTk9ERV9DTEFTU19EVE9fT0JKRUNUEAES",
+ "IgoeQlJPV1NFX05PREVfQ0xBU1NfRFRPX1ZBUklBQkxFEAISIAocQlJPV1NF",
+ "X05PREVfQ0xBU1NfRFRPX01FVEhPRBADEh8KG0JST1dTRV9OT0RFX0NMQVNT",
+ "X0RUT19PVEhFUhAEKqECChRCcm93c2VGYWlsdXJlS2luZER0bxInCiNCUk9X",
+ "U0VfRkFJTFVSRV9LSU5EX0RUT19VTlNQRUNJRklFRBAAEjAKLEJST1dTRV9G",
+ "QUlMVVJFX0tJTkRfRFRPX0NPTk5FQ1RJT05fTk9UX0ZPVU5EEAESNAowQlJP",
+ "V1NFX0ZBSUxVUkVfS0lORF9EVE9fQ09OTkVDVElPTl9OT1RfQ09OTkVDVEVE",
+ "EAISKQolQlJPV1NFX0ZBSUxVUkVfS0lORF9EVE9fTk9UX0JST1dTQUJMRRAD",
+ "EiMKH0JST1dTRV9GQUlMVVJFX0tJTkRfRFRPX1RJTUVPVVQQBBIoCiRCUk9X",
+ "U0VfRkFJTFVSRV9LSU5EX0RUT19TRVJWRVJfRVJST1IQBSqqAgobUmVhZFRh",
+ "Z1ZhbHVlc0ZhaWx1cmVLaW5kRHRvEjAKLFJFQURfVEFHX1ZBTFVFU19GQUlM",
+ "VVJFX0tJTkRfRFRPX1VOU1BFQ0lGSUVEEAASOQo1UkVBRF9UQUdfVkFMVUVT",
+ "X0ZBSUxVUkVfS0lORF9EVE9fQ09OTkVDVElPTl9OT1RfRk9VTkQQARI9CjlS",
+ "RUFEX1RBR19WQUxVRVNfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNUSU9OX05P",
+ "VF9DT05ORUNURUQQAhIsCihSRUFEX1RBR19WQUxVRVNfRkFJTFVSRV9LSU5E",
+ "X0RUT19USU1FT1VUEAMSMQotUkVBRF9UQUdfVkFMVUVTX0ZBSUxVUkVfS0lO",
+ "RF9EVE9fU0VSVkVSX0VSUk9SEAQqkwIKFFZlcmlmeUZhaWx1cmVLaW5kRHRv",
+ "EicKI1ZFUklGWV9GQUlMVVJFX0tJTkRfRFRPX1VOU1BFQ0lGSUVEEAASJwoj",
+ "VkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVU5SRUFDSEFCTEUQARInCiNWRVJJ",
+ "RllfRkFJTFVSRV9LSU5EX0RUT19BVVRIX0ZBSUxFRBACEjEKLVZFUklGWV9G",
+ "QUlMVVJFX0tJTkRfRFRPX1VOVFJVU1RFRF9DRVJUSUZJQ0FURRADEiMKH1ZF",
+ "UklGWV9GQUlMVVJFX0tJTkRfRFRPX1RJTUVPVVQQBBIoCiRWRVJJRllfRkFJ",
+ "TFVSRV9LSU5EX0RUT19TRVJWRVJfRVJST1IQBSrlAQoaU3RvcmVBbmRGb3J3",
+ "YXJkQ2F0ZWdvcnlEdG8SLgoqU1RPUkVfQU5EX0ZPUldBUkRfQ0FURUdPUllf",
+ "RFRPX1VOU1BFQ0lGSUVEEAASMgouU1RPUkVfQU5EX0ZPUldBUkRfQ0FURUdP",
+ "UllfRFRPX0VYVEVSTkFMX1NZU1RFTRABEi8KK1NUT1JFX0FORF9GT1JXQVJE",
+ "X0NBVEVHT1JZX0RUT19OT1RJRklDQVRJT04QAhIyCi5TVE9SRV9BTkRfRk9S",
+ "V0FSRF9DQVRFR09SWV9EVE9fQ0FDSEVEX0RCX1dSSVRFEAMqaAoNQWxhcm1T",
+ "dGF0ZUR0bxIfChtBTEFSTV9TVEFURV9EVE9fVU5TUEVDSUZJRUQQABIaChZB",
+ "TEFSTV9TVEFURV9EVE9fQUNUSVZFEAESGgoWQUxBUk1fU1RBVEVfRFRPX05P",
+ "Uk1BTBACKrkBCg1BbGFybUxldmVsRHRvEh8KG0FMQVJNX0xFVkVMX0RUT19V",
+ "TlNQRUNJRklFRBAAEhgKFEFMQVJNX0xFVkVMX0RUT19OT05FEAESFwoTQUxB",
+ "Uk1fTEVWRUxfRFRPX0xPVxACEhsKF0FMQVJNX0xFVkVMX0RUT19MT1dfTE9X",
+ "EAMSGAoUQUxBUk1fTEVWRUxfRFRPX0hJR0gQBBIdChlBTEFSTV9MRVZFTF9E",
+ "VE9fSElHSF9ISUdIEAUqkgEKDEFsYXJtS2luZER0bxIeChpBTEFSTV9LSU5E",
+ "X0RUT19VTlNQRUNJRklFRBAAEhsKF0FMQVJNX0tJTkRfRFRPX0NPTVBVVEVE",
+ "EAESIAocQUxBUk1fS0lORF9EVE9fTkFUSVZFX09QQ19VQRACEiMKH0FMQVJN",
+ "X0tJTkRfRFRPX05BVElWRV9NWF9BQ0NFU1MQAyroAQoTQWxhcm1TaGVsdmVT",
+ "dGF0ZUR0bxImCiJBTEFSTV9TSEVMVkVfU1RBVEVfRFRPX1VOU1BFQ0lGSUVE",
+ "EAASJAogQUxBUk1fU0hFTFZFX1NUQVRFX0RUT19VTlNIRUxWRUQQARIrCidB",
+ "TEFSTV9TSEVMVkVfU1RBVEVfRFRPX09ORV9TSE9UX1NIRUxWRUQQAhIoCiRB",
+ "TEFSTV9TSEVMVkVfU1RBVEVfRFRPX1RJTUVEX1NIRUxWRUQQAxIsCihBTEFS",
+ "TV9TSEVMVkVfU1RBVEVfRFRPX1BFUk1BTkVOVF9TSEVMVkVEEAQyhAUKElNp",
+ "dGVDb21tYW5kU2VydmljZRJsChBFeGVjdXRlTGlmZWN5Y2xlEiwuc2NhZGFi",
+ "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTGlmZWN5Y2xlUmVxdWVzdBoqLnNjYWRh",
+ "YnJpZGdlLnNpdGVjb21tYW5kLnYxLkxpZmVjeWNsZVJlcGx5EmAKDEV4ZWN1",
+ "dGVPcGNVYRIoLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLk9wY1VhUmVx",
+ "dWVzdBomLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLk9wY1VhUmVwbHkS",
+ "YAoMRXhlY3V0ZVF1ZXJ5Eiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu",
+ "UXVlcnlSZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUXVl",
+ "cnlSZXBseRJjCg1FeGVjdXRlUGFya2VkEikuc2NhZGFicmlkZ2Uuc2l0ZWNv",
+ "bW1hbmQudjEuUGFya2VkUmVxdWVzdBonLnNjYWRhYnJpZGdlLnNpdGVjb21t",
+ "YW5kLnYxLlBhcmtlZFJlcGx5EmAKDEV4ZWN1dGVSb3V0ZRIoLnNjYWRhYnJp",
+ "ZGdlLnNpdGVjb21tYW5kLnYxLlJvdXRlUmVxdWVzdBomLnNjYWRhYnJpZGdl",
+ "LnNpdGVjb21tYW5kLnYxLlJvdXRlUmVwbHkSdQoPVHJpZ2dlckZhaWxvdmVy",
+ "EjIuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuVHJpZ2dlclNpdGVGYWls",
+ "b3ZlckR0bxouLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlNpdGVGYWls",
+ "b3ZlckFja0R0b0IrqgIoWkIuTU9NLldXLlNjYWRhQnJpZGdlLkNvbW11bmlj",
+ "YXRpb24uR3JwY2IGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SitestreamReflection.Descriptor, },
new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStatusDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseNodeClassDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ReadTagValuesFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.VerifyFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.StoreAndForwardCategoryDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmLevelDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmShelveStateDto), }, null, new pbr::GeneratedClrTypeInfo[] {
@@ -598,7 +599,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ParkedRequest), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ParkedRequest.Parser, new[]{ "ParkedMessageQuery", "ParkedMessageRetry", "ParkedMessageDiscard", "RetryParkedOperation", "DiscardParkedOperation" }, new[]{ "Command" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ParkedReply), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ParkedReply.Parser, new[]{ "ParkedMessageQuery", "ParkedMessageRetry", "ParkedMessageDiscard", "ParkedOperationAction" }, new[]{ "Reply" }, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToCallRequestDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToCallRequestDto.Parser, new[]{ "CorrelationId", "InstanceUniqueName", "ScriptName", "Parameters", "Timestamp", "ParentExecutionId", "Trace" }, null, null, null, null),
- new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToCallResponseDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToCallResponseDto.Parser, new[]{ "CorrelationId", "Success", "ReturnValue", "ErrorMessage", "Timestamp", "ChildExecutionId", "TraceEvents" }, null, null, null, null),
+ new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToCallResponseDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToCallResponseDto.Parser, new[]{ "CorrelationId", "Success", "ReturnValue", "ErrorMessage", "Timestamp", "ChildExecutionId", "TraceEvents", "Truncated", "LogsTruncated" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToGetAttributesRequestDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToGetAttributesRequestDto.Parser, new[]{ "CorrelationId", "InstanceUniqueName", "AttributeNames", "Timestamp", "ParentExecutionId" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToGetAttributesResponseDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToGetAttributesResponseDto.Parser, new[]{ "CorrelationId", "Values", "Success", "ErrorMessage", "Timestamp" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToSetAttributesRequestDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.RouteToSetAttributesRequestDto.Parser, new[]{ "CorrelationId", "InstanceUniqueName", "AttributeValues", "Timestamp", "ParentExecutionId", "Trace" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, }),
@@ -28991,6 +28992,8 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
timestamp_ = other.timestamp_ != null ? other.timestamp_.Clone() : null;
childExecutionId_ = other.childExecutionId_;
traceEvents_ = other.traceEvents_.Clone();
+ truncated_ = other.truncated_;
+ logsTruncated_ = other.logsTruncated_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@@ -29097,6 +29100,34 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
get { return traceEvents_; }
}
+ /// Field number for the "truncated" field.
+ public const int TruncatedFieldNumber = 8;
+ private bool truncated_;
+ ///
+ /// Flow Debugger (Gitea #54): the site's inline trace collector dropped step rows (truncated)
+ /// or log-line rows (logs_truncated). proto3 default false from an untraced run or older site.
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool Truncated {
+ get { return truncated_; }
+ set {
+ truncated_ = value;
+ }
+ }
+
+ /// Field number for the "logs_truncated" field.
+ public const int LogsTruncatedFieldNumber = 9;
+ private bool logsTruncated_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool LogsTruncated {
+ get { return logsTruncated_; }
+ set {
+ logsTruncated_ = value;
+ }
+ }
+
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
@@ -29119,6 +29150,8 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
if (!object.Equals(Timestamp, other.Timestamp)) return false;
if (ChildExecutionId != other.ChildExecutionId) return false;
if(!traceEvents_.Equals(other.traceEvents_)) return false;
+ if (Truncated != other.Truncated) return false;
+ if (LogsTruncated != other.LogsTruncated) return false;
return Equals(_unknownFields, other._unknownFields);
}
@@ -29133,6 +29166,8 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
if (timestamp_ != null) hash ^= Timestamp.GetHashCode();
if (ChildExecutionId.Length != 0) hash ^= ChildExecutionId.GetHashCode();
hash ^= traceEvents_.GetHashCode();
+ if (Truncated != false) hash ^= Truncated.GetHashCode();
+ if (LogsTruncated != false) hash ^= LogsTruncated.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@@ -29176,6 +29211,14 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
output.WriteString(ChildExecutionId);
}
traceEvents_.WriteTo(output, _repeated_traceEvents_codec);
+ if (Truncated != false) {
+ output.WriteRawTag(64);
+ output.WriteBool(Truncated);
+ }
+ if (LogsTruncated != false) {
+ output.WriteRawTag(72);
+ output.WriteBool(LogsTruncated);
+ }
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
@@ -29211,6 +29254,14 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
output.WriteString(ChildExecutionId);
}
traceEvents_.WriteTo(ref output, _repeated_traceEvents_codec);
+ if (Truncated != false) {
+ output.WriteRawTag(64);
+ output.WriteBool(Truncated);
+ }
+ if (LogsTruncated != false) {
+ output.WriteRawTag(72);
+ output.WriteBool(LogsTruncated);
+ }
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
@@ -29240,6 +29291,12 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
size += 1 + pb::CodedOutputStream.ComputeStringSize(ChildExecutionId);
}
size += traceEvents_.CalculateSize(_repeated_traceEvents_codec);
+ if (Truncated != false) {
+ size += 1 + 1;
+ }
+ if (LogsTruncated != false) {
+ size += 1 + 1;
+ }
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
@@ -29277,6 +29334,12 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
ChildExecutionId = other.ChildExecutionId;
}
traceEvents_.Add(other.traceEvents_);
+ if (other.Truncated != false) {
+ Truncated = other.Truncated;
+ }
+ if (other.LogsTruncated != false) {
+ LogsTruncated = other.LogsTruncated;
+ }
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
@@ -29330,6 +29393,14 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
traceEvents_.AddEntriesFrom(input, _repeated_traceEvents_codec);
break;
}
+ case 64: {
+ Truncated = input.ReadBool();
+ break;
+ }
+ case 72: {
+ LogsTruncated = input.ReadBool();
+ break;
+ }
}
}
#endif
@@ -29383,6 +29454,14 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc {
traceEvents_.AddEntriesFrom(ref input, _repeated_traceEvents_codec);
break;
}
+ case 64: {
+ Truncated = input.ReadBool();
+ break;
+ }
+ case 72: {
+ LogsTruncated = input.ReadBool();
+ break;
+ }
}
}
}
diff --git a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/RouteHelper.cs b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/RouteHelper.cs
index 5ed42d5b..db80f34d 100644
--- a/src/ZB.MOM.WW.ScadaBridge.InboundAPI/RouteHelper.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.InboundAPI/RouteHelper.cs
@@ -86,6 +86,7 @@ public class RouteHelper
private readonly INodeIdentityProvider? _nodeIdentity;
private readonly bool _trace;
private readonly Action? _traceSink;
+ private readonly Action? _siteTruncationSink;
private readonly IReadOnlySet? _permittedSiteIdentifiers;
private readonly bool _captureBodies;
private readonly ILogger? _logger;
@@ -107,7 +108,7 @@ public class RouteHelper
INodeIdentityProvider? nodeIdentity = null,
ILogger? logger = null)
: this(instanceLocator, instanceRouter, CancellationToken.None, CancellationToken.None, parentExecutionId: null,
- auditWriter, nodeIdentity, trace: false, traceSink: null, permittedSiteIdentifiers: null, captureBodies: true, logger)
+ auditWriter, nodeIdentity, trace: false, traceSink: null, permittedSiteIdentifiers: null, captureBodies: true, logger, siteTruncationSink: null)
{
}
@@ -123,7 +124,8 @@ public class RouteHelper
Action? traceSink,
IReadOnlySet? permittedSiteIdentifiers,
bool captureBodies,
- ILogger? logger)
+ ILogger? logger,
+ Action? siteTruncationSink)
{
_permittedSiteIdentifiers = permittedSiteIdentifiers;
_instanceLocator = instanceLocator;
@@ -135,6 +137,7 @@ public class RouteHelper
_nodeIdentity = nodeIdentity;
_trace = trace;
_traceSink = traceSink;
+ _siteTruncationSink = siteTruncationSink;
_captureBodies = captureBodies;
_logger = logger;
}
@@ -150,7 +153,7 @@ public class RouteHelper
/// A new inheriting the given deadline token.
public RouteHelper WithDeadline(CancellationToken deadlineToken) =>
new(_instanceLocator, _instanceRouter, deadlineToken, _requestAbortedToken, _parentExecutionId,
- _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger);
+ _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger, _siteTruncationSink);
///
/// Returns a carrying the raw request-abort
@@ -164,7 +167,7 @@ public class RouteHelper
/// A new carrying the given request-abort token.
public RouteHelper WithRequestAborted(CancellationToken requestAbortedToken) =>
new(_instanceLocator, _instanceRouter, _deadlineToken, requestAbortedToken, _parentExecutionId,
- _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger);
+ _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger, _siteTruncationSink);
///
/// Audit Log (ParentExecutionId): returns a whose
@@ -179,7 +182,7 @@ public class RouteHelper
/// A new carrying the given parent execution id.
public RouteHelper WithParentExecutionId(Guid? parentExecutionId) =>
new(_instanceLocator, _instanceRouter, _deadlineToken, _requestAbortedToken, parentExecutionId,
- _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger);
+ _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger, _siteTruncationSink);
///
/// Flow Debugger (design 2026-09-05 §5.2): returns a whose routed
@@ -190,7 +193,7 @@ public class RouteHelper
/// A new carrying the flag.
public RouteHelper WithTrace(bool trace) =>
new(_instanceLocator, _instanceRouter, _deadlineToken, _requestAbortedToken, _parentExecutionId,
- _auditWriter, _nodeIdentity, trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger);
+ _auditWriter, _nodeIdentity, trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger, _siteTruncationSink);
///
/// Flow Debugger (design 2026-09-05 §7.1): returns a that also
@@ -199,10 +202,15 @@ public class RouteHelper
/// audit store. Null clears the sink.
///
/// Receives the audit events in emission order; null = none.
+ ///
+ /// Gitea #54: receives (truncated, logsTruncated) from a routed reply whose SITE-side
+ /// inline collector dropped rows, so the caller can label a short list as short. Called only
+ /// when at least one flag is set; null = none.
+ ///
/// A new carrying the sink.
- public RouteHelper WithTraceSink(Action? traceSink) =>
+ public RouteHelper WithTraceSink(Action? traceSink, Action? siteTruncationSink = null) =>
new(_instanceLocator, _instanceRouter, _deadlineToken, _requestAbortedToken, _parentExecutionId,
- _auditWriter, _nodeIdentity, _trace, traceSink, _permittedSiteIdentifiers, _captureBodies, _logger);
+ _auditWriter, _nodeIdentity, _trace, traceSink, _permittedSiteIdentifiers, _captureBodies, _logger, siteTruncationSink);
///
/// Flow Debugger outbound calls (plan 2026-09-06, D5/D7): the trace sink this helper carries,
@@ -236,7 +244,7 @@ public class RouteHelper
/// A new carrying the scope.
public RouteHelper WithSiteScope(IReadOnlySet? permittedSiteIdentifiers) =>
new(_instanceLocator, _instanceRouter, _deadlineToken, _requestAbortedToken, _parentExecutionId,
- _auditWriter, _nodeIdentity, _trace, _traceSink, permittedSiteIdentifiers, _captureBodies, _logger);
+ _auditWriter, _nodeIdentity, _trace, _traceSink, permittedSiteIdentifiers, _captureBodies, _logger, _siteTruncationSink);
///
/// Arch-review F11: returns a whose always-on RouteCall row
@@ -251,7 +259,7 @@ public class RouteHelper
/// A new carrying the flag.
public RouteHelper WithBodyCapture(bool captureBodies) =>
new(_instanceLocator, _instanceRouter, _deadlineToken, _requestAbortedToken, _parentExecutionId,
- _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, captureBodies, _logger);
+ _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, captureBodies, _logger, _siteTruncationSink);
///
/// Creates a route target for the specified instance.
@@ -262,7 +270,7 @@ public class RouteHelper
{
return new RouteTarget(
instanceCode, _instanceLocator, _instanceRouter, _deadlineToken, _requestAbortedToken, _parentExecutionId,
- _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger);
+ _auditWriter, _nodeIdentity, _trace, _traceSink, _permittedSiteIdentifiers, _captureBodies, _logger, _siteTruncationSink);
}
}
@@ -281,6 +289,7 @@ public class RouteTarget
private readonly INodeIdentityProvider? _nodeIdentity;
private readonly bool _trace;
private readonly Action? _traceSink;
+ private readonly Action? _siteTruncationSink;
private readonly IReadOnlySet? _permittedSiteIdentifiers;
private readonly bool _captureBodies;
private readonly ILogger? _logger;
@@ -301,6 +310,7 @@ public class RouteTarget
/// Arch-review F2: site identifiers this call may reach; null = unscoped.
/// Arch-review F11: false omits the request/response summary on the RouteCall row.
/// Arch-review F8: logs a Warning when the best-effort RouteCall audit write faults; null = silent.
+ /// Gitea #54: receives a routed reply's site-side truncation flags; null = none.
internal RouteTarget(
string instanceCode,
IInstanceLocator instanceLocator,
@@ -314,7 +324,8 @@ public class RouteTarget
Action? traceSink = null,
IReadOnlySet? permittedSiteIdentifiers = null,
bool captureBodies = true,
- ILogger? logger = null)
+ ILogger? logger = null,
+ Action? siteTruncationSink = null)
{
_permittedSiteIdentifiers = permittedSiteIdentifiers;
_instanceCode = instanceCode;
@@ -327,6 +338,7 @@ public class RouteTarget
_nodeIdentity = nodeIdentity;
_trace = trace;
_traceSink = traceSink;
+ _siteTruncationSink = siteTruncationSink;
_captureBodies = captureBodies;
_logger = logger;
}
@@ -382,6 +394,7 @@ public class RouteTarget
EmitRouteCall(scriptName, normalized, startedUtc, sw.ElapsedMilliseconds, response.Success,
response.ReturnValue, response.ErrorMessage, response.ChildExecutionId, response.TraceEvents);
+ ReportSiteTruncation(response);
if (!response.Success)
{
@@ -463,6 +476,23 @@ public class RouteTarget
}
}
+ ///
+ /// Gitea #54: forwards a routed reply's site-side truncation flags to the sink. Best-effort —
+ /// a misbehaving sink never fails the routed call.
+ ///
+ private void ReportSiteTruncation(RouteToCallResponse response)
+ {
+ if (_siteTruncationSink is null || !(response.Truncated || response.LogsTruncated)) return;
+ try
+ {
+ _siteTruncationSink(response.Truncated, response.LogsTruncated);
+ }
+ catch (Exception)
+ {
+ // Best-effort, like the trace sink.
+ }
+ }
+
private static string? TraceJson(object? value)
{
if (value is null) return null;
diff --git a/src/ZB.MOM.WW.ScadaBridge.ManagementService/FlowDebug/FlowDebugRunner.cs b/src/ZB.MOM.WW.ScadaBridge.ManagementService/FlowDebug/FlowDebugRunner.cs
index 37079fc2..60289eed 100644
--- a/src/ZB.MOM.WW.ScadaBridge.ManagementService/FlowDebug/FlowDebugRunner.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.ManagementService/FlowDebug/FlowDebugRunner.cs
@@ -174,7 +174,19 @@ public sealed class FlowDebugRunner
// only known once the script runs. So the operator's scope is pushed into the
// RouteHelper and enforced at route time, before any site traffic.
var scope = await ResolvePermittedSiteIdentifiersAsync(sp, user, ct).ConfigureAwait(false);
- var route = sp.GetRequiredService().WithTraceSink(evt => collector.Add(evt, lowPriority: FlowStepProjector.IsLogLine(evt))).WithSiteScope(scope);
+ // Gitea #54: a routed site run whose own collector dropped rows reports it here; the flags
+ // are OR-ed into the result so the page labels the short site lane as truncated.
+ var siteTruncated = 0;
+ var siteLogsTruncated = 0;
+ var route = sp.GetRequiredService()
+ .WithTraceSink(
+ evt => collector.Add(evt, lowPriority: FlowStepProjector.IsLogLine(evt)),
+ (truncated, logsTruncated) =>
+ {
+ if (truncated) Interlocked.Exchange(ref siteTruncated, 1);
+ if (logsTruncated) Interlocked.Exchange(ref siteLogsTruncated, 1);
+ })
+ .WithSiteScope(scope);
// Step-logs D7: a ScriptLog row rides the collector's low-priority lane so the step rows
// emitted at run end are never crowded out of the inline copy (Replay stays complete).
var executor = sp.GetRequiredService();
@@ -235,7 +247,8 @@ public sealed class FlowDebugRunner
return new FlowDebugRunResult(
root, result.Success, result.ErrorMessage, result.Success ? null : result.ErrorCode,
- ordered, Truncated: collector.Truncated, startedAt, finishedAt, LogsTruncated: collector.LogsTruncated);
+ ordered, Truncated: collector.Truncated || Volatile.Read(ref siteTruncated) == 1, startedAt, finishedAt,
+ LogsTruncated: collector.LogsTruncated || Volatile.Read(ref siteLogsTruncated) == 1);
}
///
@@ -438,8 +451,10 @@ public sealed class FlowDebugRunner
return new FlowDebugRunResult(
root, response.Success, response.ErrorMessage,
response.Success ? null : faultCode ?? CallFailedCode,
- ordered, Truncated: collector.Truncated, startedAt, DateTimeOffset.UtcNow,
- LogsTruncated: collector.LogsTruncated);
+ // Gitea #54: OR in the SITE collector's flags — central's collector only sees the
+ // rows the site sent, so a site run that dropped rows used to look complete.
+ ordered, Truncated: collector.Truncated || response.Truncated, startedAt, DateTimeOffset.UtcNow,
+ LogsTruncated: collector.LogsTruncated || response.LogsTruncated);
}
///
diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/DeploymentManagerActor.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/DeploymentManagerActor.cs
index 9a63ba4e..29657541 100644
--- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/DeploymentManagerActor.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/DeploymentManagerActor.cs
@@ -3357,7 +3357,10 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
// Flow Debugger (design §5.4): the site run's id and, for a traced
// run, its ScriptTrace events — returned inline so a Live run is
// instant. Null from an untraced run.
- result.ExecutionId, result.TraceEvents);
+ result.ExecutionId, result.TraceEvents,
+ // Gitea #54: the site collector's truncation flags ride along so a
+ // short inline list is labelled short on the Flow Debugger page.
+ result.Truncated, result.LogsTruncated);
}
return new RouteToCallResponse(
request.CorrelationId, false, null,
diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptRunLauncher.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptRunLauncher.cs
index 81d6cb94..fdbbf36a 100644
--- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptRunLauncher.cs
+++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Scripts/ScriptRunLauncher.cs
@@ -452,9 +452,8 @@ internal static class ScriptRunLauncher
// Send result to requester if this was an Ask-based call
if (!replyTo.IsNobody())
{
- replyTo.Tell(new ScriptCallResult(
- correlationId, true, state.ReturnValue, null,
- context.ExecutionId, collector?.Complete()));
+ replyTo.Tell(BuildCallResult(
+ correlationId, true, state.ReturnValue, null, context.ExecutionId, collector));
}
// Operational `script` event — execution completed successfully. Same gating as
@@ -493,8 +492,8 @@ internal static class ScriptRunLauncher
if (!replyTo.IsNobody())
{
- replyTo.Tell(new ScriptCallResult(
- correlationId, false, null, errorMsg, context?.ExecutionId, collector?.Complete()));
+ replyTo.Tell(BuildCallResult(
+ correlationId, false, null, errorMsg, context?.ExecutionId, collector));
}
completionTarget.Tell(new ScriptActor.ScriptExecutionCompleted(scriptName, false, errorMsg));
@@ -523,8 +522,8 @@ internal static class ScriptRunLauncher
if (!replyTo.IsNobody())
{
- replyTo.Tell(new ScriptCallResult(
- correlationId, false, null, errorMsg, context?.ExecutionId, collector?.Complete()));
+ replyTo.Tell(BuildCallResult(
+ correlationId, false, null, errorMsg, context?.ExecutionId, collector));
}
completionTarget.Tell(new ScriptActor.ScriptExecutionCompleted(scriptName, false, errorMsg));
@@ -540,6 +539,22 @@ internal static class ScriptRunLauncher
}
}
+ ///
+ /// Builds the Ask reply for a run. Closes the inline collector FIRST, then reads its
+ /// truncation flags, so a site run whose collector dropped rows tells the caller its
+ /// TraceEvents list is short instead of returning a silently short list (Gitea #54).
+ ///
+ private static ScriptCallResult BuildCallResult(
+ string correlationId, bool success, object? returnValue, string? error,
+ Guid? executionId, FlowTraceCollector? collector)
+ {
+ var traceEvents = collector?.Complete();
+ return new ScriptCallResult(
+ correlationId, success, returnValue, error, executionId, traceEvents,
+ Truncated: collector?.Truncated ?? false,
+ LogsTruncated: collector?.LogsTruncated ?? false);
+ }
+
///
/// Arch-review F7: a traced run that never launched (shed at the in-flight cap, or
/// suppressed by MinTimeBetweenRuns) still leaves a Failed
diff --git a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs
index f915ef1f..c081dd75 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs
@@ -203,7 +203,10 @@ internal static class SiteCommandSamples
// ── Route replies ──
Add(new RouteToCallResponse("corr-12", true, 17L, null, T1, G1, TraceSamples()),
- new RouteToCallResponse("corr-12", false, null, "script faulted", T2));
+ new RouteToCallResponse("corr-12", false, null, "script faulted", T2),
+ // Gitea #54: fields 8/9 — the site collector's truncation flags.
+ new RouteToCallResponse("corr-12", true, 17L, null, T1, G1, TraceSamples(), Truncated: true, LogsTruncated: false),
+ new RouteToCallResponse("corr-12", true, 17L, null, T1, G1, TraceSamples(), Truncated: false, LogsTruncated: true));
Add(new RouteToGetAttributesResponse("corr-13", Parameters(), true, null, T1),
new RouteToGetAttributesResponse("corr-13", new Dictionary(), false, "no instance", T2));
Add(new RouteToSetAttributesResponse("corr-14", true, null, T1),
diff --git a/tests/ZB.MOM.WW.ScadaBridge.InboundAPI.Tests/RouteHelperTraceTests.cs b/tests/ZB.MOM.WW.ScadaBridge.InboundAPI.Tests/RouteHelperTraceTests.cs
index a3d592dd..eb98d91c 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.InboundAPI.Tests/RouteHelperTraceTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.InboundAPI.Tests/RouteHelperTraceTests.cs
@@ -130,6 +130,45 @@ public class RouteHelperTraceTests
Assert.Same(siteEvents[1], sunk[2]);
}
+ ///
+ /// Gitea #54: a routed reply carrying the site collector's truncation flags is forwarded to the
+ /// truncation sink, and the sink survives the helper's clone chain (WithDeadline et al.).
+ ///
+ /// A task that represents the asynchronous operation.
+ [Fact]
+ public async Task TruncationSink_ReceivesTheReplysSiteTruncationFlags_ThroughClones()
+ {
+ var child = Guid.NewGuid();
+ _router.RouteToCallAsync("SiteA", Arg.Any(), Arg.Any())
+ .Returns(ci => new RouteToCallResponse(((RouteToCallRequest)ci[1]).CorrelationId, true, null, null,
+ DateTimeOffset.UtcNow, child, [SiteEvent(child)], Truncated: false, LogsTruncated: true));
+ var reports = new List<(bool, bool)>();
+
+ await Helper()
+ .WithTraceSink(_ => { }, (t, lt) => reports.Add((t, lt)))
+ .WithTrace(true)
+ .WithDeadline(CancellationToken.None)
+ .WithSiteScope(null)
+ .To("inst-1").Call("doWork");
+
+ Assert.Equal([(false, true)], reports);
+ }
+
+ /// Gitea #54 control: an untruncated reply does not call the truncation sink.
+ /// A task that represents the asynchronous operation.
+ [Fact]
+ public async Task TruncationSink_IsNotCalled_ForAnUntruncatedReply()
+ {
+ _router.RouteToCallAsync("SiteA", Arg.Any(), Arg.Any())
+ .Returns(ci => new RouteToCallResponse(((RouteToCallRequest)ci[1]).CorrelationId, true, null, null,
+ DateTimeOffset.UtcNow));
+ var calls = 0;
+
+ await Helper().WithTraceSink(_ => { }, (_, _) => calls++).To("inst-1").Call("doWork");
+
+ Assert.Equal(0, calls);
+ }
+
/// Verifies that a routing failure writes a failed row and still throws.
/// A task that represents the asynchronous operation.
[Fact]
diff --git a/tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/FlowDebugRunnerTests.cs b/tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/FlowDebugRunnerTests.cs
index ef7168b4..6ab896a3 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/FlowDebugRunnerTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.ManagementService.Tests/FlowDebugRunnerTests.cs
@@ -307,6 +307,38 @@ public class FlowDebugRunnerTests
Assert.Contains(_central, e => e.AsRow().Kind == AuditKind.RouteCall);
}
+ ///
+ /// Gitea #54: on the method entry the routed reply reaches the runner through RouteHelper's
+ /// sink, so the site collector's truncation flags must ride that path too.
+ ///
+ /// The site's step-row truncation flag.
+ /// The site's log-row truncation flag.
+ /// A task that represents the asynchronous operation.
+ [Theory]
+ [InlineData(true, false)]
+ [InlineData(false, true)]
+ [InlineData(false, false)]
+ public async Task RunMethod_OrsTheRoutedSitesTruncationFlagsIntoTheResult(bool truncated, bool logsTruncated)
+ {
+ var method = new ApiMethod("M", "x") { Id = 7, TimeoutSeconds = 5 };
+ _apiRepo.GetApiMethodByIdAsync(7, Arg.Any()).Returns(method);
+ _locator.GetSiteIdForInstanceAsync("inst", Arg.Any()).Returns("site-a");
+ var child = Guid.NewGuid();
+ var siteRun = ScadaBridgeAuditEventFactory.Create(AuditChannel.ScriptTrace, AuditKind.ScriptRun, AuditStatus.Delivered,
+ executionId: child, target: "work");
+ _router.RouteToCallAsync("site-a", Arg.Any(), Arg.Any())
+ .Returns(ci => new RouteToCallResponse(((RouteToCallRequest)ci[1]).CorrelationId, true, 7, null,
+ DateTimeOffset.UtcNow, child, [siteRun], truncated, logsTruncated));
+ _executor.RegisterHandler("M", ctx => ctx.Route.To("inst").Call("work"));
+
+ var result = await Runner().RunMethodAsync(_services.BuildServiceProvider(),
+ new FlowDebugRunMethodCommand(7, null), Deployer, CancellationToken.None);
+
+ Assert.True(result.Completed, result.Error);
+ Assert.Equal(truncated, result.Truncated);
+ Assert.Equal(logsTruncated, result.LogsTruncated);
+ }
+
/// Verifies that a site clock behind central still returns the sink events in emission order.
/// A task that represents the asynchronous operation.
[Fact]
@@ -908,6 +940,35 @@ public class FlowDebugRunnerTests
Assert.Equal("OtherScript", result.Events[1].Target);
}
+ ///
+ /// Gitea #54: a call-kind script run whose SITE collector dropped rows reports truncation on
+ /// the result, even though central's own collector saw only the (short) list the site sent.
+ ///
+ /// The site's step-row truncation flag.
+ /// The site's log-row truncation flag.
+ /// A task that represents the asynchronous operation.
+ [Theory]
+ [InlineData(true, false)]
+ [InlineData(false, true)]
+ [InlineData(false, false)]
+ public async Task RunScript_CallKind_OrsTheSitesTruncationFlagsIntoTheResult(bool truncated, bool logsTruncated)
+ {
+ WireScript(CallScript("Manual", """{"type":"object","properties":{"n":{"type":"integer"}},"required":["n"]}""", timeout: 5));
+ var child = Guid.NewGuid();
+ var siteRun = ScadaBridgeAuditEventFactory.Create(AuditChannel.ScriptTrace, AuditKind.ScriptRun, AuditStatus.Delivered,
+ executionId: child, target: "Manual");
+ _router.RouteToCallAsync("site-a", Arg.Any(), Arg.Any())
+ .Returns(ci => new RouteToCallResponse(((RouteToCallRequest)ci[1]).CorrelationId, true, 42, null,
+ DateTimeOffset.UtcNow, child, [siteRun], truncated, logsTruncated));
+
+ var result = await Runner().RunScriptAsync(_services.BuildServiceProvider(),
+ new FlowDebugRunScriptCommand(5, "Manual", Json("{\"n\":3}"), null), Deployer, CancellationToken.None);
+
+ Assert.True(result.Completed, result.Error);
+ Assert.Equal(truncated, result.Truncated);
+ Assert.Equal(logsTruncated, result.LogsTruncated);
+ }
+
/// Verifies that a call-kind script run routes a traced call and returns the root route-call row followed by the site rows.
/// A task that represents the asynchronous operation.
[Fact]
diff --git a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentManagerRouteTraceTests.cs b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentManagerRouteTraceTests.cs
index 0c02e37a..5ddc0260 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentManagerRouteTraceTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/DeploymentManagerRouteTraceTests.cs
@@ -46,9 +46,9 @@ public class DeploymentManagerRouteTraceTests : TestKit, IDisposable
TestLocalDb.DeleteFiles(path);
}
- private IActorRef CreateDeploymentManager() =>
+ private IActorRef CreateDeploymentManager(SiteRuntimeOptions? options = null) =>
ActorOf(Props.Create(() => new DeploymentManagerActor(
- _storage, _compilationService, _sharedScriptLibrary, null, new SiteRuntimeOptions(),
+ _storage, _compilationService, _sharedScriptLibrary, null, options ?? new SiteRuntimeOptions(),
NullLogger.Instance,
dclManager: null, healthCollector: null, serviceProvider: null, loggerFactory: null, configFetcher: null)));
@@ -56,12 +56,17 @@ public class DeploymentManagerRouteTraceTests : TestKit, IDisposable
{
InstanceUniqueName = instance,
Attributes = [new ResolvedAttribute { CanonicalName = "Mode", Value = "Auto", DataType = "String" }],
- Scripts = [new ResolvedScript { CanonicalName = "DoWork", Code = "await Instance.SetAttribute(\"Mode\", \"Manual\"); return 7;" }],
+ Scripts =
+ [
+ new ResolvedScript { CanonicalName = "DoWork", Code = "await Instance.SetAttribute(\"Mode\", \"Manual\"); return 7;" },
+ // Gitea #54: more log lines than the inline collector's low-priority share (450).
+ new ResolvedScript { CanonicalName = "Chatty", Code = "for (var i = 0; i < 600; i++) Log.Info(\"line \" + i); return 1;" },
+ ],
});
- private async Task DeployedManager(string instance)
+ private async Task DeployedManager(string instance, SiteRuntimeOptions? options = null)
{
- var actor = CreateDeploymentManager();
+ var actor = CreateDeploymentManager(options);
await Task.Delay(500);
actor.Tell(new DeployInstanceCommand("dep", instance, "sha256:x", ConfigJson(instance), "admin", DateTimeOffset.UtcNow));
ExpectMsg(TimeSpan.FromSeconds(5));
@@ -96,6 +101,30 @@ public class DeploymentManagerRouteTraceTests : TestKit, IDisposable
Assert.All(rows, r => Assert.Equal(response.ChildExecutionId, r.ExecutionId));
}
+ ///
+ /// Gitea #54: a traced routed run whose inline collector dropped log rows carries
+ /// LogsTruncated on the , so central can label the short
+ /// site lane; a run that fit reports neither flag.
+ ///
+ /// A task that represents the asynchronous operation.
+ [Fact]
+ public async Task RouteCall_WithTrace_CarriesTheSiteCollectorsTruncationFlags()
+ {
+ var actor = await DeployedManager("ChattyPump", new SiteRuntimeOptions { MaxLogLinesPerRun = 1000 });
+
+ actor.Tell(new RouteToCallRequest("rc-t", "ChattyPump", "Chatty", null, DateTimeOffset.UtcNow, Trace: true));
+ var chatty = ExpectMsg(TimeSpan.FromSeconds(10));
+ Assert.True(chatty.Success, chatty.ErrorMessage);
+ Assert.True(chatty.LogsTruncated);
+ Assert.False(chatty.Truncated);
+
+ actor.Tell(new RouteToCallRequest("rc-q", "ChattyPump", "DoWork", null, DateTimeOffset.UtcNow, Trace: true));
+ var quiet = ExpectMsg(TimeSpan.FromSeconds(10));
+ Assert.True(quiet.Success, quiet.ErrorMessage);
+ Assert.False(quiet.LogsTruncated);
+ Assert.False(quiet.Truncated);
+ }
+
/// Verifies that an untraced route call returns the execution id but no trace events.
/// A task that represents the asynchronous operation.
[Fact]
diff --git a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/ScriptRunLauncherTraceTests.cs b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/ScriptRunLauncherTraceTests.cs
index cc3535c0..b6049843 100644
--- a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/ScriptRunLauncherTraceTests.cs
+++ b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Scripts/ScriptRunLauncherTraceTests.cs
@@ -161,4 +161,38 @@ public class ScriptRunLauncherTraceTests : TestKit, IDisposable
Assert.All(logs, e => Assert.True(rows.ToList().IndexOf(e) < anchorIndex));
Assert.Equal(logs.Count, anchorIndex);
}
+
+ // ── (d) the reply reports the site collector's truncation (Gitea #54) ────────
+
+ ///
+ /// Verifies that a traced run whose inline collector dropped log-line rows says so on the
+ /// reply (LogsTruncated), instead of handing the caller a silently short list.
+ ///
+ [Fact]
+ public void TracedRun_WhoseCollectorDroppedLogRows_ReportsLogsTruncated()
+ {
+ // 600 lines is under the per-run line cap set here (1000) but over the collector's
+ // low-priority event share (DefaultMaxEvents - LowPriorityReserveEvents = 450).
+ var result = RunTraced(
+ "for (var i = 0; i < 600; i++) Log.Info(\"line \" + i); return null;",
+ Options(maxLogLines: 1000));
+
+ Assert.True(result.Success);
+ Assert.True(result.LogsTruncated);
+ Assert.False(result.Truncated);
+ Assert.True(result.TraceEvents!.Count < 600);
+ // Step rows still fit: the ScriptRun anchor is present.
+ ScriptRunRow(result);
+ }
+
+ /// Positive control: a small traced run reports neither truncation flag.
+ [Fact]
+ public void TracedRun_WithinTheCollectorCaps_ReportsNoTruncation()
+ {
+ var result = RunTraced("Log.Info(\"one\"); return null;", Options());
+
+ Assert.True(result.Success);
+ Assert.False(result.LogsTruncated);
+ Assert.False(result.Truncated);
+ }
}