@llblab/pi-actors 0.42.3 → 0.43.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.
Files changed (252) hide show
  1. package/AGENTS.md +121 -175
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +113 -276
  4. package/dist/fixtures/protocol/control-endpoint.json +6 -0
  5. package/dist/fixtures/protocol/control-record.json +9 -0
  6. package/dist/fixtures/protocol/recipe-summary.json +4 -12
  7. package/dist/fixtures/protocol/trace-event.json +9 -0
  8. package/dist/lib/async-runs.d.ts +14 -38
  9. package/dist/lib/async-runs.js +158 -108
  10. package/dist/lib/control.d.ts +12 -0
  11. package/dist/lib/control.js +84 -0
  12. package/dist/lib/execution-sessions.d.ts +17 -0
  13. package/dist/lib/execution-sessions.js +85 -0
  14. package/dist/lib/file-state.d.ts +1 -0
  15. package/dist/lib/file-state.js +17 -5
  16. package/dist/lib/inspector-actions.d.ts +2 -2
  17. package/dist/lib/inspector-actions.js +2 -2
  18. package/dist/lib/inspector-command.js +3 -3
  19. package/dist/lib/inspector-overlay.d.ts +52 -70
  20. package/dist/lib/inspector-overlay.js +532 -905
  21. package/dist/lib/inspector.d.ts +3 -71
  22. package/dist/lib/inspector.js +19 -665
  23. package/dist/lib/limits.d.ts +4 -2
  24. package/dist/lib/limits.js +4 -2
  25. package/dist/lib/observability.d.ts +16 -16
  26. package/dist/lib/observability.js +43 -82
  27. package/dist/lib/prompts.d.ts +1 -1
  28. package/dist/lib/prompts.js +2 -2
  29. package/dist/lib/recipe-control.d.ts +7 -0
  30. package/dist/lib/recipe-control.js +39 -0
  31. package/dist/lib/recipes-discovery.js +2 -0
  32. package/dist/lib/recipes-references.d.ts +1 -14
  33. package/dist/lib/recipes-references.js +6 -21
  34. package/dist/lib/review-projection.js +1 -5
  35. package/dist/lib/run-ui-runtime.js +2 -2
  36. package/dist/lib/runs-control-delivery.d.ts +21 -0
  37. package/dist/lib/runs-control-delivery.js +127 -0
  38. package/dist/lib/runs-controls.d.ts +35 -0
  39. package/dist/lib/runs-controls.js +144 -0
  40. package/dist/lib/runs-retention.d.ts +7 -0
  41. package/dist/lib/runs-retention.js +27 -3
  42. package/dist/lib/runs-start.js +4 -2
  43. package/dist/lib/runs-status.js +11 -6
  44. package/dist/lib/runs-trace.d.ts +24 -0
  45. package/dist/lib/runs-trace.js +98 -0
  46. package/dist/lib/runtime-notifier.d.ts +1 -1
  47. package/dist/lib/runtime-notifier.js +1 -1
  48. package/dist/lib/tools-inspect.d.ts +3 -3
  49. package/dist/lib/tools-inspect.js +203 -708
  50. package/dist/lib/tools-local.js +2 -10
  51. package/dist/lib/tools-message.d.ts +7 -7
  52. package/dist/lib/tools-message.js +95 -396
  53. package/dist/lib/tools-response.d.ts +1 -4
  54. package/dist/lib/tools-response.js +5 -39
  55. package/dist/lib/tools-spawn.js +16 -28
  56. package/dist/lib/tools.js +1 -2
  57. package/dist/lib/trace-projection.d.ts +22 -0
  58. package/dist/lib/trace-projection.js +165 -0
  59. package/dist/recipes/draft-review.json +0 -10
  60. package/dist/recipes/lens-swarm.json +0 -14
  61. package/dist/recipes/music-player.json +10 -19
  62. package/dist/recipes/pipeline-architect-coordinator.json +0 -11
  63. package/dist/recipes/pipeline-artifact-bundle.json +1 -22
  64. package/dist/recipes/pipeline-artifact-report.json +1 -18
  65. package/dist/recipes/pipeline-artifact-write.json +1 -18
  66. package/dist/recipes/pipeline-async-run-ops.json +0 -12
  67. package/dist/recipes/pipeline-checkpoint-continuation.json +0 -14
  68. package/dist/recipes/pipeline-development-tasking.json +0 -12
  69. package/dist/recipes/pipeline-docs-maintenance.json +0 -12
  70. package/dist/recipes/pipeline-media-library.json +0 -12
  71. package/dist/recipes/pipeline-quorum-review.json +0 -12
  72. package/dist/recipes/pipeline-release-readiness.json +0 -12
  73. package/dist/recipes/pipeline-release-summary.json +0 -12
  74. package/dist/recipes/pipeline-repo-health.json +0 -12
  75. package/dist/recipes/pipeline-research-synthesis.json +0 -11
  76. package/dist/recipes/pipeline-review-readiness.json +0 -12
  77. package/dist/recipes/resource-locker.json +27 -0
  78. package/dist/recipes/subagent-artifact.json +0 -9
  79. package/dist/recipes/subagent-checkpoint.json +0 -10
  80. package/dist/recipes/subagent-conflict-report.json +0 -11
  81. package/dist/recipes/subagent-contradiction-map.json +0 -11
  82. package/dist/recipes/subagent-critic.json +0 -11
  83. package/dist/recipes/subagent-evidence-map.json +0 -11
  84. package/dist/recipes/subagent-followup.json +0 -10
  85. package/dist/recipes/subagent-judge.json +0 -11
  86. package/dist/recipes/subagent-merge.json +0 -11
  87. package/dist/recipes/subagent-normalize.json +0 -11
  88. package/dist/recipes/subagent-plan.json +0 -11
  89. package/dist/recipes/subagent-preflight.json +0 -11
  90. package/dist/recipes/subagent-prompt.json +0 -10
  91. package/dist/recipes/subagent-quorum.json +0 -10
  92. package/dist/recipes/subagent-review-coordinator.json +0 -14
  93. package/dist/recipes/subagent-review.json +0 -11
  94. package/dist/recipes/subagent-task-card.json +0 -11
  95. package/dist/recipes/subagent-tools.json +0 -10
  96. package/dist/recipes/subagent-verify.json +0 -11
  97. package/dist/recipes/subagents-prompts.json +0 -10
  98. package/dist/recipes/tool-review.json +0 -10
  99. package/dist/scripts/async-runner.mjs +25 -25
  100. package/dist/scripts/conformance.mjs +4 -2
  101. package/dist/scripts/locker.mjs +200 -66
  102. package/dist/scripts/music-player.mjs +159 -150
  103. package/dist/scripts/recipe-utils.mjs +6 -96
  104. package/dist/scripts/release-gates.mjs +60 -0
  105. package/dist/scripts/validate-recipe.mjs +3 -53
  106. package/dist/skills/actors/SKILL.md +53 -266
  107. package/dist/skills/swarm/SKILL.md +11 -33
  108. package/docs/0.43-baseline.md +44 -0
  109. package/docs/README.md +3 -3
  110. package/docs/actor-inspector.md +26 -64
  111. package/docs/actors-deep-reference.md +92 -50
  112. package/docs/async-runs.md +81 -328
  113. package/docs/command-templates.md +2 -2
  114. package/docs/component-recipes.md +30 -133
  115. package/docs/recipe-library.md +57 -182
  116. package/docs/task-first-recipes.md +10 -12
  117. package/docs/template-recipes.md +76 -289
  118. package/docs/tool-registry.md +41 -161
  119. package/fixtures/protocol/control-endpoint.json +6 -0
  120. package/fixtures/protocol/control-record.json +9 -0
  121. package/fixtures/protocol/recipe-summary.json +4 -12
  122. package/fixtures/protocol/trace-event.json +9 -0
  123. package/lib/async-runs.ts +202 -201
  124. package/lib/control.ts +102 -0
  125. package/lib/execution-sessions.ts +111 -0
  126. package/lib/file-state.ts +17 -4
  127. package/lib/inspector-actions.ts +2 -2
  128. package/lib/inspector-command.ts +3 -3
  129. package/lib/inspector-overlay.ts +577 -1121
  130. package/lib/inspector.ts +46 -979
  131. package/lib/limits.ts +4 -2
  132. package/lib/observability.ts +60 -101
  133. package/lib/prompts.ts +2 -2
  134. package/lib/recipe-control.ts +45 -0
  135. package/lib/recipes-discovery.ts +2 -0
  136. package/lib/recipes-references.ts +9 -45
  137. package/lib/review-projection.ts +1 -5
  138. package/lib/run-ui-runtime.ts +2 -2
  139. package/lib/runs-control-delivery.ts +181 -0
  140. package/lib/runs-controls.ts +204 -0
  141. package/lib/runs-retention.ts +38 -3
  142. package/lib/runs-start.ts +4 -2
  143. package/lib/runs-status.ts +11 -6
  144. package/lib/runs-trace.ts +132 -0
  145. package/lib/runtime-notifier.ts +1 -1
  146. package/lib/tools-inspect.ts +240 -901
  147. package/lib/tools-local.ts +2 -12
  148. package/lib/tools-message.ts +112 -519
  149. package/lib/tools-response.ts +5 -52
  150. package/lib/tools-spawn.ts +16 -32
  151. package/lib/tools.ts +1 -2
  152. package/lib/trace-projection.ts +221 -0
  153. package/package.json +2 -1
  154. package/recipes/draft-review.json +0 -10
  155. package/recipes/lens-swarm.json +0 -14
  156. package/recipes/music-player.json +10 -19
  157. package/recipes/pipeline-architect-coordinator.json +0 -11
  158. package/recipes/pipeline-artifact-bundle.json +1 -22
  159. package/recipes/pipeline-artifact-report.json +1 -18
  160. package/recipes/pipeline-artifact-write.json +1 -18
  161. package/recipes/pipeline-async-run-ops.json +0 -12
  162. package/recipes/pipeline-checkpoint-continuation.json +0 -14
  163. package/recipes/pipeline-development-tasking.json +0 -12
  164. package/recipes/pipeline-docs-maintenance.json +0 -12
  165. package/recipes/pipeline-media-library.json +0 -12
  166. package/recipes/pipeline-quorum-review.json +0 -12
  167. package/recipes/pipeline-release-readiness.json +0 -12
  168. package/recipes/pipeline-release-summary.json +0 -12
  169. package/recipes/pipeline-repo-health.json +0 -12
  170. package/recipes/pipeline-research-synthesis.json +0 -11
  171. package/recipes/pipeline-review-readiness.json +0 -12
  172. package/recipes/resource-locker.json +27 -0
  173. package/recipes/subagent-artifact.json +0 -9
  174. package/recipes/subagent-checkpoint.json +0 -10
  175. package/recipes/subagent-conflict-report.json +0 -11
  176. package/recipes/subagent-contradiction-map.json +0 -11
  177. package/recipes/subagent-critic.json +0 -11
  178. package/recipes/subagent-evidence-map.json +0 -11
  179. package/recipes/subagent-followup.json +0 -10
  180. package/recipes/subagent-judge.json +0 -11
  181. package/recipes/subagent-merge.json +0 -11
  182. package/recipes/subagent-normalize.json +0 -11
  183. package/recipes/subagent-plan.json +0 -11
  184. package/recipes/subagent-preflight.json +0 -11
  185. package/recipes/subagent-prompt.json +0 -10
  186. package/recipes/subagent-quorum.json +0 -10
  187. package/recipes/subagent-review-coordinator.json +0 -14
  188. package/recipes/subagent-review.json +0 -11
  189. package/recipes/subagent-task-card.json +0 -11
  190. package/recipes/subagent-tools.json +0 -10
  191. package/recipes/subagent-verify.json +0 -11
  192. package/recipes/subagents-prompts.json +0 -10
  193. package/recipes/tool-review.json +0 -10
  194. package/scripts/async-runner.mjs +25 -25
  195. package/scripts/conformance.mjs +4 -2
  196. package/scripts/locker.mjs +200 -66
  197. package/scripts/music-player.mjs +159 -150
  198. package/scripts/recipe-utils.mjs +6 -96
  199. package/scripts/release-gates.mjs +60 -0
  200. package/scripts/validate-recipe.mjs +3 -53
  201. package/skills/actors/SKILL.md +53 -266
  202. package/skills/swarm/SKILL.md +11 -33
  203. package/dist/fixtures/protocol/actor-message-branch.json +0 -13
  204. package/dist/fixtures/protocol/mailbox-contract.json +0 -15
  205. package/dist/fixtures/protocol/room-message.json +0 -11
  206. package/dist/fixtures/protocol/room-roster.json +0 -11
  207. package/dist/fixtures/protocol/run-inbox-message.json +0 -9
  208. package/dist/fixtures/protocol/run-outbox-event.json +0 -9
  209. package/dist/lib/mailbox-loop.d.ts +0 -41
  210. package/dist/lib/mailbox-loop.js +0 -60
  211. package/dist/lib/messages.d.ts +0 -25
  212. package/dist/lib/messages.js +0 -122
  213. package/dist/lib/rooms.d.ts +0 -104
  214. package/dist/lib/rooms.js +0 -647
  215. package/dist/lib/runs-mailbox.d.ts +0 -25
  216. package/dist/lib/runs-mailbox.js +0 -146
  217. package/dist/lib/runs-messages.d.ts +0 -15
  218. package/dist/lib/runs-messages.js +0 -179
  219. package/dist/lib/runs-outbox.d.ts +0 -41
  220. package/dist/lib/runs-outbox.js +0 -87
  221. package/dist/lib/tools-mailbox.d.ts +0 -8
  222. package/dist/lib/tools-mailbox.js +0 -48
  223. package/dist/recipes/actor-worker.json +0 -39
  224. package/dist/recipes/coordinator-locker.json +0 -45
  225. package/dist/recipes/locker.json +0 -45
  226. package/dist/recipes/pipeline-room-swarm.json +0 -50
  227. package/dist/recipes/subagent-message.json +0 -32
  228. package/dist/recipes/utility-actor-message.json +0 -23
  229. package/dist/scripts/actor-worker.mjs +0 -214
  230. package/dist/scripts/coordinator.mjs +0 -799
  231. package/docs/actor-messages.md +0 -225
  232. package/fixtures/protocol/actor-message-branch.json +0 -13
  233. package/fixtures/protocol/mailbox-contract.json +0 -15
  234. package/fixtures/protocol/room-message.json +0 -11
  235. package/fixtures/protocol/room-roster.json +0 -11
  236. package/fixtures/protocol/run-inbox-message.json +0 -9
  237. package/fixtures/protocol/run-outbox-event.json +0 -9
  238. package/lib/mailbox-loop.ts +0 -144
  239. package/lib/messages.ts +0 -151
  240. package/lib/rooms.ts +0 -939
  241. package/lib/runs-mailbox.ts +0 -208
  242. package/lib/runs-messages.ts +0 -252
  243. package/lib/runs-outbox.ts +0 -144
  244. package/lib/tools-mailbox.ts +0 -56
  245. package/recipes/actor-worker.json +0 -39
  246. package/recipes/coordinator-locker.json +0 -45
  247. package/recipes/locker.json +0 -45
  248. package/recipes/pipeline-room-swarm.json +0 -50
  249. package/recipes/subagent-message.json +0 -32
  250. package/recipes/utility-actor-message.json +0 -23
  251. package/scripts/actor-worker.mjs +0 -214
  252. package/scripts/coordinator.mjs +0 -799
@@ -1,386 +1,139 @@
1
- # Async Run Standard
1
+ # Runs
2
2
 
3
- Async runs are detached executions of a template recipe or inline command template.
4
-
5
- **Meta-contract:** the command template is still the execution graph; the async run is only a lifecycle envelope with state, logs, actor messages, status, cancellation, and coordinator-scoped observability.
6
-
7
- **Scope:** run id, state path, runner pid, process-group cancellation, logs, status, tail, list, script-authored actor messages, run-local control messages, cancel, force-kill, terminal result state, ambient activity indicators, and extension-owned temp storage. No scheduler, queue daemon, workflow DSL, distributed worker, or second execution language.
8
-
9
- Actor-mode trigger: choose an async run when work may outlive the current turn, needs later steering or inspection, produces artifacts/follow-ups, runs as a service, fans out, or should become repeatable recipe memory. Keep short foreground checks in ordinary tools/templates.
10
-
11
- Layer boundary: async-run configuration may inject lifecycle values such as `{run_id}` and `{state_dir}` and may choose detached execution through `async: true`, but it does not add command-template graph syntax. Recipe imports and recipe-local references belong to the template-recipe layer; status, control messages, actor messages, cancel, and kill belong to the async-run layer.
12
-
13
- ---
14
-
15
- ## Layer Ownership
16
-
17
- Async-run standard owns:
18
-
19
- - Detached process lifecycle for one execution instance.
20
- - Run identity, state directory, pid/process-group tracking, logs, status, list, tail, actor-message inspection, run-local control, cancel, and kill.
21
- - Injected lifecycle values such as `{run_id}` and `{state_dir}`.
22
- - Coordinator-scoped observability and script-authored actor messages.
23
-
24
- Async-run standard does not own:
25
-
26
- - Command-template syntax, placeholders, graph semantics, or branch policy.
27
- - Recipe import resolution, filename-derived recipe identity, or recipe storage format.
28
- - Domain semantics for subagents, swarms, release readiness, media playback, or project policy.
29
- - Scheduling, queue daemons, distributed workers, or workflow DSLs.
30
-
31
- ## Reading Model
3
+ A Run is one detached execution instance:
32
4
 
33
5
  ```text
34
- recipe = saved JSON definition
35
- run = one execution instance
36
- lifecycle = state/logs/messages/status/control/cancel/kill envelope
37
- state dir = ordinary files for status/logs/messages/result
38
- coordinator = agent session that started the run
39
- ```
40
-
41
- Use async runs when work may outlive the current agent turn, should not block the agent, or should remain cancellable after launch.
42
-
43
- Rule of thumb:
44
-
45
- ```text
46
- short call or pipeline → foreground template/tool
47
- reusable saved graph → template recipe
48
- long or background work → spawn run actor
49
- ```
50
-
51
- ## Starting Runs
52
-
53
- A recipe with `async: true` starts detached when invoked through its registered tool:
54
-
55
- ```json
56
- {
57
- "async": true,
58
- "template": "play-audio {source}"
59
- }
6
+ Recipe --spawn--> Run
7
+ Run = Recipe + Trace + Control
60
8
  ```
61
9
 
62
- A caller can also start any recipe or inline template explicitly through `spawn`:
10
+ ## Creation
63
11
 
64
- ```json
65
- {
66
- "as": "run:music",
67
- "file": "music-player",
68
- "values": {
69
- "source": "~/Music"
70
- }
71
- }
72
- ```
73
-
74
- `spawn` always starts a detached run actor. Registered recipe tools follow the recipe's `async` flag.
12
+ `spawn` accepts a Recipe/file or inline command template and optional values, Run id, transport context, and artifact declarations. The runtime resolves the Recipe, validates typed values and current policy placeholders, claims the state directory, creates a new immutable `run_instance_id`, captures process identity, starts the runner, and appends `run.start` Trace.
75
13
 
76
- 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. The recipe filename 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:
14
+ A reused state directory fails while its prior generation remains active. Restart cleanup removes stale terminal state before the new generation starts.
77
15
 
78
- - `{run_id}`: stable run id.
79
- - `{state_dir}`: run-local state directory.
80
- - `{actor_address}`: run actor address, e.g. `run:review`.
81
- - `{default_room}`: default room address, e.g. `room:review`.
82
- - `{communication_file}`: compact communication snapshot path.
16
+ ## Identity and Ownership
83
17
 
84
- Review commands that require semantic evidence apply marker acceptance before command completion accounting. Rejected code-zero output is reported consistently as a failed command in events, progress, evidence, and outbox delivery; it cannot emit a success-level completion notification. Evidence records are written before command launch and lifecycle cancellation or kill finalizes any running record with its interrupted state, effective exit code, and attempt capture paths. Async attempt stdout/stderr files exist from attempt start, so even small partial streams remain auditable when a command never returns.
18
+ Each Run persists:
85
19
 
86
- Terminal follow-up content stays deliberately minimal: run id, status, one base path, and relative artifact names only. Pi injects it invisibly into LLM context while `triggerTurn` wakes an idle coordinator, so the transcript shows the coordinator response rather than a second custom-message copy of the same text. With declared artifacts, `Base` names their common directory and `Artifacts` lists bounded relative names; without them, `Base` names the run state directory. It never embeds stdout, stderr, semantic body, terminal error, model policy, persistence advice, completion type, or an inspect command into LLM context. The follow-up's non-LLM details retain one bounded semantic result, launch/tool-call correlation, and optional bounded scalar `transport_context`; a transport adapter can preserve an exact route such as `{ "transport": "telegram", "chat_id": 123456, "thread_id": 77 }`. When a recipe advertises `review.completed`, an explicit matching outbox envelope wins; otherwise a successful accepted review result deterministically synthesizes one from the bounded beginning of `stdout.log`. Failed runs retain their bounded terminal error as `run.failed` details.
20
+ - safe Run id and state path;
21
+ - current Pi owner id;
22
+ - immutable `run_instance_id`;
23
+ - process id plus captured process identity;
24
+ - launch source and tool-call provenance;
25
+ - captured Recipe/template/values;
26
+ - model and thinking policy provenance.
87
27
 
88
- Watcher acceleration and periodic reconciliation share one live in-flight guard. Delivery remains at-least-once across the send/handled-marker crash window, but reentrant watcher/reconciliation races do not create parallel sends. A send failure leaves the run unhandled for retry, notifies the active operator, and persists bounded attempts/error/status evidence in `terminal-delivery-failure.json`; `getRunStatus` exposes the latest record as `terminal_delivery_failure`.
28
+ Inspection, Control, cancellation, kill, retirement, and teardown filter by owner. Lifecycle mutations revalidate generation, state, and process identity under the canonical lock.
89
29
 
90
30
  ## State Files
91
31
 
92
- Use ordinary files under the extension temp directory so status tools stay simple and inspectable:
93
-
94
- - `.pi-actors-run-state.json`: runtime ownership marker binding the run id to the canonical state directory; launch reuse and destructive retention fail closed when it is absent, invalid, mismatched, or reached through a symlink alias. State reuse also fails closed whenever the persisted process identity mismatches a still-live pid, preventing corrupted metadata from admitting overlapping runners.
95
- - `run.json`: pid, cross-platform `process_identity` proof (start time, command, and canonical cwd where available), optional source metadata (`launch_source`, `tool`, `recipe`, `recipe_file`), `launch_correlation`, bounded scalar `transport_context`, command-template config, cwd, coordinator owner id, values, named `artifacts`, mailbox metadata, created time, and state dir. Existing launch cwd aliases are resolved through native `realpath` before proof matching, so symlinked working directories do not degrade control to `unsupported_proof`.
96
- - `communication.json`: compact actor communication snapshot with self/root/parent, default-room, member, and contact hints for room-aware scripts and agents.
97
- - `progress.json`: phase, active command count, completed count, failures, updated time, and optional `model_policy` provenance for inherited/explicit model and thinking values.
98
- - `events.jsonl`: append-only implementation lifecycle log.
99
- - `outbox.jsonl`: implementation storage for actor-message envelopes used by `inspect view=messages`, coordinator notifications, or follow-up context. Script-authored decision-point follow-ups may preserve bounded `body` previews plus message metadata; automatic terminal follow-ups stay limited to run id, status, one base path, and relative artifact names.
100
- - `stdout.log` and `stderr.log`: detached process output.
101
- - `prompts/command-NNN.md`: state-owned prompt files that collapse child `pi -p` natural-language positional fragments and appended recipe context into one authoritative `@file` prompt while preserving intentional file/image arguments.
102
- - `captures/command-NNN/attempt-NNN/{stdout,stderr}.log`: complete byte-exact command streams, retained even below the bounded in-memory capture limit and separated across retries.
103
- - `review-evidence.json`: stable command/stage manifest linking prompts, repeated branches, capture attempts, byte counts, exit state, semantic marker acceptance, recipe context, and model/thinking policy; terminal status aligns with the run. Review pipelines inject prior-stage `ACTOR_EVIDENCE_REF` values into downstream prompts, record cited/missing report sources, and fail closed if a normalized report claims `complete` without every required reviewer, verifier, merger, and judge reference.
104
- - `result.json`: final code, killed flag, output selector, and optional full-output path. It publishes only after terminal `progress.json` and `review-evidence.json`, so readers never observe a result before its terminal state.
105
- - `terminal-delivery-failure.json`: latest bounded failed follow-up attempt count, status, error, and timestamp; a later successful retry writes `terminal-handled.json`.
106
- - `terminal-handled.json`: durable proof that terminal follow-up delivery or an explicit terminal control completed; notification delivery writes it only after the follow-up send returns successfully.
107
-
108
- Public `spawn` always uses the runtime-owned run root; caller-selected state directories are rejected so `run:<id>` addressing and retention share one boundary. Internal adapters may still supply isolated state directories for deterministic fixtures, but those are not part of the public actor contract. Every launched runner also persists a process identity proof and revalidates it for status, state reuse, message delivery, cancellation, kill, and retirement; dead pids, reused-pid owner mismatches, and unavailable platform proofs remain distinct diagnostics and destructive controls fail closed.
109
-
110
- For pi-actors, actor run state defaults to:
111
-
112
- ```text
113
- ~/.pi/agent/tmp/pi-actors/runs/
114
- ```
115
-
116
- State files use this shape:
117
-
118
32
  ```text
119
- ~/.pi/agent/tmp/pi-actors/runs/<run>/run.json
120
- ~/.pi/agent/tmp/pi-actors/runs/<run>/communication.json
121
- ~/.pi/agent/tmp/pi-actors/runs/<run>/progress.json
122
- ~/.pi/agent/tmp/pi-actors/runs/<run>/events.jsonl
123
- ~/.pi/agent/tmp/pi-actors/runs/<run>/outbox.jsonl
124
- ~/.pi/agent/tmp/pi-actors/runs/<run>/stdout.log
125
- ~/.pi/agent/tmp/pi-actors/runs/<run>/stderr.log
126
- ~/.pi/agent/tmp/pi-actors/runs/<run>/review-evidence.json
127
- ~/.pi/agent/tmp/pi-actors/runs/<run>/captures/command-NNN/attempt-NNN/stdout.log
128
- ~/.pi/agent/tmp/pi-actors/runs/<run>/prompts/command-001.md
129
- ~/.pi/agent/tmp/pi-actors/runs/<run>/result.json
33
+ run.json
34
+ trace.jsonl
35
+ controls.jsonl
36
+ control-endpoint.json controlled services only
37
+ execution.json
38
+ progress.json
39
+ result.json
40
+ stdout.log
41
+ stderr.log
42
+ terminal.json terminal lifecycle evidence
43
+ terminal-notification.json reconciliation evidence
44
+ diagnostics.jsonl
45
+ <declared artifacts>
130
46
  ```
131
47
 
132
- Terminal status is `done` for result code 0 and `failed` for non-zero result code. A stopped run reports `cancelled` after graceful cancel or `killed` after force kill once the runner is no longer alive. If the runner process exits before writing a result and no stop event was recorded, status is `exited`.
133
-
134
- ## Reactive Coordinator Loop
135
-
136
- Async runs are designed for message-driven coordination, not polling loops. A good coordinator starts long-lived or multi-agent work, lets completion and decision-point actor messages bubble upward, and sends corrective commands only when the run asks for input or the operator changes direction.
137
-
138
- The core loop is:
139
-
140
- 1. Start an async recipe and keep the coordinator free:
141
-
142
- ```json
143
- { "recipe": "music-player.json", "as": "run:music" }
144
- ```
145
-
146
- 2. Let terminal completion, `command.done`, and script-authored follow-up messages reach the launching coordinator automatically. Terminal completion gives the coordinator only run id, status, a base path, and relative artifact names; inspect the run when result content changes the next decision. Decide whether a successful pattern deserves recipe persistence only after inspection and operator confirmation.
147
-
148
- 3. Respond with explicit run-local messages when needed:
149
-
150
- ```json
151
- { "to": "run:music", "type": "player.next", "body": "next" }
152
- ```
153
-
154
- 4. Do not inspect just because time passed. Inspect `status`, `tail`, or `messages` only when a follow-up asks for inspection, a real decision depends on it, or a suspected stuck run needs diagnosis.
155
-
156
- 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.
48
+ `run.json` carries `state_schema: "run-kernel-v1"`. New Runs do not create communication-plane state.
157
49
 
158
- ### Persistent backlog implementers
50
+ ## Trace
159
51
 
160
- 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.
161
-
162
- The stable loop is:
163
-
164
- 1. Coordinator sends `task.assign` to an idle branch actor with the exact backlog slice and validation boundary.
165
- 2. Actor posts `task.claim` to `room:<run>` before editing.
166
- 3. Actor completes the slice, validates, and posts `task.result` plus `awaiting_assignment`.
167
- 4. Actor remains alive and waits for the next coordinator message.
168
- 5. Coordinator either sends another `task.assign` or sends `control.kill` after confirming no actionable work remains.
169
-
170
- 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.
171
-
172
- ## Tool Surface
173
-
174
- The actor-level surface is:
175
-
176
- - `spawn`: start a detached `run:<id>` actor from `file`, `recipe`, or inline `template`.
177
- - `message`: send one typed envelope to `run:<id>`, `branch:<run>/<branch>`, `room:<run>`, `tool:<name>`, `coordinator`, or `session:<id>`.
178
- - `inspect`: intentionally read owned `run:<id>` status, tail, messages, artifacts, files, mailbox metadata plus recent run inbox entries, 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.
179
-
180
- Opt-in supervisor retirement uses `retire_when: "children_terminal"` as lifecycle metadata. Run summaries discover nested child run state dirs under the visible state root so bounded supervisor trees are observable. Candidate detection is conservative: a supervisor is not retirement-ready while command-template progress, descendant `pi -p` worker processes, or nested child async runs under the supervisor state dir are still active. Candidate metadata includes observed child-run counts. When the session watcher observes a ready candidate, it sends a graceful `stop` control message once; if the run has no ready control endpoint, it falls back to owned-run cancellation and records the terminal action through normal run events. Persistent or non-opt-in runs are not retirement candidates.
181
-
182
- Low-level async actions map into the actor surface instead of forming a second public model:
183
-
184
- - Start → `spawn`
185
- - Send/control → `message`
186
- - Status/tail/messages/list → `inspect`
187
- - Force kill → `message` with `control.kill`, with synchronous results
188
- - Archive/prune terminal state → `message` with `control.archive` or `control.prune`, with active runs rejected fail-closed; retained artifacts use collision-safe identity-derived filenames, preserve timestamps, skip missing optional files, and abort prune before source deletion on any copy failure
189
-
190
- Compact text is returned by default so async management does not flood agent context; use verbose inspection when the full state object is needed. List output intentionally shares one state root across music, subagents, timers, and other async work; source fields such as `tool` and `recipe` distinguish run purpose when the launcher recorded them. The run root may contain a rebuildable `index.json` with run id, state directory, owner, status, update time, and recipe/tool hints; corrupt indexes fall back to recursive scan. Registered tools are the preferred user-facing surface for reusable recipes. `control.prune` accepts `body.preserve_artifacts=true` to copy existing named artifacts beside the run root before deleting terminal state.
191
-
192
- ## Run-Local Messages
193
-
194
- `message` is the explicit coordinator-to-actor command channel. Use it when a running recipe exposes a control vocabulary, a branch needs parent-mediated control, a registered tool should be invoked as `tool:<name>`, or the coordinator needs to redirect work without killing or restarting it.
195
-
196
- Some recipes expose a run-local control channel. When present, a caller can send a typed actor message:
52
+ Trace records strict bounded events:
197
53
 
198
54
  ```json
199
- {
200
- "to": "run:music",
201
- "type": "player.next",
202
- "body": "next"
203
- }
55
+ {"id":"…","ts":"…","kind":"command.done","summary":"Command completed","data":{"code":0},"level":"info","attention":"followup"}
204
56
  ```
205
57
 
206
- For `run:<id>`, `message` adapts the body to the recipe's run-local control channel. For `branch:<run>/<branch>`, it sends the full envelope through the parent run mailbox and records a queued branch-local inbox entry at `branches/<branch>/inbox.jsonl` so the run can dispatch branch-local control. Current consumers are recipe-specific worker protocols that read the parent run mailbox or branch inbox; independent one-shot prompt processes do not automatically consume branch inbox entries. In packaged coordinator flows, queued branch inbox records are claimed immediately before the branch's next prompt is launched, appended as direct prompt-steering context, and then marked `handled` or `failed` from the prompt result. This path is not a follow-up notification; it is a runner-owned prompt queue. For `tool:<name>`, object bodies become the target tool parameters and primitive bodies are passed as `{ "input": body }`. The generic runtime records control messages but does not interpret arbitrary run mailbox content. For example, a music player may accept `play`, `pause`, `next`, and `stop`, while a collaborative agent recipe may accept `continue`, `revise:<note>`, `approve`, or `abort`. Recipes may treat terminal control messages such as `stop` as synchronously handled so the later process exit does not generate a duplicate async follow-up.
207
-
208
- Run-local control uses a platform adapter under the same `message` API. Unix recipes may keep the existing FIFO endpoint, and native Windows recipes can expose a named-pipe endpoint in run state. Recipe authors should document message vocabulary through `mailbox.accepts`, not through transport arguments. Packaged scripts that still create Unix-only endpoints remain WSL/Linux/macOS-only until migrated.
209
-
210
- Portable control matrix:
211
-
212
- | Control surface | Linux/macOS/WSL | Native Windows | Guidance |
213
- | --- | --- | --- | --- |
214
- | File-backed run inbox + wake | Supported | Supported | Preferred durable baseline. |
215
- | Mailbox-only endpoint | Supported | Supported | Use for cross-platform workers. |
216
- | FIFO endpoint | Supported | Rejected before delivery | Keep only for Unix-compatible recipes. |
217
- | Named-pipe endpoint | Optional | Supported | Use for native Windows live delivery. |
218
- | Kill | Process group signal with pid fallback | Process-tree adapter | Same public `message type=control.kill` API. |
219
-
220
-
221
- Runtime wake notifications are now modeled separately from durable queues. Message handling records canonical state in file-backed mailbox/event files before attempting optional live endpoint delivery. Runs may expose a mailbox-only control endpoint when durable inbox plus wake notification is the intended delivery path; FIFO and named-pipe endpoints remain compatibility/fast-wake paths rather than the durable queue itself. Successful FIFO or named-pipe delivery marks the run inbox entry `sent`; mailbox-only delivery leaves the entry queued for the runtime to claim. `wake.jsonl` is an advisory doorbell that lets a live runtime subscribe through file-system notifications plus explicit initial, wake-triggered, and polling reconciliation callbacks. A missed wake must not lose work because actors can re-read the canonical mailbox state. Runtime loops that consume the file-backed mailbox should claim queued run inbox entries, then mark them `handled` or `failed`; the helper path uses a small lock so concurrent reconciliation callbacks do not process the same entry twice.
222
-
223
- ## Coordinator Notifications
224
-
225
- The launching coordinator should not busy-poll long-running async runs. The extension watches run state directories and queues terminal `done`/`failed`/unhandled `killed`/`exited` transitions back to the owning session through Pi's `followUp` delivery mode with `triggerTurn: true`; a busy coordinator finishes its current work before queued actor results arrive, while an idle coordinator starts a normal turn without a racy manual idle check. Pi's configured `followUpMode` determines whether concurrently queued results arrive together or one at a time. Script-authored `notify`/`followup` actor messages still follow their declared outbox delivery policy. Terminal notifications include recipe-level named `artifacts` when declared. The generic runner also emits compact `command.done` actor messages for completed leaf commands; recipe authors declare that capability in `mailbox.emits` rather than configuring a separate delivery policy. Failures and in-flight parallel branch completions can bubble according to outbox policy, while successful final leaf completions stay diagnostic to avoid flooding long sequential pipelines. Intentional `control.kill` and recipe-local stop commands stay out of coordinator context because the initiating message already returns synchronously or is handled by actor-local policy. If a notification asks for direction, answer with `message` rather than starting a polling loop. Use explicit `inspect` only when a delivered notification requests inspection, a real decision depends on state, or a suspected stuck run needs diagnosis — never merely because a timeout elapsed.
226
-
227
- Ambient status indicators may refresh while work is active, but coordinator attention is driven from run-state changes rather than a coordinator agent loop. This lets the coordinator continue other work after `spawn`; the run signals back through lifecycle state, results, and actor messages. File-system watchers accelerate live discovery, while a bounded ten-second terminal-only reconciliation pass scans owned unhandled terminal state without reading or replaying outbox traffic. Failed root or run-directory watcher attachment, runtime errors, error-driven watcher removal, and successful rearm remain available as bounded runtime diagnostics; normal run-directory deletion stays quiet; reconciliation rearms degraded watchers but does not depend on them. An owned terminal run without `terminal-handled.json` remains retry-eligible during same-runtime and extension/session replacement reconciliation; the marker is written only after successful follow-up delivery, and initial reconciliation does not replay historical outbox traffic. Watch-triggered and periodic delivery share an in-flight guard so one live runtime sends one follow-up when both paths race. This is an at-least-once contract: a process crash after send but before marker persistence can produce a duplicate notification, while a failed send remains durably retryable. The ambient triangle count represents active async work units: each running async run contributes at least one triangle, and a run with multiple active parallel command/subagent branches contributes the reported active branch count. If a coordinator starts one parent run with four active parallel branches, four triangles are shown; if the same coordinator starts five independent single-branch runs, five triangles are shown.
58
+ Required fields: `id`, `ts`, `kind`. Optional fields: `summary`, `data`, `level`, `attention`. Trace rejects addressed-envelope fields and malformed or oversized data.
228
59
 
229
- ## Run Actor Messages
60
+ Runtime lifecycle, runner progress, command completion, cancellation, kill, parent teardown, and controlled-service observations use Trace. `inspect view=trace` projects these events with Controls, owned Pi turns, logs, results, artifacts, and diagnostics under a deterministic global bound.
230
61
 
231
- A recipe or script may emit coordinator-bound or session-bound actor message records. The runtime persists those records in the run state dir and exposes them through `inspect target=run:<id> view=messages`.
62
+ ## Control
232
63
 
233
- Shape:
64
+ A Recipe declares actor-local actions only when its process consumes them:
234
65
 
235
66
  ```json
236
- {
237
- "type": "player.track",
238
- "to": "coordinator",
239
- "from": "run:music-player",
240
- "summary": "Now playing: track.flac",
241
- "level": "info",
242
- "ts": "2026-05-19T00:00:00.000Z",
243
- "body": { "track": "/Music/track.flac", "index": 3, "count": 42 }
244
- }
67
+ {"control":["pause","resume","stop"]}
245
68
  ```
246
69
 
247
- `level` is `info`, `warning`, or `error`. The public message describes sender, receiver, type, summary, and body; it does not choose notification mechanics. Runtime attention policy infers whether a coordinator-bound message stays available for explicit `inspect`, becomes a UI notification, or re-enters the launching coordinator as compact follow-up context.
70
+ Public request:
248
71
 
249
- Use coordinator/session-bound messages for completion and decision points, not for every progress tick. Packaged multi-agent branch completion is a completion message and should bubble by default. Follow-up path lists use Markdown hierarchy: a section heading, `- Base: ...`, and `- Files: ...`, so repeated run-state prefixes do not flood agent context.
250
-
251
- ## Cancellation And Ownership
252
-
253
- An async run belongs to the current user, cwd, and launching agent session at start time. Send, cancellation, and force-kill target only the recorded runner pid when command line and cwd still match the recorded owner data. Stale pid reuse must fail closed.
254
-
255
- Immediately before signaling, control revalidates the persisted process identity a second time inside the state-directory lifecycle lock. On Unix-like systems, `control.kill` signals the runner process group when available and falls back to the exact runner pid only when group signaling returns `ESRCH` and one additional identity revalidation still matches; authorization and permission errors fail closed without fallback. On native Windows, `control.kill` uses Windows process-tree termination through the platform adapter. The runner starts command-template children in the owned process tree, so long-running descendants such as audio players should stop with the run instead of becoming orphaned background processes. A recipe may manage a true detached daemon, but then daemon ownership is recipe-local: the script must persist and verify a pid or service handle, expose status/stop behavior, and bridge `control.kill` to daemon cleanup. The generic runner does not scan for or guess detached services. After the process exits, status reflects the operator action as `killed` instead of a generic `exited`. Programmatic `cancelRun()` remains an internal lifecycle helper for retirement and tests, but it is not a documented actor-message action. Node does not expose one portable identity-stable process-group handle across Linux, macOS, and Windows, so a runner can theoretically exit and its PID/PGID can be reused after the final identity read but before the OS signal call. Generation fencing, lifecycle serialization, immediate revalidation, and error-specific fallback minimize this residual platform window; docs and evidence must not claim pidfd/handle-level atomic signaling where the host cannot provide it.
72
+ ```json
73
+ {"target":"run:player","action":"pause","input":{"reason":"operator"},"verbose":false}
74
+ ```
256
75
 
257
- State is append-only where practical. Final result writes should be atomic. Recipe-local control endpoints and actor-message logs may live in the state dir. pi-actors core owns the generic run-local message adapter and runtime attention policy; command and message vocabularies belong to the recipe/script.
76
+ The runtime:
258
77
 
259
- ## Extension Temp Directory
78
+ 1. acquires the lifecycle lock;
79
+ 2. revalidates owner, `run_instance_id`, running state, and process identity;
80
+ 3. appends a queued generation-bound record to `controls.jsonl`;
81
+ 4. resolves a matching ready endpoint from `control-endpoint.json`;
82
+ 5. writes the exact `{id, action, input?}` wire document to FIFO or named pipe;
83
+ 6. records delivered or failed outcome.
260
84
 
261
- Extension-owned temporary runtime files live under the pi agent directory:
85
+ Unix services may publish a FIFO; native Windows services publish a Windows named pipe. Native Windows FIFO delivery fails before transport rather than degrading to another protocol. FIFO wire documents above the portable 512-byte atomic-write bound fail before writing; named pipes retain the general Control input bound.
262
86
 
263
- ```text
264
- ~/.pi/agent/tmp/<extension-name>/
265
- ```
87
+ A service claims queued or transport-delivered Controls and records handled/failed outcomes under the token-owned Control journal lock. Journal snapshots replace atomically, and expected-status fencing prevents delivery failure evidence from regressing a Control already claimed or completed by a fast consumer. Terminal compaction remains bounded. Services capture their startup generation, so stale-generation Controls never execute.
266
88
 
267
- Rules:
89
+ Runtime lifecycle `kill`, retention actions, and review retry/reset remain runtime-owned rather than Recipe-declared.
268
90
 
269
- - Use the pi agent temp tree, not system temp, for extension-owned state.
270
- - Use system temp only for OS-level scratch files or explicit operator overrides.
271
- - Keep each extension in its own subdirectory named after the local extension name.
272
- - Prepare the extension temp directory on session start.
273
- - Prune stale entries on session start.
274
- - Default stale age is 24 hours unless the extension has a stronger reason.
275
- - Cleanup must be fail-open: cleanup races should not prevent extension startup.
276
- - The `runs` state root is preserved by startup cleanup; run lifecycle cleanup must be explicit and run-aware.
277
- - State that must survive restarts belongs in the agent root, not in `tmp`.
91
+ ## Execution Evidence
278
92
 
279
- ## Parent Session Teardown
93
+ `execution.json` stores general command/session provenance. The async runner keeps bounded stdout/stderr logs plus bounded complete captures when semantic validation requires untruncated evidence. Pi command execution also records owned session provenance for later Trace projection and review checks.
280
94
 
281
- Async actors may outlive individual agent turns. Every Pi `session_shutdown` reason (`quit`, `reload`, `new`, `resume`, or `fork`) scans persisted run state and attempts teardown for discovered readable `running` runs whose exact `ownerId` matches the retiring coordinator session. Each new run persists immutable `run_instance_id`; teardown carries expected owner/generation into canonical `control.kill`, which compares both while holding the state-directory lifecycle lock shared with restart. Missing ownership or generation fails closed; terminal, ambiguous, changed-generation, and other-session runs remain untouched. Teardown never signals processes directly.
95
+ Review acceptance remains a command-stage concern. General execution evidence does not imply review approval.
282
96
 
283
- Teardown remains idempotent and best-effort across discovered siblings: one signal, process-proof, or evidence-write failure does not block later candidates. A `run.parent_teardown` event is written only while the selected generation still owns that state directory; replacement generations cannot receive stale teardown evidence. Successful kills retain `run.kill`, terminal progress, process-identity fencing, and handled-marker evidence.
97
+ ## Status and Terminal Reconciliation
284
98
 
285
- This boundary intentionally does not run at ordinary `agent_end`. Teardown uses unbounded directory discovery rather than the ordinary index depth cap. Unreadable directories and corrupt run state become explicit failures, and every invocation persists a bounded summary under `<run-root>/teardown/`; shutdown warnings include that path when failures remain. Actors launched by descendant Pi sessions deliberately remain outside the exact-owner contract and rely on their own session shutdown hook. A hard OS/process kill can still prevent either hook; use the persisted summary plus OS-level/manual recovery for an orphan that a replacement session cannot control safely.
99
+ Statuses include `running`, `done`, `failed`, `exited`, `cancelled`, and `killed`. Status resolution combines persisted metadata, result/terminal evidence, and verified process state.
286
100
 
287
- ## Ambient Observability
101
+ Ambient observation detects terminal transitions and Trace attention. Terminal follow-up delivery persists handled/failure evidence so reloads retry unhandled transitions without duplicating completed notifications.
288
102
 
289
- Interactive sessions expose compact activity with minimal screen cost:
103
+ Large semantic results stay outside compact visible follow-up text and remain available in structured details, execution captures, or artifacts.
290
104
 
291
- - Footer status is shown only while async runs launched by the current coordinator session are active.
292
- - Each running async run contributes at least one `▷`; if the run reports multiple active command/sub-agent branches, those branches contribute additional triangles.
293
- - One `▶` moves across the triangles as a small wave.
294
- - With one active command, the triangle blinks between `▶` and `▷`.
295
- - Triangles disappear as concrete commands exit.
296
- - No prompt-area widget is shown by default.
297
- - Terminal `done`/`failed`/unhandled `killed`/`exited` transitions trigger compact follow-up context only in the launching coordinator session; intentional `kill` and actor-local stop actions stay out of agent context because the action already reports synchronously or belongs to recipe-local policy.
298
- - Full logs remain in state files and are accessed through `inspect target=run:<id> view=tail` or the low-level tail adapter.
105
+ ## Cancellation and Kill
299
106
 
300
- This keeps background work visible without blocking the agent, occupying the prompt area, or leaking async context into unrelated sessions.
107
+ Cancellation and kill use canonical lifecycle control:
301
108
 
302
- ## Swarm Mapping
109
+ - acquire the state lock;
110
+ - validate owner and optional generation fence;
111
+ - verify process identity;
112
+ - signal the owned process or process group/tree;
113
+ - persist lifecycle evidence and Trace;
114
+ - finalize in-flight execution and progress.
303
115
 
304
- Swarm coordinator responsibilities split like this:
116
+ Shutdown and parent teardown kill only exact owned generations. A stale pid or replacement generation fails closed.
305
117
 
306
- - Generic async runtime: start, pid tracking, status, tail, list, cancellation, stdout, stderr, logs.
307
- - Swarm semantics: lock rules, quorum manifest shape, raw review retention, merger, post-merge review, conflict policy.
308
- - Adapter config: model pool, default merger, default reviewer, prompt lens, tool allowlist, timeout.
118
+ ## Retention
309
119
 
310
- pi-actors owns generic actor recipes and run primitives. Swarm should keep domain-specific quorum and implementation-team semantics unless they become reusable across multiple domains.
120
+ Archive and prune apply only to terminal Runs and enforce path containment. Retention never removes active or foreign-owned state. The state index can rebuild from trustworthy Run directories after corruption.
311
121
 
312
- ## Collaborative Subagent Branch Adapter
122
+ ## Service Recipes
313
123
 
314
- A collaborative implementation swarm can use pi-actors as the actor runtime without making pi-actors own swarm semantics. The coordinator prepares scope files and chooses branch names. A trusted local runner owns one branch lifecycle. The async run owns fanout, state, logs, status, tail, cancel, and terminal result metadata.
124
+ Packaged controlled services demonstrate the endpoint protocol:
315
125
 
316
- Recommended flow:
126
+ - `music-player` consumes playback Controls and emits playback Trace;
127
+ - `resource-locker` consumes queue/lease actions and emits lock Trace.
317
128
 
318
- ```text
319
- coordinator writes scope files
320
- → async recipe starts one branch runner per scope
321
- → each runner clones or worktrees the repo
322
- → each runner creates one feature branch
323
- → each runner launches one subagent
324
- → each runner verifies commit and push
325
- → coordinator inspects status and tail
326
- → integrator reviews and merges ready branches
327
- ```
129
+ One-shot pipelines omit Control and terminate through their command graph.
328
130
 
329
- Scope files are preferable to large inline prompts because they are inspectable, reusable from logs, and safe for longer task groups. Keep them under an agent-owned run directory such as:
131
+ ## Inspection
330
132
 
331
133
  ```text
332
- ~/.pi/agent/tmp/pi-actors/collab-runs/<run>/scopes/agent-01.md
333
- ```
334
-
335
- Example recipe:
336
-
337
- ```json
338
- {
339
- "async": true,
340
- "parallel": true,
341
- "timeout": 1800000,
342
- "template": [
343
- {
344
- "label": "agent-01",
345
- "failure": "branch",
346
- "retry": 2,
347
- "recover": "git -C {work_dir_1} reset --hard HEAD",
348
- "timeout": 1800000,
349
- "template": "node {runner} --repo {repo} --base {base=dev} --branch {branch_1} --work-dir {work_dir_1} --scope {scope_1} --model {model}"
350
- },
351
- {
352
- "label": "agent-02",
353
- "failure": "branch",
354
- "retry": 2,
355
- "recover": "git -C {work_dir_2} reset --hard HEAD",
356
- "timeout": 1800000,
357
- "template": "node {runner} --repo {repo} --base {base=dev} --branch {branch_2} --work-dir {work_dir_2} --scope {scope_2} --model {model}"
358
- }
359
- ]
360
- }
134
+ inspect target=run:<id> view=recipe
135
+ inspect target=run:<id> view=trace source=lifecycle lines=40
136
+ inspect target=run:<id> view=control
361
137
  ```
362
138
 
363
- The runner is intentionally outside pi-actors. It is a trusted local executable, like any other command-template target. Its minimum contract is clone or worktree, checkout branch, run subagent with bounded tools, verify expected branch, verify a commit exists, push branch, and emit a structured result. If one runner fails, `failure: "branch"` preserves sibling results as a degraded run.
364
-
365
- Coordinator responsibilities stay outside the async runtime:
366
-
367
- - Partition backlog tasks by stable task IDs and non-overlapping mutation zones.
368
- - Write scope files before starting the run.
369
- - Pass scope paths and branch names as values.
370
- - Use `inspect target=run:<id> view=status` or `view=tail` after terminal run messages.
371
- - Treat pushed branches as artifacts for review, not as automatic merges.
372
- - Record failed scopes back into the backlog.
373
-
374
- Do not encode backlog parsing, task assignment, pull-request policy, merge policy, or model selection into pi-actors core. Those are swarm, project, or operator policy.
375
-
376
- ## Crystallization Questions
377
-
378
- Before adding an async feature, ask:
379
-
380
- - Is this generic for any long-running command template?
381
- - Can it be represented as state files instead of a daemon?
382
- - Does it preserve `template` plus boolean `parallel` as the only execution language?
383
- - Does failure degrade into observable metadata instead of hidden retries?
384
- - Can a registered tool own the policy instead of the runtime?
385
-
386
- If implementing async primitives requires a scheduler, queue daemon, or custom DAG syntax, stop. The async extension should remain command-template execution with a small detached run envelope.
139
+ Use `/actor-inspector` to inspect Runs as concrete actor instances in the live TUI. Runtime, Recipe registry, and tool definitions remain separate management targets.
@@ -10,7 +10,7 @@ Command templates are the portable integration format for deterministic local au
10
10
 
11
11
  Extensions may choose their own config files, selectors, placeholder sources, and examples, but should preserve this core contract.
12
12
 
13
- Layer boundary: command templates own only the synchronous execution graph. Recipe imports, import-reference expressions, recipe lookup, `async: true`, run ids, state dirs, mailbox controls, and actor-message routing are host/recipe/async-run configuration layers, not portable command-template syntax.
13
+ Layer boundary: command templates own only the synchronous execution graph. Recipe imports, import-reference expressions, Recipe lookup, `async: true`, Run ids, state dirs, Control, and Trace are host/Recipe/Run layers, not portable command-template syntax.
14
14
 
15
15
  ## Layer Ownership
16
16
 
@@ -25,7 +25,7 @@ Command-template standard does not own:
25
25
 
26
26
  - Where templates are stored or how they are named.
27
27
  - Recipe imports, import references, or file lookup.
28
- - Detached lifecycle, run ids, state dirs, logs, cancellation, mailbox controls, or actor-message routing.
28
+ - Detached lifecycle, Run ids, state dirs, logs, cancellation, Control, or Trace.
29
29
  - Registry metadata such as tool descriptions, package install paths, or operator policy.
30
30
 
31
31
  ## Shape