docs(plans): R3-04 execution notes — T6-T12 deviations recorded, T13 marked pending (live gate deferred to orchestrator)

This commit is contained in:
Joseph Doherty
2026-08-20 10:33:07 -04:00
parent 985de0b6ad
commit 027c423502
2 changed files with 52 additions and 1 deletions
@@ -502,3 +502,53 @@ gossips 'Driver' and a Primary IS elected" — is **not achievable**. What shipp
this test is actually about, without needing a second live node.
No other T1–T5 deviations from the plan.
**T6-T9 — no deviations.** Implemented as designed; `AkkaClusterOptionsValidator` gained an optional
(default-null) `EffectiveRoles?` constructor parameter rather than a required one specifically so the
pre-existing zero-arg test constructions in `AkkaClusterOptionsValidatorTests` did not all need
touching — the guard is simply inert when nothing is injected, which is also the correct behaviour
for any harness that builds this validator without the rest of the role authority.
**T8 — two additional bare-role-literal offenders found and fixed, beyond the two the plan named.**
The census's row-by-row list did not claim to be exhaustive of every bare literal in the tree, only
of the *production predicate* sites; running the guard for real (rather than reasoning about it)
found two more before it could go green:
- `DriverInstanceActor.ShouldStub`'s `roles.Contains("dev")` — a genuine Akka-cluster-role read
(`_localRoles`, threaded from `IClusterRoleInfo.LocalRoles`) gating dev-stub mode for
Windows-only drivers. Fixed to `RoleParser.GossipedRolesHave(roles, RoleParser.Dev)`.
- `ControlPlane/ServiceCollectionExtensions.AdminRole = "admin"` — a second constant duplicating the
literal `RoleParser.Admin` names, feeding Akka's own `ClusterSingletonOptions.Role` matching (the
same "not ours to change" ordinal match as `SelectOldestUpMemberOfRole`). The VALUE was already
correct (Akka's own matching is unaffected either way); fixed to alias `RoleParser.Admin` rather
than duplicate it, matching the sibling `Runtime/ServiceCollectionExtensions.DriverRole` pattern.
The guard also required a small allow-list (six files) for bare `"admin"`/`"driver"`/`"dev"` literals
that name something OTHER than an Akka `Cluster:Roles` role — a raw-tree node-KIND discriminator, an
ACL-scope entity-type name, the Sql driver's own TagConfig JSON marker (×3 files), and an LDAP-derived
AdminUI RBAC role. Each carries its reason in `RoleAuthorityGuardTests.RoleLiteralAllowListWithReasons`,
per the plan's "add to the allow-list WITH A REASON" instruction; a companion test
(`Every_allow_list_entry_has_a_reason_and_still_applies`) fails if an entry goes stale.
The falsification control (`The_scan_actually_detects_the_pre_R3_04_offenders`) could not literally
re-run the guard against the pre-T3/pre-T5 GIT COMMITS (T1–T8 landed sequentially in this same
worktree, so "the tree" is always post-fix by the time T8's test runs) — it instead feeds the scan
logic the exact pre-fix `Program.cs`/`Fleet.razor` snippets as string literals, captured verbatim
from this session's own earlier reads of those files before they were edited. Functionally
equivalent proof-of-falsifiability; recorded as a deviation because it is a different MECHANISM than
"run on the pre-T3 tree," not because the result differs.
**T9 — scope note, not a deviation.** "The driver stack" is proven via two representative slices
(`ILocalDb` resolution + the `IOpcUaUserAuthenticator` selection block), not the ENTIRE
`WithOtOpcUaRuntimeActors` Akka actor graph — replicating that too would need a real `ActorSystem`
(the exact thing `DriverOnlyNoConfigDbBootTests`'s own doc comment explains this test family avoids).
The negative control uses an inline `PreFixDerivation` helper (reading `OTOPCUA_ROLES` only, matching
pre-T3 `Program.cs:61-63` verbatim) rather than a `git stash`, for the same "already sequential
commits in one worktree" reason as T8's falsification control — and it is run in the SAME test
process against the SAME configuration, which is a stronger control than a separate stash-and-revert
cycle would have been (both derivations are proven against literally identical input).
**T11/T12 — combined into one commit.** The docker-compose.yml header comment documenting all six
nodes' role sources interleaves site-a-2 and site-b-2 on adjacent lines, so a clean git-level split
into the plan's two separate commits was not practical; both tasks' edits landed in one commit
(`985de0b6`). The rig was NOT brought up as part of either task, per the brief.
@@ -106,7 +106,8 @@
"T9",
"T11",
"T12"
]
],
"note": "Skipped by the executing agent per orchestrator instruction \u2014 the live gate runs separately, on the docker-dev rig, by the orchestrator/operator. T1-T12 are implemented, committed, and unit/integration-tested; T13 requires bringing the rig up (docker compose), which this task explicitly excluded."
}
]
}