zdd-5: Astra's review of the main merge (ACCEPT WITH FIXES for a dormant merge)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+59
−0
docs/superpowers/plans/CODEX-FINDINGS-ZDD-IMPL-5-MERGE.md+59 −0
CI passed — run details
diff --git a/docs/superpowers/plans/CODEX-FINDINGS-ZDD-IMPL-5-MERGE.md b/docs/superpowers/plans/CODEX-FINDINGS-ZDD-IMPL-5-MERGE.md| new file mode 100644 |
| index 000000000..8b2a4550f |
| --- /dev/null |
| +++ b/docs/superpowers/plans/CODEX-FINDINGS-ZDD-IMPL-5-MERGE.md |
| @@ -0,0 +1,59 @@ |
| +ACCEPT WITH FIXES |
| + |
| +Dormant merge only. I found no merge-introduced flag-off runtime defect. Correct the claims-launch assessment, record the blockers below, and obtain the controller’s complete gate on `ad766c5b`. No files or git state changed; no tests or simulations run. |
| + |
| +1. **Lease margin: preserved, with the existing launch-boundary limitations.** |
| + |
| + `d6f66ef3` changes the test TTL, not production behaviour: [checkpoint_test.go:343](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/lease/checkpoint_test.go:343). Acquisition still supplies `marginForTTL`; expiry is latched by synchronous `Err()` checks: [lease.go:195](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/lease/lease.go:195), [health.go:68](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/lease/health.go:68). |
| + |
| + The planned-wake gate checks the held lease; `ownedLocked` checks the awake entry’s replicator; `ReplaceWorker` uses that same gate: [wakeplan.go:131](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/wakeplan.go:131), [swapadmit.go:88](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/swapadmit.go:88), [workerswap.go:83](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/workerswap.go:83). The context-carried instance gates remain intact. The outcome fence waits **before acquisition**; refusing/declined planners also run before acquisition. |
| + |
| + Release still follows termination proof: [opset.go:471](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/opset.go:471), retained failed-wake cleanup at [opset.go:596](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/opset.go:596), and stop/close at [activator.go:3294](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/activator.go:3294). |
| + |
| + This preserves both flag modes’ lease semantics; it does **not** close the parked worker gap between its hook and cgroup preparation: [backend_exec.go:2137](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/backend_exec.go:2137). |
| + |
| +2. **Region-HA: flag-off behaviour preserved; flag-on integration is incomplete. P2-9 remains closed.** |
| + |
| + The resolver’s premise is wrong: production assigns `Root` at [claimconstruction.go:276](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/host/claimconstruction.go:276), and installs the root handler at [claimstop_run.go:51](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/host/claimstop_run.go:51). Claims-on launches can execute now. |
| + |
| + Admission, shape validation and root process handling survive the merge. Planned-wake gates reach `before()` immediately before the root request: [rolelaunch_root_linux.go:122](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/rolelaunch_root_linux.go:122). However, launch capability does not supply the missing rollout contracts described in answer 5. |
| + |
| + Claims-backed **swaps** remain independently refused by [claimgen.go:30](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/claimgen.go:30). That refusal does not protect planned first wakes. |
| + |
| +3. **Moves: preserved within the currently wired scope; “probes are never planned” is correct.** |
| + |
| + A probe boots moves’ prepared inputs under its own admission and attempt journal. Applying the rollout planner would select and report a different build. The exclusion at [claimwake.go:201](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/claimwake.go:201) correctly bypasses the planner—including refusing/declined planners—and its outcome fence. Probe policy, `ErrProbeFailed`, and admitted-session capture remain intact at lines 232, 303 and 314. |
| + |
| + The floor gate and landing/commit implementations are unchanged against new main. Moves retains its explicit lifecycle fence at [movespass.go:203](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/host/movespass.go:203); held-release staging correctly avoids the rollout relay at line 365. |
| + |
| + One report qualification: probes bypass **planned pre-exec publication**, not all generations publication. With generations on, a successful probe receives the canonical generation and reaches ordinary post-wake publication: [activator.go:1466](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/activator.go:1466), line 1539. Production probe callbacks remain unwired: [movespass.go:563](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/host/movespass.go:563). |
| + |
| +4. **Plan 5: prior accepted implementation preserved, but not an unconditional invariant pass.** |
| + |
| + Flag-off selection remains behind [rollout.go:142](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/host/rollout.go:142) and line 292; the index-assigned serving/generations pieces remain flag-independent. Missing delegation still prevents arming. |
| + |
| + Instance exec gates, failure-before-serving-publication, and the fail-closed outcome fence remain unchanged. Generations publication retains `genMu → a.mu`, with I/O outside `a.mu`: [generations_file.go:243](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/generations_file.go:243). Scheduler callbacks remain outside the activator lock. I found no new lock inversion. |
| + |
| + **“Hold never falls back” remains incomplete:** R3’s N5–N7 and other parked blockers still apply. Claims execution now adds the gaps below. |
| + |
| + Registry ordering is consistent: all four columns follow `hold_op` in the explicit read/write layout, scanner, insert arguments and cold-handover values: [registry.go:854](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/registry/registry.go:854), line 865, line 1151; [coldhandover.go:138](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/registry/coldhandover.go:138). Remote dispatch and error transport are correctly extended. `serving_version` is excluded from snapshot decisions; nonempty `good_*` values are tagged and hashed: [registry.go:3097](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/registry/registry.go:3097), line 3177. |
| + |
| +5. **Merge-exposed defects: all below are enablement-blocking, not dormant runtime blockers.** |
| + |
| + **High — production claims cannot honour recovery selection or fallback.** |
| + Sequence: installed B is blocked; planner selects good A; production inputs still snapshot the live link, B; [claimwake.go:351](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/claimwake.go:351) rejects the version mismatch after admission. Separately, first-wake B failure never executes `policy.Fallback`. Selection ignores the pin at [claimowners.go:374](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/host/claimowners.go:374); live-link selection is explicit at [claim_snapshot.go:87](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/claim_snapshot.go:87). The fallback is only assigned at [claimwake.go:256](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/claimwake.go:256). |
| + Smallest containment: refuse planned claims wakes before admission until the provider supports the complete contract; preserve ordinary flag-off launches. |
| + |
| + **High — a claimed hold launch can lose execution evidence and its outcome fence.** |
| + Sequence: hold B executes through root; cancellation ends readiness before success; no build failure is classified; `claimedPlanResult` returns nil. Consequently, no `GenCancelled{Executed:true}`, hold-ran marker, or outcome fence covers that execution. See [claimwake.go:524](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/claimwake.go:524), [wakeplan.go:788](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/wakeplan.go:788), and line 615. Root launch errors can also return no command after possible execution: [rolelaunch_root_linux.go:142](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/rolelaunch_root_linux.go:142). |
| + Smallest fix: propagate executed-or-unknown evidence through claimed wake results and fence delivery of the resulting restriction. |
| + |
| + **High — retained claim processes fall outside generations-file coverage.** |
| + Sequence: B launches; cleanup and `FailedAdmission` cannot prove termination; claim assembly retains the work, but `wake()` deletes the activator entry and republishes without B. Retention goes through [claimwakeassembly.go:475](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/host/claimwakeassembly.go:475); the snapshot only includes activator entries, `unprovenWakes`, and pending generations at [generations_file.go:119](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/activator/generations_file.go:119). |
| + Smallest fix: retain a publication token for the actual claimed build until claim cleanup proves it stopped. |
| + |
| + **Medium — successful claimed wakes cannot publish their good/serving identity.** |
| + Production leaves `ClaimRuntime.Generations` false and returns no `ClaimStart.Gen`: [claimwakeassembly.go:204](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/host/claimwakeassembly.go:204), line 356. `claimedPlanResult` therefore reports generation zero with the planned artifact; `wake()` separately assigns a canonical numbered generation without that artifact. After settle, [manager.go:943](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/internal/rollout/manager.go:943) rejects the mismatch. |
| + Smallest fix: assign one verified generation identity to both the installed entry and its events before publication. |
| + |
| +**Pre-enablement owed-list additions:** retain all R3 obligations; explicitly add the four claims compositions above and production-provider coverage for them. Replace “once Root is wired” with “Root is already wired.” Correct the contrary assertions at [merge-report.md:96](/home/paulca/amadan.net/carlos/platform/.claude/worktrees/zdd-5-scheduler/.superpowers/sdd/2026-10-07-zero-downtime-deploys-5-scheduler/merge-report.md:96) and line 197 before relying on that report for landing. |
| \ No newline at end of file |