Files
ScadaBridge/docs/known-issues/2026-06-24-template-inheritance-ui-and-cli-followups.md
T
Joseph Doherty 1a647cf1c4 docs(known-issues): track template-inheritance UI gaps + CLI/validation footguns
Records 7 issues found during the 2026-06-24 CvdReactor live-ops session:
- template editor omits inherited-but-unmaterialized base attrs (MoveInType etc.)
- derived templates carry incomplete/stale IsInherited row sets
- collision detector blocks adding attrs/compositions to derived templates
- CLI instance set-bindings can't set DataSourceReferenceOverride
- CLI template update full-replaces description (nulls it if omitted)
- CLI template list/get table dumps every attribute
- Central UI script editor false-flags WriteBatchAndWaitAsync/WaitAsync/WaitForAsync
  (sandbox compile surface out of sync with runtime + deploy gate)
2026-06-24 12:16:38 -04:00

92 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Follow-up tracker — template-inheritance UI gaps + CLI/validation footguns (2026-06-24 session)
**Status:** OPEN (tracker) · **Found:** 2026-06-24 · **Context:** live ops session on `wonder-app-vd03` (CvdReactor / Z28061 / Z28061Sim) — renaming the template, adding the LeakTest module, and adding MoveInType to the MESReceiver children.
**Components:** Central UI (#9), Template Engine (#1), CLI (#19), Configuration Database (#17)
Issues are listed worst-first. Severities are author estimates. None caused data loss; the runtime/flattened config and deployed instances are correct.
---
## 1. Template editor omits inherited-but-unmaterialized base attributes (user-reported)
**Severity:** Medium · **Components:** Central UI (#9), Template Engine (#1)
**Symptom:** On `/design/templates``LeftMESReceiver`, the **Attributes** tab does not list `MoveInType`. Same for `RightMESReceiver`. (Also missing from the list: all `MoveOut*` and `ScanStateCmd`.)
**Root cause:** `MoveInType` (String), the 12 `MoveOut*`, and `ScanStateCmd` live on the **base** `MESReceiver` template (id 3, 26 attrs). The derived children `LeftMESReceiver`/`RightMESReceiver` (ids 5/6) only have **12** materialized `IsInherited` rows (the `MoveIn*` basics) — the base attributes added *after* these children were derived were never materialized as child rows. The editor's main Attributes tab lists only the template's stored rows (`TemplateEdit.razor:187``GetAttributesByTemplateIdAsync(Id)`; count badge at `:415`), so the unmaterialized inherited members are invisible there.
**Not a runtime bug:** the flattener resolves the full chain, so `LeftMESReceiver.MoveInType` *is* in the flattened deploy config and is bound + live on the instances (`''` / `'na'`, Good). The page also has an "Effective inherited set" read-only preview (M9-T26b, `TemplateEdit.razor:465-491`) + a staleness banner (`:292-301`) that *do* surface these — but the main, editable Attributes list does not.
**Suggested fix:** in the Attributes tab, render the resolved inherited set (with inherited badges) rather than only materialized rows — or auto-materialize missing inherited rows on load. See #2 (shared root cause).
---
## 2. Derived templates carry incomplete/stale `IsInherited` row sets
**Severity:** Medium · **Components:** Template Engine (#1), Configuration Database (#17)
**Symptom:** `LeftMESReceiver`/`RightMESReceiver` (parent=3) have 12 stored attribute rows vs the base's 26. By contrast `LeftReactorSide`/`RightReactorSide` (parent=7) mirror the full 61. So derived row-sets are inconsistent.
**Root cause:** when a base attribute is added after a child is derived, the child's stored `IsInherited` placeholder rows are not auto-resynced. There is a staleness banner but no surfaced one-click "resync inherited members" action (or it exists and was never run for these children). This is the data root cause of #1.
**Suggested fix:** a "resync inherited members" command (CLI + UI) that materializes missing base members onto derived children; consider running it automatically when a base attribute is added.
---
## 3. Collision detector blocks adding attributes/compositions to ANY derived template
**Severity:** Medium-High · **Components:** Template Engine (#1)
**Symptom:** `template attribute add --template-id 5 --name MoveInType ...` fails with **13** "Naming collision" errors — the new attribute *plus all 12 pre-existing inherited rows*. Same class of failure when adding a composition to a derived template (hit earlier when trying to add `LeakTest` to `LeftReactorSide`).
**Root cause:** `CollisionDetector.CollectDirectMembers` (`CollisionDetector.cs`) emits every `template.Attributes` row — including `IsInherited` placeholders — with origin = child name, while `CollectInheritedMembers` emits the same names with origin = `parent '…'`. Two distinct origins for the same canonical name ⇒ reported as a collision. `AddAttributeAsync` (`TemplateService.cs:294`) and `AddCompositionAsync` (`:869`) both run `DetectCollisions`, so there is effectively **no supported API path to extend a derived template** — and the error message is misleading (it blames pre-existing inherited attrs, not the member you're adding).
**Workaround used this session:** add the feature module to the **base** template instead (LeakTest → base `ReactorSide` (7)); the flattener propagates it to all derivations.
**Suggested fix:** `CollectDirectMembers` should skip `IsInherited` rows (or the grouping should treat an inherited row and its parent source as the same origin), so only genuine cross-origin duplicates are flagged.
---
## 4. CLI `instance set-bindings` cannot set `DataSourceReferenceOverride`
**Severity:** Medium · **Components:** CLI (#19)
**Symptom:** `instance set-bindings --bindings` only accepts `[attributeName, dataConnectionId]` pairs (`InstanceCommands.cs``ConnectionBinding(name, connId)` 2-arg). The override is sent as `null`, and because `SetConnectionBindingsAsync` upserts `DataSourceReferenceOverride = b.DataSourceReferenceOverride` (`InstanceService.cs:340`), using the CLI on an attribute that already has an override would **wipe** it.
**Workaround used this session:** raw `POST /management` with `{"command":"SetConnectionBindings","payload":{...,"dataSourceReferenceOverride":"…"}}` — the wire contract `ConnectionBinding(AttributeName, DataConnectionId, DataSourceReferenceOverride?)` does carry the field; only the CLI omits it.
**Suggested fix:** add an optional 3rd element / `--ref-override` to the CLI bindings input.
---
## 5. CLI `template update` is full-replace, not partial
**Severity:** Low · **Components:** CLI (#19), Template Engine (#1)
**Symptom:** omitting `--description` on `template update` overwrites the stored description to NULL (`TemplateService.cs:124-125` assigns Name+Description unconditionally). Renaming a template silently drops its description unless you re-pass it.
**Suggested fix:** treat omitted optional fields as "leave unchanged" (nullable-not-provided vs explicit-null), or warn when a non-empty description would be cleared.
---
## 6. (Minor) CLI `template list`/`get` table output dumps every attribute
**Severity:** Low · **Components:** CLI (#19)
**Symptom:** `--format table template list` emitted ~171 KB (the full attribute set per template inline), unusable in a terminal. `--format json` is fine.
**Suggested fix:** a compact table projection (id/name/desc/#attrs/#comps) for list/get; reserve full attribute dumps for an explicit `--verbose`/`--detail` flag.
---
## 7. Central UI script editor false-flags batch/wait helpers (sandbox compile surface out of sync)
**Severity:** Medium · **Components:** Central UI (#9), Script Analysis (#25)
**Symptom:** In the template script editor (`/design/templates/{id}` → Scripts → Edit → Code), a script that calls `Attributes.WriteBatchAndWaitAsync(...)` (or on a child, `Children["X"].Attributes.WriteBatchAndWaitAsync(...)`) shows a red compile error:
`'SandboxAttributeAccessor' does not contain a definition for 'WriteBatchAndWaitAsync' ... (CS1061)`. Confirmed on `CvdReactor.MesMoveIn`; the same false error hits the base `MESReceiver.MoveIn`/`MoveOut`, which also use the helper.
**Root cause:** the editor validates against the Central UI's own sandbox surface (`CentralUI/ScriptAnalysis/SandboxScriptHost.cs`). Its `SandboxAttributeAccessor` only defines `this[string]`, `GetAsync`, `SetAsync`, `Resolve` — it is **missing `WriteBatchAndWaitAsync`, `WaitAsync`, and `WaitForAsync`** (none are defined anywhere in the CentralUI sandbox surface). The real runtime `AttributeAccessor` (`SiteRuntime/Scripts/ScopeAccessors.cs`) and the deploy-gate `ScriptCompileSurface` (`ScriptAnalysis`) both define them — so `template validate` reports the script clean and it deploys/runs fine. The error is purely the in-editor validator.
**Impact:** misleads authors and can block saving from the UI for any script using the batch-write/wait helpers, even though the script is valid. Authoring such scripts currently has to go through the management API (as was done for `MesMoveIn`).
**Suggested fix:** bring `SandboxAttributeAccessor` (and the sandbox composition/children accessors) to parity with the runtime `AttributeAccessor` — add `WriteBatchAndWaitAsync` / `WaitAsync` / `WaitForAsync` with matching signatures. Ideally enforce surface parity with a test, like the `RoslynScriptCompiler` "representative real script" corpus already does for `ScriptCompileSurface`. Three surfaces (runtime, deploy-gate `ScriptCompileSurface`, UI `SandboxScriptHost`) currently drift independently — consider collapsing to one source of truth.
---
### Minor note (not tracked separately)
The deploy-time unbound-binding validation returns one giant semicolon-joined error string (one clause per attribute). For 50194 unbound attrs it's a wall of text; a structured/summarized error (count + grouped-by-module) would be friendlier.