Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
237 commits
Select commit Hold shift + click to select a range
e50e664
P3 add sustained Sampled Values stream analyzer
masarray Sep 15, 2026
75b375f
P3 add deterministic SV sustained analysis tests
masarray Sep 15, 2026
d726b1a
docs: define P3 Sampled Values analysis boundary
masarray Sep 15, 2026
aff9ef0
P3: integrate sustained SV analysis with observation intake
masarray Sep 15, 2026
57731a3
P3: cover unified SV observation session
masarray Sep 15, 2026
d41ccbf
P3: document unified live and replay observation boundary
masarray Sep 15, 2026
c7c95ac
P3: project explicitly SCL-bound SV measurements
masarray Sep 15, 2026
bff37d8
P3: test evidence-backed SV measurement projection
masarray Sep 15, 2026
44b0a86
P3: attach SCL-bound measurement projection to SV session
masarray Sep 15, 2026
977a27e
P3: document fail-closed SCL measurement projection
masarray Sep 15, 2026
3612e18
P3: fix measurement-context diagnostic collection
masarray Sep 15, 2026
b2d0dd3
P3: add bounded engineering cycle window analyzer
masarray Sep 15, 2026
8960427
P3: test bounded engineering cycle windows
masarray Sep 15, 2026
0c61402
P3: document bounded engineering RMS phasor windows
masarray Sep 15, 2026
65a9aed
P3: integrate engineering windows into sustained session
masarray Sep 15, 2026
b6dfa60
P3: test session engineering window integration
masarray Sep 15, 2026
fad29dd
P3: fix session engineering test imports
masarray Sep 15, 2026
4dfb2f6
P3: bridge captured Ethernet frames into sustained SV analysis
masarray Sep 15, 2026
66a325c
P3: test raw capture source to engineering analysis path
masarray Sep 15, 2026
1135c92
discovery: let exact primary type refine generic status CDC
masarray Sep 20, 2026
fc235f3
discovery: refine generic CDC from exact stVal type
masarray Sep 20, 2026
995e4a7
scl: preserve exact MMS primitive types over CDC fallback
masarray Sep 20, 2026
a56f493
tests: lock exact integer status SCL semantics
masarray Sep 20, 2026
5d8c995
docs: keep standard model registry wording public-neutral
masarray Sep 20, 2026
1a9806c
fix(reporting): add typed RCB scalar mutation contract (#144)
masarray Oct 7, 2026
eef0614
fix(reporting): route RCB scalar writes through semantic contract (#144)
masarray Oct 7, 2026
18f8ae2
fix(reporting): route RCB scalar writes through semantic contract (#144)
masarray Oct 7, 2026
1bd8813
fix(reporting): route RCB scalar writes through semantic contract (#144)
masarray Oct 7, 2026
7fd2fa6
test(reporting): lock RCB semantic wire types (#144)
masarray Oct 7, 2026
6f66dd9
fix(reporting): complete scalar semantic write migration (#144)
masarray Oct 7, 2026
23a4b45
fix(reporting): complete scalar semantic write migration (#144)
masarray Oct 7, 2026
488e678
fix(reporting): keep ResvTms codec semantic-neutral within INT16 (#144)
masarray Oct 7, 2026
cebd6b2
test(reporting): cover full signed ResvTms INT16 representation (#144)
masarray Oct 7, 2026
5d301be
refactor(reporting): converge SCL and discovery on configured static …
masarray Oct 7, 2026
20c7b40
test(reporting): lock source-neutral configured static entry point (#…
masarray Oct 7, 2026
c5989b0
feat(reporting): add bounded live type evidence for RCB scalar mutati…
masarray Oct 7, 2026
338cd4f
feat(reporting): preserve typed write failure evidence (#144)
masarray Oct 7, 2026
794ebea
fix(reporting): scope semantic type evidence to one association (#144)
masarray Oct 7, 2026
c386bb8
test(reporting): distinguish missing from conflicting type evidence (…
masarray Oct 7, 2026
3e94749
fix(reporting): preserve exact-case identity in type-evidence cache (…
masarray Oct 7, 2026
34964f5
feat(mms): classify write failures from structured DataAccessError ev…
masarray Oct 7, 2026
fbedf54
feat(reporting): carry structured interoperability failure evidence (…
masarray Oct 7, 2026
b201497
refactor(reporting): drive type recovery from structured failure clas…
masarray Oct 7, 2026
6b81b9c
test(mms): lock structured interoperability recovery classification (…
masarray Oct 7, 2026
4e6b521
feat(canonical): add source-neutral static report coverage resolver (…
masarray Oct 7, 2026
13b84fe
test(canonical): prove source-neutral static coverage and ordered Dat…
masarray Oct 7, 2026
ac73e5e
chore(canonical): keep static coverage resolver allocation-minimal (#…
masarray Oct 7, 2026
9cfc1ae
fix(canonical): converge SCL and live configured reference syntax in …
masarray Oct 7, 2026
c8addff
test(canonical): prove Discovery and Open-SCL builder coverage conver…
masarray Oct 7, 2026
fab541d
fix(canonical): repair configured reference normalizer syntax (#144)
masarray Oct 7, 2026
8f8b024
feat(reporting): model reduced configured-static RCB eligibility (#144)
masarray Oct 7, 2026
c04c07b
feat(reporting): gate reduced configured-static eligibility explicitl…
masarray Oct 7, 2026
beda723
fix(reporting): preserve existing reduced-confidence explicit-free se…
masarray Oct 7, 2026
ba392fe
fix(reporting): rank explicit-free static eligibility without changin…
masarray Oct 7, 2026
6bdb6b7
test(reporting): lock missing-vs-blocking static RCB evidence policy …
masarray Oct 7, 2026
e1d4d34
test(reporting): prove reduced static policy is explicit and static-f…
masarray Oct 7, 2026
70e6e9e
test(reporting): keep reduced static interoperability disabled by def…
masarray Oct 7, 2026
4cc9b49
fix(reporting): route fresh static hybrid plans through configured li…
masarray Oct 7, 2026
4a915bf
feat(diagnostics): surface typed RCB mutation failure evidence (#144)
masarray Oct 7, 2026
45e8855
test(diagnostics): lock typed RCB interoperability counters (#144)
masarray Oct 7, 2026
815d226
feat(reporting): classify static activation failures from typed evide…
masarray Oct 7, 2026
706ad53
refactor(canonical): normalize configured DataSet and RCB identity at…
masarray Oct 7, 2026
18d0ac1
test(canonical): require configured identity equality across Discover…
masarray Oct 7, 2026
302f788
fix(canonical): repair configured-reference ingress normalizer after …
masarray Oct 7, 2026
ca41ca2
feat(reporting): add JIT configured-static readback proof policy (#144)
masarray Oct 7, 2026
c2c2799
fix(reporting): fail closed when configured-static RptEna readback is…
masarray Oct 7, 2026
ad6bfc5
test(reporting): lock configured-static JIT readback proof contract (…
masarray Oct 7, 2026
97363b9
perf(reporting): add minimal JIT RCB snapshot fast path (#144)
masarray Oct 7, 2026
ac6094e
feat(reporting): retain exact JIT RCB state evidence in snapshots (#144)
masarray Oct 7, 2026
7c6f3f6
perf(reporting): prove configured static activation with one exact re…
masarray Oct 7, 2026
86915ca
perf(reporting): use minimal JIT preflight and single exact post-enab…
masarray Oct 7, 2026
f7675a6
test(reporting): lock minimal one-readback configured-static proof (#…
masarray Oct 7, 2026
12bb6bb
test(reporting): fix busy-evidence fixture construction (#144)
masarray Oct 7, 2026
327d499
ci(#144): overlay targeted hot-path slice
masarray Oct 7, 2026
048d39d
ci(#144): overlay targeted hot-path slice
masarray Oct 7, 2026
1b64dfb
ci(#144): overlay targeted hot-path slice
masarray Oct 7, 2026
b33ce7f
ci(#144): overlay targeted hot-path slice
masarray Oct 7, 2026
7ad1193
ci(#144): overlay targeted hot-path slice
masarray Oct 7, 2026
e78f007
ci(#144): overlay targeted hot-path slice
masarray Oct 7, 2026
d129faa
ci(#144): overlay targeted hot-path slice
masarray Oct 7, 2026
1722093
ci(#144): refresh targeted hot-path read-budget fixes
masarray Oct 7, 2026
bad81df
ci(#144): refresh targeted hot-path read-budget fixes
masarray Oct 7, 2026
1a033ab
ci(#144): refresh structure type-prewarm optimization
masarray Oct 7, 2026
7cef117
ci(#144): refresh structure type-prewarm optimization
masarray Oct 7, 2026
a39e932
ci(#144): overlay asynchronous armed-to-traffic proof state
masarray Oct 7, 2026
f5e8a45
ci(#144): overlay canonical-to-live RCB target resolver
masarray Oct 7, 2026
7f7328e
ci(#144): overlay canonical-to-live RCB target resolver
masarray Oct 7, 2026
4c31f11
ci(#144): refresh canonical targeted-RCB integration
masarray Oct 7, 2026
c69bebf
ci(#144): refresh canonical targeted-RCB integration
masarray Oct 7, 2026
1868ea8
ci(#144): refresh canonical targeted-RCB integration
masarray Oct 7, 2026
c0609d5
ci(#144): refresh canonical targeted-RCB integration
masarray Oct 7, 2026
cba751f
perf(reporting): integrate event-driven report wake for exact-head CI…
masarray Oct 7, 2026
471c1f1
perf(reporting): integrate event-driven report wake for exact-head CI…
masarray Oct 7, 2026
d5d82c5
perf(reporting): integrate event-driven report wake for exact-head CI…
masarray Oct 7, 2026
71a8a52
test(reporting): prove burst reports coalesce without stale wake (#144)
masarray Oct 7, 2026
9bb2f93
feat(reporting): integrate P6 source-aware acquisition preflight for …
masarray Oct 7, 2026
93e1a80
feat(reporting): integrate P6 source-aware acquisition preflight for …
masarray Oct 7, 2026
edf41a8
feat(reporting): integrate source-bound P6 preflight for exact-head C…
masarray Oct 7, 2026
959ca81
feat(reporting): integrate source-bound P6 preflight for exact-head C…
masarray Oct 7, 2026
060a217
feat(reporting): integrate source-bound P6 preflight for exact-head C…
masarray Oct 7, 2026
866b10d
feat(reporting): integrate source-bound P6 preflight for exact-head C…
masarray Oct 7, 2026
89c655e
test(reporting): prove live MMS inventory authority is stamped at dis…
masarray Oct 7, 2026
cd7002d
feat(reporting): integrate canonical structural inventory projection …
masarray Oct 7, 2026
b0860f6
feat(reporting): integrate canonical structural inventory projection …
masarray Oct 7, 2026
4d97751
feat(reporting): integrate canonical structural inventory projection …
masarray Oct 7, 2026
b8ff24b
test(reporting): use canonical SCL evidence enum name (#144)
masarray Oct 7, 2026
51fa709
test(reporting): use canonical SCL evidence enum name (#144)
masarray Oct 7, 2026
5858a86
feat(reporting): integrate P6.1 targeted live RCB reconciliation for …
masarray Oct 7, 2026
9c52925
feat(reporting): integrate P6.1 targeted live RCB reconciliation for …
masarray Oct 7, 2026
79f9de0
fix(scl): resolve same-IED ServerAt chains with fail-closed owner sem…
masarray Oct 8, 2026
8b57df8
fix(scl): preserve referenced Server model for ServerAt endpoint proj…
masarray Oct 8, 2026
f111948
fix(scl): recognize valid ServerAt in engineering profile; flag inval…
masarray Oct 8, 2026
ebffc41
test(scl): Siemens-style J Server plus F ServerAt dual endpoint regre…
masarray Oct 8, 2026
cee8021
fix(scl): resolve ServerAt owner for exact MMS domain inventory on se…
masarray Oct 8, 2026
90ec4f2
fix(scl): carry ServerAt model through SCL-assisted initial FC-read p…
masarray Oct 8, 2026
0f32a71
test(scl): ServerAt must preserve both MMS domains and SCL-assisted i…
masarray Oct 8, 2026
e45259b
test(scl): import exact domain and initial-read authority namespace
masarray Oct 8, 2026
352c81e
test(scl): retain no-server fail-closed check with ServerAt-aware dia…
masarray Oct 8, 2026
fd1e8f4
feat(discovery): close static dataset LN schemas without full name en…
masarray Oct 9, 2026
f42318c
test(discovery): gate new LN roots on exact dataset plus successful G…
masarray Oct 9, 2026
8b0c0f7
fix(discovery): restore complete policy source and deterministic memb…
masarray Oct 9, 2026
d8dc2d2
feat(identity): exact trusted-SCL IED/LD mapping on pinned smart-disc…
masarray Oct 10, 2026
d34757e
fix(scl): thread verified IED/LD identity through canonical live expo…
masarray Oct 10, 2026
00ad281
test(identity): construct canonical fixture with an observed logical …
masarray Oct 11, 2026
5559406
fix(simulation): serialize MMS InformationReport emission per associa…
masarray Oct 11, 2026
ef0fe44
ci: validate engine staging pull requests in existing Windows .NET wo…
masarray Oct 11, 2026
fa93c9f
fix(mms): quarantine contradictory RptID/DatSet reports before proces…
masarray Oct 11, 2026
d700b0d
fix(mms): fail closed instead of silently dropping overflowed report …
masarray Oct 11, 2026
9bd0190
fix(mms): bound canonical report ingress and fail closed on overflow/…
masarray Oct 12, 2026
98f2119
fix(scl): decode unambiguous BER-packed AP-title in trusted associati…
masarray Oct 12, 2026
67c6635
fix(control): identify BSC TapChg from live ValWithTrans status path
masarray Oct 12, 2026
a43b9b4
P10.9K: gate generic control semantics and reuse per-association MMS …
masarray Oct 12, 2026
55fa34c
P10.9L: add bounded read-only exact MMS ctlModel evidence probe
masarray Oct 12, 2026
5e17da5
fix: remove escaped newline from P10.9L probe declaration
masarray Oct 12, 2026
f7a4e3b
P10.9Q: explicit guarded one-shot CF ctlModel commissioning with exac…
masarray Oct 12, 2026
d1dd8fc
P10.9R: support explicit ctlModel status-only value 0 in one-shot CF …
masarray Oct 12, 2026
f3860d9
P10.9T: verify structured MMS status; allow normal SBO without option…
masarray Oct 12, 2026
9d82523
P10.9T: repair structured-status implementation syntax and keep typed…
masarray Oct 12, 2026
0ae297c
P10.9U: resolve CSWI Pos ST status via single typed MMS read when dis…
masarray Oct 12, 2026
1a7ce83
P10.9U: fix xUnit analyzer violations in truncated-NameList control t…
masarray Oct 12, 2026
ad43399
P10.9U: align structured position regression with exactly one typed S…
masarray Oct 12, 2026
38420f1
fix(control): honor exact typed live BSC over stale SPC projection
masarray Oct 13, 2026
036e2c0
test(control): cover stale SPC to exact BSC and fail-closed mismatches
masarray Oct 13, 2026
79e48bb
fix(fault-records): add exact RIO sidecar to verified COMTRADE bundle
masarray Oct 16, 2026
aecaa3c
test(fault-records): exact basename/directory RIO inclusion and orpha…
masarray Oct 16, 2026
cfd2a54
fix(m217k): project typed ST enum status FCD tuples for C264 Mod/PhyH…
masarray Oct 17, 2026
54bdc4b
test(m217k): physical C264 typed Mod/Beh/PhyHealth ST FCD and strict …
masarray Oct 17, 2026
e61989f
ci(m217k): run engine Windows test gate on pinned PR169 stacked branch
masarray Oct 17, 2026
51c2eef
test(m217k): incomplete live schema must not suppress typed C264 ST F…
masarray Oct 17, 2026
b27842a
test(identity): reproduce truncated device-name suffix and unverified…
masarray Oct 19, 2026
bcc8e22
fix(identity): preserve exact shared prefix and mark unverified domai…
masarray Oct 19, 2026
e1ba425
test(identity): align pre-existing shared-prefix expectation with pro…
masarray Oct 19, 2026
f2bf05e
test(identity): require all MMS-only and operator identities remain u…
masarray Oct 19, 2026
5b30f51
test(identity): require provisional confidence for suffix and operato…
masarray Oct 19, 2026
fbd6c4f
test(identity): require exact five-LD SCL and fail-closed AP/IP/domai…
masarray Oct 19, 2026
4cc3bde
test(identity): five-LD SCL proof and fail-closed missing endpoint
masarray Oct 19, 2026
10b3584
fix(identity): do not mark operator aliases or MMS suffix heuristics …
masarray Oct 19, 2026
1f3a601
fix(identity): mark all MMS suffix inference and operator alias as pr…
masarray Oct 19, 2026
f2bdb7f
fix(identity): require exact SCL domain/AP and connected endpoint proof
masarray Oct 19, 2026
a662834
fix(identity): fail closed on topology-equivalent AP with missing end…
masarray Oct 19, 2026
9e6b142
fix(identity): reject all duplicate topology-compatible APs before en…
masarray Oct 19, 2026
2dbfc21
test(identity): preserve distinct case-sensitive live MMS LD domain n…
masarray Oct 19, 2026
3c841f2
test(identity): AP selector cannot conceal another indistinguishable AP
masarray Oct 19, 2026
a12cee6
fix(identity): evaluate all AP ambiguity before applying operator AP …
masarray Oct 19, 2026
cd3b631
fix(identity): preserve case-sensitive MMS domain inventory and exact…
masarray Oct 19, 2026
313af3c
test(identity): distinct MMS domain casing must not overwrite alias i…
masarray Oct 19, 2026
ccf31f6
fix(identity): retain exact case-sensitive MMS aliases in resolved id…
masarray Oct 19, 2026
0504654
test(rcb): reproduce 66/300 candidate global guard and require exact-…
masarray Oct 19, 2026
dbf1189
feat(rcb): exact-target indexed read admission with stable bounded co…
masarray Oct 19, 2026
b2d3519
fix(rcb): replace global 64/128 admission abort with exact dataset sc…
masarray Oct 19, 2026
dc31e0f
fix(rcb): fence continuation cursor to accepted MMS association lifetime
masarray Oct 19, 2026
f2765f5
fix(rcb): fence continuation cursor to accepted MMS association lifetime
masarray Oct 19, 2026
f9f0189
fix(rcb): fence continuation cursor to accepted MMS association lifetime
masarray Oct 19, 2026
7f96daf
fix(rcb): fence continuation cursor to accepted MMS association lifetime
masarray Oct 19, 2026
adffc51
test(rcb): prove occupied matching RCB blocked while exact free sibli…
masarray Oct 19, 2026
37cd183
perf(rcb): prioritize indexed configured RCB instances for read-only …
masarray Oct 19, 2026
c79ee7d
perf(rcb): hash-index prioritized candidate exclusion rather than rep…
masarray Oct 19, 2026
954e48f
perf(rcb): stop paged reads after each exact DataSet has strong non-b…
masarray Oct 19, 2026
3d4599f
test(rcb): prioritize two indexed instances in 302 catalog without fa…
masarray Oct 19, 2026
6391244
test(rcb): correct 300 unrelated plus two relevant catalog cardinality
masarray Oct 19, 2026
1a3d82b
test(rcb): reject wrong live DatSet even when configured RCB referenc…
masarray Oct 19, 2026
edf9294
fix(rcb): refuse exact-name fallback when live DatSet binding contrad…
masarray Oct 19, 2026
59ecf1b
feat(rcb): bounded resumable exact-target availability pager without …
masarray Oct 19, 2026
15f9d55
test(rcb): replace preflight global target budget rejection with 66/3…
masarray Oct 19, 2026
e8b6be6
fix(rcb): page exact-target availability and stop on safe eligible ca…
masarray Oct 19, 2026
d9e7952
fix(rcb): count deferred exact targets by actual probe admission, not…
masarray Oct 19, 2026
ad7e65b
fix(mms): reject malformed primitive wire payloads instead of fabrica…
masarray Oct 19, 2026
b1682e8
fix(mms): enforce BER boolean payload width before typed admission
masarray Oct 19, 2026
5dbccbc
test(mms): malformed boolean/int/float/bitstring cannot become synthe…
masarray Oct 19, 2026
91894b3
feat(mms): typed access-failure taxonomy distinct from read result pa…
masarray Oct 19, 2026
1c8e105
feat(mms): propagate typed single read failure evidence without synth…
masarray Oct 19, 2026
e58f33c
feat(mms): propagate typed ordered batch read failure evidence withou…
masarray Oct 19, 2026
186b844
fix(mms): quarantine entire batch when access-result ordinal count mi…
masarray Oct 19, 2026
1414948
ci(p0-c): run full Windows engine gate on P0-B-stacked typed read branch
masarray Oct 19, 2026
ba21d88
test(p0-c): typed per-access MMS Read failure, invoke fence, strict o…
masarray Oct 19, 2026
17600f2
feat(p0-g): preserve explicit SCL Edition 2.2 identity in engine model
masarray Oct 20, 2026
bd67169
fix(p0-g): identify SCL 2007/C/5 as Edition 2.2 and reject contradict…
masarray Oct 20, 2026
329fa0f
test(p0-g): synthetic Edition 1/2/2.1/2.2 SCL root matrix and invalid…
masarray Oct 20, 2026
ded5036
ci(p0-g): exact-SHA Windows gate for stacked P0-C engine successor
masarray Oct 20, 2026
c85d4e2
fix: isolate RCB reports from control indications and expose control …
masarray Oct 20, 2026
3aa0caf
feat(p0-c): attribute SBOw latency to negative-indication observation…
masarray Oct 20, 2026
9c7cb40
test(p0-c): reject immediate and delayed SBOw LastApplError without s…
masarray Oct 20, 2026
7929969
perf(mms): bound independent RCB attribute enrichment by negotiated o…
masarray Oct 21, 2026
07c86b8
testable(policy): negotiated-window and candidate bounded report-enri…
masarray Oct 21, 2026
63f2536
perf(mms): use tested negotiated RCB worker-policy admission
masarray Oct 21, 2026
4829f9d
test(p0): deterministic report window caps and no extra MMS Read/writ…
masarray Oct 21, 2026
d095b3a
fix(discovery): mark interrupted RCB worker on association loss inste…
masarray Oct 21, 2026
f2b18df
feat(control-telemetry): measure exact confirmed MMS send, response w…
masarray Oct 21, 2026
3850e7b
feat(control-telemetry): measure exact confirmed MMS send, response w…
masarray Oct 21, 2026
695df4e
feat(control-telemetry): measure exact confirmed MMS send, response w…
masarray Oct 21, 2026
4ed76cc
test(control): pin per-invoke opt-in send/confirmed-response stages a…
masarray Oct 21, 2026
bd9a2bb
fix(control): recognize IEC 61850 prefixed CSWI/XCBR/XSWI LN identiti…
masarray Oct 22, 2026
3a09b1e
fix: correct grouping of strict Boolean DPC ctlVal/status condition
masarray Oct 22, 2026
48c4582
feat(IEC control): prove Boolean DPC by exact live two-bit stVal, ind…
masarray Oct 22, 2026
5744f30
fix(control): reuse typed stVal proof from targeted probe without dup…
masarray Oct 22, 2026
951449f
fix(control): recover renamed Boolean controls under truncated MMS Na…
masarray Oct 22, 2026
a4ddbc7
fix(control): recover BSC TapChg behind truncated NameList via bounde…
masarray Oct 22, 2026
24aae46
perf(control): preserve typed ST read proof and avoid duplicate same-…
masarray Oct 22, 2026
ef17070
merge(engine): consolidate verified #189 + #186 + #187 + #182 without…
masarray Oct 22, 2026
5077d6a
merge(engine): retain #170 RIO sidecar and sync reviewed CI mainline
masarray Oct 22, 2026
14b19d3
merge(engine): preserve sustained SV analysis #130 and source-typed S…
masarray Oct 22, 2026
b3688be
merge(staging): consolidate 7 source lanes with verified Windows CI (…
masarray Oct 22, 2026
44ac755
test(deps): safely rebase #171 package updates onto staging preservin…
masarray Oct 22, 2026
a50c946
feat(discovery): port #155 verified DataSet-first late-LN type hints …
masarray Oct 22, 2026
d086ed5
merge(staging): verified DataSet-first late LN type-probe opt-in (#193)
masarray Oct 22, 2026
553f008
test(identity): preserve original #175 global identity behavior witho…
masarray Oct 22, 2026
725662b
merge(staging): retain #175 global IED identity regression coverage (…
masarray Oct 22, 2026
bfc94a2
fix(mms): reject mismatched single-variable Write response cardinality
masarray Oct 23, 2026
4f75b0c
test(mms): fail closed on empty/multiple Write results and wrong invo…
masarray Oct 23, 2026
92f8143
test(mms): correct BER constructed Write response fixture length
masarray Oct 23, 2026
fc998bc
test(mms): correct two-access Write BER fixture child length from 6 to 4
masarray Oct 23, 2026
f75e323
stage(mms): enforce single-result Write response cardinality and BER …
masarray Oct 23, 2026
5bc562d
mms: reject contradictory short DatSet even when RptID matches
masarray Oct 27, 2026
003a0ef
mms: preserve exact shortened LN.DataSet compatibility
masarray Oct 27, 2026
ca502b8
test: four SG7 RCB identities and abbreviated DataSet conflict fail c…
masarray Oct 27, 2026
fbbee71
test: restore exact baseline and add literal-safe SG7 routing cases
masarray Oct 27, 2026
5923029
MMS: fail-closed short DatSet identity during Report routing
masarray Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Control/report isolation trial — 2026-10-20

- Reject non-RCB InformationReport shapes before persistent single-monitor fallback; control termination and LastApplError remain available to independent control subscribers.
- Include monotonic service duration and post-response wait in each control wire-step detail. UTC marks local service start, not wire send. This separates SBOw/Operate service latency from asynchronous completion wait without changing timeout, checks, or command sequencing.
- Synthetic regression coverage added; physical latency improvement is not yet established.

All notable public changes to ARIEC61850 are recorded here. The project is still evolving toward stable semantic releases; entries are grouped by engineering milestone until a formal versioning policy is adopted.

## Unreleased — public wording, provenance and release assurance
Expand Down
139 changes: 139 additions & 0 deletions docs/P3_SAMPLED_VALUES_ANALYSIS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# P3 — Sampled Values Analysis

P3 begins the `ROADMAP.md` Sampled Values analysis priority without replacing the established IEC 61850-9-2 parser, payload decoder, SCL binding, or publisher code.

## Engine boundary

P3 now has a sustained, bounded stream-analysis layer plus a source-neutral observation session after successful SV decoding:

```text
Live capture / PCAP replay
|
v
existing SV frame parser
|
v
SampledValuesFrame
|
v
SvSustainedObservationSession
|
+--> existing SvStreamObservationManager
| `--> profile / SCL comparison
|
+--> SvSustainedStreamAnalyzer
| +--> bounded stream registry
| +--> smpCnt continuity / missing-sample evidence
| +--> arrival-rate / jitter / dropout evidence
| +--> payload-length stability
| `--> smpSynch observations
|
`--> optional explicit SCL profile
`--> existing SampledValuesPayloadDecoder
`--> SvSclBoundMeasurementProjector
`--> SvEngineeringWindowAnalyzer
`--> SvSignalWindowAnalyzer
```

`SvSustainedObservationSession` is deliberately downstream of the existing frame parser. It accepts an already parsed `SampledValuesFrame`, sends the frame through `SvStreamObservationManager` first, and advances sustained state only when that canonical observation path accepts the frame. Live capture and PCAP replay therefore share the same parsed-frame admission and stream-identity path. The session does not add a raw capture parser, a second SV decoder, or a second channel model.

`SvSustainedStreamAnalyzer` retains incremental counters and timing statistics rather than packet payload history. Stream cardinality is bounded, idle streams are evicted, and the oldest stream is evicted when the configured registry capacity is reached. The default registry limit is 256 streams.

The stream identity reuses the existing `SvObservedStreamKey` (`APPID`, source/destination MAC, VLAN, `svID`, and DataSet reference), so this phase does not introduce a second stream-identity model.

## Source provenance

`SvObservationInputKind` remains the provenance marker for the established observation path (`LiveCapture` or `PcapReplay`). The new session preserves that marker while making the sustained metrics source-neutral: equivalent parsed frames with equivalent timestamps produce equivalent sustained evidence regardless of whether the caller obtained them from live capture or PCAP replay.

This is an integration boundary, not a claim that the repository now contains every live-capture or PCAP-file reader required by a production application. Capture-specific byte acquisition remains outside this analyzer and must feed the established SV parser before entering the session.

## Continuity evidence

Sample-counter continuity reuses `SvSampleCounterTracker`. P3 records continuous transitions, normal wraps, forward gaps, missing-sample counts, duplicates, and out-of-order transitions. A caller may supply a trusted/configured counter modulus; otherwise the existing tracker remains profile-neutral.

A sample-counter gap means samples were not observed by this analyzer. It is evidence of an observation gap, not by itself proof of physical-network packet loss.

The engineering-window layer reuses the same tracker rather than implementing a second counter algorithm. An incomplete one-cycle engineering window is discarded on a gap, duplicate, out-of-order transition, restart, channel-metadata change, or timebase/evidence change. A gap/out-of-order/restart sample may begin a new clean window; a duplicate is not counted as a new time sample.

## Timing evidence and claim boundary

P3 records mean frame interval, observed frame rate, estimated sample rate, arrival-interval standard deviation, maximum observed arrival jitter, and large arrival intervals.

Timestamp provenance is explicit:

- `HostSoftwareTimestamp` is ordinary host/capture-arrival evidence only.
- `HardwareTimestamp` records that the caller supplied hardware timestamp evidence, but does **not** by itself prove clock accuracy, PTP synchronization quality, or IEC 61850 process-bus timing performance.
- `Unknown` makes no stronger timing claim.

Applications must carry this claim boundary forward. A Windows or other ordinary host timestamp must never be relabeled as precision synchronization evidence.

## Synchronization evidence

The analyzer counts observed `smpSynch` values (0, 1, 2, and other values) exactly as decoded. This is wire evidence. P3 does not infer clock quality, grandmaster identity, or station synchronization health solely from these counts.

## Payload-layout evidence

For a stable stream identity, P3 records the first ASDU payload length and marks the stream when later ASDUs change length. This complements the existing SCL-aware payload decoder and configuration comparer; it does not guess signal semantics from raw word positions.

When no explicit `SampledValuesPublisherProfile` is supplied, `SamplePayload` remains opaque to the observation session. When a profile is supplied, `SvSclBoundMeasurementProjector` reuses that profile's existing `SampledValuesPayloadLayout` and `SampledValuesPayloadDecoder`; it does not infer a new layout from packet shape.

## Evidence-backed channel projection

`SvSclBoundMeasurementProjector` provides the conservative bridge from an explicitly bound SCL publisher profile into numeric channel samples. Before decoding it requires exact APPID, destination MAC, VLAN, `svID`, DataSet reference, and `confRev` compatibility. Unsupported SCL layout elements or a payload-length mismatch fail closed rather than shifting offsets and continuing with guessed semantics.

Numeric values always retain their decoded raw value. Engineering values are emitted only when the existing `SvEngineeringScaleResolver` has sufficient SCL-backed evidence. The currently supported installed-base scaling rule additionally requires the exact fixed eight-value/eight-quality, 64-byte layout, four SCL-derived current channels, four SCL-derived voltage channels, and protection-rate evidence. Other valid SCL layouts remain raw-only until a separate explicit scale rule exists.

CT/VT conversion is also explicit. An optional `SvStreamMeasurementContext` is accepted only when its validated stream key and optional `svID` match the observed stream. Primary/secondary-equivalent values are then produced through `SvMeasurementDomainResolver`; a missing, invalid, or mismatched context never causes a ratio to be guessed.

## Bounded engineering windows, RMS, and phasor

`SvEngineeringWindowAnalyzer` is the bridge from successfully SCL-bound/scaled projected samples into the existing `SvSignalWindowAnalyzer`. It never decodes payload bytes and never manufactures engineering units. Samples whose projection remains raw-only are intentionally excluded from engineering RMS/phasor state.

The caller must provide `SvEngineeringWindowEvidence` containing a finite positive sample rate and fundamental frequency plus their provenance. `Unknown` and `ProfileInferred` provenance is rejected for these values, so the analyzer never chooses 50 Hz versus 60 Hz itself. The ratio `sampleRateHz / fundamentalFrequencyHz` must resolve to an integral one-cycle sample count within the configured tolerance and bounded maximum before any state is created.

State is bounded at three dimensions: maximum streams, maximum channels per stream, and maximum samples per cycle. The default configuration is 256 streams × 32 channels × 512 samples/cycle, with an additional validation guard that rejects option combinations whose theoretical retained `double` sample buffers could exceed 64 MiB. The analyzer stores only the current incomplete cycle for each active channel; completed cycle history is not retained internally.

Each channel is keyed by the SCL projection element index and guarded by exact signal reference, CDC, engineering unit, scale source, and scale confidence. A metadata change resets the partial waveform and counter state before accepting the new identity. Timebase, nominal-frequency, or counter-wrap evidence changes likewise reset partial state across that stream.

`SvSignalWindowAnalyzer` remains the deterministic one-cycle-window primitive. It receives exactly one complete, continuity-clean engineering window and returns:

- true window RMS;
- fundamental RMS magnitude;
- fundamental phase angle; and
- sample count.

No frequency, channel meaning, CT/VT ratio, engineering unit, or missing sample is guessed by either layer.

## Deterministic regression coverage

Synthetic tests cover:

- sustained 4 kHz stream-rate estimation;
- continuous sample counters and synchronization observations;
- sample-counter gaps and missing-sample totals;
- arrival-time dropout diagnostics with explicit non-network-loss wording;
- bounded stream-registry eviction;
- payload-length changes inside one stream identity;
- host-vs-hardware timestamp claim boundaries;
- RMS/fundamental phasor accuracy for a deterministic sine wave;
- one-ingress coordination of observation and sustained snapshots;
- equivalent sustained metrics for equivalent live-capture and PCAP-replay parsed frames;
- fail-closed behavior when the canonical observation path rejects an empty-payload frame;
- a 10,000-frame synthetic ingestion regression that keeps the sustained registry at its configured stream bound;
- fixed SCL-bound current/voltage projection using the existing payload decoder;
- explicit primary-to-secondary CT/VT display conversion;
- raw-only preservation for SCL layouts without an approved engineering-scale rule;
- fail-closed APPID and `confRev` mismatch handling before payload projection;
- one-cycle engineering RMS/phasor from explicitly scaled samples;
- raw-only exclusion from engineering-window state;
- partial-window reset after `smpCnt` gap and duplicate evidence;
- normal counter-wrap continuity;
- channel-metadata change reset;
- fail-closed non-integral samples-per-cycle and inferred-frequency input; and
- bounded engineering stream/channel registries.

These are unit-test and synthetic-fixture claims only. This phase does not claim production timing accuracy, formal conformance, universal device interoperability, or operational-substation validation.

## Remaining P3 work

The per-channel engineering-window slice is now implemented, but the roadmap priority is not complete. Follow-up work should connect application live-capture and PCAP replay byte sources to the established parser plus `SvSustainedObservationSession`, carry explicit timebase/frequency evidence into `SvEngineeringWindowAnalyzer`, add sanitized real/replay validation fixtures and longer bounded soak evidence, and expose evidence/export contracts without retaining customer or live-network identifiers.
61 changes: 49 additions & 12 deletions src/AR.Iec61850.Simulation/MmsServer/MmsReportingRuntime.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Globalization;
using System.Threading.Channels;
using AR.Iec61850.Asn1;
using AR.Iec61850.Mms;

Expand Down Expand Up @@ -192,6 +193,17 @@ public sealed class MmsAssociationReportingRuntime : IMmsAssociationRuntime, IDi
private readonly Dictionary<string, Timer> _integrityTimers = new(StringComparer.OrdinalIgnoreCase);
private readonly object _gate = new();
private readonly CancellationTokenSource _cts = new();
// One FIFO per MMS association. A distinct Task.Run per report previously
// allowed send delegates to acquire the socket lock in a different order
// from the SqNum assignment, manufacturing on-wire discontinuities.
private readonly Channel<(MmsRcbRuntimeState State, byte Reason)> _sendQueue =
Channel.CreateUnbounded<(MmsRcbRuntimeState, byte)>(
new UnboundedChannelOptions
{
SingleReader = true,
SingleWriter = false,
AllowSynchronousContinuations = false
});
private bool _disposed;

public MmsAssociationReportingRuntime(
Expand Down Expand Up @@ -226,6 +238,12 @@ public MmsAssociationReportingRuntime(
IntgPd = (uint)Math.Max(0, rcb.IntegrityPeriodMs)
};
}

// One asynchronous worker is allocated per association, not per report.
// Capture the token here: a delayed worker must never access a CTS
// after Dispose() has disposed its source.
var senderToken = _cts.Token;
_ = Task.Run(() => DrainReportQueueAsync(senderToken));
}

public IReadOnlyCollection<MmsRcbRuntimeState> States => _states.Values;
Expand Down Expand Up @@ -414,6 +432,7 @@ public void Dispose()
return;

_disposed = true;
_sendQueue.Writer.TryComplete();
_cts.Cancel();
lock (_gate)
{
Expand Down Expand Up @@ -449,21 +468,39 @@ private void QueueReport(MmsRcbRuntimeState state, byte reason)
if (_disposed)
return;

_ = Task.Run(async () =>
// Channel FIFO is the report ordering authority. No per-report Task.Run,
// no competing asynchronous socket writers and no silent report drop.
_sendQueue.Writer.TryWrite((state, reason));
}

private async Task DrainReportQueueAsync(CancellationToken cancellationToken)
{
try
{
try
{
await SendReportAsync(state, reason, _cts.Token).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
// Association closing.
}
catch (Exception ex) when (ex is IOException or ObjectDisposedException or System.Net.Sockets.SocketException or InvalidOperationException)
await foreach (var request in _sendQueue.Reader.ReadAllAsync(cancellationToken)
.ConfigureAwait(false))
{
_activity?.Invoke(state.MmsReference, false, $"InformationReport send failed: {ex.Message}");
try
{
await SendReportAsync(request.State, request.Reason, cancellationToken)
.ConfigureAwait(false);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
return;
}
catch (Exception ex) when (ex is IOException or ObjectDisposedException or
System.Net.Sockets.SocketException or InvalidOperationException)
{
_activity?.Invoke(request.State.MmsReference, false,
$"InformationReport send failed: {ex.Message}");
}
}
}, CancellationToken.None);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
// Association closing: pending reports are not sent on a dead socket.
}
}

private async Task SendReportAsync(MmsRcbRuntimeState state, byte reason, CancellationToken cancellationToken)
Expand Down
10 changes: 9 additions & 1 deletion src/AR.Iec61850/Control/Iec61850ControlModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ public sealed class Iec61850ControlObjectDescriptor
public MmsTypeSpecificationNode? CancelSpecification { get; init; }
public string StatusReference { get; init; } = string.Empty;
public string StatusFunctionalConstraint { get; init; } = string.Empty;
/// <summary>
/// Live MMS Read proved a two-bit stVal Dbpos on the SAME control DataObject.
/// This typed evidence, not an LN/DO name, can distinguish Boolean DPC
/// Oper.ctlVal from a Boolean SPC control.
/// </summary>
public bool LiveStatusIsDoublePoint { get; init; }
public TimeSpan? SboTimeout { get; init; }
public TimeSpan? OperTimeout { get; init; }
public bool SupportsTimeActivatedOperate { get; init; }
Expand All @@ -174,7 +180,9 @@ public sealed class Iec61850ControlObjectDescriptor
ControlModel is not Iec61850ControlModel.StatusOnly and not Iec61850ControlModel.Unknown &&
!string.IsNullOrWhiteSpace(ObjectReference) &&
!string.IsNullOrWhiteSpace(CtlValSpecification.MmsType) &&
(!RequiresSelect || CancelSpecification != null) &&
// Normal SBO Select -> Operate does not depend on optional Cancel.
// Enhanced SBO still requires Cancel for sequence recovery.
(ControlModel != Iec61850ControlModel.SelectBeforeOperateEnhanced || CancelSpecification != null) &&
(ControlModel != Iec61850ControlModel.SelectBeforeOperateEnhanced || SelectWithValueSpecification != null) &&
(!IsEnhanced || SupportsCommandTermination);

Expand Down
Loading
Loading