feat(spawn): opt-in actas readiness handshake for turn/off drivers#438
Open
Masashi-Ono0611 wants to merge 2 commits into
Open
feat(spawn): opt-in actas readiness handshake for turn/off drivers#438Masashi-Ono0611 wants to merge 2 commits into
Masashi-Ono0611 wants to merge 2 commits into
Conversation
Two P2s found by /review:self-multi-model (Codex + Fugu, independently converging on the same gap): - ready.sh mark/check now take an optional per-launch nonce. spawn.sh generates one whenever handshake=actas applies, exports it (with the resolved team) as AGMSG_SPAWN_TEAM/AGMSG_SPAWN_NONCE before launch, and requires the exact nonce on check. Without this, a mark from an abandoned/timed-out earlier spawn attempt for the same (team, agent) could satisfy a LATER spawn's wait, reporting status=ready before that later launch's own agent had actually booted. - The grok-build template now marks with AGMSG_SPAWN_TEAM/AGMSG_SPAWN_NONCE when present (i.e. launched by spawn) instead of the team resolved from identities.sh, which can return more than one team for the same agent name — previously causing a 300s timeout despite the agent completing bootstrap in the intended team. Also quotes the mark arguments (unquoted dynamic team/agent names could break/misparse). ADR 0003 updated to record the nonce in the Decision section.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
handshake=actas: a driver declaresthat its
actasflow has a reliable, explicit completion point (callingready.sh mark <team> <agent>once identity claim + any delivery setup isdone), independent of watcher liveness.
spawn.shnow branches on this key: types withhandshake=actaswait on theone-shot
actas-ready.<team>__<agent>sentinel (clearing stale ones first,consuming it after observation, 300s minimum timeout) instead of the
existing watcher-liveness wait. Types without the key keep current behavior
unchanged (
monitor=yeswatcher wait,monitor=noimmediate return,--no-waitstill an explicit opt-out everywhere).grok-buildto this handshake (type.conf: handshake=actas,template.mdstep 6 callsready.sh markafter identity claim — and afterthe monitor tool confirms the watcher is running/streaming in monitor mode).
scripts/ready.sh(mark|check|clear <team> <agent>) andagmsg_actas_ready_path()inscripts/lib/actas-lock.sh, using a filename(
actas-ready.*) deliberately disjoint from the existing watcherready.<team>__<agent>sentinel so the two protocols (one-shot bootstrapedge vs. ongoing watcher liveness) never collide.
docs/adr/0003-actas-spawn-readiness-handshake.mdrecords the alternativesconsidered (unconditional wait, default-on with opt-out, conditioning on
delivery mode, reusing the watcher sentinel, staying fire-and-forget) and why
each was rejected.
Motivation
Issue #338 (Gap 2, credit @Salmonellasarduri) reports that Grok Build spawns in
turn/offdelivery mode have no watcher to wait on, so the existingwatcher-readiness wait either hangs forever or (if disabled) reopens a
cold-start race where the parent can address work to the new agent before it
has claimed its identity. Issue #338 also documents observed first-turn
startup times of 143–187 seconds, which motivated the 300s floor here (vs. the
existing 90s watcher-readiness default).
This is scoped narrowly to the handshake mechanism itself; it does not touch
monitor=yeswatcher-readiness wait behavior, delivery mode selection, or anyother driver's
type.conf.Operations / Limitations
following
template.mdstep 6. If it doesn't,spawnwaits out the 300sfloor and exits with
status=timeout(exit 3) — this is not a spawnfailure, just an unconfirmed bootstrap. On timeout, check whether the agent
is still booting before deciding between
--no-wait(fire-and-forget) orre-spawn.
ready.sh markrecords only "actas bootstrap completed," not watcherliveness. A separate PR (feat(delivery): per-identity watcher liveness in status #436) addresses per-identity watcher liveness
reporting in
delivery.sh statususing the pre-existing watcher pidfileconvention this PR does not change.
Test plan
bats tests/test_ready.bats tests/test_spawn.bats tests/test_type_registry.bats— 90/90 passing (new + updated coverage for the opt-in key, the 300s floor,
spawnable-type-registry surface, and the node-launcher path).
bats tests/*.bats— 728/729 passing; the sole failure(
install: watch.sh self-cleans a prior watcher on re-invocation for the same sid) is a pre-existing order-dependent flake unrelated to this diff —confirmed by running
tests/test_install.batsalone (46/46 pass).Cross-reviewed by two independent peers before submission (both approved,
no P1 findings; P2 feedback on mark-timing and Operations wording is already
incorporated above and in
template.mdstep 4/6).CI green
Update (2026-07-19): additional review pass, one more fix
A follow-up
/review:self-multi-modelpass (Codex + Fugu, independentlyconverging on the same gap) found a P2 before this had any maintainer eyes
on it, now fixed in the latest commit:
by
(team, agent), with no way to tell WHICH launch produced it. If anearlier spawn attempt for the same
(team, agent)had already given up(
--no-wait, or past its own 300s timeout) but its agent was stillbooting, that agent's eventual
ready.sh markcould land after a LATERspawn's clear-before-launch and satisfy the later spawn's check —
reporting
status=readybefore the later launch's own agent had actuallycompleted bootstrap. Fixed by having
spawn.shgenerate a per-launch nonceand export it (with the resolved team) as
AGMSG_SPAWN_TEAM/AGMSG_SPAWN_NONCE; the template echoes both back onmark, and
checknow requires an exact match.mark from
identities.sh, which returns every team the agent name isregistered under — ambiguous when the same name exists in more than one
team. The template now prefers
AGMSG_SPAWN_TEAM(set by spawn) over thatresolution when present, and the mark arguments are quoted.
Full suite re-verified: 736/736 (this worktree's copy of the pre-existing
install: watch.sh self-cleans...flake did not reproduce on this run).