Skip to content

Add dedicated IO List Testing import and binding workspace - #111

Merged
masarray merged 32 commits into
mainfrom
agent/io-list-testing-foundation
Jul 28, 2026
Merged

masarray merged 32 commits into
mainfrom
agent/io-list-testing-foundation

Conversation

@masarray

@masarray masarray commented Jul 28, 2026 •

Copy link
Copy Markdown
Owner

Purpose

Implement the first usable IO List Testing phase as a dedicated FAT workspace without mixing the customer-facing test flow into the existing protocol workstation.

Imported FAT workflow

  • adds an IO List Testing launcher to the engineering workstation header
  • imports schema ARSAS-FAT-IO-1.0 directly from the ARSAS_SIGNAL_IMPORT XLSX sheet
  • groups the imported SDI scope by IED name and IP address
  • opens a separate maximized IoListTestingWindow
  • hides the engineering window while the focused FAT workspace is open
  • shows only imported IEDs and imported SDI signals, never the complete discovered IED model

XLSX import safety

  • no new Excel runtime dependency; the importer reads the Open XML package directly
  • required headers, schema, project identity, IED/IP ownership, TestPointId uniqueness, DataType=SDI, FC=ST and binary ON/OFF state definitions are validated
  • invalid workbooks are rejected as a whole instead of guessed or partially executed
  • non-SDI rows are skipped with explicit warnings
  • source workbook name and SHA-256 are retained
  • safety bounds: 50 MB workbook and 20,000 imported signal rows

Live binding preview

  • matches imported IEDs against currently loaded ARSAS devices using IED identity and IP
  • matches exact object references first, then a unique normalized IED-prefix telegram
  • distinguishes IED-not-loaded, signal-missing, model-bound, normalized-bound and already-live points
  • displays current value, quality and acquisition source when a matching live monitor point already exists

Evidence foundation

  • explicit IO project, IED, signal, runtime observation and transition-evidence models
  • restart-aware OFF → ON → OFF state machine
  • no PASS from a signal that was already ON when the attempt started
  • duplicate/out-of-order observations do not create evidence
  • first image after reconnect is baseline only
  • reconnect after ON evidence forces REVIEW rather than inventing OFF evidence
  • invalid quality never advances the state machine

Current boundary

This phase provides import, validation, IED-scoped workspace navigation and live-binding preview. FAT execution remains intentionally locked until the next tranche connects the point-update controller, session lifecycle and durable append-only evidence journal.

There is no IEC 61850 command or configuration write in this PR.

Regression coverage

  • normal OFF → ON → OFF PASS
  • initial-ON baseline protection
  • duplicate and out-of-order observations
  • invalid/questionable quality
  • reconnect interruption
  • generated XLSX contract import and per-IED grouping
  • missing required-header rejection
  • exact and normalized live binding
  • active live-point current value/quality/source preview
  • explicit missing-device status

Validation requested

The complete Windows solution build and ARSAS.Tests workflow must compile the WPF launcher/window and execute the full regression suite before this draft is promoted.

@masarray masarray changed the title Add dedicated IO List Testing foundation Add dedicated IO List Testing import and binding workspace Jul 28, 2026
@masarray
masarray marked this pull request as ready for review July 28, 2026 07:35
@masarray
masarray merged commit 242403e into main Jul 28, 2026
4 checks 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: eab99602fa

ℹ️ 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 +170 to +172
var ipMatches = devices.Where(device =>
device.IpAddress.Equals(plan.IpAddress, StringComparison.OrdinalIgnoreCase)).ToList();
return ipMatches.Count == 1 ? ipMatches[0] : null;

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 Require matching IED identity before binding by IP

When the imported IP uniquely matches a workspace device whose IED name differs, this fallback binds that device anyway. Signals with unprefixed references can subsequently match exactly or through telegram normalization, causing the FAT preview to display values from a different IED; an identity mismatch should instead block automatic binding or require explicit confirmation.

Useful? React with 👍 / 👎.

Comment on lines +229 to +231
var sourceRow = ParseInt(Get(values, "SourceRow"), row.RowNumber);
var onRaw = ParseInt(Get(values, "ExpectedONRaw"), 1);
var offRaw = ParseInt(Get(values, "ExpectedOFFRaw"), 0);

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 Reject malformed expected-state cells instead of defaulting

When either required ExpectedONRaw or ExpectedOFFRaw cell is blank or non-numeric, these defaults silently turn it into 1 or 0. The validator then sees distinct valid binary values and accepts the workbook, so a malformed or accidentally inverted test definition is imported instead of being rejected; parsing failures should produce findings before constructing the point.

Useful? React with 👍 / 👎.

Comment on lines +363 to +367
private static XDocument LoadXml(ZipArchive archive, string entryPath)
{
var entry = archive.GetEntry(entryPath) ?? throw new InvalidDataException($"XLSX entry '{entryPath}' is missing.");
using var stream = entry.Open();
return XDocument.Load(stream, LoadOptions.None);

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 Bound decompressed XLSX entries before loading XML

For a highly compressed or malicious workbook, the 50 MB check only limits the ZIP file itself, while XDocument.Load eagerly expands each entry without an uncompressed-size or character limit. A small XLSX can therefore allocate an arbitrarily large XML tree and exhaust the application's memory; validate entry lengths and/or parse through a size-limited streaming reader before materialization.

Useful? React with 👍 / 👎.

masarray added a commit that referenced this pull request Sep 16, 2026
Promote the exact field-tested trial head after Build #2850, Installer #1003, COMTRADE #247, Legacy SAS RCB guard #111, IO List #1380, and SV evidence #1830 all passed.
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