#480 lead rollover: /clear and bootstrapText concatenate into one line — the roll never bootstraps #489

Open
opened 2026-09-12 02:18:36 +02:00 by ltms · 0 comments
Owner

Measured live on the Mac, 2026-09-12, first real rollover of the shipped feature.

What happened

fleet_handover{action:"confirm"} was accepted, the turn ended, and the pane received a single submitted line:

/clearFresh lead session. First run fleet_whoami; …

Claude Code answered Unknown command: /clearFresh. The context was not cleared, nothing was destroyed, and the handover file stayed intact. The roll failed safely, and did nothing.

Evidence

From the lead session transcript (d17cb4ad-….jsonl, lines 2352-2354) and fleetd/fleetd.out:

00:03:43.560  system turn_duration                     <- the calling turn ends
00:03:43.998  lead-rollover: rolled token=94d81e93-...  (fleetd.out)
00:03:44.309  warning: Unknown command: /clearFresh
00:03:44.310  warning: Args from unknown skill: lead session. First run fleet_whoami; ...

/clear + Fresh lead session. ... = /clearFresh lead session. ..., joined with no space, because a paste lands at the cursor. The whole four-step roll ran in 438 ms of a 20-second budget.

Cause

Two faults, in LeadRollover.runRollover (fleetd/src/main/java/dev/ltms/fleet/lead/LeadRollover.java:380-392):

  1. The second gate is a no-op. waitUntilAtTurnBoundary(lead, clearSettleSeconds) returns on its first poll, because /clear starts no turn and the pane never leaves IDLE. LeadRolloverTest:204 already says this out loud - "default agentStatus is idle - both waits settle immediately" - and nobody asked whether it should. The first gate (turnSettleSeconds) is fine; it is what consumed the 13 seconds before the failure.
  2. The submit keystroke raced the paste. AgentControl.submit's own javadoc records this: "The submit that accompanies a delivery can race the paste ... leaving the text unsubmitted; the injector nudges it with this until the worker actually picks up (CB-113)." LeadRollover bypasses Injector on purpose (routing /clear through it wedges the pane forever), so it inherits none of that nudging. The /clear Enter was lost, the text sat in the input box, and the next paste appended to it.

A live probe on a throwaway sonnet member confirms the second half: a /clear sent through Injector executed cleanly - a new transcript was born at 07:15:29 whose line 4 is literally <command-name>/clear</command-name>. The difference between that success and this failure is the nudge.

The fix

Copy the pattern Injector already ships for post-turn /clear housekeeping (fleetd #306, Injector.java:293-334): after sending /clear, re-send Enter with AgentControl.submit on each poll while the pane is still injectable and no pickup has been seen, bounded like PICKUP_GRACE_POLLS = 8. A second Enter on an empty Claude Code prompt is a no-op, so the nudge is safe to repeat. Only then send bootstrapText.

Related

  • fleetd #480 - acceptance criterion 6 ("the bootstrap prompt lands in the fresh session") is now answered negatively, not merely unproven. wiki/11-Features.md and .claude/skills/handover/SKILL.md both still say "not yet proven end-to-end" and need correcting to "measured failing".
  • fleetd #486 - the settle poll has no bound of its own.
  • fleetd #482 - a context reset changes the peer's session id.
Measured live on the Mac, 2026-09-12, first real rollover of the shipped feature. ## What happened `fleet_handover{action:"confirm"}` was accepted, the turn ended, and the pane received a single submitted line: ``` /clearFresh lead session. First run fleet_whoami; … ``` Claude Code answered `Unknown command: /clearFresh`. The context was **not** cleared, nothing was destroyed, and the handover file stayed intact. The roll failed safely, and did nothing. ## Evidence From the lead session transcript (`d17cb4ad-….jsonl`, lines 2352-2354) and `fleetd/fleetd.out`: ``` 00:03:43.560 system turn_duration <- the calling turn ends 00:03:43.998 lead-rollover: rolled token=94d81e93-... (fleetd.out) 00:03:44.309 warning: Unknown command: /clearFresh 00:03:44.310 warning: Args from unknown skill: lead session. First run fleet_whoami; ... ``` `/clear` + `Fresh lead session. ...` = `/clearFresh lead session. ...`, joined with no space, because a paste lands at the cursor. The whole four-step roll ran in 438 ms of a 20-second budget. ## Cause Two faults, in `LeadRollover.runRollover` (`fleetd/src/main/java/dev/ltms/fleet/lead/LeadRollover.java:380-392`): 1. **The second gate is a no-op.** `waitUntilAtTurnBoundary(lead, clearSettleSeconds)` returns on its first poll, because `/clear` starts no turn and the pane never leaves `IDLE`. `LeadRolloverTest:204` already says this out loud - *"default agentStatus is idle - both waits settle immediately"* - and nobody asked whether it should. The first gate (`turnSettleSeconds`) is fine; it is what consumed the 13 seconds before the failure. 2. **The submit keystroke raced the paste.** `AgentControl.submit`'s own javadoc records this: *"The submit that accompanies a delivery can race the paste ... leaving the text unsubmitted; the injector nudges it with this until the worker actually picks up (CB-113)."* `LeadRollover` bypasses `Injector` on purpose (routing `/clear` through it wedges the pane forever), so it inherits none of that nudging. The `/clear` Enter was lost, the text sat in the input box, and the next paste appended to it. A live probe on a throwaway sonnet member confirms the second half: a `/clear` sent through `Injector` executed cleanly - a new transcript was born at `07:15:29` whose line 4 is literally `<command-name>/clear</command-name>`. The difference between that success and this failure is the nudge. ## The fix Copy the pattern `Injector` already ships for post-turn `/clear` housekeeping (fleetd #306, `Injector.java:293-334`): after sending `/clear`, re-send Enter with `AgentControl.submit` on each poll while the pane is still injectable and no pickup has been seen, bounded like `PICKUP_GRACE_POLLS = 8`. A second Enter on an empty Claude Code prompt is a no-op, so the nudge is safe to repeat. Only then send `bootstrapText`. ## Related - fleetd #480 - acceptance criterion 6 ("the bootstrap prompt lands in the fresh session") is now answered **negatively**, not merely unproven. `wiki/11-Features.md` and `.claude/skills/handover/SKILL.md` both still say "not yet proven end-to-end" and need correcting to "measured failing". - fleetd #486 - the settle poll has no bound of its own. - fleetd #482 - a context reset changes the peer's session id.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: fleet/fleetd#489