Skip to content

SV core: unify generic analysis and measurement ownership - #45

Merged
masarray merged 39 commits into
mainfrom
agent/sv-core-unification
Jul 27, 2026
Merged

SV core: unify generic analysis and measurement ownership#45
masarray merged 39 commits into
mainfrom
agent/sv-core-unification

Conversation

@masarray

@masarray masarray commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Purpose

Make ARIEC61850 the single source of truth for reusable IEC 61850 Sampled Values protocol, measurement, evidence, Publisher-support, and Subscriber-analysis behavior that had diverged inside ARSVIN's embedded engine.

Migrated reusable core

  • generic APDU/ASDU and raw seqOfData inspection
  • evidence-gated engineering scaling with raw fallback
  • timebase resolution without a hidden 50/60 Hz assumption
  • profile-neutral smpCnt continuity, wrap, restart, duplicate, gap, and out-of-order analysis
  • semantic IEC 61850 quality decoding and Publisher quality encoding
  • explicit CT/VT ratio and primary/secondary measurement-domain context
  • versioned measurement-context JSON
  • multi-ASDU Publisher profile/session behavior
  • Sampled Values payload generation, frame preview, validation, PCAP export, and Publisher evidence contracts
  • transmitter timing-health evidence
  • unified live/PCAP observation windows and stable logical stream keys
  • SCL-versus-wire configuration comparison
  • vendor-neutral profile evidence and confidence model
  • Subscriber evidence serialization and regression comparison

Generic architecture rule

Manufacturer or product identity never selects parser layout, ordered dataset mapping, scaling, quality interpretation, nominal frequency, or stream-health result. Runtime semantics come from protocol evidence, SCL, an explicit standard layout, reviewed user context, or known-injection evidence.

Validation

Head fcc05de1f4b11560195e2589aa032e1d4c4b95f7 passed .NET CI run 235:

  • source hygiene, provenance, wording, and license boundaries
  • full restore and Release build
  • complete deterministic test suite
  • uploaded diagnostics

No unresolved review thread remains.

Merge boundary

The reusable engine is ready to merge based on deterministic automated validation and its guarded/evidence-labelled behavior. The following remain post-merge field acceptance tests before calibrated, interoperability, or conformance claims are made:

  • Publisher → PCAP → Subscriber end-to-end replay
  • no-SCL raw fallback inspection
  • matching-SCL ordered dataset mapping
  • nofASDU=1 and multi-ASDU replay
  • known-injection scaling/RMS/phasor comparison
  • authorized isolated live MU test

This merge does not claim formal IEC 61850 conformance or calibrated measurement validation.

masarray added 30 commits July 23, 2026 09:18
@masarray
masarray marked this pull request as ready for review July 27, 2026 07:26
@masarray
masarray merged commit 0f84531 into main Jul 27, 2026
1 check passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fcc05de1f4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +63 to +64
else if (noAsdu > 1)
Add(findings, SampledValuesPublisherValidationSeverity.Info, "SV_NOFASDU_PACKING", $"nofASDU={noAsdu} ASDU(s) per Ethernet frame.", "The publisher will pack sequential samples into one SavPdu.");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject multi-ASDU profiles until publisher callers batch them

For nofASDU=2..8, this validator now reports that sequential samples will be packed, but the inspected GUI publish loop in SvPublisherViewModel.cs still constructs exactly one ASDU per frame, while the CLI path in Program.cs calls PublishNextAsync, which explicitly throws for these profiles. Thus the GUI can transmit frames inconsistent with the SCL configuration and the CLI aborts at runtime; keep these profiles unsupported until both callers use the batch API.

AGENTS.md reference: AGENTS.md:L173-L177

Useful? React with 👍 / 👎.

Comment on lines +142 to +144
if (normalizedChannel.StartsWith("V", StringComparison.OrdinalIgnoreCase) ||
normalizedChannel.Contains("TVTR", StringComparison.OrdinalIgnoreCase) ||
normalizedChannel.Contains("VolSv", StringComparison.OrdinalIgnoreCase))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Check SCL channel tokens before the identifier prefix

When Kind is empty and a fully qualified current-channel reference starts with V because of its IED name—for example VT01/LD0/TCTR1.AmpSv.instMag.i—the prefix check returns Voltage before reaching the explicit TCTR/AmpSv evidence. With otherwise valid fixed-layout evidence, Resolve then labels the current as volts and applies the 0.01 voltage multiplier instead of the 0.001 current multiplier; prioritize the semantic SCL tokens over the arbitrary leading identifier.

AGENTS.md reference: AGENTS.md:L144-L147

Useful? React with 👍 / 👎.

}
private static void Text(ICollection<SvEvidenceFieldChange> changes, string category, string field, string baseline, string candidate, SvEvidenceChangeSeverity severity, string message) { if (!string.Equals(baseline ?? string.Empty, candidate ?? string.Empty, StringComparison.Ordinal)) changes.Add(Change(category, field, severity, baseline, candidate, message)); }
private static void Issue(ICollection<SvEvidenceFieldChange> changes, string field, int baseline, int candidate, SvEvidenceChangeSeverity severity) { if (baseline != candidate) changes.Add(Change("Runtime", field, candidate > baseline ? severity : SvEvidenceChangeSeverity.Info, baseline.ToString(CultureInfo.InvariantCulture), candidate.ToString(CultureInfo.InvariantCulture), candidate > baseline ? $"{field} increased." : $"{field} decreased.")); }
private static void Rate(ICollection<SvEvidenceFieldChange> changes, string field, double? baseline, double? candidate) { if (!baseline.HasValue || !candidate.HasValue) return; var tolerance = Math.Abs(baseline.Value) * RateTolerancePercent / 100.0; if (Math.Abs(candidate.Value - baseline.Value) > tolerance) changes.Add(Change("Rate", field, SvEvidenceChangeSeverity.Warning, baseline.Value.ToString("0.###", CultureInfo.InvariantCulture), candidate.Value.ToString("0.###", CultureInfo.InvariantCulture), "Observed rate moved outside the comparison tolerance.")); }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Treat missing candidate rate as an evidence regression

If the baseline has an observed sample rate but the candidate cannot calculate one—for example because its observation window contains only one timestamped frame—this early return records no change. A comparison with otherwise identical evidence is consequently marked unchanged and may report NO REGRESSION DETECTED even though timing evidence disappeared; distinguish baseline-missing, candidate-missing, and both-missing cases, treating candidate loss as at least a warning.

AGENTS.md reference: AGENTS.md:L173-L178

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant