diff --git a/AI_READ_FIRST.md b/AI_READ_FIRST.md index dccfa502c..5a94e2737 100644 --- a/AI_READ_FIRST.md +++ b/AI_READ_FIRST.md @@ -4,7 +4,7 @@ This repository contains protocol behavior that has been reconstructed from stan Read the topic contract before changing the corresponding code: -- **Current native Qt Workbench / IED Browser progress, exact baseline, red PR and optimized coding handoff:** [`docs/WORKBENCH_CURRENT_HANDOFF.md`](docs/WORKBENCH_CURRENT_HANDOFF.md). Read this before working on `apps/ied_simulator` Browser/Reports/DataSets/Global Data/q/t. +- **Native Qt Workbench / IED Browser cross-thread strategy, ARSAS design reference, SSOT, milestones, ownership and merge gates:** [`docs/WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md`](docs/WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md). **Current checkpoint and active PRs:** [`docs/WORKBENCH_CURRENT_HANDOFF.md`](docs/WORKBENCH_CURRENT_HANDOFF.md). Read **both** before editing `apps/ied_simulator` Browser/Reports/DataSets/Global Data/SG/q/t. - **Live IP discovery vs trusted-SCL online connect:** [`docs/ONLINE_MODEL_CONNECT_DECISION.md`](docs/ONLINE_MODEL_CONNECT_DECISION.md), then [`LIVE_DISCOVERY_PROFILE.md`](LIVE_DISCOVERY_PROFILE.md). - **RCB reporting, URCB/BRCB activation, report bit semantics, replay/recovery:** [`RCB_REPORTING.md`](RCB_REPORTING.md). - **Open SCL, live MMS reconstruction, canonical model normalization, IED-name resolution, and Edition 2 / Edition 1 export:** [`SCL_EXPORT.md`](SCL_EXPORT.md), then [`docs/SCL_IMPORT_NORMALIZATION_PROFILE.md`](docs/SCL_IMPORT_NORMALIZATION_PROFILE.md) and [`docs/SCL_EXPORT_RECONSTRUCTION_PROFILE.md`](docs/SCL_EXPORT_RECONSTRUCTION_PROFILE.md). diff --git a/PROJECT_HANDOFF.md b/PROJECT_HANDOFF.md index 1133fa617..061b6c53b 100644 --- a/PROJECT_HANDOFF.md +++ b/PROJECT_HANDOFF.md @@ -2,7 +2,7 @@ This file is the **current-state handoff** for a new engineer or AI thread. Read [`NORTH_STAR.md`](NORTH_STAR.md) first for the long-term direction, then use this file to continue active development without reconstructing the bench history from chat. -> **Current native IEC 61850 Workbench / Browser engineering track (M2A–M2G):** read [docs/WORKBENCH_CURRENT_HANDOFF.md](docs/WORKBENCH_CURRENT_HANDOFF.md) before resuming Qt Browser, DataSets, Global Data, Reports, typed q/t, CI or Windows Workbench work. This is a dated, SHA-backed checkpoint and lists the active red PR. The SMV/ESP32-P4 release history below belongs to a separate product track. +> **Current native IEC 61850 Workbench / Browser engineering track (M2A–M2J merged; M2K PR #176 active as of 2026-10-15):** read [docs/WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md](docs/WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md) for the shared ARSAS-inspired GUI/SSOT execution plan, cross-thread ownership and CI/merge gates; then read [docs/WORKBENCH_CURRENT_HANDOFF.md](docs/WORKBENCH_CURRENT_HANDOFF.md) for the latest checkpoint and active blockers. **Always refresh GitHub refs**. The SMV/ESP32-P4 release history below is a separate product track. Last major product milestone update: **2026-09-15 — stable public SMV Injector v0.1.0 released**. diff --git a/docs/WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md b/docs/WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md new file mode 100644 index 000000000..78de76d5e --- /dev/null +++ b/docs/WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md @@ -0,0 +1,179 @@ +# ARStack61850 native IED Browser — ARSAS-inspired, SSOT-first engineering strategy + +**Status:** cross-thread execution contract; first written 2026-10-15 (WIB), against ARStack main a328da13133a and ARSAS main 45348eccf24e941dd185e5fb729217923846c610. **Re-query GitHub before acting.** This is a living strategy, not a claim of completed functionality. + +**Product:** the installed **native Qt/QML ARStack Workbench** (apps/ied_simulator), **not** a web GUI, a new desktop app, a WPF port, or the separate ESP32-P4 timing/SV firmware track. The objective is an IEDScout-class engineering workflow while borrowing effective visual/interaction patterns from the ARSAS/ARIEC61850 Windows Explorer. ARStack's own IEC 61850 models and wire evidence remain authoritative. + +## 0. Read order for every thread + +1. [AGENTS.md](../AGENTS.md) and [AI_READ_FIRST.md](../AI_READ_FIRST.md) — hard rules. +2. [This strategy](WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md) — common direction, SSOT, handoffs, gates, ownership. +3. [WORKBENCH_CURRENT_HANDOFF.md](WORKBENCH_CURRENT_HANDOFF.md) — live checkpoint; update after each accepted milestone. +4. [CI_WORKFLOW_ROUTING.md](CI_WORKFLOW_ROUTING.md), [RCB_REPORTING_REFERENCE.md](RCB_REPORTING_REFERENCE.md), [ONLINE_MODEL_CONNECT_DECISION.md](ONLINE_MODEL_CONNECT_DECISION.md) as applicable. +5. Recheck GitHub main SHA, open PRs and their review threads, exact-head Actions, and current file content. This document's SHAs and status are **as-of-snapshot**, not a substitute for live checks. + +**Reviewable design references (pinned to an actual ARSAS revision):** + +- [ARSAS MainWindow.xaml — IEC 61850 Explorer / LIVE SIGNAL VALUES](https://github.com/masarray/arsas/blob/45348eccf24e941dd185e5fb729217923846c610/MainWindow.xaml): IED cards, Connect/Open SCL/Add IED workflow, dense live grid (Signal, IEC Telegram, Value, Quality, IED Timestamp, Acquisition), search, and guarded command panel. +- [ARSAS ExplorerSignalGrid](https://github.com/masarray/arsas/blob/45348eccf24e941dd185e5fb729217923846c610/MainWindow.ExplorerSignalGrid.cs): column sizing and timestamp detail. +- [ARSAS SclLiveModelAuthority](https://github.com/masarray/arsas/blob/45348eccf24e941dd185e5fb729217923846c610/MainWindow.SclLiveModelAuthority.cs) and [live projection](https://github.com/masarray/arsas/blob/45348eccf24e941dd185e5fb729217923846c610/SclLiveSignalModelProjection.Authority.cs): design/live authority reconciliation. +- [ARSAS shared static DataSet authority](https://github.com/masarray/arsas/blob/45348eccf24e941dd185e5fb729217923846c610/MainWindow.SharedStaticDataSetAuthority.cs): preserve static report-first behavior, without automatic cyclic MMS. +- [ARSAS IoList FAT workspace](https://github.com/masarray/arsas/blob/45348eccf24e941dd185e5fb729217923846c610/IoListTestingWindow.xaml): multi-IED selection and engineering context. + +**Copy the *interaction principles*, not WPF/C# runtime, invented values, unsupported IEC semantics, or duplicated services.** ARSAS' IEC 61850 Explorer is a useful reference, but not proof that every ARSAS screen literally matches an IEDScout tab. + +## 1. Exact baseline, active work and merge dependencies + +At creation: +- ARStack main: [a328da13 (M2J merged)](https://github.com/masarray/arstack61850/commit/a328da13133a6473dc6a28a69f5d2aebab7a7198). M2H [#171](https://github.com/masarray/arstack61850/pull/171), M2I [#173](https://github.com/masarray/arstack61850/pull/173) and M2J [#174](https://github.com/masarray/arstack61850/pull/174) are merged. +- M2J post-merge Qt, release hardening, SCL-assisted connect and SCL-assisted Workbench workflows completed successfully at this main SHA. +- **Active integration candidate M2K: [PR #176](https://github.com/masarray/arstack61850/pull/176)**, head **5c5e425c20acb1b849399f39bf62da0f68c0942b** at writing. The SCL-Assisted Workbench CI passed; its exact-head native Qt run [38678320479](https://github.com/masarray/arstack61850/actions/runs/38678320479) was still **in progress** when last inspected. **Do not mark M2K merged/green or start conflicting edits from an assumption.** +- Unmerged PR [#172](https://github.com/masarray/arstack61850/pull/172) (another q/t visual QA branch), [#164](https://github.com/masarray/arstack61850/pull/164) (older q/t branch), and legacy Browser recovery PRs exist. They are **not automatically safe to merge**; review differences against main and accepted M2I/M2J first. Some PTP/SV and native Studio branches are distinct tracks (for example #175). +- M2K's approved scope is the ARSAS-inspired native All-IED live grid, explicit Quality / IED Timestamp columns, bounded search and truthful sample-received state in the canonical MMS tree, with regression gates. The existing M2K branch owns those files until merged/closed. **One integration owner**, no duplicate competing PR for M2K. +- Every future milestone lists both base SHA and exact PR head, a bounded change set, CI links, review resolution and merge SHA. Update the companion [current handoff](WORKBENCH_CURRENT_HANDOFF.md) at accepted checkpoints, not after every experimental commit. + +## 2. Authoritative architecture — a single model, multiple views + +The graph is a dependency contract, **not a request to add layers**: + + Open SCL / normalize ----------+ + | + Online MMS discovery -----------+--> IedEngineeringContextController + | | + Trusted-SCL assisted validation-+ +--> canonical MMS model / MmsLiveTreeModel + | indexed domain/item and IEC aliases + per-IED MMS association (MmsClientController)-+--> actual read samples + typed evidence + per-IED RCB association (MmsReportController)--+--> actual report frames + RCB lifecycle + | + QML navigation, Data Model, DataSets, + Reports, Global Data, SG, Files, GOOSE + | + All-IED is a **bounded presentation only**, + never a second protocol model or acquisition owner + +Current code authority / edit boundaries: + +| Concern / role | Owned source; do not clone | +| --- | --- | +| IED source identity, SCL vs online, context generation | apps/ied_simulator/src/IedEngineeringContextController.* | +| Canonical domain/LD/LN/DO/DA, indexed IEC/MMS aliases, value and selected state | apps/ied_simulator/src/MmsLiveTreeModel.hpp/.cpp | +| MMS confirmed request/read and per-IED session | apps/ied_simulator/src/MmsClientController.* and IedBrowserFleetController.* | +| IEC Quality and UTC TimeQuality type validation | apps/ied_simulator/src/MmsEngineeringEvidence.hpp (**one shared typed decoder**) | +| Trusted-SCL initial mapped Read | apps/ied_simulator/src/MmsSclClientProjection.hpp, with Qt conversion only in Workbench boundary | +| RCB activation, framed InformationReport, replay and cleanup | apps/ied_simulator/src/MmsReportController.* and BrowserReportMemberProjection.hpp | +| Navigation, viewport and inspectors | apps/ied_simulator/qml/IedBrowserWorkspace.qml, IedBrowserNavigation.qml, BrowserDataModelPane.qml, BrowserDataSetPane.qml, BrowserReportPane.qml | +| Per-IED watchlist (presentation only) | apps/ied_simulator/qml/BrowserGlobalDataPane.qml | +| Cross-IED watchlist (bounded, view only) | apps/ied_simulator/qml/FleetGlobalDataPane.qml and Main.qml | +| SG/File/GOOSE existing behavior | existing MmsFileSettingsController, BrowserGoosePane, service/controller paths; identify live owner before editing | + +**No new protocol parser in QML, separate signal store, second SCL model, second quality decoder, UI-owned MMS polling, or WPF/.NET subsystem.** Only already-confirmed source values can become live evidence. All-IED aggregation must carry the original IED slot and never silently redirect an action to a different association. + +### Provenance and lifecycle state contract + +- A discovered/structurally **readable DA is not a received MMS value**. The canonical tree must distinguish: loaded/discovered, no sample (NOT READ), successful sample (including a legitimate empty scalar), failed/unknown, offline, and mismatched/stale generation. Do not mark LIVE from readable alone. +- Keep value, typed q/t, server timestamp, local receipt time (only if really captured), acquisition source (explicit Read versus confirmed RCB report versus design-only) and source-generation coherent. Extend metadata **only on the current authoritative event-ingress path**; do not invent second value caches to satisfy the grid. +- On a new SCL/IED identity, disconnect, generation replacement or report lifecycle reset: invalidate context-dependent selection, unverified live claims, stale q/t/SG evidence and delayed callbacks. A late callback from an obsolete generation must be dropped, not applied to the next IED. +- Distinguish a displayed '-' for absent evidence from valid IEC Boolean false, validity good, TimeQuality false bits, or a *received empty value*. 'Unknown' must not be silently converted into false. +- Typed q/t inspection must be sourced from actual MMS BIT STRING/UTC Time and correct leaf **only**. No guessed q/t bit positions, no timestamp synthesis, no q/t from arbitrary decimal strings. +- Angle exists only when source type/CDC/structured vector supports a phasor angle (for example an applicable complex measurement); **never append angle to frequency Hz, TotW, or generic scalar just because another row had an angle**. Units/multipliers require SCL or validated metadata, not a hardcoded unit-per-column shortcut. Do not project every measurement as a generic magnitude/angle tuple. + +### Protocol/reporting constraints + +- Report/DataSet members maintain confirmed ordered FCDA identity and **received frame ordinal**; Report ID and optional fields must be decoded from the real frame. Missing/invalid/segmented values cannot be shifted to a neighboring member. +- **Static DataSet/RCB must remain report-first/report-only** where configured; no silent periodic Read to fill missing rows. Initial bounded snapshot and user-triggered explicit Read are distinct authorities. URCB reservation and BRCB behavior cannot be collapsed. +- Controls/write/SG switching/file operations require effective server-state readback/guarded user intent and clear error presentation. A successful request submission alone is not proof of effect. + +## 3. UX target and user workflow (ARSAS guidance, IEDScout-class outcome) + +**Primary journey:** Open SCL or Add IED by endpoint -> resolve exact IED/AP/domain -> inspect offline hierarchy -> Connect/Discover/Validate -> browse Data Model/Measurement -> select DA / Read explicitly -> inspect typed Value/Quality/TimeQuality/unit/provenance -> choose bounded DataSet -> inspect ordered FCDA -> inspect report controls -> confirm/enable static RCB under correct guard -> receive evidence mapped to report member -> monitor All-IED grid -> disconnect/reopen without cross-context residue. + +| Native workbench surface | Required contents and behavior | ARSAS idea adopted / exact acceptance | +| --- | --- | --- | +| Fleet header / IED cards | one card per IED; endpoint, loaded/connected state, action availability, explicit selected IED | ARSAS Explorer card-driven navigation; no global implicit Connect All | +| Data Model / Measurement | LD/LN/DO/DA indexed tree; FC and MMS/SCL type; current scalar/vector value; engineering unit if proven; q/t & read-state visible | dense selected inspector, lazy drilldown; scalar frequency/power never borrow phase angle | +| DataSets | searchable ordered FCD/FCDA members; one FC label, valid alias resolution, bounded lazy DO->DA expansion | selection changes inspector without MMS Read; no duplicate FC or phantom value | +| Reports | RCB list grouped by LLN0; selected RCB attributes / effective state; last actual InformationReport and aligned members | DataSet binding, RptID, state, GI, reason, q/t; static report-only path preserved | +| Setting Groups | actual SGCB state, active/edit SG, selected group parameter values with typed semantics | never claim write applied before effective readback; no phantom SG values | +| Files | file listing, safe names/sizes, guarded transfer/download progress, cancellation/errors | IO bounded, no blocking UI; user-visible provenance of local vs server | +| GOOSE | configured GOOSE attributes/selection/evidence, source identity | no auto-subscribe/transmit or fabricated live state on SCL-only source | +| Per-IED Global Data | canonical-selected DA, DataSet, Report, GOOSE watchlist | add/remove/refresh explicit; display read status and q/t as separate evidence | +| All-IED Global Data | IED, IEC reference, Value, Quality, IED Timestamp, acquisition/status; filter by IED/ref/value | 1:1 slot+reference identity, visible q/t, event-driven row patch, bounded presentation and no cross-IED requests | + +**Presentation rules:** professional dense hierarchy and consistent affordances; show why action is disabled (offline, busy, no loaded model, incompatible trusted SCL). Do not hide primary QA fields in tooltips only. Prefer stable row identity and virtualization over resetting the list on every report. Filters change only what is visible, not the watchlist, subscription or report authority. Preserve selection/scroll state across value-only updates when possible. Test at realistic Windows scaling and narrow/wide sizes; do not claim pixel parity without actual captured selected-state screenshots and human review. + +## 4. Bounded, optimized implementation contract + +Existing enforceable or established bounds to **preserve** (verify against current source at every milestone): +- Canonical large-model fixture exercises **60,106 nodes**; continue lazy/virtualized tree projection and indexed MMS/IEC lookups; no full-tree QML rewalk per value. +- MmsLiveDetailModel caps its projected rows at **4,096**; per FCDA lazy expansion at **64 children**. +- Global Data explicit MMS refresh caps at **64 targets per action**; do not multiply requests by each visible delegate. +- Per-IED watchlist **256 entries**, All-IED presentation **2,048 rows**, per-presented text preview **256 chars** (M2K scope). +- RCB report GUI member projection **256 members**, display preview **1,024 chars**, initial typed q/t evidence budget **96 items**. These caps are presentation/initial projection limits, **not permission to drop or truncate authoritative source frames**. +- No unbounded search index, duplicate semantic cache, one Timer per row, eager QString formatting of attacker-sized MMS strings, blocking conversion on packet callback, or heap growth proportional to unlimited incoming events. + +**Optimization sequence:** measure before changing data structure; use already-built indexes, model roles and stable key projections; patch changed rows and coalesce bursts on GUI event loop; keep conversion off the UI and protocol hot paths; validate bounds **before** string allocation. No speculative abstraction layers, broad refactors, more background workers, fixed sleeps or fake evidence merely to pass a test. + +**Capacity and performance acceptance:** record node/visible count, model build and selection latency, filter latency, UI update/refresh time, result count, allocations or bounded-memory high water where instrumented; compare to **last known good CI under same runner/workload**. No increase of asymptotic complexity; any material regression needs a measured justification. For interactive views, test repeated value bursts, 8 independent IEDs, sparse/empty lists, 2,048 watched rows, large SCL and oversized untrusted values. + +## 5. Staged delivery order and integration gates + +Every milestone is a **small vertical slice** (one actual user action through the existing model to rendered evidence, plus negative/regression cases). Do not wait for one giant UI rewrite. + +| Gate | Scope and dependencies | Merge acceptance | +| --- | --- | --- | +| **M2K — ongoing, PR #176** | ARSAS-style All-IED grid + canonical hasReceivedValue; finish exact-head CI and review, **then** merge | visible q/t, correct NOT READ vs empty received, stable coalesced updates, multi-IED P6E and 60k regression, PR SHA matches CI | +| **M2L — next** | **Canonical measurement semantics / provenance first**, building on merged M2K: correct scalar vs vector, engineering unit, quality, clock, read state, acquisition; one typed projection contract | fixture matrix: MX magnitude, structured vector+angle when valid, frequency (Hz), TotW/power, Boolean, invalid unit/type/q/t, stale generation; no angle on Hz/TotW; no 'LIVE' without sample | +| **M2M** | Data Model and DataSets **rendered native workflow**: selection, FCDA aliases, tree expansion, inspector/read button, per-IED Global Data handoff | deterministic native screenshots with actual selected DA/FCDA (not overview only), no implicit Read, 64 child bound, multi-IED isolation | +| **M2N** | Reports/RCB and Global Data provenance: requested vs effective RCB; actual report q/t and ordered frame members; consolidated live grid acquisition | static report-only; GI/URCB/BRCB and cleanup, malformed/omitted/segmented report tests, actual selected native screenshot and no cross-IED leakage | +| **M2O** | Setting Groups / Files / GOOSE productivity and safety; one controller and explicit user workflow per feature | selected SG values and readback, negative/safe control cases, guarded transfer/cancel, configured-vs-live GOOSE state | +| **M2P** | End-to-end visual/interaction/scale polish, Windows executable delivery and physical IED trials | screenshot compare with reference by section/state, keyboard/mouse/resize, stress + cancel/reconnect, exact Windows installer artifact lineage, real IED evidence distinguished from simulation | + +Milestone order may be rearranged **only for explicit blockers/dependencies**, and the current handoff must record the reason. A screenshot-only cosmetic PR cannot silently supersede a missing semantic/measurement test. Full GUI parity remains a **goal**, not a CI status. + +## 6. Parallel-thread ownership and collaboration protocol + +**Integration steward** (one thread at a time): +- Maintains this strategy and current handoff, checks PR queue, decides dependency order, owns final exact-head merge with expected SHA, reconciles conflicts and performs post-merge main check. +- Publishes a short checkpoint per accepted milestone (baseline SHA, PR number/HEAD, changed source, green exact-head runs, artifacts, unverified gaps). +- Does **not** auto-merge legacy/parallel branches #172, #164, #136/#137 or firmware PRs on name similarity alone. First compare with main and accepted work. + +**Track A — canonical data/provenance** (serial owner): MmsLiveTreeModel, typed evidence, context/source generation, measurement semantics and hardening; ARSAS-inspired output **must** come from these existing models. Typical M2L. Any report decoder overlap requires an explicit handoff to Track C. + +**Track B — native Qt UX** (parallel only on disjoint paths): IedBrowserNavigation, BrowserDataModelPane, BrowserDataSetPane, Global Data QML, selection/visual states and GUI QA. No decoder, new model, timer-driven polling, or another source of truth. Typical M2M. + +**Track C — protocol-dependent panels**: MmsReportController/Report projection, SG/File/GOOSE controller APIs, actual RCB lifecycle/cleanup. Follow reporting profile; no network/polling behavioral changes as “UI polish”. Typical M2N–M2O. + +**Track D — evidence/CI/release**: fixture matrix, native Qt smoke, screenshot capture of selected states, large-model/performance and Windows artifacts. Works concurrently on **test paths not already being modified**; coordinates test_browser_convergence.py and test_multi_ied_workspace.py with the feature owner (these files are shared cross-cutting conflict points). Never “fix” failing CI by relaxing a correct invariant. + +**Ownership rule:** avoid two open PRs editing the same authoritative source file. If needed, designate one integration candidate and explicitly merge/rebase/reconcile prior changes **before** new work; compare diffs and check lease, never force-push another thread's branch. Prefer separate feature PRs based on merged main. Cross-thread coordination is visible **in the PR description and the handoff**, not assumed from chat context. + +**Handoff contract for a thread opening work:** include base/ref and fresh main SHA; active dependency PRs with HEAD; precise canonical owner and target files; observed failure/UX gap with source/fixture; expected semantic invariants; acceptance tests and performance budget. On exit update current handoff with status (planned, in progress, exact-head green, merged, or blocked), logs/artifact links, review objections and next-step owner. Another thread must first reconcile these entries with live GitHub, not blindly reuse them. + +## 7. CI, QA and production acceptance + +**Before code**: read the relevant files and source contracts, reproduce/trace current behavior, enumerate model consumers, identify exact no-read/no-poll/no-cross-IED invariants, and inspect current GitHub PR state. + +**Before pushing**: do local/source preflight for touched files, deterministic negative tests, and a single coherent batch. Avoid re-triggering heavy CI with one-line follow-up commits that were preventable by review. Keep all tests that assert semantically correct contracts; update only **stale coupling to implementation spelling** after verifying the new runtime route. + +**Targeted CI** (select only relevant gates, see CI routing policy): +- Qt compile/QML smoke + Browser convergence + P6E Multi-IED authority + canonical engineering context/60k large model. +- SCL-assisted Connect/Workbench when changing SCL projection, source reconciliation or session ownership. +- RCB/Interop/Control/Files/Settings tests when changing those services. +- Native screenshot QA for *selected* q/t/DataSet/RCB states and malformed/unread variants; an overview screenshot alone proves only layout. +- Windows Qt lifecycle/release-hardening where changes touch actual Windows behavior; **Studio Windows installer is tag/manual release**, not every Browser source PR. + +**Never equate:** source token tests with rendered UX; CI green with physical IED interoperability; release job complete with downloadable installer unless an exact artifact/release exists; synthetic test input with a physical IED capture; shown timestamp with a proven device-quality timestamp. + +**Required negative matrix:** offline/disconnected; empty source; multiple IEDs with same LD name; failed or timed-out Read; late response after source generation changes; report member omissions/segmentation; q/t truncated/wrong MMS type; SG unsupported/readback mismatch; FCDA alias/FC mismatch; long untrusted metadata; exceeding each budget; repeated filter + selection + reconnect. Run high-impact negative cases in native QML/C++ integration tests, not just string checks. + +**Merge gate:** review live diff/ownership, verify no unresolved review thread, require **completed/success, non-skipped, exact PR-head** relevant gates, squash merge with expected_head_sha, re-read main HEAD, then verify post-merge CI separately. A docs-only PR should use relevant cheap document/link checks, not dispatch unrelated firmware/Windows build storms. + +## 8. Immediate handoff to the next two threads + +**Integrator now:** check [PR #176](https://github.com/masarray/arstack61850/pull/176) against current main and exact-head Qt run [38678320479](https://github.com/masarray/arstack61850/actions/runs/38678320479). Its source and routing regression changes must stay coordinated. If green and reviews resolved, squash-merge with SHA lease, then verify main integration. If red, use the failed job log and fix the **actual** root cause in #176; do not open a duplicate M2K branch. + +**Track A (after M2K merged):** start M2L by tracing actual Measurement DO/DA typed metadata and quality/time provenance, with baseline screenshots/fixtures including **Hz/TotW must not have phasor angle**. Produce a signed-off data-contract test **before** changing presentation. + +**Track B:** study and build the ARSAS-vs-ARStack **screen-state comparison matrix** while Track A owns the canonical model. Avoid overlapping #176's All-IED QML before merge. Implement only after A's model contracts are confirmed, using the existing QML panels; propose small selected-state screenshot QA in a separate non-conflicting path. + +**Definition of progress:** merged code, verified CI, inspectable native screenshots, honest unverified items and an updated on-repo handoff. More lines of code, a second GUI stack, or an unchecked screenshot do not count. diff --git a/docs/WORKBENCH_CURRENT_HANDOFF.md b/docs/WORKBENCH_CURRENT_HANDOFF.md index 76d78f5f7..c39aa3227 100644 --- a/docs/WORKBENCH_CURRENT_HANDOFF.md +++ b/docs/WORKBENCH_CURRENT_HANDOFF.md @@ -1,117 +1,59 @@ -# Native IEC 61850 Workbench — current engineering / AI-thread handoff +# Native Qt IEC 61850 Workbench — current cross-thread handoff -> **Scope:** native Qt IEC 61850 Workbench in `apps/ied_simulator` of `masarray/arstack61850`, not the legacy web application. -> **Verified snapshot:** 2026-10-15 (WIB). Always refresh GitHub refs before editing; this document records a specific checkpoint. -> **Mandatory context:** [AGENTS.md](../AGENTS.md), [AI_READ_FIRST.md](../AI_READ_FIRST.md), [PROJECT_HANDOFF.md](../PROJECT_HANDOFF.md), [CI policy](CI_WORKFLOW_ROUTING.md), [RCB reporting contract](../RCB_REPORTING.md). +> **Updated:** 2026-10-15 (WIB), snapshot only; always refresh GitHub refs and PR state before editing. +> **Primary strategy and ownership contract:** [WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md](WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md). +> **Scope:** installed native ARStack Workbench in apps/ied_simulator. Not a web app, WPF clone, or the separate ESP32-P4/SMV Studio track. -## A. Live GitHub baseline at the snapshot +## Current checkpoint -| Topic | Verifiable status | +| Item | Verified at this snapshot | | --- | --- | -| Repository/default branch | [masarray/arstack61850](https://github.com/masarray/arstack61850), `main` | -| Latest *Workbench code* baseline before this docs-only commit | `a4f0abe2536c318b24f2877b491107bca981cd45` | -| M2A Reports layout | PR [#159](https://github.com/masarray/arstack61850/pull/159), merged `6081df29` | -| M2B canonical indexed DataSets | PR [#160](https://github.com/masarray/arstack61850/pull/160), merged `d527c894` | -| M2C Global Data IEC/MMS read | PR [#161](https://github.com/masarray/arstack61850/pull/161), merged `d4374434` | -| M2D-1 typed q/t MMS Read | PR [#163](https://github.com/masarray/arstack61850/pull/163), merged `e749617f` | -| M2D-2 typed q/t RCB reports | PR [#165](https://github.com/masarray/arstack61850/pull/165), merged `af3ced5d` | -| M2E bounded report GUI projection | PR [#167](https://github.com/masarray/arstack61850/pull/167), merged `35eda54d` | -| M2F streaming value preview | PR [#168](https://github.com/masarray/arstack61850/pull/168), **merged** as `a4f0abe2`; Qt run [38644305224](https://github.com/masarray/arstack61850/actions/runs/38644305224) **success** | -| M2G bounding untrusted RCB metadata | PR [#169](https://github.com/masarray/arstack61850/pull/169), **OPEN, RED** at `c6cf52c2b8c37d1f5ca55c9e7399c3a5ad4035aa`; Qt run [38646373741](https://github.com/masarray/arstack61850/actions/runs/38646373741) **failure** | +| Repo / production branch | [masarray/arstack61850](https://github.com/masarray/arstack61850), main | +| main before documentation-only update | [a328da13133a6473dc6a28a69f5d2aebab7a7198](https://github.com/masarray/arstack61850/commit/a328da13133a6473dc6a28a69f5d2aebab7a7198) | +| M2G | PR [#169](https://github.com/masarray/arstack61850/pull/169) **already superseded by merged later work**; old “fix PR #169” instructions are obsolete | +| M2H / M2I / M2J | PR [#171](https://github.com/masarray/arstack61850/pull/171), [#173](https://github.com/masarray/arstack61850/pull/173), [#174](https://github.com/masarray/arstack61850/pull/174) **merged** | +| M2J post-merge | Exact-main Qt, SCL-assisted Connect/Workbench and Release Hardening **success** | +| **M2K live work** | PR [#176](https://github.com/masarray/arstack61850/pull/176), head **5c5e425c20acb1b849399f39bf62da0f68c0942b** when checked | +| M2K SCL-assisted | [run 38678320482](https://github.com/masarray/arstack61850/actions/runs/38678320482) **success** on that head | +| M2K native Qt | [run 38678320479](https://github.com/masarray/arstack61850/actions/runs/38678320479) **in progress** when last checked; do not assume a merge or success | +| Parallel/legacy PRs | #172, #164, older Browser recovery; evaluate against current main, do not auto-merge duplicate work. PTP/SMV/Studio PRs are separate | -Merging a docs-only handoff can advance `main` without changing Workbench code. Treat the SHA above as **code checkpoint at snapshot**, not the perpetual HEAD. Many open Draft PRs belong to separate PTP/SMV, earlier Browser recovery or parallel q/t work (#164); do not conflate them or merge obsolete branches casually. +## No-regression source of truth -## B. Immediate blocker: fix M2G PR #169, do not open a duplicate +1. Open SCL and live discovery converge in the existing IedEngineeringContextController and canonical MmsLiveTreeModel; index IEC/MMS references instead of reparsing or duplicating trees. +2. MmsClientController is the only confirmed Read/write path; MmsReportController owns report/RCB states; MmsEngineeringEvidence.hpp is the shared q/t decoder. +3. DA readable does **not** imply a sample was received. Preserve actual empty-string sample vs NOT READ, unknown quality/time, and generation/association provenance. No stale evidence after reconnect/source replacement. +4. Report member reference and evidence must map to exact received frame ordinal and actual Report ID. Static reporting remains report-only without implicit periodic MMS Read. +5. Preserve verified bounds: 60k+ node large-model regression, 4,096 detail rows, 64 lazy FCDA DAs, 64 explicit Read targets, 256 per-IED watched objects, 2,048 All-IED rendered objects, 256-char All-IED preview, 256 visible report members, 1,024-char report preview, 96 initial typed q/t details. These are presentation bounds; do not drop authoritative frames. +6. Scalar Hz and total power (TotW) do not acquire an “angle” through a generic presentation shortcut; only display units/phasor components proven by typed metadata. +7. Never claim pixel-level IEDScout/ARSAS parity, latest installer parity, or real physical IED interop on synthetic fixtures alone. -**Exact observed failure:** `BROWSER_REPORT_BOUNDED_PROJECTION_FAIL missing=#include "BrowserBoundedMmsPreview.hpp"previewMmsValue(*member.value`. +## Immediate action and owners -GitHub Actions log confirms native Qt **Build passed**, then **Browser convergence source-contract** failed. Root cause is missing comma in `apps/ied_simulator/test_browser_convergence.py`: Python silently concatenates two adjacent string literals in the `projection_header` required-token list. +**Integration owner (first):** re-query main, PR #176 head, exact-head Qt result, review threads. Fix failures in **that PR**, not in a new duplicate. If green, squash-merge with expected-head lease, verify main integration and update this table. -```python -'#include "BrowserBoundedMmsPreview.hpp"' -'previewMmsValue(*member.value', -``` +**Canonical/SSOT owner (second):** M2L Measurement semantics and value/q/t/unit/angle provenance on the existing MMS model. Tests for MX vector, scalar Hz, TotW, malformed q/t, unset value, SCL-vs-live authority and source-generation mismatch first. -Add the comma after the first string, **preserve both assertions**, run the targeted test and then the exact-head Qt workflow on PR #169. Do not revert the correct M2F/M2G performance work to appease the stale contract. +**QML/UX owner (parallel on disjoint files):** compare ARSAS Explorer live grid, selected-state IEDScout screenshots and ARStack Qt Data Model/DataSets/Reports/SG. Build a screen-state matrix and deterministic native captures; do not change the canonical model or edit #176's All-IED files concurrently. -PR #169 changes only: -- `apps/ied_simulator/src/BrowserReportMemberProjection.hpp` -- `apps/ied_simulator/src/ied_browser_large_model_qa.cpp` -- `apps/ied_simulator/test_browser_convergence.py` +**Protocol/RCB owner:** preserve exact Reporting contract ([RCB_REPORTING_REFERENCE.md](RCB_REPORTING_REFERENCE.md)); no new polling, invented report values or uncontrolled writes. -Its goal: cap huge untrusted DataSet reference strings and Reason-for-Inclusion before QString conversion, cap complete GUI preview including marker, flag truncated identities honestly, and never decode q/t evidence from a truncated reference. Regression includes ~1.5 MB reference/reason strings and many reason entries. **Not yet accepted / merged** at snapshot. +**QA/CI owner:** source-contract, actual rendered selected-state screenshots, 60k-node stress, 8-IED isolation, oversized metadata, read error and reconnect. Coordinates shared test files with the feature owner; source token checks alone do not establish rendered semantics. -## C. User objective: engineering-grade IEDScout-like GUI/UX +## One-turn resume checklist -The target is a **native Windows Qt Workbench** resembling reference IEDScout *Global Data, File, Browser, Reports and DataSets* workflow, backed by truthful IEC 61850 data. User values measurable improvements and rejects naive coding, noisy UI, mismatched screenshots and excessive CI. +1. Read [strategy](WORKBENCH_ARSAS_GUI_SSOT_STRATEGY.md), [AGENTS](../AGENTS.md), [AI_READ_FIRST](../AI_READ_FIRST.md) and [CI policy](CI_WORKFLOW_ROUTING.md). +2. Inspect live main, open PRs and run results, exact affected files and current integration owner. Record base SHA/head SHA before touching a file. +3. Reproduce observed wrong behavior, identify canonical state owner, set typed/value provenance requirements, then make **one small coherent vertical slice**, including failure/large-input regression. +4. Check applicable exact-head CI, review, squash merge with expected_head_sha and re-read main; never call in-progress/skipped CI PASS. +5. Update this handoff with accepted checkpoint and links. Keep separate lifecycle: code merged vs native artifact built vs actual Windows installer vs real IED tested. -- `Open SCL` and `Discovery IED` must converge onto **one canonical IED model** and same browsing / static Dataset / reporting pipeline. Do not fork semantic trees or repeat outdated discovery base code. -- Expose clear `Browse IED` and `Dataset Signals` choices. **Static RCB reporting must remain report-only** when selected; never silently mix in cyclic MMS polling. -- LD/LN/DO/DA hierarchy with clean LD labels (avoid repeated IED name in UI), correct per-node value, q/t detail and engineering unit only when source provides it. -- Reports inspector follows `Control Block Attributes → Information Received in Last Report → Data`. Match report frames by **Report ID**, and member evidence by exact **received-frame member ordinal**, not assumed DataSet index. -- DataSets: dense ordered FCDA list, exactly **one FC tag**, lazy FC-filtered DO→DA expansion, no automatic MMS read merely on navigation. -- File download/open, splitters, screen density and pixel-level visual parity still need separate explicit QA. **CI green ≠ screenshot parity or real-device validation.** +## Useful commands (if native Qt toolchain available) -Do not confuse this track with the released **native ARStack Studio / ESP32-P4 SMV Injector** (`apps/arstack_studio`) or the separate ARSAS repository. No firmware/PTP/SMV changes are authorized by this GUI handoff. + python3 apps/ied_simulator/test_browser_convergence.py apps/ied_simulator/qml/IedBrowserWorkspace.qml apps/ied_simulator/qml/IedBrowserNavigation.qml apps/ied_simulator/qml/BrowserStatusConsole.qml apps/ied_simulator/qml/BrowserDataModelPane.qml + cmake -S apps/ied_simulator -B build-ied-simulator-qt -G Ninja -DCMAKE_BUILD_TYPE=Release + cmake --build build-ied-simulator-qt --target arstack_ied_simulator ied_browser_large_model_qa ied_browser_session_qa ied_report_workspace_qa --parallel 2 + ./build-ied-simulator-qt/ied_browser_large_model_qa + QT_QPA_PLATFORM=offscreen ./build-ied-simulator-qt/arstack_ied_simulator --smoke-test -## D. Ownership and key source paths - -| Layer | Authoritative source | -| --- | --- | -| Canonical IEC/MMS DO/DA + indexed IEC/MMS aliases + current value/evidence | `apps/ied_simulator/src/MmsLiveTreeModel.hpp/.cpp` | -| SCL and discovered engineering model | `apps/ied_simulator/src/IedEngineeringContextController.*` | -| Successful typed MMS Read / post-write evidence | `apps/ied_simulator/src/MmsClientController.cpp` | -| **Single** IEC Quality 13-bit / UTC TimeQuality typed decoder | `apps/ied_simulator/src/MmsEngineeringEvidence.hpp` | -| Existing RCB runtime/snapshot projection, ReportID & members | `apps/ied_simulator/src/MmsReportController.cpp` | -| Bounded RCB member presentation, currently modified by M2G | `apps/ied_simulator/src/BrowserReportMemberProjection.hpp` | -| Presentation-only streaming MMS preview (M2F) | `apps/ied_simulator/src/BrowserBoundedMmsPreview.hpp` | -| Native Qt Browser layout | `apps/ied_simulator/qml/IedBrowserWorkspace.qml`; `IedBrowserNavigation.qml` | -| Qt inspectors | `BrowserDataModelPane.qml`, `BrowserDataSetPane.qml`, `BrowserGlobalDataPane.qml`, `BrowserReportPane.qml`, `BrowserEngineeringEvidence.qml` | -| QA | `apps/ied_simulator/test_browser_convergence.py`; `src/ied_browser_large_model_qa.cpp` | -| CI routing | `.github/workflows/ied-simulator-qt.yml` and `docs/CI_WORKFLOW_ROUTING.md` | - -**Non-negotiable invariants:** - -1. Never fabricate measurements, quality flags, timestamps or RCB state; absent or malformed evidence is `Unknown` / `—`, **not** assumed false. -2. One canonical model / typed decoder; never build second semantic cache, reporting association, implicit polling loop or new q/t parser in QML. -3. Keep full authoritative MMS report frame intact; cap **presentation only**. Established limits: **256 displayed report members**, **1024-character GUI preview**, **96 typed q/t evidence items per snapshot**, **64 DAs per lazy expanded DataSet row**. M2F streams large values before allocating huge intermediary strings; M2G bounds metadata before QString allocation. -4. Evidence from an RCB frame aligns to the actual received member ordinal and Report ID. Failed/untyped values must not show fabricated details. Do not misalign on omitted members. -5. No periodic MMS reads on expand, no protocol/firmware regression, no hidden blocking allocations on hot callbacks. Follow [AGENTS.md](../AGENTS.md). - -## E. Mandatory optimized implementation & CI workflow - -Use **RECON -> EXACT BASELINE -> ROOT CAUSE -> INVARIANTS -> SMALL COHERENT DESIGN -> IMPLEMENT -> NEGATIVE/LARGE INPUT QA -> ONE COMMIT -> TARGETED EXACT-SHA CI -> REVIEW/MERGE**. - -For the current Browser source contract, run locally if code/toolchain is available: - -```bash -python3 apps/ied_simulator/test_browser_convergence.py \ - apps/ied_simulator/qml/IedBrowserWorkspace.qml \ - apps/ied_simulator/qml/IedBrowserNavigation.qml \ - apps/ied_simulator/qml/BrowserStatusConsole.qml \ - apps/ied_simulator/qml/BrowserDataModelPane.qml - -cmake -S apps/ied_simulator -B build-ied-simulator-qt -G Ninja -DCMAKE_BUILD_TYPE=Release -cmake --build build-ied-simulator-qt \ - --target arstack_ied_simulator ied_browser_large_model_qa ied_browser_session_qa ied_report_workspace_qa \ - --parallel 2 -./build-ied-simulator-qt/ied_browser_large_model_qa -QT_QPA_PLATFORM=offscreen ./build-ied-simulator-qt/arstack_ied_simulator --smoke-test -``` - -See the actual workflow for all required CI gates, including MMS data-plane/GUI checks. Do not claim success based solely on Build, skipped checks, or generic screenshots. - -- Fix open PR **#169 first**. Inspect **current** PR head before pushing (other threads may advance it). Commit to the **same PR**, not a duplicate. Never force-push or overwrite parallel work. -- Prefer one coherent commit / at most necessary regression correction, with local preflight before expensive CI. Avoid build storms and unrelated ESP-IDF, Studio installer, C++ matrices. -- If CI red, inspect exact failed job logs. Fix real code/test cause without reverting correct architecture. Verify exact-head and required checks before squash merge. -- Keep Windows artifact lineage honest: earlier M2D-1 ZIP is **not** latest M2F/M2G. Physical IED q/t and full IEDScout GUI parity remain **unverified** until actually tested. - -## F. Next-step acceptance sequence - -1. Requery `main`, PR #169 status/head and latest Actions; do not assume snapshot still current. -2. If still red due missing comma, fix the Python token-list typo, run Browser contract, exact-head Qt CI; verify 1.5 MB metadata tests, no eager QString conversion, correct q/t provenance, preview bounds. -3. Once CI success, inspect PR #169 diff, squash-merge with `expected_head_sha` and verify new `main` integration. -4. Select **one** meaningful next milestone: exact-screen visual regression for DataSets/Data Model/Quality/TimeQuality versus provided IEDScout references; or measured value/report memory/latency profiling. Do not promise pixel parity without screenshots and Windows/IED evidence. -5. Separate known-good and unfinished behavior in progress reports. New thread must **perform repository actions and provide verifiable PR/commit/CI links**, not merely restate strategy. - -**Status at snapshot:** M2A–M2F merged; M2G open/CI red; IEDScout GUI parity, full real-IED q/t interoperability and latest Windows installer not yet accepted. +The full workflow defines the remaining real MMS, P6E Multi-IED and native QA gates. Follow [CI policy](CI_WORKFLOW_ROUTING.md) for cost-efficient targeting.