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 ++++++++++++++++++++++ 1 file changed, 98 insertions(+) (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 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. -- cgit v1.2.3