Unsubscribe paths now delete through the existing DeleteSubscriptionAsync seam so a test can hold the delete open >grace. Mutation: dropping the post-delete restamp fails both slow-delete tests.
Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
HandlePublishError treated any anonymous BadNoSubscription (subscription id 0)
as loss of a tracked subscription whenever anything was tracked. A publish the
SDK queued while the session briefly held no subscription (the driver had just
deleted its last one) is answered BadNoSubscription and can be handled after the
replacement is registered, so a routine unsubscribe->resubscribe declared the new
subscription lost: Degraded health, a BadNoCommunication quality-only annotation
on every alarm condition and ConnectionLost (host re-initialise). That annotation
is the extra Unspecified event the #728 ConditionRefresh wire test saw.
- A BadNoSubscription that names a subscription id now counts only if the id is
tracked (same rule as BadSubscriptionIdInvalid).
- An anonymous BadNoSubscription within StaleNoSubscriptionGrace (5 s) of a
delete that left the driver tracking nothing is ignored (Debug log). The window
is stamped on removal and restarted when the delete completes; failed-subscribe
removes stamp it too; it resets with the session. A delete that leaves another
subscription tracked opens no window. A genuine loss inside the window is still
caught by the PublishingStopped heuristic; only the immediate ConnectionLost is
forgone.
- OpcUaClientStaleNoSubscriptionTests: stale error after alarm and data
resubscribe (fail without the fix), id-attributed stale error, plus genuine-loss
controls (after the grace, no recent delete, non-last delete, session release),
each mutation-checked.
- The ConditionRefresh wire test now records Kind, AlarmType, message, severity,
quality, restatement and timestamp of every post-resubscribe event on failure.
Wire test locally: 1/10 passing before (all 9 failures the 0x80310000
ConditionType quality-only annotation), 12/12 after.
Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV