A lead rollover reports rolled while the bootstrap paste is lost: the send skips the MemberPresence gate that exists for exactly this race
#809
Closed
opened 2026-10-07 06:50:35 +02:00 by ltms
·
3 comments
No Branch/Tag Specified
main
worker/811-disable-terminal-title-85cfbd-1
worker/808-0c71eb-2
worker/797-disable-box-gate-5b5478-12
worker/799-a76336-9
worker/796-a7911a-5
worker/778-e301b0-1
worker/791-fleet-plugin-0-3-0-9e25b0-2
worker/790-observer-to-lead-send-523d45-1
worker/788-eb7dd0-1
worker/782-styling-probe-4ceb10-9
worker/778-12988a-4
worker/782-18f8bc-5
worker/780-faf58b-3
worker/759-authz-comment-and-role-list-e3f0e5-5
worker/756-758-observer-pane-discovery-7e6ffd-1
worker/759-role-model-comments-5d8409-3
worker/743-pane-discovery-ad5b75-5
worker/743-observer-send-4706db-6
worker/749-edge-baseline-28d1a0-3
worker/748-dead-comment-refs-f42ac5-4
worker/737-9c61d3-4
worker/737-a263f3-3
worker/737-20d1d9-1
worker/737-b038f7-2
worker/726-unit2-75cb13-4
worker/737-owner-key-ff061f-10
worker/736-presence-forget-f35144-9
worker/705-observer-14c258-6
worker/722-024c34-5
worker/726-ea34a0-2
worker/726-10cbf0-1
worker/729-5961c6-3
worker/727-ee14ed-3
worker/719-bdd95e-4
worker/702-4f5c7f-2
worker/715-5c43fc-1
worker/721-70f9ea-5
worker/718-99362b-2
worker/task-15-af0d10-12
worker/task-16-50a702-13
worker/task-12-4d0479-9
worker/task-13-823ce2-10
worker/705-ticket-owner-af9928-8
worker/703-list-collaborators-9c06c2-7
worker/669-example-truth-0b303d-6
worker/669-collab-deliverability-9ba859-3
worker/669-collab-reload-report-2a21bd-4
worker/669-7e80a6-1
worker/669-unit-d-efbbd7-1
worker/669-1b786a-1
worker/669-1d1d9f-1
worker/692-4afb9d-2
worker/689-02fced-13
worker/693-cf23fa-14
worker/677-fix-lead-collision-f69073-12
worker/638-fix-overmask-dbb1bf-11
worker/675-5b7478-4
worker/669-unit-a-70cc8f-3
worker/677-8cdaaf-5
worker/638-a7b391-1
worker/683-4536d6-2
worker/651-a75bbe-8
worker/680-20607d-7
worker/664-c12e95-3
worker/668-08534d-4
worker/672-0f2469-2
worker/670-7d1022-1
worker/661-ac7c28-2
worker/664-37fb9b-3
worker/663-remove-3arg-read-3f6783-1
worker/659-remove-dead-backcompat-ba5e6f-1
worker/637-revision-60a488-23
worker/656-redact-regression-tests-892903-19
worker/637-context-gauge-threshold-466eb5-16
worker/639-redact-line-numbers-de4ac4-17
worker/641-set-reformat-guard-6f96a4-18
worker/642-herdr-guard-scope-5de0e4-15
worker/650-javadoc-scope-95f3b3-14
worker/612-01e9f7-13
worker/612-a-r4-quarantine-outage-7ab0e8-5
worker/612-a-r9-r11-capacity-coverage-peers-cfcc79-7
worker/612-a-r10-loophealth-ccc872-8
worker/612-a-r12-turnregistrar-9e3bb7-9
worker/612-a-r5-leadconfigdir-9e70cf-6
lead/config-edit-redact-anchor-wording
worker/config-edit-seam-ca8dc1-1
worker/612-r67-630-lifecycle-290b8d-3
worker/629-625-ports-seams-da7d5d-4
worker/612-r12-exhaustion-f37cd7-1
worker/612-r38-amqp-24b083-2
worker/fleetd-612-unita-87807e-1
worker/612-b3-mcpwirings-da2b58-3
worker/612-b2-cb185-176d3a-2
worker/612-b1-completion-457459-1
worker/612-agaps-73a926-2
worker/608-sleeps-3a64ff-3
worker/621-b4520b-1
worker/618-b83894-2
worker/fleetd-615-e05481-5
worker/lead-autocompact-5f1ab2-3
worker/fleetd-613-f85deb-3
worker/fleetd-608-flaky-nudge-test-d0c2d1-3
worker/lead-context-gauge-ad404f-1
worker/gauge-wiring-9158c1-4
worker/redeploy-slowstart-ead0e5-5
worker/charter-bytes-13668c-6
worker/rollover-outcome-291483-2
worker/589-f64303-2
worker/593-1a8025-5
worker/589-fcd2aa-1
worker/568-9fdaa2-3
worker/571-attempted-outcome-5739f7-2
worker/581-completionresolver-cas-sites-0542b7-6
worker/562-loop-health-wiring-test-99611c-5
worker/562-surface-loop-health-7df5cc-4
worker/575-waiter-cleanup-sites-62ad80-1
worker/572-answer-lock-release-46a9ae-5
worker/567-probe-channel-leak-a38fc5-6
worker/551-record-before-send-7cbf56-1
worker/561-listener-fanout-survives-a-throw-61d538-2
worker/555-redeploy-main-flow-seam-65c2f5-2
worker/556-injector-owns-registration-e027a5-1
worker/552-post-restart-mktemp-abort-bc2672-4
worker/553-onstatus-completion-leak-0da881-2
worker/550-shasum-linux-196132-1
worker/538-loop-dies-on-error-4a5eeb-6
worker/426-health-coverage-ef1fd4-4
worker/504-failed-reported-clean-3cfd66-3
worker/537-capturedlog-close-e4c437-2
worker/459-broken-link-targets-cadc17-5
worker/535-appender-leak-fe74c1-1
worker/512-part2-shutdown-detection-434701-9
worker/529-logger-level-sweep-2a5533-8
worker/528-drain-gate-call-site-5de83d-7
charter/forge-mcp-vs-token
worker/521-swap-guard-unpinned-28e931-5
worker/519-probe-test-harness-d25ab8-4
worker/525-logger-level-leak-1b4eb0-6
worker/518-fleetmcp-resolver-wiring-8ef96c-1
worker/512-drain-complete-line-7edd71-3
worker/517-abort-branch-and-jar-id-41b641-2
worker/500-9e52c9-3
worker/509-4912f4-2
worker/511-9a4b23-1
worker/493-479f45-2
worker/505-03f8b2-1
worker/492-followup-detect-unclear
worker/501-a31fa0-7
worker/498-451d1c-5
worker/494-1015ce-2
worker/492-209647-1
worker/489-001902-2
worker/480-relative-handover-path-906323-1
worker/480-b-handover-skill-45bf1f-5
worker/474-followup-source-pin-f54a55-17
worker/474-charter-check-on-reload-f54a55-17
worker/466-quarantine-repeatcount-report
worker/393-opencode-skill-seeding-71854b-13
worker/469-canonical-tool-names-2a472a-16
worker/466-quarantine-escalation-5ae9c1-15
worker/446-hot-exhausted-pattern-0af580-6
worker/464-charter-tool-name-guard-a85635-12
worker/463-listfleet-default-fails-open-f1c76c-11
worker/458-invariant-5-by-purpose-862f9a-10
worker/439-coordinator-row-gate-bc032a-8
worker/449-herdr-protocol-576015-4
worker/450-abstract-spawn-599e1c-5
worker/437-ack-refuses-177d91-1
worker/444-placement-window-feb56a-2
worker/440-helddurable-derived-d462d7-13
worker/425-rework-placement-resolve-c58ba1-9
worker/421-lead-peek-held-msgs-cdbad2-10
worker/435-fixed-policy-cap-fe11de-12
worker/422-gate-state-observability-9e79d6-11
worker/431-memberregistry-live-readers-cdbad2-10
worker/424-architect-slot-hot-038b41-7
worker/422-model-gate-spawn-c29f48-6
worker/425-default-profile-live-f55534-8
worker/415-coverage-wording-2cbf9c-5
worker/416-3ad1da-1
worker/418-588283-3
worker/deterministic-stamp-race-409-3cb7b6-10
worker/armed-reads-live-config-404-ed931f-9
worker/reply-peer-refusal-391-5a34bd-7
worker/models-allowlist-aa9e9b-3
worker/ttl-stamp-race-399-f1122f-8
worker/scrub-receipt-400-316b3e-5
worker/exhaustion-detection-395-105105-6
worker/scrub-abort-394-316b3e-5
fix/scrub-uid-abort
worker/task-scrub-517574-2
worker/t386-clock-bd5b78-4
worker/t384-scrub-813790-5
worker/t381-cc-748314-2
worker/t373-336973-2
worker/t365-3920c5-3
worker/t358-6e989b-1
worker/t355-8b321c-1
worker/fleetd-369-hermetic-git-tests-e8b19a-3
worker/fleetd-368-stale-lead-binding-f5682e-2
worker/fleetd-360-deploy-units-0d3793-1
worker/359-dead-lead-tabs-f1253b-4
worker/362-worktree-skills-c03e51-3
worker/361-coord-visibility-655144-1
362-plugin-visibility-and-drift
worker/errscan-bed2ca-2
worker/amqp-log-identity-bed2ca-2
worker/withdefaults-guard-561704
worker/sleepguard-82076d-1
worker/fd334-9ee1b6-5
worker/fd348-f1ab27-4
worker/fd335-a71c35-1
worker/fd342-174a17-2
worker/fd345-490d0f-3
worker/fleetd-337-5ec7d4-21
worker/fleetd-341-af5a6b-24
worker/fleetd-339-5ca0a2-23
worker/fleetd-338-83a4a1-22
worker/fleetd-333-281f46-18
worker/fleetd-329-11bdbb-16
worker/fleetd-330-2770fb-17
worker/fix-326-50506e-15
worker/fix-324-3e9bbf-14
worker/fix-323-b8287d-13
worker/fix-316b-bd0860-11
worker/fix-318-76ca36-9
worker/fix-317-486aec-8
worker/fix-315-ce47c5-6
worker/fix-307-275890-6
worker/fix-308-b4f664-7
worker/fix-309-ec3939-8
worker/fix-310-7a3974-9
worker/fix-302-52ad0e-9
worker/fix-298-ce1acb-8
worker/fix-297-66bd11-7
worker/fix-296-104622-6
worker/fix-293-bare-closetab-eb22b5-3
worker/fix-280-gone-ask-lapse-bca98e-2
worker/fix-290-reapidle-guard-coverage-9b0dd1-1
worker/fix-285-trust-seed-8f3565-10
worker/fix-284-backend-error-seat-85912c-11
worker/fix-282-chained-ask-e6d0bb-8
worker/fix-283-teardown-leaks-f40dfa-9
worker/fix-281-pin-handler-actions-4921ac-7
worker/audit-rendezvous-lifecycle-d072ae-2
worker/audit-health-placement-1a2476-6
worker/audit-teardown-exits-e207a5-3
worker/audit-launcher-asymmetry-27e370-4
worker/audit-rest-authz-6ca53c-5
worker/investigate-275-abandon-asking-fdef52-8
worker/fix-274-worktree-leak-b0095d-7
worker/fix-273-exhausted-pattern-9665b5-6
worker/fleetd-267-model-check-bd8068-1
worker/fleetd-131-archunit-18b834-7
worker/fleetd-266-sshagent-rename-a014ff-6
worker/fleetd-184-uid-claim-8e1f31-4
worker/fleetd-184-warn-b381ee-10
worker/fleetd-184-docs-be1d12-9
worker/fleetd-257-9bf010-7
worker/fleetd-103-23a113-6
worker/fleetd-247-342356-5
worker/fleetd-116-04dea8-4
worker/fleetd-252-a830e0-3
worker/fleetd-111-7e8673-9
worker/fleetd-155c-f8ef4b-8
worker/fleetd-176-b928ca-3
worker/fleetd-249-7a7878-2
worker/cb248-composition-root-b-9acdf7-15
worker/cb148-envrc-default-fa6c82-12
worker/cb201-unit5-wiring-6c12e6-8
worker/cb241-fallback-echo-1175e9-11
worker/cb149-trust-dialog-2392a5-9
worker/cb134-148-overlay-visible-c9b986-10
worker/cb234-session-id-keyed-04e1fc-1
worker/cb201-unit3-nudge-abdf5c-6
worker/cb201-unit2-policy-c1102c-5
worker/cb201-unit4-outcome-a13bfa-7
worker/cb201-unit1-classifier-91b9b1-4
worker/cb201-227-refine-831980-3
worker/cb175-model-readback-0f085f-1
worker/cb222-charter-tmpdir-17f013-1
worker/cb226-architect-slot-race-cd3aa8-3
worker/cb224-worktree-root-group-024523-2
worker/cb-123-role-demotion-c600f7-2
worker/cb-219-opencode-roots-1f677e-1
worker/cb214-claude-session-id-b9eab4-4
worker/cb213-zdotdir-wrong-process-dd6de4-3
worker/cb211-exhaustion-classification-9546e0-2
worker/cb137-ambiguous-task-4df3d8-4
worker/cb209-agentsessionid-4dfdb6-2
worker/cb185-hostenvnames-2692b5-3
worker/cb206-opencode-sqlite-128718-2
worker/cb185-worktree-group-fc0c99-1
worker/cb-137-ask-ticket-e7760c-2
worker/cb-172-broker-uri-d36ae4-4
worker/cb-175-model-readback-76ead6-3
worker/cb-161-pane-ancestry-293510-1
worker/cb-164-rebase-885863-8
worker/cb-164-empty-scrape-false-success-1a80af-3
fix/cb-197-ticket-ttl-from-completion
worker/cb-189-remote-url-coverage-4692f3-1
worker/cb-185-blockers-027756-4
worker/cb-192-gap-log-11b631-2
worker/cb-633-fix-5f4396-3
worker/cb185-router-d6436d-3
worker/cb185-router-routing-gaps-9e9d33-3
worker/cb185-paneids-992586-2
worker/cb-633-allow-list-union-ed374b-1
worker/cb-157-credential-in-remote-url-496e44-2
worker/cb-641-health-herdr-evidence-8f1f54-6
worker/cb-640-health-msg-evidence-99c9cd-1
worker/cb-642-fleets-status-skill-bbbc40-5
cb-634-ide-mcp
worker/lead-comms-wiring-c014b9-7
worker/lead-mailbox-c19577-6
worker/autocompact-window-82bc2f-5
worker/cb-634-probe-18056f-4
worker/cb635-broker-urienv
worker/cb-632-config-retry-8e0efa-7
lead/cb-622e-claude-md
lead/cb-622-followup
worker/cb-622a-165dff-1
lead/cb-622d-opencode-mount
worker/cb-622b-717c67-2
worker/cb-622c-ab7759-3
worker/cb-617b2-20ca4b-3
worker/cb-617a-5c2f4a-1
worker/cb596-4e49ef-3
worker/cb586-10500c-1
worker/cb-606-b9343a-25
worker/cb604-1445f8-24
worker/cb582-477374-21
worker/cb584-8c2281-22
worker/cb600-e6b9a9-20
worker/cb602-ce257f-19
worker/cb601-b42837-18
worker/cb598-6c7ba7-17
worker/cb599-740fe4-16
worker/cb597-282224-15
worker/cb590fix-185e9a-10
worker/cb528-recovery-race
worker/cb594-96bead-8
worker/cb590-916766-2
worker/cb527-997d99-3
worker/cb592-env-leak-3cbf9c-1
worker/cb588-async-ticket-nudge-3218f7-5
worker/cb578b-9dcb13-6
worker/cb581-d24826-5
worker/m2-u5-ef8c42-15
worker/cb578a-516499-2
worker/cb576-01a04b-17
worker/cb579-lead-tab-acba06-20
worker/cb580-terminal-health-ed6058-21
worker/cb577-f36fdc-18
worker/cb573b-3db06f-16
worker/cb568c-f36fdc-18
worker/cb568-drop-cause-c3ac1c
worker/cb575-cancelled-notification-c3ac1c
worker/m4-sol-a2cbec-3
worker/cb574-async-ask-c3ac1c
worker/cb573-health-model-8ca857-14
worker/cb572-unknown-target-7f2e35-13
worker/u4-700706-9
worker/u3-b9fcb6-6
worker/u2-ef5b68-4
worker/u1-469dce-1-clean
worker/u1-469dce-1
worker/cb-564-health-events-70cf7e-2
worker/cb-565-recycle-drops-role-98e58f-3
worker/cb-563-missing-reply-df2866-1
worker/cb-562-readiness-gate-silent-6c23c9-3
worker/cb-560-architect-presence-da8155-1
worker/cb-561-architect-silent-off-a71cab-2
worker/cb-548-bind-architect-slot-fe1b8c-1
worker/parity-overlay-settings-5fb711-1
secrets-central-store
cb-559-hot-key-correction
cb-557-fleet-role-pools
worker/cb-553-maxload-explicit-spawn-305ee3-6
worker/cb-551-idle-lead-heartbeat-f1633c-1
worker/cb-544-drain-preserves-worktree-925fad-3
worker/cb-552-docs-sync-1cb9cf-4
worker/cb-548-rendezvous-guard-rebased
worker/cb-548-rendezvous-guard-116b53-10
worker/cb-548-authz-v2-586df6-8
worker/cb-548-authz-264363-5
salvage/cb-528b-codex-home
salvage/cb-528a-codex-launcher
CB-518-primary-flow
feature/peer-launcher-spi
cb-103-injector
v1.1.0
v1.0.0
Labels
Clear labels
blocked
needs-live-proof
ready-to-delegate
silent-default
Cannot start until something else lands. The body says what.
Merged and green, but never shown working on the running daemon. Not the same as done.
Scope, files and acceptance criteria are written. A worker can be briefed from the body alone.
A feature that compiles, passes tests, and ships turned off. Nine recurrences and counting.
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: fleet/fleetd#809
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Measured on this host (mac) on 2026-10-07. This is #796 happening again, in the other direction. #796's fix made the send stop failing; it did not make the send arrive. The roll logged
rolled, the successor got nothing, and the operator had to type the resume by hand.MemberPresence's own class javadoc already names the mechanism.LeadRolloveris the one delivery path in the daemon that does not read it.What the log says
fleetd/fleetd.outlines 130629-130632. The file carries no dates; these times are CEST on 2026-10-07.Read the order.
rolledis 3ms after the tab scanner line, sosendBootstrapWithRetryreturnedsent=trueon its first attempt, at about06:26:06.526. The fresh Claude Code connected its MCP client 583ms later. The daemon typed the bootstrap into a pane whose agent had not booted yet, herdr accepted the keystrokes, and the text went nowhere.There is no
bootstrapText was never sentline and noBOOTSTRAP_NEVER_SENToutcome. The retry window (relaunchReadySeconds, default 45s, not set infleetd.yaml) was never used, because nothing refused.What the session transcripts say
The successor's own transcript is
~/.ccs/instances/ltms/projects/-Users-dai-ha-LTMS-claude-bridge/611c0301-….jsonl. Its first entry is the operator's/clearat2026-10-07T04:42:01.817Z— 06:42:01 CEST, 16 minutes after the launch. Nothing was recorded in between, because nothing arrived. The first real message is the operator's own, at 04:42:52Z.Counting every transcript in that directory that holds the bootstrap as a received user message:
That last one is 07:20:49.031 CEST, and its roll logged
rolledat 07:20:48.707 — 324ms earlier. So a delivered bootstrap does show up in the transcript, within a third of a second. Nothing is recorded for 2026-10-06 or 2026-10-07. Two rolls, two losses: #796's (loud) and this one (silent).Re-measure with:
Cause, read in the code
MemberPresence.java:6-17describes this exact failure, and says the daemon already has the right signal:So for a spawned member,
Injectorholds the first delivery until MCP presence. For a fresh lead,LeadRolloverdoes not:LeadRollover.waitUntilPaneReady(LeadRollover.java:898) pollsagents.status(newTerminal)and acceptsIDLEorDONE. That is herdr'sagent_status— the signalMemberPresence's javadoc says you must not trust for this. Its own javadoc claims it stopsbootstrapTextbeing "typed into a pane that has not actually finished booting". It cannot keep that promise.LeadRollover.sendBootstrapWithRetry(LeadRollover.java:781) callsagents.send— raw herdr keystrokes. It is the only message in the daemon that does not go throughInjector.enqueue, so it gets no status gate, noPaneInboxcollection route for a mod-served pane, and no delivery future. "herdr accepted the keystrokes" is the only thing the roll can check, and it is not evidence of receipt.Two separate defects, then:
agent_statusisidleduring the boot window.Why this is the worst outcome a roll can have
A refused roll keeps your context. This one threw the context away and put nothing in its place. The successor has no handover file, no ticket, no token to call
fleet_handover{action:"status"}with, and no reason to suspect anything is wrong. Here it sat idle for 16 minutes until a person noticed.Suggested fix
waitUntilPaneReadyrequire MCP presence as well as a turn boundary.MemberPresence.isPresent(newTerminal)is the signal. Its existing timeout stateRELAUNCH_NEVER_READYalready covers the failure, so this adds no new outcome, and it makes that method's javadoc true.agents.send, wait a bounded time for the fresh pane to start a turn (agent_statusWORKING). If it never does, record a new terminal outcome and log a WARN, so a lost paste is visible instead of being reported asrolled. Report only — do not re-send, because a second paste into a session that did receive the first would be worse.FleetConfig.relaunchReadySeconds's javadoc was corrected under #796 to say it bounds three waits. A new wait makes it four. Correct it in the same pass, and update the outcome table in.claude/skills/handover/SKILL.md.bootstrapTextthroughInjector.enqueueinstead of rawagents.send, and wait on theDeliveryfuture. That would give the bootstrap the same status gate, inbox-collection route and delivery proof every other message already has, instead of re-implementing a weaker version of each.Not measured
MemberPresence's own documented one, not my own reading of herdr.initializerequest is the earliest moment the TUI accepts input. It may be later still, in which case presence is necessary but may not be sufficient — which is the second half of the fix.lead-rollover: rolledlines are in the currentfleetd.outagainst 19 recorded deliveries, but that file spans more than this project's rolls, so I am not treating the difference as two extra losses.Correction from the lead for the worker on
worker/809-ed41e4-1. This comment is newer than your brief and it wins.Your
mvn clean installis not slow, it is spinning. Do not wait for it. I took a thread dump of your forked surefire JVM (pid 83235) at 07:17:24:7 minutes of CPU on one test,
runnablethe whole time, and no new surefire report since 07:10:16.The cause, and it is your change, not that test
Your new post-send wait polls for
AgentStatus.WORKINGand bounds it withrelaunchReadySeconds(45s). No existing full-roll test ever drives the fresh terminal toWORKING—FakeHerdrleaves it at the turn boundary — so every roll in those tests now pays the whole bound.statusHistoryDoesNotGrowPastItsCapdrivesOUTCOME_HISTORY_CAP + 50= 250 rolls withnowMillis = () -> clock.addAndGet(1)andpollSleeper = () -> { }, so that is 250 × 45,000 = about 11 million iterations of a no-sleep loop, each one calling intoFakeHerdr. It terminates eventually; it is useless as a test run.The presence gate is not the problem.
newRolloverForAFullRollalready defaultsmcpPresentto_ -> true, and that part of your change looks right.What to do
relaunchReadySecondswas my suggestion in the brief and it was wrong: 45s is sized for a pane to boot, not for an agent that has already been handed a prompt to start acting on it. Pick a bound of a few seconds, name it in the code, and say in your reply what you chose and why. That also keeps theFleetConfigjavadoc at three waits instead of four, so skip that part of the brief — but still add the newRollStaterow to.claude/skills/handover/SKILL.md.FakeHerdrable to report aWORKINGstatus for the fresh terminal and have the full-roll helper use it, so the existing tests stay fast and keep assertingROLLED.agent_statusis polled every 250ms in production. A successor that starts its turn and finishes it inside one poll interval would never be observed asWORKING, and your wait would then report a lost bootstrap that in fact landed — a false alarm in the one place an operator must be able to trust. Prefer a signal that cannot be missed between polls: any departure from the turn boundary, or the session's turn counter if one is reachable from here. Choose one, say which, and say what you rejected.Unchanged
Everything else in the brief stands: report only, no re-send; do not grow
FleetdAssembly.assembleAndStart;mvn clean installunpiped with the realTests run:line; your own PR; no merge and no redeploy.Kill the running build before you start — it is burning a core for nothing.
Lead note for the worker — one thing I did to your worktree, so a confusing build failure has an explanation.
The spinning build was never killed, so at 07:22 two
mvnruns were live in/Users/dai.ha/LTMS/.bridged-worktrees/447965-1at once: the old one (pid 83008, 12m13s elapsed) and your new one (pid 9918, started 07:21:06). They sharefleetd/target. I killed 83008 and its surefire children; your 9918 is untouched.If your current build fails in a way that makes no sense — a missing class, a half-written jar, a surefire report for a test you did not run — that is why. Re-run
mvn -o clean installonce and treat the second result as the real one. Also notetarget/surefire-reportscan still hold XML from the killed run; a stale report counts tests that never ran in your build, so read theTests run:total from the build output, not from the report files.Your ticket
task-8dd115-1has also gone terminal (30-minute async timeout) while you were building, so the id no longer accepts a reply. Still end your turn with exactly onefleet_reply— it lands in your pane's inbox and I drain it withfleet_poll{target}. Nothing is lost.No other change to your tree, and nothing else in the previous comment is altered.
Fixed on
mainina144dbe.What changed
waitUntilPaneReadynow requires two signals, not one: a real turn boundary (IDLEorDONE) andmcpPresent—MemberPresence::isPresent, wired atFleetdAssembly.java:460. That is the same signalInjectoralready uses to hold a spawned member's first delivery.LeadRolloverwas the only delivery path that did not read it.RELAUNCH_NEVER_READYnow names which of the two was missing:last status=… (a real turn boundary is IDLE or DONE), bridge MCP connected=…. The old message named only the turn boundary, so the presence half would have been invisible.After the send, a new
waitUntilTurnStartedpolls for a live turn (WORKINGorBLOCKED), bounded byBOOTSTRAP_CONFIRM_TIMEOUT_SECONDS = 5— notrelaunchReadySeconds. That budget sizes a pane booting a CLI; this one sizes an agent reacting to text it already holds, which takes one status poll. A miss reports the newBOOTSTRAP_NOT_CONFIRMEDand re-sends nothing: the status is polled every 250ms, so a turn shorter than one interval reads as unconfirmed, and a second paste into a session that did receive the first is worse than one unconfirmed roll. The detail text says so, and tells the reader to check the successor.Verified
mvn -o clean installin a throwaway worktree, unpiped:BUILD SUCCESS,Tests run: 2249, Failures: 0, Errors: 0, Skipped: 0, 0^[ERROR]lines. Merge was a fast-forward andHEAD^{tree}matched the tree I built.if (atTurnBoundary && mcpSeen)→if (atTurnBoundary)failsfreshTerminalAtTurnBoundaryButNotMcpPresentNeverBecomesReadyNeverSendsBootstrapText(expected: <0> but was: <1>prompt calls).bootstrapTextSentButNeverConfirmedEndsInBootstrapNotConfirmedWithNoResend(expected: <BOOTSTRAP_NOT_CONFIRMED> but was: <ROLLED>).grep -c "lead-rollover: rolled" fleetd/fleetd.out= 21, of which exactly one carries the restart path'soldLead=… newTerminal=…shape. The other 20 loglead=…and ran under the old/clearbehaviour. So the restart path had been exercised once, and that once lost the bootstrap.Not fixed here, and worth knowing
The daemon running while I write this is still the 06:21 jar, so this fix is not live until a redeploy. That is next.
FakeHerdrgainedturnStartsOnPrompt(): after eachagent.promptit reports"working"for the next twoagent.getreads. Two, because oneAgentControl.status()costs two raw reads —resolveTargetissues its ownagent.getfirst. It is bounded rather than sticky so a test can roll more than once; the earlier sticky version made every multi-roll test spin forever against a non-advancing fake clock.FleetdLeadRolloverAssemblyTestnow callsmarkPresent("term_new_1"), because no real Claude boots in that test and the gate would otherwise stop the roll at readiness before it reaches the behaviour the test is about.Docs:
.claude/skills/handover/SKILL.mdgains theBOOTSTRAP_NOT_CONFIRMEDrow and corrects the timeout section — four waits now, under three budgets, not "four times 45".wiki/11-Features.mdreplaces its "nobody has rolled under the restart path yet" gotcha, which this ticket falsified.