WhenTerminated watchdog calls IHostApplicationLifetime.StopApplication() when
the ActorSystem dies outside StopAsync (SBR self-down + run-coordinated-shutdown-when-down),
so the service supervisor restarts the node as a fresh incarnation. Optional
ctor param keeps every existing construction site compiling.
Plan's deploy/wonder-app-vd03/install.ps1 service-recovery-actions edit is
skipped: that production deploy artifact is not tracked in this repo (Task 16
skipped its appsettings.Central.json for the same reason).
Validator lowers the seed-count floor to 1 when AllowSingleNodeCluster is set,
otherwise still requires 2 and points operators at the flag. The plan's
deploy/wonder-app-vd03/appsettings.Central.json edit is skipped: that production
deploy artifact is not tracked in this repo (only its deployment record doc is).
Rewritten from the plan's oldest-crash scenario: empirically, 2-node keep-oldest downs
the non-oldest partition, so a hard crash of the OLDEST makes the younger survivor down
itself (total cluster loss) — the survivable case is a crash of the younger node. The
member-removal assertion has teeth (impossible under the pre-fix NoDowning default).
See the test's XML doc for the active/oldest-node-crash gap.
`dotnet ef migrations add --no-build` scaffolds off the stale prebuilt DLL and
can emit an empty migration; build first and delete the empty Migrations files
if it happens (migrations remove needs a live DB). Placed next to the existing
EF migrations line in Code Organization.
`dotnet test ZB.MOM.WW.ScadaBridge.slnx` silently skips
ZB.MOM.WW.ScadaBridge.CLI.Tests (the one test project not in the slnx), so a
green solution run can hide CLI tests that never compiled. Add the test
command and point at testing the CLI project directly.
Reconcile the Sister Projects section to mirror the peer repos
(MxAccessGateway/HistorianGateway): frame ~/Desktop/scadaproj as the parent
workspace whose CLAUDE.md is the canonical umbrella index that indexes this
repo, point there for the full family list + cross-project map, and add the
previously-missing peers (HistorianGateway, histsdk, scadaproj). Add the
reciprocal "propagate cross-repo changes to the umbrella index" Editing Rule
so an index-recorded fact change here updates the ScadaBridge entry in
../scadaproj/CLAUDE.md in the same change.
Remove project bookkeeping citations from shipped code comments across the
solution: hyphenated task IDs (WP-14, StoreAndForward-025), milestone/task/
issue refs (M3, Task 4, Audit Log #23, #21), Bundle X task-bundle labels,
and C/D/K/S/T phase labels.
Comment text only — no code logic, string/log literals, or XML-doc structure
changed. Genuine descriptions are preserved (only the citation is stripped),
and technical lookalikes are retained (UTF-8, SHA-256, T00:00:00, M365,
UTC-5, pre-C4/pre-C5 schema versions). Flagged by the new CommentChecker
TaskReferenceInComment / TrackingReferenceInComment checks plus targeted
grep passes; full solution builds clean, append-only guard tests pass.
CompileAndRegister only swaps the cached handler on a successful compile, so a
management (or DB) save of a non-compiling inbound script silently kept the
previously-registered handler serving — stale results, still HTTP 200 — while
UpdateApiMethod reported success. A broken save thus looked like a no-op, with
the real Roslyn error only in the central log.
Surface the diagnostics instead: a new CompileAndRegister(method, out errors)
overload reports the compile/trust-model errors (the bool overload is kept for
existing callers), and HandleCreate/UpdateApiMethod return them as a top-level
compileWarning on the management result (null when the script compiled). The
save still persists and the previously registered version keeps serving — the
warning just stops a non-compiling save from looking like a success.
- InboundScriptExecutor: Compile returns its diagnostics alongside the handler.
- ManagementActor: TryCompileAndDescribe + flat ApiMethodResult projection so
compileWarning rides at the top level without polluting the ApiMethod POCO.
- Component-InboundAPI.md: document the non-fatal-but-surfaced contract.
- Tests: executor diagnostics + non-compiling-update-keeps-previous-handler,
plus an end-to-end ManagementActor test asserting compileWarning is returned.
Fully suppress search UI (box + results panel) when ShowSearch=false, and
reset search state on ShowAsync so a reused dialog never shows stale results.
Notify-and-fetch follow-ups:
- PendingDeploymentPurgeActor: a central cluster singleton (not
readiness-gated, best-effort) that sweeps expired PendingDeployment
staging rows on CommunicationOptions.PendingDeploymentPurgeInterval
(default 1h). Modeled on the kpi-history-recorder pattern: self-scheduling
timer, per-tick DI scope -> IDeploymentManagerRepository, continue-on-error.
Wired in AkkaHostedService.RegisterCentralActors (manager + proxy + drain);
resolves the deferred TODO in DeploymentService. Correctness never depends
on it (supersession bounds rows to <=1/instance; the fetch endpoint enforces
the TTL), so it is deliberately absent from RequiredSingletonsHealthCheck.
- SQL Server integration test for StagePendingIfAbsentAsync re-staging an
instance's OWN DeploymentId over an expired row against the real UNIQUE
index on DeploymentId — confirms EF orders DELETE before INSERT in one
SaveChanges (SQLite's constraint timing differs from SQL Server's). Plus
a same-instance supersession variant on real SQL Server.
Tests: 2 TestKit actor tests + 2 SQL Server integration tests (both ran
green against the infra MSSQL container); 235 Communication + 15
PendingDeployment tests pass; Host builds 0 warnings.
The 128 KB Akka frame-size deploy trap is fixed and merged. Record the
resolution at the top of the writeup (notify-and-fetch on both the
central->site deploy hop and the site active->standby replication hop;
AskTimeout classification fix; startup reconciliation + topology perf fix),
link the design + plan docs, and note the live-smoke validation. The
diagnosis is retained as historical record.