fix(virtual-tags): resolve High code-review finding (Core.VirtualTags-001)

OnScriptSetVirtualTag updated the value cache, notified observers, and
recorded history for the written path but never scheduled a cascade for
tags depending on that path. This contradicts docs/VirtualTags.md, which
states ctx.SetVirtualTag writes "still participate in change-trigger
cascades": a change-triggered virtual tag reading a script-written tag
went stale until an unrelated trigger fired.

OnScriptSetVirtualTag now launches a fire-and-forget CascadeAsync for the
written path, mirroring OnUpstreamChange. The cascade is scheduled rather
than invoked inline because the callback runs inside EvaluateInternalAsync
while the non-reentrant _evalGate semaphore is held.

Added regression test
SetVirtualTag_within_script_cascades_to_dependents_of_the_written_tag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-05-22 06:17:40 -04:00
parent e3f8fa535a
commit 66e8bfbab3
3 changed files with 43 additions and 3 deletions

View File

@@ -7,7 +7,7 @@
| Review date | 2026-05-22 |
| Commit reviewed | `76d35d1` |
| Status | Reviewed |
| Open findings | 13 |
| Open findings | 12 |
## Checklist coverage
@@ -36,7 +36,7 @@ a category produced nothing rather than leaving it blank.
| Severity | High |
| Category | Correctness & logic bugs |
| Location | `src/Core/ZB.MOM.WW.OtOpcUa.Core.VirtualTags/VirtualTagEngine.cs:306` |
| Status | Open |
| Status | Resolved |
**Description:** `OnScriptSetVirtualTag` updates `_valueCache`, notifies observers, and
records history for the written path, but it does not schedule a cascade for tags that
@@ -58,7 +58,7 @@ held), or (b) if cascading from a script write is intentionally unsupported, cor
documentation and `VirtualTagContext` XML doc to say so. Decide deliberately and make
code and docs agree.
**Resolution:** _(open)_
**Resolution:** Resolved 2026-05-22 — `OnScriptSetVirtualTag` now launches a fire-and-forget `CascadeAsync(path, ...)` after updating the cache, mirroring `OnUpstreamChange`, so change-triggered dependents of a script-written tag are re-evaluated; added a regression test.
### Core.VirtualTags-002