feat(opcua): add AddressSpaceChangeClassifier — typed delta classification for the applier (R2-07 T1)

This commit is contained in:
Joseph Doherty
2026-07-13 11:38:30 -04:00
parent 1a698cbb97
commit bb226f45ed
4 changed files with 472 additions and 66 deletions
@@ -5,92 +5,123 @@
{
"id": "T1",
"subject": "Phase 1: AddressSpaceChangeClassifier + table-driven tests (move TagDeltaIsSurgicalEligible/VtagDeltaIsNodeIrrelevant)",
"status": "pending",
"status": "completed",
"blockedBy": []
},
{
"id": "T2",
"subject": "Phase 1: route AddressSpaceApplier.Apply through the classifier PureAdd skips rebuild (high-risk)",
"subject": "Phase 1: route AddressSpaceApplier.Apply through the classifier \u2014 PureAdd skips rebuild (high-risk)",
"status": "pending",
"blockedBy": ["T1"]
"blockedBy": [
"T1"
]
},
{
"id": "T3",
"subject": "Phase 1: ComputeAddAnnouncements + AnnounceAddedNodes on the applier (dedup parent NodeAdded announces)",
"status": "pending",
"blockedBy": ["T1"]
"blockedBy": [
"T1"
]
},
{
"id": "T4a",
"subject": "Phase 1: idempotent MaterialiseAlarmCondition (skip-if-present-and-same-kind) (high-risk)",
"status": "pending",
"blockedBy": ["T1"]
"blockedBy": [
"T1"
]
},
{
"id": "T4b",
"subject": "Phase 1: OpcUaPublishActor calls AnnounceAddedNodes after the Materialise passes on non-rebuild applies (high-risk)",
"status": "pending",
"blockedBy": ["T2", "T3", "T4a"]
"blockedBy": [
"T2",
"T3",
"T4a"
]
},
{
"id": "T5",
"subject": "Phase 1: over-the-wire SubscriptionSurvivalTests subscribe, pure-add, item survives + new node browsable",
"subject": "Phase 1: over-the-wire SubscriptionSurvivalTests \u2014 subscribe, pure-add, item survives + new node browsable",
"status": "pending",
"blockedBy": ["T4b"]
"blockedBy": [
"T4b"
]
},
{
"id": "T6",
"subject": "Phase 1: MANDATORY live-/run gate on docker-dev (rebuild BOTH centrals; Client.CLI subscribe survives +1-tag deploy; kind=PureAdd rebuild=False) Phase 1 shippable boundary",
"subject": "Phase 1: MANDATORY live-/run gate on docker-dev (rebuild BOTH centrals; Client.CLI subscribe survives +1-tag deploy; kind=PureAdd rebuild=False) \u2014 Phase 1 shippable boundary",
"status": "pending",
"blockedBy": ["T5"]
"blockedBy": [
"T5"
]
},
{
"id": "T7",
"subject": "Phase 2: add RemoveVariableNode/RemoveAlarmConditionNode/RemoveEquipmentSubtree to ISurgicalAddressSpaceSink + DeferredAddressSpaceSink forwarding guard-first with observed negative control (high-risk)",
"subject": "Phase 2: add RemoveVariableNode/RemoveAlarmConditionNode/RemoveEquipmentSubtree to ISurgicalAddressSpaceSink + DeferredAddressSpaceSink forwarding \u2014 guard-first with observed negative control (high-risk)",
"status": "pending",
"blockedBy": ["T6"]
"blockedBy": [
"T6"
]
},
{
"id": "T8",
"subject": "Phase 2: OtOpcUaNodeManager.RemoveVariableNode + BuildNodesRemovedModelChange (NodeDeleted) (high-risk)",
"status": "pending",
"blockedBy": ["T7"]
"blockedBy": [
"T7"
]
},
{
"id": "T9",
"subject": "Phase 2: OtOpcUaNodeManager.RemoveAlarmConditionNode (+ native-flag cleanup) (high-risk)",
"status": "pending",
"blockedBy": ["T7"]
"blockedBy": [
"T7"
]
},
{
"id": "T10",
"subject": "Phase 2: OtOpcUaNodeManager.RemoveEquipmentSubtree (descendants + notifier demotion) + SdkAddressSpaceSink forwards (high-risk)",
"status": "pending",
"blockedBy": ["T8", "T9"]
"blockedBy": [
"T8",
"T9"
]
},
{
"id": "T11",
"subject": "Phase 2: applier PureRemove arm terminal Bad/RemovedConditionState writes, equipment subsumption, false-to-rebuild ratchet (high-risk)",
"subject": "Phase 2: applier PureRemove arm \u2014 terminal Bad/RemovedConditionState writes, equipment subsumption, false-to-rebuild ratchet (high-risk)",
"status": "pending",
"blockedBy": ["T10"]
"blockedBy": [
"T10"
]
},
{
"id": "T12",
"subject": "Phase 2: remove-side subscription-survival integration test + live-/run remove gate (kind=PureRemove rebuild=False) Phase 2 shippable boundary",
"subject": "Phase 2: remove-side subscription-survival integration test + live-/run remove gate (kind=PureRemove rebuild=False) \u2014 Phase 2 shippable boundary",
"status": "pending",
"blockedBy": ["T11"]
"blockedBy": [
"T11"
]
},
{
"id": "T13",
"subject": "Phase 3: AddRemoveMix routing removes-then-adds surgically, same-NodeId remove-then-recreate ordering test (high-risk)",
"subject": "Phase 3: AddRemoveMix routing \u2014 removes-then-adds surgically, same-NodeId remove-then-recreate ordering test (high-risk)",
"status": "pending",
"blockedBy": ["T12"]
"blockedBy": [
"T12"
]
},
{
"id": "T14",
"subject": "Phase 3: mixed-deploy integration test + live-/run mixed gate + STATUS.md/P1 close-out plan complete",
"subject": "Phase 3: mixed-deploy integration test + live-/run mixed gate + STATUS.md/P1 close-out \u2014 plan complete",
"status": "pending",
"blockedBy": ["T13"]
"blockedBy": [
"T13"
]
}
]
}