@llblab/pi-actors 0.16.4 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -9,12 +9,12 @@
9
9
 
10
10
  ## Concept
11
11
 
12
- `pi-actors` is a local-first actor runtime and orchestrator for pi. It wraps trusted local programs, scripts, services, pipelines, and recipes as addressable actors that agents can `spawn`, control with typed `message` envelopes, and observe with `inspect`. It also persists user/agent-registered actor-control tools in `~/.pi/agent/actors-tools.json`, giving agents durable operational muscle memory for launching and managing the local actor zoo.
12
+ `pi-actors` is a local-first actor runtime and orchestrator for pi. It wraps trusted local programs, scripts, services, pipelines, and recipes as addressable actors that agents can `spawn`, control with typed `message` envelopes, and observe with `inspect`. It also persists user/agent-registered actor-control tools as recipe files under `~/.pi/agent/recipes`, giving agents durable operational muscle memory for launching and managing the local actor zoo.
13
13
 
14
14
  ## Topology
15
15
 
16
16
  - `/index.ts`: Minimal extension coordinator/composition root; it wires live pi ports and should avoid owning domain behavior
17
- - `/lib/*.ts`: Flat Domain DAG modules for cohesive reusable behavior; `command-templates.ts` mirrors the shared portable command-template standard, `schema.ts` owns tool arg declarations and placeholder-derived tool schemas, `identity.ts` owns names, `config.ts` owns config persistence, `registry.ts` owns registry register/update/delete use-cases, `output.ts` owns result formatting/truncation, `execution.ts` owns registered-tool execution, `recipe-references.ts` owns template recipe reference detection and path resolution, `async-runs.ts` owns async run state, `observability.ts` owns ambient run summaries, `temp.ts` owns pi-agent temp cleanup, `prompts.ts` owns LLM-facing copy, `tools.ts` owns pi-facing tool definitions for both `register_tool`, async run primitives, and generated runtime tools, `runtime.ts` owns load/conflict/registration coordination, and `paths.ts` owns config/tmp path resolution
17
+ - `/lib/*.ts`: Flat Domain DAG modules for cohesive reusable behavior; `command-templates.ts` mirrors the shared portable command-template standard, `schema.ts` owns tool arg declarations and placeholder-derived tool schemas, `identity.ts` owns names, `config.ts` owns config persistence, `registry.ts` owns registry register/update/delete use-cases, `output.ts` owns result formatting/truncation, `execution.ts` owns registered-tool execution, `recipe-references.ts` owns template recipe reference detection and path resolution, `async-runs.ts` owns async run state, `actor-rooms.ts` owns room timelines/rosters/communication snapshots, `actor-communication-tui.ts` owns compact terminal previews for actor communications, `observability.ts` owns ambient run summaries, `temp.ts` owns pi-agent temp cleanup, `prompts.ts` owns LLM-facing copy, `tools.ts` owns pi-facing tool definitions for both `register_tool`, async run primitives, and generated runtime tools, `runtime.ts` owns load/conflict/registration coordination, and `paths.ts` owns config/tmp path resolution
18
18
  - `index.ts` should import local domains as namespaces (`import * as CommandTemplates from "./lib/command-templates.ts"`) so orchestration reads through domain names instead of flat helper imports
19
19
  - `/scripts/*.mjs`: Thin helper processes for detached async run execution; keep policy in registered tool config and reusable logic in `/lib`
20
20
  - `/recipes/*.json`: Packaged standard recipe library; keep recipes optional, composable, and policy-light; prefer public args for operator/agent decisions instead of baking project-specific prompts, file names, or concrete model-version defaults into reusable recipes
@@ -38,19 +38,19 @@
38
38
  ## Durable Conventions
39
39
 
40
40
  - `Knowledge surface separation`: pi-actors has distinct knowledge surfaces with different context-entry behavior: injected prompt is always present and should stay a tiny bootstrap/reminder; packaged `actors` skill is auto-matched by name/description and should signal that its body is the highest-density practical guide for operating the extension plus the shortest navigator to bundled recipes; packaged `swarm` skill is auto-matched for multi-agent methodology, strategies, standards, and portable examples; README is the human entrypoint explaining concept, rhythm, benefits, and scenarios but is not automatically in context; `/docs` are detailed transportable standards read on demand; `AGENTS.md` is project context and architectural constraints for agents changing the repo | Trigger: Editing prompt copy, README, docs, skills, or project context | Action: Keep each surface on its own wave, avoid duplicating prompt and skill headers, keep the actors skill recipe navigator compact and concrete, avoid duplicating scenario catalogs or changelog narratives in the actors skill, avoid turning the prompt into docs, keep multi-agent methodology in swarm-oriented guidance rather than the actors skill, keep packaged extension skill metadata versions synchronized with `package.json` version, and avoid extra colons in skill frontmatter scalar lines because skill formatters treat them poorly
41
- - `Tool registry source`: `~/.pi/agent/actors-tools.json` is the persistent user config | Trigger: Any runtime registration or migration work | Action: Preserve atomic writes and avoid hidden format changes without an explicit migration path
41
+ - `Tool registry is executable muscle memory`: `~/.pi/agent/recipes/*.json` is the persistent user tool surface by location: every recipe in that agent root is automatically registered as an agent tool across sessions, and `register_tool` creates/updates/deletes recipe files there under the hood | Trigger: Any runtime registration, recipe discovery, migration, docs, skill, prompt, or recipe authoring work | Action: Treat the directory like `MEMORY.md` for executable habits; preserve filename identity, atomic writes, explicit operator-gated migration paths, and never author a recipe-owned `tool` property in repository recipes, docs, or fixtures; packaged/ad hoc recipes outside the agent root are components, not tools
42
42
  - `Current runtime contract`: Register trusted command templates with tool names from registry keys, placeholder-derived args, progressive typed arg declarations, inline/default/`??`/ternary config fallback, placeholder-derived numeric node controls, split-first command-arg construction, sequential or `parallel: true` composition, direct no-shell execution, optional per-node `when`, optional per-node positive `timeout` disabled by default, lightweight warnings for obvious trusted-executable risk shapes, per-node `delay`, bounded leaf/node `retry`, `failure: "continue|branch|root"` propagation, `recover` cleanup between retry attempts, template recipes with explicit `async: true` detached mode, actor-oriented `spawn`/`message`/`inspect` tools with run-local JSONL outbox messages, Unix FIFO send, graceful cancel, and force kill, generic detached run primitives with process-group cancellation, injected async `{run_id}` and `{state_dir}` values, coordinator-scoped event-driven observability with at least one triangle per active async run and extra triangles for active parallel branches, runtime-inferred `command.done` bubbling for packaged multi-agent fanout, named recipe `artifacts`, recipe `mailbox` metadata, terminal follow-ups for `done`/`failed`/unhandled `killed`/`exited` states, `template` recipe references, recipe-layer `imports`, co-located recipe entries, `~/.pi/agent/recipes/*.json` template recipe files, run state under `~/.pi/agent/tmp/pi-actors/runs`, and `{file}` as the canonical local file path arg | Trigger: Changing registration or invocation behavior | Action: Keep README, command-template docs, template-recipe docs, async-run docs, actor-message docs, implementation, and migration notes aligned
43
43
  - `Typed arg authoring`: Typed args support `string`, `path`, `int`, `number`, `bool`, and `enum(...)` plus two equivalent readability styles: metadata-first (`args` + `defaults` + simple `{name}` placeholders) for long command lines, and inline-first (`{name:type=default}` placeholders) for compact one-property templates | Trigger: Changing arg parsing, docs, schema generation, or registry serialization | Action: Preserve both styles, keep explicit `args` type declarations higher priority than inline placeholder types, and make breaking cleanup explicit when removing old arg shapes
44
44
  - `Template recipe graph`: The valid execution chain is `tool → template → recipe → run → template`; file-backed and co-located recipes are storage variants of that chain | Trigger: Adding registry bindings, recipes, docs, or runtime shortcuts | Action: Keep command templates synchronous and portable, use `async: true` as the detached run switch, require every recipe to own `template` directly, and reject cyclic shortcuts such as recipe-owned `tool`
45
45
  - `Layer boundary discipline`: Command-template evolution must be separated from template-recipe configuration and async-run lifecycle configuration | Trigger: Adding syntax, placeholders, imports, async controls, or docs | Action: Put portable execution graph semantics in `docs/command-templates.md`, recipe storage/import/default/reference behavior in `docs/template-recipes.md`, and detached lifecycle/state/IPC behavior in `docs/async-runs.md`; type imported recipes as command-template-shaped recipe definitions, not async-run instances
46
46
  - `Executable script recipes`: Recipe templates may point directly at executable helper scripts, including JavaScript `.mjs` files with shebangs; do not prefix such recipes with `node` unless the script is intentionally not executable | Trigger: Adding or editing script-backed recipes and docs | Action: Keep the script executable bit, call `{repo}/scripts/name.mjs ...` directly, and keep the standard library on one maintained wrapper per capability unless a second wrapper has a concrete platform reason
47
- - `Template migration boundary`: Tool definitions use `template`, not `script` | Trigger: Loading or editing persisted config | Action: Reject `script` entries explicitly and do not silently rewrite user config outside the repo
48
- - `Reserved tool names`: Built-in or core tool names must not be shadowed | Trigger: Adding or renaming registration logic | Action: Keep conflict checks before persistence and runtime registration
47
+ - `Registry safety boundaries`: Tool definitions use `template`, not `script`, and built-in/core tool names must not be shadowed | Trigger: Loading/editing persisted config or registration logic | Action: Reject legacy `script` entries explicitly, avoid silent user-config rewrites outside the repo, and keep conflict checks before persistence/runtime registration
49
48
  - `Async run observability`: Ambient triangles count active async work units: each running async run contributes at least one triangle, and its reported active parallel command/subagent branches contribute the visible branch count when greater than one. Event-driven terminal/outbox watchers should initiate follow-up for unhandled terminal completion/failure states, failed or in-flight `command.done` branch completions, and coordinator-bound script-authored messages with bounded body previews; actor `message` is the explicit coordinator-to-run command channel paired with these upward events. Do not restore busy-polling loops, sleep-then-status smoke examples, duplicate follow-ups for final successful leaf commands, or duplicate follow-ups for `cancel`, `kill`, or control-stop actions already handled by synchronous tool results. | Trigger: Changing async run UI, notifications, actor-message routing, or smoke-test interpretation | Action: Preserve branch-aware triangles from `progress.activeSubagents`, runtime-inferred branch bubbling for packaged fanout completion, terminal notifications as event-driven behavior, and docs/examples that teach reactive run→coordinator→message loops before sleep-polling patterns.
50
49
  - `Communication direction`: The design target is an organic universal message layer across sync tasks, async runs, branches, tools, and coordinators. Breaking changes are allowed to compress concepts, remove accidental duplication, and make duplex communication symmetric where the domain is symmetric. | Trigger: Designing APIs or recipes that communicate | Action: Prefer a concentrated actor/message protocol (`spawn`, `message`, `inspect`, addressed endpoints, typed message envelopes, mailbox accepts/emits) over exposing FIFO/outbox/status mechanics directly; use one envelope for upward, downward, lateral, parent/branch, and branch/parent messages; absorb runtime async primitives into actor API instead of preserving parallel public concepts.
51
- - `Output discipline`: Tool stdout is returned with bounded context impact | Trigger: Changing execution or formatting | Action: Keep tail truncation, full-output temp files, and failure formatting intact
52
- - `Extension temp directory`: Temporary runtime files belong under `~/.pi/agent/tmp/pi-actors`; session start prepares the directory and prunes stale entries | Trigger: Adding temp files, run state, logs, or artifacts | Action: Do not use system tmp for extension-owned state unless the operator explicitly overrides a path
50
+ - `Runtime IO discipline`: Tool stdout and temp state must stay bounded and local | Trigger: Changing execution, formatting, temp files, run state, logs, or artifacts | Action: Keep tail truncation/full-output temp files/failure formatting intact; keep extension-owned temp state under `~/.pi/agent/tmp/pi-actors` unless explicitly overridden
53
51
  - `Backlog is planning, not history`: `BACKLOG.md` should contain current/future work, blockers, gates, and next leverage points; completed delivery history belongs in `CHANGELOG.md`, and durable behavior belongs in README/docs | Trigger: Editing backlog or reconciling completed slices | Action: Remove historical progress narratives, keep current task/scope/exit criteria, and prefer an 80/20 focus list when many remaining tasks compete for attention
52
+ - `Release artifact hygiene`: PR/release summaries become stale during active branch work and do not belong in the repository documentation tree | Trigger: Preparing release notes or PR bodies | Action: Create temporary/operator-facing artifacts outside the repo only during explicit release finalization; keep durable release evidence in `CHANGELOG.md` and open gates in `BACKLOG.md`
53
+ - `Persistent implementer workflows are recipe composition`: Backlog implementer scenarios should be launched through reusable component recipes, not one-off scripts or ad hoc shell orchestration | Trigger: Designing implementer swarms, backlog workers, coordinator-assigned task loops, or related recipes | Action: Compose cells such as `coordinator-locker`, subagent launchers, and actor-message utilities; preserve JSON envelope object shape across handoffs; add missing reusable component recipes only when needed; update the actors skill launcher map with supported scenarios
54
54
  - `Context sync`: Meaningful implementation or docs changes must reconcile `BACKLOG.md`, `CHANGELOG.md`, README, and docs navigation | Trigger: Closing, narrowing, or discovering work | Action: Run the context validator before final status when practical
55
55
  - `Public path hygiene`: Published docs must not include machine-local absolute paths | Trigger: Adding validation commands, examples, or local instructions to README/AGENTS/docs/changelog | Action: Use `~/.pi/...`, `<repo>/...`, `${SKILL_DIR}/...`, or relative paths
56
56
 
package/BACKLOG.md CHANGED
@@ -2,27 +2,58 @@
2
2
 
3
3
  ## Open Work
4
4
 
5
- No release-blocking work remains for `0.16.0`.
5
+ ### Actor Rooms, Roster, and Cross-Branch Messaging
6
6
 
7
- ## Future Work
7
+ - Priority: High.
8
+ - Goal: Continue evolving actor communication without adding a second public messaging model.
9
+ - Direction:
10
+ - Evaluate whether room storage/routing should remain built into the tool adapter or move behind a dedicated non-LLM communication actor recipe/script, possibly singleton-scoped. Preserve the same public `room:<run>` address and envelope either way.
11
+ - Consider reducing direct file-backed state where it improves coherence: model room/roster state as actor-owned data structures served by helper scripts/actors, with files retained only for durable snapshots, recovery, artifacts, or audit logs.
12
+ - Add selected-recipient multicast for a subset of actors without creating subrooms.
13
+ - Exit:
14
+ - Any backend/storage change preserves existing `spawn` / `message` / `inspect` semantics and room address compatibility.
15
+ - Selected-recipient multicast remains route-based and does not introduce named subrooms.
16
+
17
+ ### Actor Communication TUI Preview
18
+
19
+ - Priority: Medium.
20
+ - Goal: Make actor-to-actor communication more navigable in the terminal UI without exposing large payloads by default.
21
+ - Direction:
22
+ - Add explicit filters for current branch, room, direct messages, unread messages, and mentions.
23
+ - Add a roster panel for current run/room participants with address, role, caps, status, and last seen.
24
+ - Collapse long bodies by default and respect sensitive/redacted metadata.
25
+ - Rate-limit noisy rooms and keep full body inspection intentional.
26
+ - Exit:
27
+ - Operators can answer “what are the actors saying?” from the TUI at a glance, then intentionally inspect full room or direct-message bodies when needed.
28
+
29
+ ### Persistent Backlog Implementer Workflow
30
+
31
+ - Priority: Medium.
32
+ - Goal: Express persistent front/back backlog implementers as reusable extension-level recipe composition instead of bespoke workflow scripts.
33
+ - Direction:
34
+ - Use existing coordination cells such as `coordinator-locker` for queue/assignment/locking semantics.
35
+ - Compose existing subagent launcher recipes for execution slices rather than adding dedicated implementer scripts.
36
+ - Add missing reusable component recipes only when an implementer scenario cannot be expressed with the existing library.
37
+ - Update `skills/actors/SKILL.md` whenever a new implementer/coordinator recipe is added so agents know which scenario to launch and which packaged recipes to use.
38
+ - Preserve the protocol insight: implementers report `task.result` / `awaiting_assignment`, stay alive between assignments, and stop only after coordinator-issued control.
39
+ - Exit:
40
+ - A packaged workflow, if added, is described by recipes and existing helper cells; no one-off backlog-implementer scripts are required.
41
+ - The actors skill documents the supported launch scenarios and the concrete packaged recipes for each.
8
42
 
9
- ### Recipe Registry Curation UX
43
+ ### Recipe Schema Simplification
10
44
 
11
45
  - Priority: Medium.
12
- - Status: `inspect target=recipes view=status|summary` exposes active, shadowed, invalid, disabled, and diagnostic recipe state. User-owned recipes track extension-maintained `usage.calls` and `usage.last_called`.
13
- - Goal: Help operators curate the sticky `~/.pi/agent/recipes` tool surface without automatic deletion or demotion.
46
+ - Goal: Remove recipe metadata that duplicates storage context.
14
47
  - Direction:
15
- - Include usage fields in recipe registry summaries.
16
- - Add cleanup recommendations for stale, duplicate, low-use, too-specific, invalid, disabled, and shadowing recipes.
17
- - Recommend explicit actions only: keep as tool, set `tool: false`, merge, delete, or archive.
18
- - Keep cleanup operator-gated; never silently delete or demote during unrelated work.
48
+ - Remove `name` from the recipe standard. Recipe identity should come from the recipe filename/id rather than a redundant JSON property. Keep migration/backward compatibility explicit for existing packaged and user recipes.
49
+ - Finish hardening validators/discovery against recipe-owned tool exposure: tool status should be determined by location under `~/.pi/agent/recipes/*.json`, while packaged/ad hoc/component recipes are not tools by default. Repository recipes and docs no longer author `tool`.
19
50
  - Exit:
20
- - Operators can ask why a recipe/tool exists and what cleanup action is reasonable without reading files manually.
51
+ - Docs, validators, packaged recipes, discovery, and migration behavior all agree on filename-derived identity and location-derived tool exposure.
21
52
 
22
53
  ### Host-Level Tool Unregistration
23
54
 
24
55
  - Priority: Low.
25
- - Status: Deleted recipe files are removed from the active tool set on reactive reload; host-level registered tool definitions cannot currently be unregistered by this extension.
56
+ - Blocked by: Host API support for custom tool unregistration.
26
57
  - Goal: Remove stale dynamically registered tool definitions completely when the host API supports it.
27
58
  - Direction:
28
59
  - Track pi extension API support for custom tool unregistration.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## Unreleased
4
+
5
+ ## 0.17.0: Actor Rooms And Inspector
6
+
7
+ - `[Actor Messages]` Added the 0.17 actor-room communication slice: `room:<run>` task rooms, append-only room timelines, room rosters, join/leave handling, same-run room/direct provenance checks, branch/run communication snapshots, `inspect room:<run> view=status|messages|previews|roster|contacts`, and `inspect run:<id> view=communication`. Impact: run actors and contacted branches can discover peers, post shared task messages, and inspect communication state through the same `spawn` / `message` / `inspect` actor model.
8
+ - `[TUI]` Added the hidden-by-default actor inspector widget with `/actors-inspector-toggle` and `/actors-inspector-verbosity-toggle`, compact and verbose layouts, current-run scoping, chronological sequence numbers, owner filtering, JSONL-tolerant preview reads, mobile-width and wide-glyph-aware truncation, and transparent/dark row striping. Impact: operators can see the current actor conversation at a glance without flooding the prompt or leaking unrelated session previews.
9
+ - `[Registry]` Added usage metadata and operator-gated cleanup recommendations to recipe registry summaries, removed stale public references to the old tool config filename, removed recipe-owned `tool` properties from repository recipes/docs/fixtures, and fixed the 0.17 registry model around location-derived tool exposure: every recipe in `~/.pi/agent/recipes/*.json` is an agent tool, `register_tool` creates recipe files there under the hood, and packaged/ad hoc recipes outside that root are components. Impact: the sticky agent tool surface is explicit executable muscle memory, maintained like capability state rather than configured through per-recipe tool flags.
10
+ - `[Docs]` Updated README, actor-message docs, async-run docs, recipe-library docs, actors skill, backlog, and project context around the room/roster protocol, inspector behavior, release-artifact hygiene, and the persistent-backlog-implementer protocol. The implementer workflow remains future recipe-composition work around reusable cells such as `coordinator-locker`, not bespoke release scripts.
11
+ - `[Package]` Bumped package and packaged skill metadata to `0.17.0`; validated with `npm run validate` and context validation. PR #42 tracks the squashed `actor-rooms-017` branch as one release commit against `main` with green checks.
12
+
3
13
  ## 0.16.4: Recipe Usage Fingerprints
4
14
 
5
15
  - `[Recipe Usage]` Added content fingerprints to user recipe usage metadata. Impact: when a recipe file is edited and its authored meaning changes, the next launch resets `usage.calls`, records `usage.reset_at`, and starts counting usage for the current recipe content.
@@ -22,20 +32,20 @@
22
32
  ## 0.16.1: Recipe Registry Hotfix
23
33
 
24
34
  - `[Runtime]` Prevented invalid user recipe files from aborting extension startup when tool-schema generation fails, surfacing a warning and skipping the offending tool instead. Impact: one bad recipe in `~/.pi/agent/recipes` no longer takes down the pi-actors extension.
25
- - `[Recipe Discovery]` Excluded the legacy migration report file from recipe discovery. Impact: `actors-tools-migration-report.json` no longer appears as a broken recipe/tool candidate after migration.
35
+ - `[Recipe Discovery]` Excluded the legacy migration report file from recipe discovery. Impact: legacy migration reports no longer appear as broken recipe/tool candidates after migration.
26
36
  - `[Package]` Bumped package and packaged skill metadata to `0.16.1` for the hotfix release.
27
37
 
28
38
  ## 0.16.0: File-Discovered Recipe Registry Migration
29
39
 
30
- - `[Version]` Began the `0.16.0` breaking-change cycle and captured the file-discovered recipe registry migration plan in `BACKLOG.md`. Impact: the next release target is now explicit: replace `actors-tools.json` as live registry with validated recipe files, filename identity, `tool` exposure, override/disable semantics, migration reporting, registry inspection, and usage-informed cleanup.
40
+ - `[Version]` Began the `0.16.0` breaking-change cycle and captured the file-discovered recipe registry migration plan in `BACKLOG.md`. Impact: the next release target is now explicit: replace the legacy live registry with validated recipe files, filename identity, `tool` exposure, override/disable semantics, migration reporting, registry inspection, and usage-informed cleanup.
31
41
  - `[Recipe References]` Started filename-identity support for recipes by deriving the recipe id from the JSON filename when `name` is omitted, while preserving optional `tool`, `disabled`, and `description` metadata through recipe resolution. Impact: new recipe files can move toward filename-as-identity without losing human-readable descriptions or tool exposure flags.
32
42
  - `[Recipe Discovery]` Added an initial file-discovered recipe registry domain with flat root scanning, filename ids, priority shadowing, invalid high-priority recipe blocking, disabled overrides, and `tool: true` exposure detection. Impact: the 0.16 registry migration now has a tested discovery core before wiring it into runtime loading.
33
- - `[Recipe Migration]` Added a legacy registry migration domain that converts `actors-tools.json` entries into user recipe files with `tool: true`, preserves descriptions/args/defaults/templates, refuses to overwrite existing recipe files, writes a migration report, and archives the source only when migration has no conflicts or invalid entries. Impact: the breaking registry transition now has a tested compatibility path from the old live registry.
43
+ - `[Recipe Migration]` Added a legacy registry migration domain that converts old registry entries into user recipe files with `tool: true`, preserves descriptions/args/defaults/templates, refuses to overwrite existing recipe files, writes a migration report, and archives the source only when migration has no conflicts or invalid entries. Impact: the breaking registry transition now has a tested compatibility path from the old live registry.
34
44
  - `[Recipe Discovery]` Captured the priority model that treats packaged pi-actors recipes as a standard library below ad hoc user-selected recipe files and below `~/.pi/agent/recipes/*.json`, with priority applying only to matching filename ids. Impact: override behavior now has a documented lens and a regression for standard-library versus user recipe precedence.
35
45
  - `[Recipe Discovery]` Added source-level default tool exposure so the high-priority user recipe root can behave as the operator-managed tool set by default, while packaged/ad hoc recipes stay component-like unless they opt in with `tool: true` and any recipe can opt out with `tool: false`. Impact: 0.16 keeps the discoverability advantage of the old tool-only registry without forcing a separate live tool config.
36
46
  - `[Runtime]` Wired session-start tool loading to migrate the legacy registry, discover recipe-file tools from `~/.pi/agent/recipes` and packaged recipes, and register only active exposed recipes as runtime tools. Impact: the new recipe-discovered registry path is now active in runtime loading instead of only existing as standalone discovery/migration helpers.
37
47
  - `[Registry]` Changed `register_tool` persistence to write/update/delete user recipe files under the recipe root instead of mutating the legacy JSON registry, while still activating the tool in the current session. Impact: newly registered tools now enter the 0.16 recipe-discovered registry directly.
38
- - `[Docs]` Reworked tool-registry documentation, README examples, recipe docs, actor skill guidance, and prompt copy around recipe-file persistence, the user recipe directory as the default tool set, packaged recipes as standard-library components, and `actors-tools.json` as legacy migration input. Impact: public guidance now matches the 0.16 runtime path instead of the old live JSON registry.
48
+ - `[Docs]` Reworked tool-registry documentation, README examples, recipe docs, actor skill guidance, and prompt copy around recipe-file persistence, the user recipe directory as the default tool set, packaged recipes as standard-library components, and recipe files as the persistent tool surface. Impact: public guidance now matches the 0.16 runtime path instead of the old live JSON registry.
39
49
  - `[Skill]` Added actors-skill guidance for same-name recipe priority, recipe-root-as-muscle-memory, usage counters, and an explicit cleanup rule for stale/default tools without automatic deletion or demotion. Impact: agents get the override model, sticky-tool tradeoff, and cleanup heuristic directly in the compact operational reference.
40
50
  - `[Recipe Usage]` Added extension-maintained recipe launch metadata updates for user-owned runtime tools and direct async recipe starts, tracking `usage.calls` and `usage.last_called` without failure counters while leaving packaged standard-library recipes immutable, then documented the cleanup interpretation in recipe and tool-registry docs. Impact: the operator-managed recipe/tool set now accrues cleanup evidence for muscle-memory review from actual extension launches rather than manual agent bookkeeping.
41
51
  - `[Runtime]` Added a best-effort user recipe-root watcher that debounces file changes and reloads recipe-backed tools during the active session, plus runtime-tool fingerprinting so repeated reloads do not re-register unchanged tools while changed definitions refresh, and stale recipe tools are removed from the active tool set on reload when their recipe disappears. Impact: newly created or edited valid recipe files can be connected without a full restart, without duplicate registration churn for unchanged recipes, while deleted recipe tools are deactivated even though host-level unregistration is still not available.
@@ -179,12 +189,8 @@
179
189
 
180
190
  ## 0.12.2: Registry Migration Notes
181
191
 
182
- - `[Docs]` Added explicit rename migration instructions for copying `~/.pi/agent/auto-tools.json` or the short-lived `~/.pi/agent/tools.json` to `~/.pi/agent/actors-tools.json`. Impact: operators keep control of config migration while the package avoids silent rewrites of old registry files.
183
-
184
192
  ## 0.12.1: Actor Tool Registry Name
185
193
 
186
- - `[Registry]` Renamed the new pi-actors registry filename from `tools.json` to `actors-tools.json`. Impact: the persisted config name now clearly describes actor-control tools instead of implying every pi tool belongs to this extension.
187
-
188
194
  ## 0.12.0: Rename to pi-actors
189
195
 
190
196
  - `[Rename]` Renamed the package and current public surface from `@llblab/pi-auto-tools` / `pi-auto-tools` to `@llblab/pi-actors` / `pi-actors`, moved the persistent registry filename from `auto-tools.json` to `tools.json`, and moved runtime state defaults from `~/.pi/agent/tmp/pi-auto-tools` to `~/.pi/agent/tmp/pi-actors`. Impact: the package name now matches the actor API model introduced in 0.10-0.11, while the durable registry becomes the generic pi agent tools config.
package/README.md CHANGED
@@ -53,6 +53,7 @@ The key move is not just “register a command.” It is to wrap a process in an
53
53
  - **Actor Runtime**: Starts local templates and recipes as addressable `run:<id>` actors with state, logs, message mailboxes, cancellation, and artifacts.
54
54
  - **Agent-Managed Processes**: Wraps sub-agents, media players, pipelines, diagnostics, and other local programs as controllable entities instead of one-off commands.
55
55
  - **Message-Oriented Control**: Uses `spawn`, `message`, and `inspect` as the public coordination vocabulary for start, control, and observation.
56
+ - **Actor Rooms**: Lets actors post shared messages to `room:<run>`, update join/leave rosters, inspect room timelines or members, read compact run communication snapshots, and see recent actor communication previews in the terminal without adding a heavyweight broker.
56
57
  - **Mailbox Contracts**: Lets recipes declare what messages they accept and emit, so agents can discover how to interact with an actor.
57
58
  - **Actor Tool Registry**: Stores persistent actor-control tools as recipe files in `~/.pi/agent/recipes/*.json` and registers them automatically on session start.
58
59
  - **Command Template Substrate**: Keeps process launch portable with named placeholders, typed args, defaults, sequences, guarded nodes, retries, failure policy, and `parallel: true` fanout.
@@ -83,9 +84,7 @@ pi install git:github.com/llblab/pi-actors
83
84
  ~/.pi/agent/recipes/*.json
84
85
  ```
85
86
 
86
- That directory is the operator-managed tool set: user recipe files there become tools by default unless they set `tool: false`. Packaged recipes are the lower-priority standard library of declarative actor components and opt into tools with `tool: true`.
87
-
88
- If `~/.pi/agent/actors-tools.json` exists from an older release, pi-actors treats it as legacy compatibility input, migrates entries into recipe files when possible, writes a migration report, and archives the legacy file only when migration is clean.
87
+ That directory is the operator-managed executable memory: user recipe files there become tools by location and survive across sessions. `register_tool` writes recipes there under the hood. Packaged recipes are the lower-priority standard library of declarative actor components; they are not tools unless copied or registered into the agent recipe root.
89
88
 
90
89
  ## Mental Model
91
90
 
@@ -96,6 +95,7 @@ command template = how to start work
96
95
  actor recipe = saved actor definition
97
96
  spawn = create actor instance
98
97
  message = connect/control actors
98
+ room = shared actor timeline + roster
99
99
  inspect = observe intentionally
100
100
  artifacts = persist outcomes
101
101
  mailbox = declare interaction contract
@@ -107,7 +107,37 @@ mailbox = declare interaction contract
107
107
  - A **registered tool** gives a template or actor recipe a stable agent-facing name.
108
108
  - A **run actor** is one execution instance with state, logs, actor messages, mailbox metadata, status, cancellation, and kill control.
109
109
 
110
- The template remains the execution substrate. The recipe is the actor definition. `async: true` opts into detached actor lifecycle. `spawn` creates actors, `message` connects or controls them, and `inspect` observes them without teaching agents to poll blindly.
110
+ The template remains the execution substrate. The recipe is the actor definition. `async: true` opts into detached actor lifecycle. `spawn` creates actors, `message` connects or controls them, and `inspect` observes them without teaching agents to poll blindly. Async run templates receive lifecycle and communication values such as `{run_id}`, `{state_dir}`, `{actor_address}`, `{default_room}`, and `{communication_file}`. Use `inspect run:<id> view=communication` to read the compact visible communication snapshot.
111
+
112
+ ## Actor Rooms
113
+
114
+ Each spawned run gets a default room at `room:<run>`. Actors can post shared messages there, discover peers through the roster, and still send private messages directly to `run:<id>` or `branch:<run>/<branch>` addresses.
115
+
116
+ ```json
117
+ {
118
+ "to": "room:review",
119
+ "from": "branch:review/security",
120
+ "type": "actor.join",
121
+ "body": {
122
+ "role": "reviewer",
123
+ "caps": ["security-review"],
124
+ "claim": "Review auth boundary risks"
125
+ }
126
+ }
127
+ ```
128
+
129
+ Inspect the communication surface intentionally:
130
+
131
+ ```text
132
+ inspect target=run:review view=communication
133
+ inspect target=room:review view=status
134
+ inspect target=room:review view=roster
135
+ inspect target=room:review view=contacts
136
+ inspect target=room:review view=previews
137
+ inspect target=room:review view=messages
138
+ ```
139
+
140
+ Room posts require `from` to belong to the same run, so room rosters stay provenance-safe and do not mix actors from unrelated runs. `view=contacts` returns roster-derived direct-message targets without forcing agents to parse the full roster JSON. The extension also shows a small default terminal widget with recent room, direct actor-message, and coordinator/session broadcast previews. Full bodies remain an intentional `inspect` action.
111
141
 
112
142
  ## Operator Onboarding
113
143
 
@@ -216,7 +246,6 @@ When keeping metadata and the recipe body together is clearer, `register_tool` w
216
246
  ```json
217
247
  {
218
248
  "description": "Start an async docs review",
219
- "tool": true,
220
249
  "async": true,
221
250
  "args": ["scope:path", "model:string"],
222
251
  "template": "pi -p --model {model} --tools read,bash \"Review {scope}\""
@@ -254,7 +283,6 @@ The commands above persist files under `~/.pi/agent/recipes/`. Tool names come f
254
283
  ```json
255
284
  {
256
285
  "description": "Transcribe a local audio file",
257
- "tool": true,
258
286
  "template": "/path/to/stt --file {file} --lang {lang=ru}"
259
287
  }
260
288
  ```
@@ -262,7 +290,6 @@ The commands above persist files under `~/.pi/agent/recipes/`. Tool names come f
262
290
  ```json
263
291
  {
264
292
  "description": "Run pi as a non-interactive sub-agent",
265
- "tool": true,
266
293
  "args": ["prompt:string", "model:string"],
267
294
  "template": "pi -p --model {model} --no-tools {prompt}"
268
295
  }
@@ -278,7 +305,7 @@ Start from an inline template as an addressable run actor:
278
305
 
279
306
  ```json
280
307
  {
281
- "as": "run:docs-review",
308
+ "as": "run:docs_review",
282
309
  "template": "pi -p --model {model} --no-tools {prompt}",
283
310
  "values": {
284
311
  "prompt": "Review docs/spec.md for contradictions.",
@@ -290,13 +317,13 @@ Start from an inline template as an addressable run actor:
290
317
  Do not check it on a timer. Let follow-up actor messages arrive from the run, then react to a run-local request or redirect a long-lived recipe without polling/restarting it:
291
318
 
292
319
  ```json
293
- { "to": "run:docs-review", "type": "control.continue", "body": "continue" }
320
+ { "to": "run:docs_review", "type": "control.continue", "body": "continue" }
294
321
  ```
295
322
 
296
323
  Read recent actor messages or logs only after a follow-up asks for inspection, at a real decision point, or during diagnosis:
297
324
 
298
325
  ```json
299
- { "target": "run:docs-review", "view": "tail", "lines": "80" }
326
+ { "target": "run:docs_review", "view": "tail", "lines": "80" }
300
327
  ```
301
328
 
302
329
  Reusable local recipes live in `~/.pi/agent/recipes/*.json`; recipe tools honor each file's `async` flag. Use `spawn` for explicit detached starts from a file or inline template, and `inspect target=coordinator view=runs status=running`, `inspect target=session:<id> view=runs status=running`, or `inspect target=session:all view=runs` for explicit inventory/diagnosis. List output includes `tool` and `recipe` when the launcher recorded that source context.
@@ -320,7 +347,7 @@ register_tool name=subagents_prompts \
320
347
  description="Start parallel no-tools subagents from a prompt array as one run actor" \
321
348
  template="subagents-prompts.json"
322
349
 
323
- subagent_prompt prompt="Review docs/async-runs.md for unclear wording." run_id=docs-review
350
+ subagent_prompt prompt="Review docs/async-runs.md for unclear wording." run_id=docs_review
324
351
  subagent_tools prompt="Inspect package metadata and report risks." tools="read,bash" run_id=package-review
325
352
  subagents_prompts \
326
353
  prompts='["Review README.md for unclear release-onboarding wording. Return concise findings.","Review docs/template-recipes.md for unclear recipe-import wording. Return concise findings."]' \
@@ -368,7 +395,7 @@ See [`docs/recipe-library.md`](./docs/recipe-library.md) for install notes and r
368
395
  - Obvious high-risk templates such as shells, interpreter eval modes, and broad filesystem mutation surface lightweight warnings without blocking existing tools.
369
396
  - `async: true` on a recipe selects detached run-actor lifecycle; omitted or false runs the recipe foreground through registered tools.
370
397
  - Layer boundaries stay explicit: command templates define synchronous execution graphs; template recipes add saved JSON metadata/import resolution and named `artifacts`; run actors add detached lifecycle, state, IPC, and observability.
371
- - `spawn`, `message`, and `inspect` are high-level actor adapters. `spawn` creates `run:<id>` actors from recipes or inline templates with optional state/artifact metadata, `message` sends one typed envelope to `run:<id>` mailboxes, `branch:<run>/<branch>` mailboxes, `tool:<name>` calls, or coordinator/session attention paths, and `inspect` intentionally reads `run:<id>` status/tail/messages/mailbox metadata, coordinator/session run status, or registered `tool:<name>` contracts while the broader actor/message protocol is refined.
398
+ - `spawn`, `message`, and `inspect` are high-level actor adapters. `spawn` creates `run:<id>` actors from recipes or inline templates with optional state/artifact metadata, `message` sends one typed envelope to `run:<id>` mailboxes, `branch:<run>/<branch>` mailboxes, `room:<run>` task rooms, `tool:<name>` calls, or coordinator/session attention paths, and `inspect` intentionally reads `run:<id>` status/tail/messages/mailbox metadata, `room:<run>` status/messages/previews/roster/contacts, coordinator/session run status, or registered `tool:<name>` contracts while the broader actor/message protocol is refined.
372
399
  - `spawn`, `message`, and `inspect` are the public async coordination vocabulary. Low-level async actions map to this actor API: start belongs to `spawn`; send/control/stop/kill belongs to `message`; status/tail/messages/list belongs to `inspect`. Use `inspect view=messages` for actor-envelope streams. Use `control.stop`, `control.cancel`, and `control.kill` for run termination; runtime-prefixed control aliases are no longer part of the public surface.
373
400
  - Actor management returns compact text by default; pass `verbose: true` to `inspect` when full JSON state is needed.
374
401
  - Detached runs inject `{run_id}` and `{state_dir}` into template values for run-local artifacts or recipe-specific control endpoints.
package/banner.jpg CHANGED
Binary file
@@ -32,7 +32,19 @@ session:<id>
32
32
  tool:<name>
33
33
  ```
34
34
 
35
- Future forms may include `chat:<id>` or package-specific endpoints, but the envelope stays the same.
35
+ Cross-branch communication adds one organic endpoint kind:
36
+
37
+ ```text
38
+ room:<run>
39
+ ```
40
+
41
+ A room is the task's single shared discussion channel: an addressable mailbox with an append-only message log and a compact member roster stored under the owning run state. It is not a broker or coordinator: it accepts normal actor-message envelopes, records shared timeline entries, tracks join/leave presence, and lets actors discover peers for direct messages. `room:<run>` is the public address; named subrooms are intentionally not exposed in 0.17.
42
+
43
+ An alternate implementation shape is a dedicated non-LLM communication actor: a small script-backed service recipe, possibly singleton-scoped, that owns room timelines, rosters, subscriptions, and fanout. This is attractive when communication needs outgrow simple file-backed room state, but it should remain an implementation adapter behind the same `room:<run>` address and message envelope. The public model should not fork into a separate chat API.
44
+
45
+ That actor-backed shape can also reduce direct file storage. Instead of every protocol feature owning JSON files as primary state, a helper actor can keep live room/roster structures in memory or another local structure and write files only as snapshots, audit logs, artifacts, or recovery checkpoints. The decision boundary is practical: keep files when durability and inspectability are the main value; prefer actor-owned structures when live coordination, subscriptions, fanout, unread state, or mutation consistency becomes the main value.
46
+
47
+ Package-specific endpoints may still exist, but the envelope stays the same.
36
48
 
37
49
  ## Message Envelope
38
50
 
@@ -73,6 +85,8 @@ run -> coordinator
73
85
  run -> run
74
86
  parent -> branch
75
87
  branch -> parent
88
+ branch -> room
89
+ room -> branch notification
76
90
  coordinator -> tool
77
91
  ```
78
92
 
@@ -81,10 +95,56 @@ Transports differ, but the public contract does not:
81
95
  - `to: run:<id>` routes through the run-local control channel selected by that recipe or runtime adapter.
82
96
  - `to: coordinator` routes to the runtime attention path when `from` names a run actor. `to: session:<id>` uses the same actor-message path only when the sender run is owned by that session, making explicit session-directed checkpoints possible without exposing runtime delivery knobs. Generic async-runner `command.done` messages and explicit coordinator/session-bound messages include the actor envelope fields alongside runtime metadata.
83
97
  - `to: branch:<run>/<branch>` routes through the parent run mailbox with the full envelope preserved so the run can dispatch branch-local control.
98
+ - `to: room:<run>` appends the full envelope to the room timeline and updates room state for room-control types such as `actor.join` and `actor.leave`.
84
99
  - `to: tool:<name>` invokes an executable pi tool by name. Object bodies become tool parameters; primitive bodies are passed as `{ "input": body }`.
85
100
 
86
101
  Transport is not public API unless a recipe explicitly documents a custom endpoint.
87
102
 
103
+ ## Rooms and Rosters
104
+
105
+ The task room is the discovery and shared-context layer for actors whose spawn-tree positions do not give them each other's addresses. The spawn tree remains the lifecycle/provenance structure; the task room describes the group communication graph. Direct messages and room messages can share the same semantic `type` such as `chat.message`; the route (`to: branch:*` versus `to: room:*`) determines whether delivery is private or group-wide.
106
+
107
+ A minimal join message:
108
+
109
+ ```json
110
+ {
111
+ "to": "room:review",
112
+ "from": "branch:review/security",
113
+ "type": "actor.join",
114
+ "summary": "Security reviewer joined",
115
+ "body": {
116
+ "role": "reviewer",
117
+ "caps": ["security-review", "risk-analysis"],
118
+ "claim": "Review auth boundary risks"
119
+ }
120
+ }
121
+ ```
122
+
123
+ A leave message removes that actor from the roster while preserving the timeline entry:
124
+
125
+ ```json
126
+ {
127
+ "to": "room:review",
128
+ "from": "branch:review/security",
129
+ "type": "actor.leave"
130
+ }
131
+ ```
132
+
133
+ Room messages require `from` so roster presence and provenance stay explicit. The sender must belong to the room's run (`run:<run>` or `branch:<run>/<branch>`), which prevents accidental cross-run roster pollution. Other room posts also refresh sender presence, defaulting the role hint to `actor` when no richer role is known.
134
+
135
+ Roster entries should keep identity axes separate:
136
+
137
+ - `address`: Stable route for direct messages.
138
+ - `parent`: Spawn-tree parent for provenance and ownership checks.
139
+ - `role`: Current task function; dynamic and prompt-dependent.
140
+ - `caps`: Capabilities the actor can offer.
141
+ - `claim`: Current work claim or focus.
142
+ - `status` / `last_seen`: Presence and staleness hints.
143
+
144
+ Compact roster inspection includes these hints when present so agents can discover direct-message targets without verbose JSON.
145
+
146
+ Actors should receive a compact visible communication snapshot rather than a full global tree: self, parent/root, joined rooms, relevant sibling/member addresses, and role/capability hints. Current run actors get `communication.json` in their state dir, and async templates receive `{communication_file}`, `{actor_address}`, and `{default_room}` values. The snapshot includes `self`, `root`, optional `parent`, the default room, current default-room members, direct-message `contacts` derived from the room roster, and `updated_at`. Branch-local snapshots are refreshed when a branch joins or posts in the default room, so actors can discover peers without reading full timelines. Full timelines and rosters remain intentional inspection surfaces. For TUI and compact operator display, `view=previews` returns bounded message preview records with `timestamp`, `from`, `to`, `type`, optional `summary`, and optional `body_preview`.
147
+
88
148
  ## Mailbox Declaration
89
149
 
90
150
  Recipes can declare their conversational surface:
@@ -131,7 +191,7 @@ Recipes can declare their conversational surface:
131
191
  }
132
192
  ```
133
193
 
134
- The implementation supports `status`, `tail`, `messages`, `artifacts`, `files`, and `mailbox` for `run:<id>` actors, `status`/`runs` for `coordinator`, `session:<id>`, and `session:all` actors with optional status filtering, and `status`/`schema` for registered `tool:<name>` actors. Use `messages` for actor-envelope inspection. `inspect target=coordinator` requires a current coordinator session; use `session:<id>` or `session:all` when the session is intentionally explicit. Direct `run:<id>` inspection respects coordinator-session ownership when the current session is known. `inspect` is for decision points and diagnosis only; examples must not teach sleep-then-inspect polling.
194
+ The implementation supports `status`, `tail`, `messages`, `artifacts`, `files`, `mailbox`, and `communication` for `run:<id>` actors, `status`, `messages`, `previews`, `roster`, and `contacts` for `room:<run>` actors, `status`/`runs` for `coordinator`, `session:<id>`, and `session:all` actors with optional status filtering, and `status`/`schema` for registered `tool:<name>` actors. Room `status` returns compact message/roster counts plus `last_message_at`, `last_message_from`, `last_message_type`, and `last_message_summary` when available. Use `messages` for actor-envelope inspection. `inspect target=coordinator` requires a current coordinator session; use `session:<id>` or `session:all` when the session is intentionally explicit. Direct `run:<id>` and `room:<run>` inspection respects coordinator-session ownership when the current session is known. `inspect` is for decision points and diagnosis only; examples must not teach sleep-then-inspect polling.
135
195
 
136
196
  ## Runtime Direction
137
197
 
@@ -152,4 +212,5 @@ intentional observe -> inspect
152
212
  - No public transport-path vocabulary in recipe args.
153
213
  - No polling-first examples.
154
214
  - No separate upward and downward message schemas.
215
+ - No heavyweight chat/broker subsystem when an addressable room mailbox is enough.
155
216
  - No broad facade that hides artifacts, logs, or ownership checks.
@@ -72,13 +72,20 @@ A caller can also start any recipe or inline template explicitly through `spawn`
72
72
 
73
73
  `spawn` always starts a detached run actor. Registered recipe tools follow the recipe's `async` flag.
74
74
 
75
- Use `run_id` on async recipe tools or `as: "run:<id>"` on `spawn` when the caller wants a stable id for later inspection or control. Recipe `name` identifies the saved definition; the run id identifies one execution instance of that recipe. Async runs inject `{run_id}` and `{state_dir}` into template values so scripts can write run-local status files or control endpoints.
75
+ Use `run_id` on async recipe tools or `as: "run:<id>"` on `spawn` when the caller wants a stable id for later inspection or control. Recipe `name` identifies the saved definition; the run id identifies one execution instance of that recipe. Async runs inject lifecycle and communication values into template values so scripts can write run-local status files, control endpoints, or room-aware coordination messages:
76
+
77
+ - `{run_id}`: stable run id.
78
+ - `{state_dir}`: run-local state directory.
79
+ - `{actor_address}`: run actor address, e.g. `run:review`.
80
+ - `{default_room}`: default room address, e.g. `room:review`.
81
+ - `{communication_file}`: compact communication snapshot path.
76
82
 
77
83
  ## State Files
78
84
 
79
85
  Use ordinary files under the extension temp directory so status tools stay simple and inspectable:
80
86
 
81
87
  - `run.json`: pid, optional source metadata (`tool`, `recipe`, `recipe_file`), command-template config, cwd, coordinator owner id, values, named `artifacts`, mailbox metadata, created time, and state dir.
88
+ - `communication.json`: compact actor communication snapshot with self/root/parent, default-room, member, and contact hints for room-aware scripts and agents.
82
89
  - `progress.json`: phase, active command count, completed count, failures, and updated time.
83
90
  - `events.jsonl`: append-only implementation lifecycle log.
84
91
  - `outbox.jsonl`: implementation storage for actor-message envelopes used by `inspect view=messages`, coordinator notifications, or follow-up context. Coordinator follow-ups preserve bounded `body` previews plus message metadata for decision points.
@@ -95,6 +102,7 @@ State files use this shape:
95
102
 
96
103
  ```text
97
104
  ~/.pi/agent/tmp/pi-actors/runs/<run>/run.json
105
+ ~/.pi/agent/tmp/pi-actors/runs/<run>/communication.json
98
106
  ~/.pi/agent/tmp/pi-actors/runs/<run>/progress.json
99
107
  ~/.pi/agent/tmp/pi-actors/runs/<run>/events.jsonl
100
108
  ~/.pi/agent/tmp/pi-actors/runs/<run>/outbox.jsonl
@@ -129,13 +137,27 @@ The core loop is:
129
137
 
130
138
  Addressed `message` calls and coordinator follow-ups are the paired control plane: run-to-coordinator actor messages flow upward, while coordinator-to-run actor messages flow downward. Recipe scripts own the message vocabulary (`next`, `pause`, `approve`, `revise`, `continue`, and so on); pi-actors owns the safe run-local transport, coordinator-session ownership checks, and coordinator attention policy.
131
139
 
140
+ ### Persistent backlog implementers
141
+
142
+ Backlog implementer actors should be long-lived workers, not one-shot prompts, when the coordinator wants continuous branch work. A typical run starts two actors, such as `branch:<run>/front` and `branch:<run>/back`, that claim from opposite ends of the canonical backlog and share `room:<run>` for visibility.
143
+
144
+ The stable loop is:
145
+
146
+ 1. Coordinator sends `task.assign` to an idle branch actor with the exact backlog slice and validation boundary.
147
+ 2. Actor posts `task.claim` to `room:<run>` before editing.
148
+ 3. Actor completes the slice, validates, and posts `task.result` plus `awaiting_assignment`.
149
+ 4. Actor remains alive and waits for the next coordinator message.
150
+ 5. Coordinator either sends another `task.assign` or sends `control.stop` after confirming no actionable work remains.
151
+
152
+ Implementer recipes should declare this contract in `mailbox.accepts` and `mailbox.emits`. They should not self-terminate after a successful slice, and they should not silently self-select a new task unless the coordinator deliberately configured that policy for the run. This keeps task choice centralized while preserving actor-local execution autonomy.
153
+
132
154
  ## Tool Surface
133
155
 
134
156
  The actor-level surface is:
135
157
 
136
158
  - `spawn`: start a detached `run:<id>` actor from `file`, `recipe`, or inline `template`.
137
- - `message`: send one typed envelope to `run:<id>`, `branch:<run>/<branch>`, `tool:<name>`, `coordinator`, or `session:<id>`.
138
- - `inspect`: intentionally read owned `run:<id>` status, tail, messages, artifacts, files, or mailbox metadata; read current `coordinator` run inventory only when a coordinator session is known; read `session:<id>` or `session:all` run inventory with optional status filtering when the session is explicit; read `tool:<name>` status or schema for registered tool actors.
159
+ - `message`: send one typed envelope to `run:<id>`, `branch:<run>/<branch>`, `room:<run>`, `tool:<name>`, `coordinator`, or `session:<id>`.
160
+ - `inspect`: intentionally read owned `run:<id>` status, tail, messages, artifacts, files, mailbox metadata, or communication snapshot; read `room:<run>` status, messages, previews, roster, or contacts; read current `coordinator` run inventory only when a coordinator session is known; read `session:<id>` or `session:all` run inventory with optional status filtering when the session is explicit; read `tool:<name>` status or schema for registered tool actors.
139
161
 
140
162
  Low-level async actions map into the actor surface instead of forming a second public model:
141
163
 
@@ -59,9 +59,9 @@ register_tool name=subagent_prompt \
59
59
  Start it:
60
60
 
61
61
  ```text
62
- subagent_prompt prompt="Review docs/async-runs.md for unclear wording." run_id=docs-review
63
- inspect target=run:docs-review view=status
64
- inspect target=run:docs-review view=tail
62
+ subagent_prompt prompt="Review docs/async-runs.md for unclear wording." run_id=docs_review
63
+ inspect target=run:docs_review view=status
64
+ inspect target=run:docs_review view=tail
65
65
  ```
66
66
 
67
67
  ## Composed Pipelines
@@ -78,7 +78,7 @@ Recipe priority only matters when two discovered recipes have the same filename
78
78
  3. Explicitly referenced ad hoc user recipe files located outside `~/.pi/agent/recipes`.
79
79
  4. User recipe files under `~/.pi/agent/recipes/*.json`.
80
80
 
81
- The high-priority user recipe directory is also the default tool set: recipes placed there are agent tools unless they explicitly set `tool: false`. This preserves the old advantage of a tool-only registry because listing `~/.pi/agent/recipes` shows the operator-managed tool surface. Packaged and ad hoc recipes are recipe components by default; they opt into agent-tool exposure with `tool: true`.
81
+ The high-priority user recipe directory is also the default tool set: recipes placed there are agent tools by location. This preserves the old advantage of a tool-only registry because listing `~/.pi/agent/recipes` shows the operator-managed tool surface. Packaged and ad hoc recipes are recipe components by default; they become tools only when copied or registered into the agent recipe root.
82
82
 
83
83
  Higher-priority files shadow lower-priority files with the same basename. A highest-priority invalid recipe is still visible and blocks fallback so operators do not accidentally run packaged behavior when a user override is broken. A highest-priority recipe with `disabled: true` also blocks fallback and intentionally disables that id.
84
84
 
@@ -97,7 +97,7 @@ User-owned recipes may accumulate extension-maintained usage metadata:
97
97
 
98
98
  The extension increments `usage.calls` and updates `usage.last_called` when it starts that concrete recipe, either through a recipe-backed tool call or a direct async recipe-file run. It also stores a content `usage.fingerprint`; if the authored recipe content changes, the next launch resets `usage.calls` before counting the new launch and records `usage.reset_at`. Agents should treat these fields as cleanup evidence, not as authored recipe contract. Packaged standard-library recipes are not mutated for usage metadata.
99
99
 
100
- There is intentionally no failure counter in the recipe contract. A failed launch can reflect caller misuse, missing runtime values, or an environmental problem rather than recipe uselessness. Cleanup decisions should be explicit operator work: keep as a tool, set `tool: false`, merge, delete, or archive.
100
+ There is intentionally no failure counter in the recipe contract. A failed launch can reflect caller misuse, missing runtime values, or an environmental problem rather than recipe uselessness. Cleanup decisions should be explicit operator work: keep as a tool, move out of the agent recipe root to retain recipe-only memory, merge, delete, or archive.
101
101
 
102
102
  For object form, keep `template` last. Recipe metadata comes first; executable content stays last.
103
103
 
@@ -203,12 +203,11 @@ Call-time params override file params. `values` are merged with file values; cal
203
203
 
204
204
  ## Registered Recipe Tools
205
205
 
206
- A registered tool is a recipe file exposed as an agent tool. User recipes under `~/.pi/agent/recipes/*.json` are tools by default; packaged/ad hoc recipes opt in with `tool: true`:
206
+ A registered tool is a recipe file exposed as an agent tool. User recipes under `~/.pi/agent/recipes/*.json` are tools by location; packaged/ad hoc recipes are components unless copied or registered into that user recipe root:
207
207
 
208
208
  ```json
209
209
  {
210
210
  "description": "Start an async docs review actor",
211
- "tool": true,
212
211
  "async": true,
213
212
  "args": ["scope:path", "model:string"],
214
213
  "template": "review {scope} --model {model}"