aboutsummaryrefslogtreecommitdiff
path: root/.ai/workflows/helper-mode.org
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-07-30 07:42:47 -0500
committerCraig Jennings <c@cjennings.net>2026-07-30 07:42:47 -0500
commit84bd121683add4440a3652b12b70e6e2d45f5384 (patch)
treeb4a2cd0b2d9a3c862db02ae0216a9f7511dd246d /.ai/workflows/helper-mode.org
parent73e8c01fa49f48766a283e2db933e38951f656ab (diff)
downloadrulesets-84bd121683add4440a3652b12b70e6e2d45f5384.tar.gz
rulesets-84bd121683add4440a3652b12b70e6e2d45f5384.zip
feat(ai): add --helper for a second session in a live project
A helper is a second agent session in a project that already has a live one. It reads freely, makes only scoped single-heading edits, and never touches git. Until now the only way to get one was to tell a session by hand it was a helper, and nothing checked whether that was true. --helper runs agent-roster first, so the claim gets verified rather than asserted. It opens its own tmux window and hands the session helper-mode.org instead of the normal startup workflow. Git prep is skipped because pulls belong to the primary. With no other agent live it warns and falls back to a primary launch. When the roster can't answer, it opens a helper anyway. I picked that direction because a helper that turns out to be alone merely does less, while a primary that turns out not to be alone runs pulls and rsync underneath a live session. Wrap-up gains a Step 0 branch. A helper archives its own context file and stops, and the primary's next commit carries its edits. An orphaned helper whose primary already exited runs the full wrap, because otherwise its edits strand as a dirty tree nobody owns. That branch resolves the project root before consulting the roster. agent-roster defaults to $PWD and only matches agents at or inside it, so a call from a subdirectory would miss a primary at the root and report the helper orphaned. That is the one path that commits and pushes. The agent id is sanitized to the charset session-context-path keeps, because it's interpolated into the command typed into the pane. A helper launching a helper gets a fresh id rather than inheriting its parent's. Two agents resolving to one context file is the collision the contract exists to prevent. Startup still has no roster check, so a bare claude launched into a busy project runs full primary startup regardless. helper-mode.org and protocols.org now say so instead of listing the routing as though it works.
Diffstat (limited to '.ai/workflows/helper-mode.org')
-rw-r--r--.ai/workflows/helper-mode.org29
1 files changed, 24 insertions, 5 deletions
diff --git a/.ai/workflows/helper-mode.org b/.ai/workflows/helper-mode.org
index a6acfa7..b32d574 100644
--- a/.ai/workflows/helper-mode.org
+++ b/.ai/workflows/helper-mode.org
@@ -12,13 +12,14 @@ The governing fact behind every rule below: the session-context split isolates e
* When to Use This Workflow
-No operator trigger phrase. A helper reaches this contract one of three ways:
+No operator trigger phrase. A helper reaches this contract one of two ways:
- The =ai --helper= launcher routes here after the roster confirms a live agent (the deterministic path).
-- Startup's roster check finds the session is not alone and routes here instead of running normal startup (the safety net for a raw =claude= launch).
- An explicit "you are a helper, follow helper-mode.org" instruction (the manual fallback).
-If none of those applies — the roster shows the session is alone — this is a primary session. Run normal [[file:startup.org][startup.org]], not this.
+There is deliberately no third way, and the gap matters: *startup does not check the roster*. A bare =claude= launched into a project that already has a live session runs full primary startup — pulls, rsync, inbox processing — without ever reaching this file. That safety net is designed (see Status below) but unbuilt, so nothing catches a raw launch. Use =ai --helper=.
+
+If neither route applies, this is a primary session. Run normal [[file:startup.org][startup.org]], not this.
* Identity
@@ -92,10 +93,28 @@ A helper does not run normal startup. It runs a light version:
When the helper's work is done:
-1. Re-run the roster (=.ai/scripts/agent-roster=) to learn whether a primary is still live.
+1. Re-run the roster to learn whether a primary is still live. Pass the project root explicitly — =agent-roster= defaults to =$PWD= and keeps only agents at or inside that root, so calling it from a subdirectory hides a primary sitting at the root and reports "alone":
+
+ #+begin_src bash
+ root="$(git rev-parse --show-toplevel 2>/dev/null || pwd)"
+ if [ -x "$root/.ai/scripts/agent-roster" ]; then
+ "$root/.ai/scripts/agent-roster" "$root"; rc=$?
+ else
+ rc=2
+ fi
+ echo "roster rc=$rc"
+ #+end_src
+
+ Read rc as =wrap-it-up.org= Step 0 does: 1 means a primary is still live, 0 means this helper is orphaned, and 2 (or an absent script) means unavailable — which takes the same archive-only path as 1, because leaving work uncommitted is recoverable and committing under a live primary is not.
2. *Primary still live (the normal case):* finalize the Summary in the helper's own =.ai/session-context.d/<id>.org=, archive it to =.ai/sessions/YYYY-MM-DD-HH-MM-<id>-<description>.org=, and stop. Do NOT commit, push, or run hygiene — the primary's next commit picks up the archived file and any scoped edits the helper left in the tree.
3. *Orphaned helper (roster shows the helper is now alone):* the primary already exited, so the helper assumes full closing duties — the git ban lifts because the concurrency that justified it is gone. Commit and push the tree (including the helper's own edits, which would otherwise strand as a dirty tree), per the normal wrap-up flow in [[file:wrap-it-up.org][wrap-it-up.org]].
* Status
-Phase 1.5 of the generic-agent-runtime spec. This contract is the canonical home; the spawn paths (=ai --helper=, startup's roster branch) and the [[file:wrap-it-up.org][wrap-it-up.org]] helper branch route here. Those wiring pieces ship behind the spec's bats-then-drills-then-pilot gate and are not yet live; until then, the manual "you are a helper" instruction is how a session adopts this contract.
+Phase 1.5 of the generic-agent-runtime spec. This contract is the canonical home; the spawn paths and the [[file:wrap-it-up.org][wrap-it-up.org]] helper branch route here.
+
+Live now: =ai --helper <project>= (roster check, id assignment, helper opener, its own tmux window), the explicit "you are a helper" instruction, and the wrap-it-up.org Step 0 helper branch.
+
+Not built yet, and worth knowing because it is the gap you can fall into: *startup has no roster check*. A second session launched as a bare =claude= in a project that already has one runs full primary startup — pulls, rsync, inbox processing — with no idea another agent is live. Until that safety net exists, =ai --helper= is not merely the preferred path, it is the only one that makes a helper without being told.
+
+Also unbuilt: the live-helper gate that pauses a primary's file-wide hygiene passes (=todo-cleanup.el=, =lint-org.el=, =wrap-org-table.el=) while a helper is mid-edit. Data-integrity rule 1 above describes the intended behavior; nothing enforces it yet, so a primary running hygiene can still clobber a helper's just-written scoped edit.