From f4b856b9eacc5a7ce8af3a031d72e7b7d6840305 Mon Sep 17 00:00:00 2001 From: Craig Jennings Date: Thu, 11 Jun 2026 19:36:39 -0500 Subject: docs(spec): add helper-instance slice to the agent-runtime spec The v0 draft covered identity and message targeting for concurrent agents but not spawn mechanics or write-safety for the shared files the session-context split doesn't isolate. I added a section for the motivating case (a second Claude in one project doing lookups and safe task updates): ai --helper spawn with automatic AI_AGENT_ID, a tiered read/write contract where helpers make scoped single-heading org edits and file-wide passes plus all git mutation stay primary-only, light helper startup, and helper wrap-up. Phase 1.5 sequences the slice independently of the runtime-neutral phases 2-6. --- .../2026-05-28-generic-agent-runtime-spec.org | 98 ++++++++++++++++++++++ todo.org | 17 ++++ 2 files changed, 115 insertions(+) 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 8c16043..5e547e0 100644 --- a/docs/design/2026-05-28-generic-agent-runtime-spec.org +++ b/docs/design/2026-05-28-generic-agent-runtime-spec.org @@ -57,6 +57,14 @@ Sources checked: Draft v0. This is not an implementation plan yet; it is a product/architecture spec for the next =rulesets= refactor. +Amended 2026-06-11: the resolver half of Phase 1 shipped +(=.ai/scripts/session-context-path= + the protocols.org agent-scoped path +contract); the launcher half has not. A new section, /Concurrent same-project +agents (helper instances)/, covers Craig's motivating case the v0 draft left +under-specified — spawning a second Claude in the same project to look things +up or update tasks safely — and a new Phase 1.5 sequences that slice ahead of +the runtime-neutral phases 2-6, which remain pending a go/no-go. + * Problem =rulesets= is named and wired as a Claude Code rules distribution: @@ -355,6 +363,80 @@ the same project are both active. Receivers should ignore messages targeted at another =TARGET_AGENT_ID= unless the user explicitly asks them to take over. +** Concurrent same-project agents (helper instances) — 2026-06-11 amendment + +The motivating case (Craig, 2026-06-11): spawn a second Claude in the same +project to look things up or update tasks safely while the primary session +works. This is same-runtime concurrency — it needs none of the runtime +manifests or local-model machinery from phases 2-6. It sits on the shipped +session-context split plus the contracts below, which the v0 draft didn't +cover: identity assignment at spawn, and write-safety for the files the +session-context split does /not/ isolate. + +First, the boundary with subagents: when the lookup fits a dispatched +subagent (the Agent tool), use that — no second session exists and nothing +here applies. A helper instance is for interactive, long-lived parallel work +Craig drives himself in a second terminal. + +*** Identity and spawn + +- The primary keeps the unset-id singleton (=.ai/session-context.org=), per + Phase 1's compatibility rule. Zero friction for the overwhelmingly common + one-agent case, and the asymmetry is harmless: the helper's writes land in + =.ai/session-context.d/=, away from the singleton. +- The launcher assigns helper identity: =ai --helper [project]= detects a live + anchor (the singleton exists, or =session-context.d/= is non-empty), exports + =AI_AGENT_ID=helper-= (sanitized by =session-context-path=), and names + the tmux window =:helper-=. Spawning a helper into a project + with /no/ live anchor still works — it just means the "primary" duties below + have no owner, so the helper warns and runs as a normal full session instead. +- =--helper= also sets =AI_HELPER=1= so workflows can branch on role without + parsing the id. + +*** Read/write contract for shared files + +The session-context split isolates per-agent session state. Everything else +in the project is shared mutable state — =todo.org=, =.ai/notes.org=, +=inbox/=, docs — and two Edit-tool writers on one org file lose updates +silently (both read, both write, last write wins). The contract, by tier: + +- /Always safe:/ any read; writes to the helper's own + =session-context.d/.org=. +- /Safe by discipline (task updates — the case Craig named):/ scoped writes to + shared org files under four rules: re-read the file region immediately + before each edit; anchor the edit on a unique heading; scope each edit to a + single heading's subtree; never reflow, restructure, or sweep the file. + Appending a new =**= task at a section end and editing one task's body or + state both qualify. The race window collapses to seconds, and a collision + corrupts one heading rather than the file. +- /Primary-only:/ file-wide passes (=todo-cleanup.el=, =lint-org.el=, + =wrap-org-table.el=, archive sweeps), inbox processing, template sync, and + ALL git mutation — commit, push, pull, stash. Two committers in one + worktree contend on the index lock and interleave staging; the helper + leaves its tree changes for the primary's next commit, or describes them in + a targeted cross-agent message. The helper also never runs startup's + Phase A.0 pulls or the =.ai/= rsync — the primary already did, and a + concurrent pull-under-edit is exactly the race the startup guards exist to + prevent. +- /Escalation:/ anything the contract blocks routes through the targeted + cross-agent form already specced above (=machine.project.agent-id=), or + just gets reported to Craig. + +*** Helper startup and wrap-up + +Helper startup is deliberately light: resolve the context path, read +=protocols.org=, optionally read the primary anchor's =* Summary= only (never +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. + ** Hook and validation strategy V1 should not pretend all runtimes have Claude's hooks. @@ -410,6 +492,22 @@ Rationale: - Keep legacy =.ai/session-context.org= fallback. - Add tests for two simultaneous session-context files. +** Phase 1.5: Helper instances (concurrent same-project Claude) — added 2026-06-11 + +Independent of the phases 2-6 go/no-go; same-runtime only. + +- =ai --helper= flag: live-anchor detection, =AI_AGENT_ID= + =AI_HELPER= + export, tmux window naming, no-live-anchor warning path. +- The shared-file read/write contract documented where agents will obey it + (protocols.org, with startup.org and wrap-it-up.org carrying the helper + branches). +- Bats tests: id assignment and sanitization through the launcher, helper vs + primary path resolution, two simultaneous context files (extends the + existing =session-context-path= suite). +- Manual validation: Craig runs a real helper session against a live primary + — a task lookup, one scoped =todo.org= edit, wrap-up — and the primary's + next commit picks up the helper's edit cleanly. + ** Phase 2: Introduce runtime manifests and generic install commands - Add =runtimes/claude.toml= and make current install behavior data-driven. diff --git a/todo.org b/todo.org index 1cd298b..bb1c2cb 100644 --- a/todo.org +++ b/todo.org @@ -40,6 +40,20 @@ CLOSED: [2026-06-11 Thu] Cancelled 2026-06-11: Craig confirmed the decision — one todo queue with a single Open Work / Resolved pair. Home reshapes its consolidated file to that form, and the existing single-pair tooling works unmodified. No code change needed. +** TODO [#B] Helper-instance support — concurrent same-project Claude :feature: +:PROPERTIES: +:CREATED: [2026-06-11 Thu] +:LAST_REVIEWED: 2026-06-11 +:END: +Implement Phase 1.5 of the generic-agent-runtime spec ([[file:docs/design/2026-05-28-generic-agent-runtime-spec.org][spec]], amended 2026-06-11 with the "Concurrent same-project agents" section). Craig's case: spawn a second Claude in the same project to look things up or update tasks safely while the primary works. The session-context split (AI_AGENT_ID + session-context.d/) already shipped; this builds the rest: + +- =ai --helper= flag: live-anchor detection, auto AI_AGENT_ID + AI_HELPER export, tmux window naming, warn-and-run-normal when no primary is live. +- Shared-file read/write contract into protocols.org (helper: scoped single-heading org edits only; file-wide passes, inbox processing, and all git mutation stay primary-only); helper branches in startup.org (light path, no pulls/rsync) and wrap-it-up.org (archive own file, skip hygiene + commit). +- Bats: launcher id assignment/sanitization, helper-vs-primary resolution, two simultaneous context files. +- Manual validation with Craig: live helper against a live primary — lookup, one scoped todo.org edit, wrap-up, primary commits the helper's edit cleanly. + +Independent of the spec's phases 2-6 (runtime-neutral refactor), which stay gated on their own go/no-go. + ** VERIFY Should new personal projects start as areas inside home rather than standalone ~/projects entries? Home's consolidation (2026-06-11) leaves ~/projects with home and work only. The open template question: when Craig starts a new personal project, does =first-session.org= / =install-ai.sh= guidance now say "create an area in home" by default, with standalone reserved for code projects in ~/code? Affects first-session.org, install-ai.sh docs, and the triggers.md "Launch project X" resolution (folded names like "finances" no longer resolve as projects; an area-aware launch could map them to home). @@ -1123,6 +1137,9 @@ Before any implementation: needs a real review pass on the spec, and a decision *** 2026-06-10 Wed @ 14:13:55 -0500 Noted Phase 1 already shipped; narrowed scope to the phases 2-6 decision Phase 1 (the correctness fix) is live: protocols.org documents the AI_AGENT_ID-scoped session-context path (=.ai/session-context.d/.org=) and =.ai/scripts/session-context-path= resolves it. The singleton race Codex flagged is closed. What remains is the spec review plus a go/no-go on the broader runtime-neutral refactor: runtimes/ adapter manifests, generic install commands, language-bundle split, launcher refactor, local model service. +*** 2026-06-11 Thu @ 19:26:26 -0500 Spec amended with the helper-instance slice; implementation split out +Craig's motivating case (a second Claude in the same project for lookups and safe task updates) was under-specified in v0 — it had identity and message targeting but no spawn mechanics and no write-safety contract for the shared files the session-context split doesn't isolate. Added the "Concurrent same-project agents (helper instances)" section (subagent boundary, identity/spawn via =ai --helper=, the tiered read/write contract, light startup, helper wrap-up) and Phase 1.5 to the migration plan. Implementation filed as its own [#B] task ("Helper-instance support"); this task stays scoped to the phases 2-6 go/no-go. + * Rulesets Resolved ** DONE [#C] Fix =cj-scan= false positives on cj fences nested inside other =#+begin_*= blocks :bug: CLOSED: [2026-05-15 Fri] -- cgit v1.2.3