@llblab/pi-actors 0.17.0 → 0.17.1

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/README.md CHANGED
@@ -1,236 +1,178 @@
1
1
  # pi-actors
2
2
 
3
- > Actor runtime and orchestrator for agent-managed local processes.
3
+ > Local Actor Kernel for Pi
4
4
 
5
- [<img alt="Actors*" src="banner.jpg" />](https://github.com/llblab/pi-actors "pi-actors")
5
+ ![Actors](./banner.jpg)
6
6
 
7
- `pi-actors` turns local programs, scripts, services, recipes, and long-running processes into addressable actors that agents can start, message, inspect, and compose. A music player, a sub-agent fanout, a repo-health pipeline, or any trusted local process can become an actor when it has a template-backed launch path, a mailbox contract, and observable runtime state.
7
+ `pi-actors` turns trusted local programs, scripts, recipes, services, pipelines, and sub-agents into addressable actors that agents can spawn, message, inspect, and compose.
8
8
 
9
- The persistent tool registry is still useful: it lets agents keep durable operational muscle memory for trusted local commands and wrappers. But the project lens is broader than stored tools. `pi-actors` is a local-first orchestration runtime for wrapping capabilities as agent-managed entities with explicit interfaces.
10
-
11
- ## Start Here
12
-
13
- - [Project Context](./AGENTS.md)
14
- - [Open Backlog](./BACKLOG.md)
15
- - [Changelog](./CHANGELOG.md)
16
- - [Documentation](./docs/README.md)
17
- - [Actors skill](./skills/actors/SKILL.md) — dense agent-facing reference for operating the extension
18
- - [Swarm skill](./skills/swarm/SKILL.md) — multi-agent methodology, strategies, standards, and portable examples for actor-backed swarms
19
- - [Swarm MAWP notes](./skills/swarm/references/development-swarm.md) — optional small-team development swarm reference
20
-
21
- ## What It Is
22
-
23
- `pi-actors` is the runtime layer that lets a pi agent turn a local capability into a controllable actor:
9
+ It is not just a command registry. A tool is a verb. An actor is a noun with time: address, lifecycle, state, logs, mailbox, artifacts, and an interaction contract.
24
10
 
25
11
  ```text
26
- program/process/service
12
+ program / process / service
27
13
  → command template
28
14
  → actor recipe
29
15
  → spawn
30
- addressable actor
16
+ run:<id>
31
17
  → message / inspect / artifacts
32
18
  ```
33
19
 
34
- An actor can be:
35
-
36
- - A sub-agent running `pi -p` in a clean context.
37
- - A background music player controlled by `player.next` or `player.pause` messages.
38
- - A validation or repo-health pipeline that reports completion and artifacts.
39
- - A parallel quorum review with branch-level progress.
40
- - Any trusted local process with a launch template and a useful control surface.
41
-
42
- The key move is not just “register a command.” It is to wrap a process in an agent-readable contract:
43
-
44
- - **Launch**: `spawn` starts the actor from a template or recipe.
45
- - **Interface**: `mailbox` declares accepted and emitted message types.
46
- - **Control**: `message` sends typed envelopes to runs, branches, tools, or the coordinator.
47
- - **Observation**: `inspect` reads status, logs, messages, mailbox metadata, files, and artifacts intentionally.
48
- - **Persistence**: `artifacts` and state files make outcomes durable.
49
- - **Memory**: `~/.pi/agent/recipes/*.json` stores reusable actor-control wrappers across sessions.
50
-
51
- ## Key Features
52
-
53
- - **Actor Runtime**: Starts local templates and recipes as addressable `run:<id>` actors with state, logs, message mailboxes, cancellation, and artifacts.
54
- - **Agent-Managed Processes**: Wraps sub-agents, media players, pipelines, diagnostics, and other local programs as controllable entities instead of one-off commands.
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.
57
- - **Mailbox Contracts**: Lets recipes declare what messages they accept and emit, so agents can discover how to interact with an actor.
58
- - **Actor Tool Registry**: Stores persistent actor-control tools as recipe files in `~/.pi/agent/recipes/*.json` and registers them automatically on session start.
59
- - **Command Template Substrate**: Keeps process launch portable with named placeholders, typed args, defaults, sequences, guarded nodes, retries, failure policy, and `parallel: true` fanout.
60
- - **Composable Actor Recipes**: Stores reusable recipe JSON under `~/.pi/agent/recipes/*.json`; recipes can import other recipes, reuse defaults, declare artifacts, and opt into detached actor lifecycle with `async: true`.
61
- - **Coordinator-Scoped Observability**: Shows ambient triangles for active actor runs and sends compact completion or request-for-attention follow-ups only to the launching coordinator.
62
- - **Bounded Context Impact**: Returns compact output by default, truncates oversized stdout, and keeps full logs/artifacts in files for intentional inspection.
63
- - **Local-First Tool Memory**: Still lets agents create durable semantic tools from trusted commands so they do not repeatedly reconstruct shell invocations.
20
+ ## Core Contract
64
21
 
65
- ## Install
22
+ `pi-actors` compresses local agent orchestration to three durable verbs:
66
23
 
67
- From npm:
24
+ ```text
25
+ spawn create an addressable actor
26
+ message send one typed envelope to one address
27
+ inspect intentionally read state, logs, messages, contracts, or artifacts
28
+ ```
29
+
30
+ Everything else is an adapter until proven otherwise.
31
+
32
+ Use `spawn` when work may outlive the current turn. Use `message` when the actor should be steered rather than restarted. Use `inspect` at decision points, after actor follow-ups, or during diagnosis. Do not build polling loops as the default coordination pattern.
33
+
34
+ ## Install
68
35
 
69
36
  ```bash
70
37
  pi install npm:@llblab/pi-actors
71
38
  ```
72
39
 
73
- From git:
40
+ Or from git:
74
41
 
75
42
  ```bash
76
43
  pi install git:github.com/llblab/pi-actors
77
44
  ```
78
45
 
79
- ## Registry Migration
80
-
81
- `pi-actors` now reads persistent actor-control tools from:
82
-
83
- ```text
84
- ~/.pi/agent/recipes/*.json
85
- ```
86
-
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.
88
-
89
- ## Mental Model
46
+ ## Address Surface
90
47
 
91
- `pi-actors` separates launch mechanics from actor semantics:
48
+ Actors and coordination endpoints are addressed with compact route strings:
92
49
 
93
50
  ```text
94
- command template = how to start work
95
- actor recipe = saved actor definition
96
- spawn = create actor instance
97
- message = connect/control actors
98
- room = shared actor timeline + roster
99
- inspect = observe intentionally
100
- artifacts = persist outcomes
101
- mailbox = declare interaction contract
51
+ run:<id> one detached actor run
52
+ branch:<run>/<branch> branch-local actor endpoint
53
+ room:<run> shared run-local task room
54
+ coordinator launching coordinator attention path
55
+ session: current session actor surface
56
+ session:all cross-session inventory surface
57
+ tool:<name> executable registered tool
102
58
  ```
103
59
 
104
- - A **command** is one concrete local process.
105
- - A **command template** is the reusable launch shape for that process, with named placeholders.
106
- - An **actor recipe** is saved JSON containing a template, defaults, imports, mailbox metadata, artifacts, and optional detached lifecycle.
107
- - A **registered tool** gives a template or actor recipe a stable agent-facing name.
108
- - A **run actor** is one execution instance with state, logs, actor messages, mailbox metadata, status, cancellation, and kill control.
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. 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.
60
+ Actor messages use one envelope shape:
115
61
 
116
62
  ```json
117
63
  {
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
- }
64
+ "to": "run:review",
65
+ "from": "coordinator",
66
+ "type": "control.continue",
67
+ "summary": "Continue after checkpoint",
68
+ "body": "continue",
69
+ "reply_to": "msg_123",
70
+ "correlation_id": "task_456",
71
+ "metadata": {}
126
72
  }
127
73
  ```
128
74
 
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.
75
+ Routing is inferred from `to`, actor ownership, and runtime policy. Recipes should expose semantic message types, not transport knobs.
141
76
 
142
- ## Operator Onboarding
77
+ ## Golden Path
143
78
 
144
- Start with foreground templates when the work is short and deterministic:
79
+ Create a reusable async actor recipe in the user recipe root:
145
80
 
146
- ```text
147
- register_tool name=lint_docs description="Lint docs" template="npm run lint:docs"
148
- ```
149
-
150
- Move to actor recipes when work is long-running, parallel, service-like, or agentic:
81
+ ```bash
82
+ mkdir -p ~/.pi/agent/recipes
151
83
 
152
- ```json
84
+ cat > ~/.pi/agent/recipes/docs_review.json <<'JSON'
153
85
  {
154
- "name": "docs_review",
86
+ "description": "Start an async docs review actor",
155
87
  "async": true,
156
88
  "args": ["scope:path", "model:string"],
157
- "defaults": {},
158
89
  "mailbox": {
159
- "accepts": ["control.stop"],
90
+ "accepts": ["control.stop", "control.continue"],
160
91
  "emits": ["review.completed", "run.failed"]
161
92
  },
162
93
  "template": "pi -p --model {model} --no-tools \"Review {scope} for unclear actor-runtime onboarding. Return concise findings.\""
163
94
  }
95
+ JSON
164
96
  ```
165
97
 
166
- Expose a reusable actor recipe as a normal capability:
98
+ Because it lives under `~/.pi/agent/recipes/`, the file becomes a persistent agent tool by location. The filename is the tool id.
99
+
100
+ Start it:
167
101
 
168
102
  ```text
169
- register_tool name=docs_review description="Start an async docs review actor" template="docs_review" args="scope:path,model:string"
103
+ docs_review scope="README.md" model="current-review-model" run_id=docs_review
170
104
  ```
171
105
 
172
- `Task` is the user's work item. `Template` is the execution graph. `Actor recipe` is saved JSON. `Run` is one actor instance with status, logs, messages, cancellation, artifacts, and ambient triangles.
173
-
174
- ## Compose Recipes With Imports
106
+ Inspect only when there is a reason:
175
107
 
176
- Recipes can import other recipe files and reuse them as named nodes. This keeps reusable steps small while letting a parent recipe decide whether the combined graph runs foreground or as one detached run actor.
108
+ ```text
109
+ inspect target=run:docs_review view=status
110
+ inspect target=run:docs_review view=tail lines=80
111
+ inspect target=run:docs_review view=messages
112
+ inspect target=run:docs_review view=mailbox
113
+ ```
177
114
 
178
- `review-one.json`:
115
+ Steer it through messages:
179
116
 
180
- ```json
181
- {
182
- "name": "review-one",
183
- "args": ["scope:string", "model:string"],
184
- "defaults": {},
185
- "template": "pi -p --model {model} --no-tools \"Review {scope}\""
186
- }
117
+ ```text
118
+ message to=run:docs_review type=control.continue body=continue
119
+ message to=run:docs_review type=control.stop body=stop
187
120
  ```
188
121
 
189
- `review-pair.json`:
122
+ ## Actor Rooms
190
123
 
191
- ```json
192
- {
193
- "name": "review-pair",
194
- "async": true,
195
- "imports": {
196
- "review": "review-one.json"
197
- },
198
- "parallel": true,
199
- "failure": "branch",
200
- "template": [
201
- { "name": "review", "values": { "scope": "README.md" } },
202
- { "name": "review", "values": { "scope": "docs/template-recipes.md" } }
203
- ]
204
- }
124
+ Every spawned run can have a shared room at `room:<run>`. A room is not a broker and not a chat app. It is a run-local coordination surface: append-only timeline, compact roster, member discovery, and previews.
125
+
126
+ Actors can join, post, leave, and discover peers:
127
+
128
+ ```text
129
+ message \
130
+ to=room:review \
131
+ from=branch:review/security \
132
+ type=actor.join \
133
+ summary="Security reviewer joined" \
134
+ body='{"role":"reviewer","caps":["security-review"],"claim":"Review auth boundary risks"}'
205
135
  ```
206
136
 
207
- Register only the parent when that is the operator-facing capability:
137
+ Inspect the room intentionally:
208
138
 
209
139
  ```text
210
- register_tool name=review_pair \
211
- description="Start a parallel async docs review" \
212
- template="review-pair.json"
140
+ inspect target=room:review view=status
141
+ inspect target=room:review view=previews
142
+ inspect target=room:review view=roster
143
+ inspect target=room:review view=contacts
144
+ inspect target=room:review view=messages
213
145
  ```
214
146
 
215
- Imported recipes are recipe definitions, not nested run actors. The parent recipe's `async: true` creates one run actor with one state dir; imported recipes contribute command-template graph, args, defaults, and values.
147
+ Room posts require a same-run sender, so unrelated runs do not pollute the roster. Direct messages and room messages use the same envelope; only the address changes.
148
+
149
+ ## Registry Model
150
+
151
+ The persistent tool surface is file-discovered:
152
+
153
+ ```text
154
+ ~/.pi/agent/recipes/*.json
155
+ ```
216
156
 
217
- ## Register Actor-Control Tools
157
+ That directory is operator-managed executable memory.
218
158
 
219
- `register_tool` lists, registers, updates, or deletes persistent actor-control tools. Call it without arguments to list the current registry. These tools are convenient handles for creating or invoking actors, not the whole runtime model.
159
+ Rules:
220
160
 
221
- ### Local command: transcription
161
+ - User recipes in `~/.pi/agent/recipes/` are tools by location;
162
+ - Recipe filenames define tool ids;
163
+ - User recipes override same-name lower-priority recipes;
164
+ - Packaged recipes are standard-library components, not automatically installed operator policy;
165
+ - `register_tool` creates, updates, lists, or deletes user recipe files through the normal agent interface.
222
166
 
223
- `pi-actors` is also useful for exposing stable local commands as normal tools. For example, register an STT command:
167
+ Example foreground tool:
224
168
 
225
169
  ```text
226
- register_tool name=transcribe \
170
+ register_tool name=transcribe_audio \
227
171
  description="Transcribe a local audio file" \
228
- template="/path/to/stt --file {file} --lang {lang=ru}"
172
+ template="~/bin/transcribe {file:path} {lang=ru} {model:string}"
229
173
  ```
230
174
 
231
- ### Template recipe
232
-
233
- For reusable actor workflows, keep the large template and mailbox contract in a recipe file and register a small tool:
175
+ Example recipe-backed tool:
234
176
 
235
177
  ```text
236
178
  register_tool name=docs_review \
@@ -239,180 +181,107 @@ register_tool name=docs_review \
239
181
  args="scope:path,model:string"
240
182
  ```
241
183
 
242
- If the recipe file contains `async: true`, calling `docs_review` starts a detached run and returns metadata immediately. If `async` is omitted or false, the same recipe runs foreground and returns normal tool output.
243
-
244
- When keeping metadata and the recipe body together is clearer, `register_tool` writes a complete user recipe file:
184
+ Inspect the discovered registry:
245
185
 
246
- ```json
247
- {
248
- "description": "Start an async docs review",
249
- "async": true,
250
- "args": ["scope:path", "model:string"],
251
- "template": "pi -p --model {model} --tools read,bash \"Review {scope}\""
252
- }
186
+ ```text
187
+ inspect target=recipes view=status
188
+ inspect target=recipes view=summary verbose=true
253
189
  ```
254
190
 
255
- The filename is the recipe id/tool name, `async: true` selects detached run mode, and `template` remains the executable body.
191
+ ## Command Templates
256
192
 
257
- ### Sub-agent
193
+ A command template is the portable launch substrate. It can be a string, a sequence, or a composed graph.
258
194
 
259
- ```text
260
- register_tool name=call_subagent \
261
- description="Run pi as a non-interactive sub-agent" \
262
- template="pi -p --model {model} --no-tools {prompt}" args="prompt:string,model:string"
263
- ```
195
+ Templates support:
264
196
 
265
- Use `update=true` to overwrite an existing tool. Omit `template` during update to keep the previous template:
197
+ - Named placeholders: `{file}`, `{model}`, `{prompt}`;
198
+ - Compact types: `string`, `path`, `int`, `number`, `bool`, `enum(a,b)`;
199
+ - Defaults: `{lang=ru}`, `{dry_run:bool=true}`;
200
+ - Fallback and small ternary forms;
201
+ - Sequences with stdin flow;
202
+ - Parallel nodes;
203
+ - Retries, recovery, failure policy, delays, and guarded execution;
204
+ - Async run values such as `{run_id}`, `{state_dir}`, `{actor_address}`, `{default_room}`, and `{communication_file}`.
266
205
 
267
- ```text
268
- register_tool name=call_subagent \
269
- description="Run a focused pi sub-agent without tools" \
270
- update=true
271
- ```
206
+ The template owns execution shape. The recipe owns saved metadata, defaults, imports, mailbox, and artifacts. The run actor owns detached lifecycle, state, messages, cancellation, and inspection.
272
207
 
273
- Delete a tool:
208
+ ## Recipe Library
274
209
 
275
- ```text
276
- register_tool name=call_subagent template=null
277
- ```
210
+ Packaged recipes live under `recipes/` and helper scripts live under `scripts/`.
278
211
 
279
- ## Resulting Recipe Files
212
+ The library includes:
280
213
 
281
- The commands above persist files under `~/.pi/agent/recipes/`. Tool names come from recipe filenames. Stored recipes keep `template` last so flags and metadata are read before executable content:
214
+ - Sub-agent launchers;
215
+ - Review, critic, planner, verifier, merger, judge, normalizer, and artifact atoms;
216
+ - Quorum and lens-style pipelines;
217
+ - Repo-health, release-summary, research-synthesis, development-tasking, docs-maintenance, and room-swarm pipelines;
218
+ - Coordinator-locker and actor-message utilities;
219
+ - Local music-player actor recipe.
282
220
 
283
- ```json
284
- {
285
- "description": "Transcribe a local audio file",
286
- "template": "/path/to/stt --file {file} --lang {lang=ru}"
287
- }
288
- ```
221
+ Packaged recipes are building blocks. Copy them into `~/.pi/agent/recipes/` or register tools that point at them when they should become durable operator-facing capabilities.
289
222
 
290
- ```json
291
- {
292
- "description": "Run pi as a non-interactive sub-agent",
293
- "args": ["prompt:string", "model:string"],
294
- "template": "pi -p --model {model} --no-tools {prompt}"
295
- }
296
- ```
223
+ ## When To Use What
297
224
 
298
- The recipe directory is the durable actor-tool registry. `register_tool` is the interactive API; recipe files are the persisted state loaded on future sessions.
225
+ Use a foreground registered tool when the work is short, bounded, and does not need lifecycle.
299
226
 
300
- ## Manage Actors
227
+ Use an async recipe or `spawn` when the work is long-running, service-like, parallel, agentic, artifact-producing, or needs later control.
301
228
 
302
- Use `spawn` when a command template, service, pipeline, or recipe may outlive the current turn. It starts the work now as an addressable actor, returns immediately with state metadata, and keeps ordinary files under `~/.pi/agent/tmp/pi-actors/runs/<run>` for later inspection.
229
+ Use `room:<run>` when multiple actors in the same run need shared context, roster discovery, or group-visible progress.
303
230
 
304
- Start from an inline template as an addressable run actor:
231
+ Use artifacts when outputs should survive context compression.
305
232
 
306
- ```json
307
- {
308
- "as": "run:docs_review",
309
- "template": "pi -p --model {model} --no-tools {prompt}",
310
- "values": {
311
- "prompt": "Review docs/spec.md for contradictions.",
312
- "model": "current-review-model"
313
- }
314
- }
315
- ```
233
+ Use mailbox declarations when an actor has a stable conversational surface.
316
234
 
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:
235
+ ## Safety Boundary
318
236
 
319
- ```json
320
- { "to": "run:docs_review", "type": "control.continue", "body": "continue" }
321
- ```
237
+ `pi-actors` is local-first, not sandbox-first.
322
238
 
323
- Read recent actor messages or logs only after a follow-up asks for inspection, at a real decision point, or during diagnosis:
239
+ Commands execute directly without shell evaluation where possible, but trusted executables still run with the same system permissions as Pi. Only register commands, scripts, recipes, and paths you trust.
324
240
 
325
- ```json
326
- { "target": "run:docs_review", "view": "tail", "lines": "80" }
327
- ```
241
+ High-risk templates such as shells, interpreter eval modes, and broad filesystem mutation may surface warnings, but the runtime is not a security boundary.
328
242
 
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.
243
+ Prefer:
330
244
 
331
- ## Recipe Library
245
+ - Narrow commands;
246
+ - Explicit paths;
247
+ - Typed args;
248
+ - Bounded timeouts for bounded work;
249
+ - Explicit tool allowlists for sub-agents;
250
+ - Deterministic utility recipes for filesystem writes;
251
+ - Human approval for destructive or external side effects.
332
252
 
333
- Packaged standard recipes live under root `recipes/` with helper scripts under root `scripts/`. They are reusable library definitions, not automatically installed operator policy.
253
+ ## Non-Goals
334
254
 
335
- The subagent component recipes start non-interactive pi subagents as detached run actors or compose component recipes into higher-level coordinator pipelines. Use the no-tools recipe for the safest default, the explicit-tool variant when a bounded tool allowlist is needed, or the prompts fanout parent recipe to see imported subagent recipe nodes composed into one run actor:
255
+ `pi-actors` is NOT:
336
256
 
337
- ```text
338
- register_tool name=subagent_prompt \
339
- description="Start an async no-tools pi subagent" \
340
- template="subagent-prompt.json"
341
-
342
- register_tool name=subagent_tools \
343
- description="Start an async pi subagent with an explicit tool allowlist" \
344
- template="subagent-tools.json"
345
-
346
- register_tool name=subagents_prompts \
347
- description="Start parallel no-tools subagents from a prompt array as one run actor" \
348
- template="subagents-prompts.json"
349
-
350
- subagent_prompt prompt="Review docs/async-runs.md for unclear wording." run_id=docs_review
351
- subagent_tools prompt="Inspect package metadata and report risks." tools="read,bash" run_id=package-review
352
- subagents_prompts \
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."]' \
354
- run_id=review-prompts
355
- inspect target=run:review-prompts view=tail
356
- ```
257
+ - A generic workflow DSL;
258
+ - A remote agent interoperability protocol;
259
+ - A heavyweight broker or chat subsystem;
260
+ - A sandbox;
261
+ - A facade that hides logs, artifacts, ownership, or local side effects;
262
+ - A polling-first async runner.
357
263
 
358
- The music player recipe starts a local file, URL, directory, or playlist as a run actor, keeps the agent unblocked, shows the ambient triangle indicator in the launching coordinator, and can be controlled with addressed `message` calls. The standard library ships one Node.js wrapper recipe:
264
+ Its job is narrower: make trusted local capabilities addressable, messageable, inspectable, and reusable by agents.
359
265
 
360
- ```text
361
- register_tool name=music_player \
362
- description="Start async music player playback through the Node.js wrapper" \
363
- template="music-player.json" \
364
- args="source:string,loop:bool=true,volume:int=70,player:enum(auto,mpv,ffplay,cvlc,play)=auto"
365
-
366
- music_player source="~/Music" volume=55 run_id=music
367
- message to=run:music type=player.next body=next
368
- message to=run:music type=player.pause body=pause
369
- message to=run:music type=player.play body=play
370
- message to=run:music type=player.stop body=stop
371
- ```
266
+ ## Documentation
267
+
268
+ Start here:
372
269
 
373
- See [`docs/recipe-library.md`](./docs/recipe-library.md) for install notes and recipe requirements.
374
-
375
- ## Runtime Contract
376
-
377
- - Actor-control tool names are normalized to snake_case.
378
- - Reserved built-in names are blocked.
379
- - Templates are split into shell-like words first, then placeholders are substituted per command arg.
380
- - Tool args are derived from placeholders when `args` is omitted.
381
- - Typed arg declarations are progressive: `file:path`, `request_timeout:int=60000`, `speed:number=1.5`, `dry_run:bool=true`, `prompts:array`, and `mode:enum(check,fix)=check` can live in `args` or inline placeholders such as `{request_timeout:int=60000}`. They generate narrower tool schemas and runtime validation while existing untyped `args` and placeholders keep working.
382
- - `{arg=default}` inline defaults resolve after runtime values and stored `defaults`; `{arg??fallback}` handles empty/null fallback values; `{flag?--flag:}` ternaries map small truthy/falsy values to strings such as optional CLI flags.
383
- - Runtime actor-tool argument errors include a compact usage hint when typed normalization or template value resolution fails, including example call shape plus required and optional fields.
384
- - `template: [...]` sequences execute left to right; each successful step passes stdout to the next step on stdin.
385
- - Object nodes may set `parallel: true`; children receive the same stdin and joined stdout flows to the next sequence step.
386
- - Parallel nodes use soft-quorum semantics: failed branches are reported as degraded coverage unless failure propagation escalates to the root.
387
- - For long-running work or agentic fanout, prefer `async: true` recipes or `spawn` so lifecycle and ambient activity status remain visible.
388
- - Timeout is disabled by default; set a positive `timeout` on bounded commands that should fail closed. Numeric node fields may read placeholders such as `timeout: "{timeout_ms}"`.
389
- - Nodes may set `when` to skip conditional work and `delay` in milliseconds to wait before launch; delay is not inherited.
390
- - Failed steps default to `failure: "continue"`, which records the failure and continues with empty stdin.
391
- - `failure: "branch"` stops the current sequence/subtree without cancelling sibling parallel branches; `failure: "root"` aborts the composition.
392
- - `retry` retries a leaf or whole node on non-zero exit; default attempts is `1`.
393
- - `recover` runs a cleanup command template between failed retry attempts and stops retries if cleanup fails.
394
- - Commands execute directly without shell evaluation, but trusted executables still run with the same permissions as pi.
395
- - Obvious high-risk templates such as shells, interpreter eval modes, and broad filesystem mutation surface lightweight warnings without blocking existing tools.
396
- - `async: true` on a recipe selects detached run-actor lifecycle; omitted or false runs the recipe foreground through registered tools.
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.
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.
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.
400
- - Actor management returns compact text by default; pass `verbose: true` to `inspect` when full JSON state is needed.
401
- - Detached runs inject `{run_id}` and `{state_dir}` into template values for run-local artifacts or recipe-specific control endpoints.
402
- - Runtime actor messages are persisted in the run state dir; coordinator attention is inferred by the runtime, not exposed as recipe or message-envelope input. Follow-ups preserve bounded body previews and metadata for decision messages.
403
- - Native Windows should use WSL or a recipe-specific transport for run-local message-controlled recipes; Linux uses stricter `/proc` runner ownership checks for stale PID protection.
404
- - Registered tools may set `template` to a recipe JSON path/name; calling them follows that recipe's `async` mode.
405
- - File-backed recipes may declare `imports` and embed imported recipes with `{ "name": "alias" }` nodes, or read `{alias.defaults.key}`, `{alias.defaults.key=fallback}`, and `{alias.values.key?yes:no}` references before command-template execution.
406
- - Interactive sessions show ambient actor activity as stable `▷` triangles aggregated across runs started by the current agent session. Each running run actor contributes at least one triangle; parallel active branches can contribute more. One `▶` wave moves over the active set; terminal `done`/`failed`/unhandled `killed`/`exited` messages are delivered as compact follow-up context only to the launching coordinator agent, while intentional `cancel`, `kill`, and `stop` actions stay silent because the action already reports synchronously. Failed commands and in-flight parallel branch completions can bubble through `command.done`; successful final leaf completions remain diagnostic to avoid sequential pipeline noise.
407
- - Use `{file}` as the canonical local file path arg.
408
- - Stored `script` entries are rejected with migration guidance.
409
-
410
- See [`docs/command-templates.md`](./docs/command-templates.md) for the portable synchronous command-template contract; [`docs/template-recipes.md`](./docs/template-recipes.md) for saved recipe JSON; [`docs/async-runs.md`](./docs/async-runs.md) for detached lifecycle, state files, cancellation, and observability; [`docs/tool-registry.md`](./docs/tool-registry.md) for registry storage; and [`docs/recipe-library.md`](./docs/recipe-library.md) for the packaged standard recipe library.
411
-
412
- ## Notes
413
-
414
- - Only register trusted local commands. Registered tools run with the same system permissions as pi.
415
- - `index.ts` is a small composition root; reusable behavior lives in flat `/lib` domains covered by focused tests.
270
+ - [Project context](./AGENTS.md)
271
+ - [Changelog](./CHANGELOG.md)
272
+ - [Open backlog](./BACKLOG.md)
273
+ - [Documentation index](./docs/README.md)
274
+ - [Actors skill](./skills/actors/SKILL.md)
275
+ - [Swarm skill](./skills/swarm/SKILL.md)
276
+
277
+ Core docs:
278
+
279
+ - [Command templates](./docs/command-templates.md)
280
+ - [Template recipes](./docs/template-recipes.md)
281
+ - [Async runs](./docs/async-runs.md)
282
+ - [Actor messages](./docs/actor-messages.md)
283
+ - [Tool registry](./docs/tool-registry.md)
284
+ - [Recipe library](./docs/recipe-library.md)
416
285
 
417
286
  ## License
418
287
 
@@ -94,7 +94,7 @@ Transports differ, but the public contract does not:
94
94
 
95
95
  - `to: run:<id>` routes through the run-local control channel selected by that recipe or runtime adapter.
96
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.
97
- - `to: branch:<run>/<branch>` routes through the parent run mailbox with the full envelope preserved so the run can dispatch branch-local control.
97
+ - `to: branch:<run>/<branch>` routes through the parent run mailbox with the full envelope preserved so the run or recipe-specific worker protocol can dispatch branch-local control. It is not a broadcast room and it does not make an arbitrary prompt process consume the message automatically.
98
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`.
99
99
  - `to: tool:<name>` invokes an executable pi tool by name. Object bodies become tool parameters; primitive bodies are passed as `{ "input": body }`.
100
100
 
@@ -104,6 +104,8 @@ Transport is not public API unless a recipe explicitly documents a custom endpoi
104
104
 
105
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
106
 
107
+ Use direct branch messages only when the receiving branch is backed by a worker or recipe that reads the parent run mailbox and dispatches branch-targeted envelopes. Room roster contacts are discovery hints, not a guarantee that an independent prompt process is subscribed to its branch address. For ad hoc or transcript-driven swarms, prefer room-visible replies and mentions so every participant can inspect the shared timeline.
108
+
107
109
  A minimal join message:
108
110
 
109
111
  ```json
@@ -82,6 +82,7 @@ Pipeline recipes demonstrate second-order composition:
82
82
  - `recipes/pipeline-development-tasking.json`: Plan → task card → critique → integrator handoff.
83
83
  - `recipes/pipeline-docs-maintenance.json`: Docs index → documentation review → maintenance plan → artifact report.
84
84
  - `recipes/pipeline-media-library.json`: Playlist build → media-library artifact report.
85
+ - `recipes/pipeline-room-swarm.json`: Room participants join `room:<run>`, coordinate over repeated room-visible rounds, leave cleanly, and synthesize the room transcript into a caller-provided artifact path. Keep model/thinking/mission policy caller-owned. Custom roles can be supplied with `roles_path` as a JSON array of `{ "name", "persona", "glyph" }` objects; `name` stays ASCII-safe for `branch:<run>/<name>` addresses, while optional `glyph` is display-only for room summaries and operator scanning. The packaged swarm uses contacts for peer awareness but does not rely on direct branch delivery unless a caller-specific worker protocol consumes branch envelopes. Set `locker=true` to compose a local `coordinator-locker` cell under `{state_dir}/locker` for artifact ownership, resource lease locks, and a decision journal without merging locker policy into the room-participant script.
85
86
  - `recipes/pipeline-artifact-report.json`: Normalize → artifact-shaped output → actor-message-shaped record. This pipeline prepares a candidate artifact and emits `artifact.prepared`/`artifact.blocked`; the `artifact_path` is a target path, not a guarantee that the file was written.
86
87
  - `recipes/pipeline-artifact-write.json`: Normalize → artifact-shaped output → deterministic artifact write → actor-message-shaped record. Use only when the caller explicitly wants filesystem writes; `write_mode` is `create`, `overwrite`, or `append`.
87
88
  - `recipes/pipeline-artifact-bundle.json`: Optional validation → deterministic artifact write → machine-readable manifest generation → deterministic manifest write → actor-message-shaped record. Use when the caller explicitly wants a filesystem handoff bundle with both artifact and manifest paths.