aboutsummaryrefslogtreecommitdiff
path: root/docs/design
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-11 20:05:16 -0500
committerCraig Jennings <c@cjennings.net>2026-06-11 20:05:16 -0500
commit65b99e86d570e489bcd91f377b71193cd7eaba44 (patch)
tree346bce8950cb0832f14041ef4d3ab955960607fd /docs/design
parent00fc6f10d132e61adde26613372cf845a5abe776 (diff)
downloadrulesets-65b99e86d570e489bcd91f377b71193cd7eaba44.tar.gz
rulesets-65b99e86d570e489bcd91f377b71193cd7eaba44.zip
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.
Diffstat (limited to 'docs/design')
-rw-r--r--docs/design/2026-05-28-generic-agent-runtime-spec.org63
1 files changed, 50 insertions, 13 deletions
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 =<project>:helper-<id>=), 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-<rand4>=, =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 =<project>:helper-<id>=. 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-<id>-<desc>.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-<id>-<desc>.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).