Closes the operator parity gap the deferred-work register tracked as #12: native
alarm source overrides could only be set one-at-a-time, while attribute overrides
had a CSV bulk path. Adds an all-or-nothing CSV import for native sources.
- Commons: extract the RFC-4180 line splitter into a shared CsvLineSplitter
(refactor OverrideCsvParser onto it — no behavior change, pinned by its tests);
new NativeAlarmSourceOverrideCsvParser (header SourceName,Connection,
SourceReference,Filter; blank = inherited).
- Commons: NativeAlarmSourceOverrideEntry + bulk SetInstanceNativeAlarmSource-
OverridesCommand (auto-registered via the reflection command registry).
- ManagementService: Deployer-gated handler — flattens once, validates every
source resolves + is unlocked + no duplicates up front, then upserts the whole
batch under a single SaveChanges (true all-or-nothing txn). Added to the frozen
authorization matrix; dispatch-coverage guard passes.
- CLI: `instance native-alarm-source import --instance-id --file` (parity with
`instance import-overrides`) + README.
- Tests: native parser (Commons), CLI parse/entry mapping, 3 bulk-handler tests
(happy path single-commit, locked-source reject, unresolved-source reject).
Also corrects a stale XML-doc line in ScriptRuntimeContext (WaitForAttribute
quality-gated mode is shipped, not "planned") and updates the deferred-work
register: marks #7/#13/#15/#16/#20 verified-resolved, #12 as CLI/API-shipped with
only the Central UI upload affordance still pending.
Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
Manual verification (task step 3) skipped: this worktree cannot reach a
live environment to fetch the deployed DelmiaRecipeDownload script via
`scadabridge api-method get`. Documents only the mandated contract per
PLAN-06 Task 23; verifying the deployed script against it is deferred to
whoever has live environment access.
Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
New Commons seam: ScriptArtifactsChanged record + ScriptArtifactKinds + the
IScriptArtifactChangeBus pub/sub interface. Host ships InProcessScriptArtifactChangeBus
(lock-free copy-on-write, swallow-and-log per subscriber) registered as a central-role
singleton. BundleImporter gains an optional IScriptArtifactChangeBus? and, AFTER
tx.CommitAsync, publishes one notification per script-bearing kind (ApiMethod/
SharedScript/Template) whose resolution was Overwrite/Rename, using post-resolution
names — fully guarded so a bad subscriber can't fail a committed import. Contract +
plan-06 handoff table documented. No consumer yet (additive; publisher is correct).
Claude-Session: https://claude.ai/code/session_01MtdgwpEeCUn6cUA5f1LMPj
Compact Native-AOT win-x64 console app DELMIA invokes to notify ScadaBridge of a
recipe download via POST /api/DelmiaRecipeDownload (X-API-Key). Drop-in CLI/output
parity with legacy WWNotifier; appsettings.json + SCADABRIDGE_API_KEY env var;
comma-list base URLs with connect-failure-only failover.
Match the shipped InboundDatabaseHelper throughout the implementation plan:
QuerySingle->QuerySingleAsync (and Query->QueryAsync) — async signatures
(async Task<T?>), awaited async ADO.NET (ExecuteScalarAsync/ExecuteReaderAsync/
ReadAsync with the deadline token), async Task test methods with await, and the
architecture/step/acceptance prose + pseudocode now call
await Database.QuerySingleAsync<T>(...). Sibling fix to the design-doc correction.
The IpsenMES MoveIn design-doc pseudocode and helper-surface sketch used the
synchronous, read-only `Database.QuerySingle<T>`/`Query`. The shipped
InboundDatabaseHelper is async and write-capable: `await QuerySingleAsync<T>`,
`QueryAsync`, `ExecuteAsync` (InboundAPI-026/027).
Three inbound methods authored from this draft (IpsenMESMoveIn, MesMoveIn,
MesMoveOut) failed Roslyn compilation in production until corrected to
`await Database.QuerySingleAsync<...>(...)` (2026-06-25). Fix the pseudocode,
the helper-surface bullet, and the inline reference, and add a dated correction
note pointing at the authoritative Component-InboundAPI.md surface.
Tabbed Attributes/Alarms view with collapsible composition trees derived
from path-qualified canonical names; all configured alarms (computed +
native) shown with current status; branch-level status roll-up; native
source bindings as nodes with conditions nested. Site snapshot enriched
with placeholder rows for idle native sources via an additive
IsConfiguredPlaceholder field on AlarmStateChanged.
SAPID(+side) -> BTDB Machine.SAPID -> Code -> instance; inbound script does
the lookup via a new scoped read-only DB helper, then routes to a new T1
template script that gates on MoveInReadyFlag and writes the MoveIn to the
correct Left/Right MES receiver. -LT deferred.