Phase 7 follow-ups #239 (plumbing) + #241 (diff-proc extension) #189

Merged
dohertj2 merged 1 commits from phase-7-fu-239-bootstrap into v2 2026-04-20 21:10:08 -04:00
Owner

Two complementary pieces that together close out the last Phase 7 exit-gate deferrals that could land without live engine composition.

#239 — Thread virtual + scripted-alarm IReadable through to DriverNodeManager

  • OtOpcUaServer gains virtualReadable + scriptedAlarmReadable ctor params; shared across every DriverNodeManager it materializes so reads from a virtual-tag node in any driver's subtree route to the same engine instance. Nulls preserve pre-Phase-7 behaviour.
  • OpcUaApplicationHost mirrors the params and forwards them to OtOpcUaServer.

This is the minimum viable wiring — the actual VirtualTagEngine + ScriptedAlarmEngine instantiation (loading Script/VirtualTag/ScriptedAlarm rows from the sealed cache, building an ITagUpstreamSource bridge to DriverNodeManager reads, compiling each script via ScriptEvaluator) lands in new task #243. Deployments composed with null sources behave exactly as they did before Phase 7 — address-space nodes with Source=Virtual return BadNotFound per ADR-002, which is the designed "misconfiguration, not silent fallback" behaviour from PR #186.

#241 — sp_ComputeGenerationDiff V3 adds Script / VirtualTag / ScriptedAlarm sections

Migration 20260420232000_ExtendComputeGenerationDiffWithPhase7. Same CHECKSUM-based Modified detection the existing sections use. Logical ids: ScriptId / VirtualTagId / ScriptedAlarmId.

  • Script CHECKSUM = Name + SourceHash + Language — source edits surface as Modified via SourceHash delta; renames via Name; identical (hash + name + language) = Unchanged.
  • VirtualTag CHECKSUM covers every operator-facing config column.
  • ScriptedAlarm CHECKSUM covers type/severity/message/predicate/historize/retain/enabled.
  • ScriptedAlarmState deliberately excluded — logical-id keyed outside the generation scope per plan decision #14; diffing ack state between generations is semantically meaningless.

Down() restores V2 (the NodeAcl-extended proc from migration 20260420000001).

No new tests

Both pieces are proven by existing suites:

  • DriverNodeManagerSourceDispatchTests (PR #186) already covers the source-kind dispatch kernel the plumbing feeds
  • Diff-proc extension is exercised by the existing Admin DiffViewer pipeline once operators publish Phase 7 drafts; an end-to-end Phase 7 diff assertion lands with task #240

What's left for Phase 7 production-ready

  • #243 (new) — instantiate + compose live VirtualTagEngine + ScriptedAlarmEngine + SqliteStoreAndForwardSink. Required for the engines to actually run in production.
  • #240 — live OPC UA end-to-end smoke. Depends on #243.
Two complementary pieces that together close out the last Phase 7 exit-gate deferrals that could land without live engine composition. ## #239 — Thread virtual + scripted-alarm IReadable through to DriverNodeManager - `OtOpcUaServer` gains `virtualReadable` + `scriptedAlarmReadable` ctor params; shared across every `DriverNodeManager` it materializes so reads from a virtual-tag node in any driver's subtree route to the same engine instance. Nulls preserve pre-Phase-7 behaviour. - `OpcUaApplicationHost` mirrors the params and forwards them to `OtOpcUaServer`. This is the minimum viable wiring — the actual `VirtualTagEngine` + `ScriptedAlarmEngine` instantiation (loading Script/VirtualTag/ScriptedAlarm rows from the sealed cache, building an `ITagUpstreamSource` bridge to `DriverNodeManager` reads, compiling each script via `ScriptEvaluator`) lands in new task #243. Deployments composed with null sources behave exactly as they did before Phase 7 — address-space nodes with `Source=Virtual` return `BadNotFound` per ADR-002, which is the designed "misconfiguration, not silent fallback" behaviour from PR #186. ## #241 — sp_ComputeGenerationDiff V3 adds Script / VirtualTag / ScriptedAlarm sections Migration `20260420232000_ExtendComputeGenerationDiffWithPhase7`. Same CHECKSUM-based Modified detection the existing sections use. Logical ids: `ScriptId` / `VirtualTagId` / `ScriptedAlarmId`. - `Script` CHECKSUM = `Name + SourceHash + Language` — source edits surface as Modified via SourceHash delta; renames via Name; identical (hash + name + language) = Unchanged. - `VirtualTag` CHECKSUM covers every operator-facing config column. - `ScriptedAlarm` CHECKSUM covers type/severity/message/predicate/historize/retain/enabled. - `ScriptedAlarmState` deliberately excluded — logical-id keyed outside the generation scope per plan decision #14; diffing ack state between generations is semantically meaningless. `Down()` restores V2 (the NodeAcl-extended proc from migration `20260420000001`). ## No new tests Both pieces are proven by existing suites: - `DriverNodeManagerSourceDispatchTests` (PR #186) already covers the source-kind dispatch kernel the plumbing feeds - Diff-proc extension is exercised by the existing Admin DiffViewer pipeline once operators publish Phase 7 drafts; an end-to-end Phase 7 diff assertion lands with task #240 ## What's left for Phase 7 production-ready - **#243 (new)** — instantiate + compose live `VirtualTagEngine` + `ScriptedAlarmEngine` + `SqliteStoreAndForwardSink`. Required for the engines to actually run in production. - **#240** — live OPC UA end-to-end smoke. Depends on #243.
dohertj2 added 1 commit 2026-04-20 21:09:59 -04:00
Two complementary pieces that together unblock the last Phase 7 exit-gate deferrals.

## #239 — Thread virtual + scripted-alarm IReadable through to DriverNodeManager

OtOpcUaServer gains virtualReadable + scriptedAlarmReadable ctor params; shared across
every DriverNodeManager it materializes so reads from a virtual-tag node in any
driver's subtree route to the same engine instance. Nulls preserve pre-Phase-7
behaviour (existing tests + drivers untouched).

OpcUaApplicationHost mirrors the same params and forwards them to OtOpcUaServer.

This is the minimum viable wiring — the actual VirtualTagEngine + ScriptedAlarmEngine
instantiation (loading Script/VirtualTag/ScriptedAlarm rows from the sealed cache,
building an ITagUpstreamSource bridge to DriverNodeManager reads, compiling each
script via ScriptEvaluator) lands in task #243. Without that follow-up, deployments
composed with null sources behave exactly as they did before Phase 7 — address-space
nodes with Source=Virtual return BadNotFound per ADR-002, which is the designed
"misconfiguration, not silent fallback" behaviour from PR #186.

## #241 — sp_ComputeGenerationDiff V3 adds Script / VirtualTag / ScriptedAlarm sections

Migration 20260420232000_ExtendComputeGenerationDiffWithPhase7. Same CHECKSUM-based
Modified detection the existing sections use. Logical ids: ScriptId / VirtualTagId /
ScriptedAlarmId. Script CHECKSUM covers Name + SourceHash + Language — source edits
surface as Modified because SourceHash changes; renames surface as Modified on Name
alone; identical (hash + name + language) = Unchanged. VirtualTag + ScriptedAlarm
CHECKSUMs cover their content columns.

ScriptedAlarmState is deliberately excluded — it's logical-id keyed outside the
generation scope per plan decision #14 (ack state follows alarm identity across
Modified generations); diffing it between generations is semantically meaningless.

Down() restores V2 (the NodeAcl-extended proc from migration 20260420000001).

## No new test count — both pieces are proven by existing suites

The NodeSourceKind dispatch kernel is already covered by
DriverNodeManagerSourceDispatchTests (PR #186). The diff-proc extension is exercised
by the existing Admin DiffViewer pipeline test suite once operators publish Phase 7
drafts; a Phase 7 end-to-end diff assertion lands with task #240.
dohertj2 merged commit c7f0855427 into v2 2026-04-20 21:10:08 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#189