fleetd #651: raise turnSettleSeconds default to 300, fix injectable javadoc #682

Closed
agent wants to merge 0 commits from worker/651-a75bbe-8 into main
Member

Code half of fleetd #651.

Raises turnSettleSeconds default from 20 to 300 in FleetConfig.LeadRollover's compact constructor, matching leadHeartbeat.idleAfterSeconds (also default 300) rather than the single 20394ms observation that exposed the bug. The wait stays bounded, as decided — not unbounded.

Fixes FleetConfig.java's javadoc for turnSettleSeconds/clearSettleSeconds, which wrongly described both waits as waiting for an "injectable" state again. The code (LeadRollover.waitUntilAtTurnBoundary) requires IDLE or DONE specifically and excludes BLOCKED (a live turn merely paused) — exactly the state where /clear would destroy context. LeadRollover.java's own javadoc already said this correctly; only FleetConfig.java needed the fix.

Adds FleetConfigTest coverage for criterion (a): turnSettleSeconds unset → 300, a positive value → itself, 0 or negative → 300.

Criteria (b) and (c) from the ticket (a roll that settles in time proceeds to /clear; a roll that never settles writes TURN_NEVER_SETTLED and sends none; BLOCKED is never treated as settled) were already pinned by existing LeadRolloverTest tests (turnThatNeverSettlesSendsNoClearAtAll, statusReportsTurnNeverSettledAfterTheRollIsAbandoned, statusReportsRolledForACompletedRoll, blockedTheWholeTurnSettleWindowSendsNoClearAtAll, blockedAfterClearNeverSendsBootstrapText) and needed no new test.

Build

cd fleetd && mvn -o clean install — Tests run: 1932, Failures: 0, Errors: 0, Skipped: 0, BUILD SUCCESS. target/surefire-reports/*.xml count after a fresh rm -rf: 172.

Mutation testing

  1. Reverted the default 300 → 20: FleetConfigTest.turnSettleSecondsDefaultsTo300WhenUnset and turnSettleSecondsFallsBackTo300WhenZeroOrNegative both failed (expected 300, got 20). Reverted.
  2. Changed waitUntilAtTurnBoundary's check to also accept BLOCKED as settled: the existing LeadRolloverTest.blockedTheWholeTurnSettleWindowSendsNoClearAtAll failed (expected 0 prompt calls, got 1). Reverted.

Fixes fleetd#651 (code half only — the live config value and the handover skill's survival check are the lead's).

Code half of fleetd #651. Raises `turnSettleSeconds` default from 20 to 300 in `FleetConfig.LeadRollover`'s compact constructor, matching `leadHeartbeat.idleAfterSeconds` (also default 300) rather than the single 20394ms observation that exposed the bug. The wait stays bounded, as decided — not unbounded. Fixes `FleetConfig.java`'s javadoc for `turnSettleSeconds`/`clearSettleSeconds`, which wrongly described both waits as waiting for an "injectable" state again. The code (`LeadRollover.waitUntilAtTurnBoundary`) requires `IDLE` or `DONE` specifically and excludes `BLOCKED` (a live turn merely paused) — exactly the state where `/clear` would destroy context. `LeadRollover.java`'s own javadoc already said this correctly; only `FleetConfig.java` needed the fix. Adds `FleetConfigTest` coverage for criterion (a): `turnSettleSeconds` unset → 300, a positive value → itself, 0 or negative → 300. Criteria (b) and (c) from the ticket (a roll that settles in time proceeds to `/clear`; a roll that never settles writes `TURN_NEVER_SETTLED` and sends none; `BLOCKED` is never treated as settled) were already pinned by existing `LeadRolloverTest` tests (`turnThatNeverSettlesSendsNoClearAtAll`, `statusReportsTurnNeverSettledAfterTheRollIsAbandoned`, `statusReportsRolledForACompletedRoll`, `blockedTheWholeTurnSettleWindowSendsNoClearAtAll`, `blockedAfterClearNeverSendsBootstrapText`) and needed no new test. ## Build `cd fleetd && mvn -o clean install` — `Tests run: 1932, Failures: 0, Errors: 0, Skipped: 0`, `BUILD SUCCESS`. `target/surefire-reports/*.xml` count after a fresh `rm -rf`: 172. ## Mutation testing 1. Reverted the default 300 → 20: `FleetConfigTest.turnSettleSecondsDefaultsTo300WhenUnset` and `turnSettleSecondsFallsBackTo300WhenZeroOrNegative` both failed (expected 300, got 20). Reverted. 2. Changed `waitUntilAtTurnBoundary`'s check to also accept `BLOCKED` as settled: the existing `LeadRolloverTest.blockedTheWholeTurnSettleWindowSendsNoClearAtAll` failed (expected 0 prompt calls, got 1). Reverted. Fixes fleetd#651 (code half only — the live config value and the `handover` skill's survival check are the lead's).
agent added 1 commit 2026-10-03 21:36:29 +02:00
fleetd #651: raise turnSettleSeconds default from 20 to 300
CI / shell-tests (pull_request) Failing after 7s
CI / contract (pull_request) Successful in 56s
CI / build (pull_request) Failing after 1m55s
5d8b9d365c
A lead that runs the documented handover procedure writes its goodbye
message in the same turn as fleet_handover confirm. The deferred roll
then waits turnSettleSeconds for that same pane to reach IDLE or DONE.
An ordinary goodbye turn took 20394ms, so a 20s budget was too small
and the roll refused itself with TURN_NEVER_SETTLED. The refusal
branch is correct; only the budget was wrong.

300 is not derived from that single 20394ms observation. It matches
leadHeartbeat.idleAfterSeconds (also default 300), the only other
constant in this codebase answering "how long may a lead legitimately
be mid-turn", whose own javadoc reasons that 5 minutes absorbs normal
pauses without stalling. The two constants answer the same question
and should not disagree by a factor of fifteen. The wait stays bounded
on purpose: an unbounded wait would let a lead whose turn never ends
park a continuation and hold a pending token forever, which is harder
to notice than a logged refusal.

Also corrects FleetConfig's javadoc for turnSettleSeconds and
clearSettleSeconds, which described both waits as waiting for the
pane to report an "injectable" state again. The code requires IDLE or
DONE specifically and excludes BLOCKED (a live turn merely paused),
which is the exact state where sending /clear would destroy context.
LeadRollover.java's javadoc already states this correctly; only
FleetConfig.java's was wrong.

Adds FleetConfigTest coverage for the default's resolution: unset,
positive, and <= 0 all resolve as expected. Coverage for the two
turn-boundary properties (settles-in-time vs. never-settles, and
BLOCKED is not treated as settled) already existed in
LeadRolloverTest and needed no change — confirmed by mutating the
default back to 20 and the IDLE||DONE check to also accept BLOCKED;
both mutations were caught by existing or new tests, then reverted.
ltms closed this pull request 2026-10-03 21:43:40 +02:00
Some checks are pending
CI / shell-tests (pull_request) Failing after 7s
CI / contract (pull_request) Successful in 56s
CI / build (pull_request) Failing after 1m55s

Pull request closed

Sign in to join this conversation.