diff --git a/fleetd/src/test/java/dev/ltms/fleet/session/SessionManagerTest.java b/fleetd/src/test/java/dev/ltms/fleet/session/SessionManagerTest.java index 3f99ffb..2daf2fc 100644 --- a/fleetd/src/test/java/dev/ltms/fleet/session/SessionManagerTest.java +++ b/fleetd/src/test/java/dev/ltms/fleet/session/SessionManagerTest.java @@ -2219,6 +2219,64 @@ class SessionManagerTest { + "on the worktree path alone (fleetd #425 rework, round 2)"); } + /** + * fleetd #425 rework, round 4: the exact regression a mutation test found that 186 green tests + * missed — {@code acquireWithWorktree} dropping the {@link + * dev.ltms.fleet.placement.PlacementDecision} it already resolved via {@code launcher.place}, + * and letting the unqualified spawn re-run placement a second time (a blank-profile {@code + * launcher.spawn(spawnReq)}) instead of carrying that decision forward via {@code + * launcher.spawn(spawnReq, decision)}. Every earlier test in this file uses {@code + * PlacementPolicies.fixed()}, which returns the same answer on every {@code select()} call, so + * dropping the decision is invisible under it — two {@code select()} calls simply agree by + * accident. {@code PlacementPolicies.roundRobin()} is deterministic AND stateful: its {@code + * select()} advances an internal index on every call, so two consecutive calls for the SAME + * spawn (one from {@code place()} to provision the worktree, a second from a dropped-decision + * blank-profile {@code spawn(spawnReq)}) land on DIFFERENT profiles from a two-profile pool — + * index 0 ("a"), then index 1 ("b"). + * + *
This test does not hardcode which profile wins — asserting one specific name would pass
+ * for the wrong reason the moment the rotation order changes (round-4 brief invariant 3). It
+ * asserts AGREEMENT instead: whichever profile the worktree's parity overlay was provisioned
+ * for must be the SAME profile the member actually spawned on. Each profile's overlay list is
+ * named after the profile itself ({@code "a.mcp.json"}/{@code "b.mcp.json"}), so comparing the
+ * recorded overlay against {@code s.profile() + ".mcp.json"} checks agreement without ever
+ * naming an expected winner.
+ */
+ @Test
+ void acquireWithWorktreeSpawnsOnTheSameProfileItProvisionedTheWorktreeForUnderARotatingPolicy() {
+ Map