From 65b99e86d570e489bcd91f377b71193cd7eaba44 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 11 Jun 2026 20:05:16 -0500 Subject: docs(spec): deterministic helper spawn and session-end ordering rules The launcher becomes the spawn mechanism: a shell script runs the roster check, assigns the id, and launches with the helper instructions in order, where a model-followed startup instruction can skip a step. The in-session roster check stays as the safety net for raw launches and still splits a live anchor into crashed versus concurrent. Session-end ordering was unhandled: a helper outliving the primary stranded a dirty worktree, since the helper may not commit and the agent allowed to is gone. The git ban on helpers is concurrency-scoped, so it lifts when the helper finds itself alone at wrap-up and the last agent out closes the door with the full wrap-up. The mirror case pauses too: a primary wrapping with live helpers stops at the commit and asks whether to sweep the helper's in-flight work, wait, or leave closing to the helper. --- .../2026-05-28-generic-agent-runtime-spec.org | 63 +++++++++++++++++----- 1 file changed, 50 insertions(+), 13 deletions(-) (limited to 'docs/design') diff --git a/docs/design/2026-05-28-generic-agent-runtime-spec.org b/docs/design/2026-05-28-generic-agent-runtime-spec.org index 243eac3..2b451cc 100644 --- a/docs/design/2026-05-28-generic-agent-runtime-spec.org +++ b/docs/design/2026-05-28-generic-agent-runtime-spec.org @@ -429,10 +429,21 @@ operator created deliberately and can manage manually. not operator-triggerable by phrase; startup's detection is its entry point, plus an explicit "you are a helper" instruction as the manual fallback. -- =ai --helper= remains as a convenience (exports =AI_AGENT_ID= and - =AI_HELPER=1=, names the tmux window =:helper-=), but it is - no longer the mechanism — detection is. The flag's value is a clearer - tmux roster and skipping the self-assignment step. +- The launcher is the deterministic spawn path (Craig, 2026-06-11, fourth + revision): a shell script can't skip a step the way a model-followed + instruction can. =ai --helper [project]= does three things in order — + (a) runs =agent-roster= for the target directory, (b) assigns and exports + the id (=AI_AGENT_ID=helper-=, =AI_HELPER=1=) when the roster shows + a live agent, and (c) launches the agent in that directory with the + helper opening instruction (read and follow =helper-mode.org=) already in + the prompt. Window named =:helper-=. Roster empty → it warns + and launches a normal primary session instead. +- The in-session startup check (previous subsection) stays as the safety + net, not the mechanism: it catches agents started raw (=claude= in a + terminal, no launcher) and is still what splits a live anchor into + crashed-vs-concurrent. Belt and suspenders: the launcher makes the common + path deterministic; the startup roster keeps the uncommon path safe. + Both call the same =agent-roster= script. *** Read/write contract for shared files @@ -520,13 +531,34 @@ Helper startup is deliberately light: resolve the context path, read its Session Log — the context-contamination rule above), and start working. No pulls, no rsync, no inbox processing, no staleness nudges. -Helper wrap-up: archive its own file to -=.ai/sessions/YYYY-MM-DD-HH-MM--.org= (existing rule), skip the -hygiene passes and the commit/push steps, and surface any uncommitted tree -changes it left so the primary or Craig picks them up. A helper that dies -uncleanly leaves its file in =session-context.d/= — the next startup's -existence check surfaces it as an interrupted agent, same as the singleton -today. +Helper wrap-up forks on the roster, because session-end /ordering/ is not +guaranteed — the primary may wrap and leave while helpers keep working +(Craig, 2026-06-11): + +- /Others still live:/ archive its own file to + =.ai/sessions/YYYY-MM-DD-HH-MM--.org=, skip the hygiene passes + and the commit/push steps, and surface any uncommitted tree changes so + the remaining agents or Craig pick them up. Today's helper contract. +- /Alone (orphaned helper — the primary already wrapped):/ last agent out + closes the door. Without this, the helper's edits would strand as a dirty + worktree with nobody allowed to commit them. The git ban on helpers + exists for /concurrency/ (index-lock contention, interleaved staging), + and an orphaned helper has no concurrency — so the ban lifts, and the + helper assumes closing duties: the full wrap-up, including hygiene passes + (it is alone; the gate is satisfied), commit through the normal + review/voice flow, and push. + +The mirror case — the /primary/ wrapping while helpers still live — extends +the hygiene gate to the wrap-up commit itself: a wrap-up commit sweeps the +whole tree, including a helper's in-progress edits. With live helpers on the +roster, the primary's wrap-up pauses and asks Craig: commit the helper's +work-in-progress along with its own (the helper's log-before-write journal +shows what was in flight), wait for the helper to finish, or wrap without +the shared-file hygiene and leave the helper to close the door as above. + +A helper that dies uncleanly leaves its file in =session-context.d/= — the +next session's roster-aware startup surfaces it as an interrupted agent, +same as the singleton today. ** Hook and validation strategy @@ -597,8 +629,13 @@ Independent of the phases 2-6 go/no-go; same-runtime only. - =helper-mode.org= template workflow — the role contract: identity self-assignment, the read/write tiers, light start, helper wrap-up. INDEX entry marked auto-routed (no operator trigger phrase). -- =ai --helper= flag as the optional convenience: =AI_AGENT_ID= + =AI_HELPER= - export, tmux window naming. +- =ai --helper= as the deterministic spawn path: roster check, id + assignment + export, launch with the helper-mode opening instruction, + tmux window naming, warn-and-run-primary when the roster is empty. +- Wrap-up ordering rules: helper wrap-up re-runs the roster and assumes + full closing duties (hygiene + commit + push) when orphaned; primary + wrap-up with live helpers pauses at the commit and asks (commit helper + WIP / wait / leave closing to the helper). - The shared-file read/write contract documented where agents will obey it (protocols.org pointing at =helper-mode.org=, with startup.org and wrap-it-up.org carrying the helper branches). -- cgit v1.2.3