@llblab/pi-actors 0.42.3 → 0.43.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.
Files changed (279) hide show
  1. package/AGENTS.md +127 -175
  2. package/BACKLOG.md +189 -1
  3. package/CHANGELOG.md +183 -292
  4. package/README.md +115 -276
  5. package/dist/fixtures/protocol/control-endpoint.json +6 -0
  6. package/dist/fixtures/protocol/control-record.json +9 -0
  7. package/dist/fixtures/protocol/recipe-summary.json +4 -12
  8. package/dist/fixtures/protocol/trace-event.json +9 -0
  9. package/dist/index.js +1 -1
  10. package/dist/lib/async-runs.d.ts +15 -38
  11. package/dist/lib/async-runs.js +173 -111
  12. package/dist/lib/automatic-review-runtime.d.ts +1 -1
  13. package/dist/lib/automatic-review-runtime.js +5 -5
  14. package/dist/lib/command-templates.d.ts +2 -0
  15. package/dist/lib/command-templates.js +38 -4
  16. package/dist/lib/control-projection.d.ts +20 -0
  17. package/dist/lib/control-projection.js +66 -0
  18. package/dist/lib/control.d.ts +15 -0
  19. package/dist/lib/control.js +97 -0
  20. package/dist/lib/draft-sleep.js +3 -3
  21. package/dist/lib/execution-sessions.d.ts +17 -0
  22. package/dist/lib/execution-sessions.js +85 -0
  23. package/dist/lib/file-state.d.ts +2 -0
  24. package/dist/lib/file-state.js +114 -46
  25. package/dist/lib/inspector-actions.d.ts +2 -2
  26. package/dist/lib/inspector-actions.js +2 -2
  27. package/dist/lib/inspector-command.js +3 -3
  28. package/dist/lib/inspector-overlay.d.ts +54 -70
  29. package/dist/lib/inspector-overlay.js +576 -910
  30. package/dist/lib/inspector.d.ts +3 -71
  31. package/dist/lib/inspector.js +19 -665
  32. package/dist/lib/limits.d.ts +7 -3
  33. package/dist/lib/limits.js +7 -3
  34. package/dist/lib/observability.d.ts +16 -16
  35. package/dist/lib/observability.js +43 -82
  36. package/dist/lib/prompts.d.ts +1 -1
  37. package/dist/lib/prompts.js +3 -3
  38. package/dist/lib/recipe-control.d.ts +7 -0
  39. package/dist/lib/recipe-control.js +43 -0
  40. package/dist/lib/recipes-discovery.js +2 -0
  41. package/dist/lib/recipes-references.d.ts +1 -14
  42. package/dist/lib/recipes-references.js +6 -21
  43. package/dist/lib/review-control.d.ts +1 -1
  44. package/dist/lib/review-control.js +4 -5
  45. package/dist/lib/review-projection.js +1 -5
  46. package/dist/lib/run-ui-runtime.js +2 -2
  47. package/dist/lib/runs-control-delivery.d.ts +28 -0
  48. package/dist/lib/runs-control-delivery.js +150 -0
  49. package/dist/lib/runs-controls.d.ts +37 -0
  50. package/dist/lib/runs-controls.js +146 -0
  51. package/dist/lib/runs-retention.d.ts +7 -0
  52. package/dist/lib/runs-retention.js +27 -3
  53. package/dist/lib/runs-start.js +4 -2
  54. package/dist/lib/runs-status.js +11 -6
  55. package/dist/lib/runs-trace.d.ts +24 -0
  56. package/dist/lib/runs-trace.js +102 -0
  57. package/dist/lib/runtime-identity.d.ts +7 -0
  58. package/dist/lib/runtime-identity.js +35 -0
  59. package/dist/lib/runtime-notifier.d.ts +1 -1
  60. package/dist/lib/runtime-notifier.js +1 -1
  61. package/dist/lib/runtime-triage.d.ts +29 -0
  62. package/dist/lib/runtime-triage.js +76 -0
  63. package/dist/lib/tool-review-scheduler.js +7 -7
  64. package/dist/lib/tools-inspect.d.ts +3 -3
  65. package/dist/lib/tools-inspect.js +241 -707
  66. package/dist/lib/tools-local.js +2 -10
  67. package/dist/lib/tools-message.d.ts +6 -7
  68. package/dist/lib/tools-message.js +95 -396
  69. package/dist/lib/tools-response.d.ts +1 -5
  70. package/dist/lib/tools-response.js +5 -48
  71. package/dist/lib/tools-spawn.js +16 -28
  72. package/dist/lib/tools.d.ts +1 -1
  73. package/dist/lib/tools.js +2 -3
  74. package/dist/lib/trace-projection.d.ts +22 -0
  75. package/dist/lib/trace-projection.js +185 -0
  76. package/dist/recipes/draft-review.json +0 -10
  77. package/dist/recipes/lens-swarm.json +0 -14
  78. package/dist/recipes/music-player.json +10 -19
  79. package/dist/recipes/pipeline-architect-coordinator.json +0 -11
  80. package/dist/recipes/pipeline-artifact-bundle.json +1 -22
  81. package/dist/recipes/pipeline-artifact-report.json +1 -18
  82. package/dist/recipes/pipeline-artifact-write.json +1 -18
  83. package/dist/recipes/pipeline-async-run-ops.json +0 -12
  84. package/dist/recipes/pipeline-checkpoint-continuation.json +0 -14
  85. package/dist/recipes/pipeline-development-tasking.json +0 -12
  86. package/dist/recipes/pipeline-docs-maintenance.json +0 -12
  87. package/dist/recipes/pipeline-media-library.json +0 -12
  88. package/dist/recipes/pipeline-quorum-review.json +0 -12
  89. package/dist/recipes/pipeline-release-readiness.json +0 -12
  90. package/dist/recipes/pipeline-release-summary.json +0 -12
  91. package/dist/recipes/pipeline-repo-health.json +0 -12
  92. package/dist/recipes/pipeline-research-synthesis.json +0 -11
  93. package/dist/recipes/pipeline-review-readiness.json +0 -12
  94. package/dist/recipes/resource-locker.json +27 -0
  95. package/dist/recipes/subagent-artifact.json +0 -9
  96. package/dist/recipes/subagent-checkpoint.json +0 -10
  97. package/dist/recipes/subagent-conflict-report.json +0 -11
  98. package/dist/recipes/subagent-contradiction-map.json +0 -11
  99. package/dist/recipes/subagent-critic.json +0 -11
  100. package/dist/recipes/subagent-evidence-map.json +0 -11
  101. package/dist/recipes/subagent-followup.json +0 -10
  102. package/dist/recipes/subagent-judge.json +0 -11
  103. package/dist/recipes/subagent-merge.json +0 -11
  104. package/dist/recipes/subagent-normalize.json +0 -11
  105. package/dist/recipes/subagent-plan.json +0 -11
  106. package/dist/recipes/subagent-preflight.json +0 -11
  107. package/dist/recipes/subagent-prompt.json +0 -10
  108. package/dist/recipes/subagent-quorum.json +0 -10
  109. package/dist/recipes/subagent-review-coordinator.json +0 -14
  110. package/dist/recipes/subagent-review.json +0 -11
  111. package/dist/recipes/subagent-task-card.json +0 -11
  112. package/dist/recipes/subagent-tools.json +0 -10
  113. package/dist/recipes/subagent-verify.json +0 -11
  114. package/dist/recipes/subagents-prompts.json +0 -10
  115. package/dist/recipes/tool-review.json +0 -10
  116. package/dist/scripts/async-runner.mjs +25 -25
  117. package/dist/scripts/conformance.mjs +4 -2
  118. package/dist/scripts/locker.mjs +196 -69
  119. package/dist/scripts/music-player.mjs +162 -159
  120. package/dist/scripts/recipe-utils.mjs +6 -96
  121. package/dist/scripts/release-gates.mjs +91 -0
  122. package/dist/scripts/validate-recipe.mjs +8 -57
  123. package/dist/skills/actors/SKILL.md +57 -265
  124. package/dist/skills/swarm/SKILL.md +10 -34
  125. package/docs/0.43-baseline.md +39 -0
  126. package/docs/README.md +4 -6
  127. package/docs/actor-inspector.md +26 -64
  128. package/docs/async-runs.md +81 -328
  129. package/docs/command-templates.md +8 -118
  130. package/docs/recipe-library.md +55 -182
  131. package/docs/releasing.md +28 -0
  132. package/docs/template-recipes.md +76 -289
  133. package/docs/tool-registry.md +41 -161
  134. package/fixtures/protocol/control-endpoint.json +6 -0
  135. package/fixtures/protocol/control-record.json +9 -0
  136. package/fixtures/protocol/recipe-summary.json +4 -12
  137. package/fixtures/protocol/trace-event.json +9 -0
  138. package/index.ts +1 -1
  139. package/lib/async-runs.ts +218 -204
  140. package/lib/automatic-review-runtime.ts +7 -7
  141. package/lib/command-templates.ts +44 -4
  142. package/lib/control-projection.ts +105 -0
  143. package/lib/control.ts +117 -0
  144. package/lib/draft-sleep.ts +3 -3
  145. package/lib/execution-sessions.ts +111 -0
  146. package/lib/file-state.ts +84 -64
  147. package/lib/inspector-actions.ts +2 -2
  148. package/lib/inspector-command.ts +3 -3
  149. package/lib/inspector-overlay.ts +617 -1126
  150. package/lib/inspector.ts +46 -979
  151. package/lib/limits.ts +7 -3
  152. package/lib/observability.ts +60 -101
  153. package/lib/prompts.ts +3 -3
  154. package/lib/recipe-control.ts +52 -0
  155. package/lib/recipes-discovery.ts +2 -0
  156. package/lib/recipes-references.ts +9 -45
  157. package/lib/review-control.ts +4 -5
  158. package/lib/review-projection.ts +1 -5
  159. package/lib/run-ui-runtime.ts +2 -2
  160. package/lib/runs-control-delivery.ts +209 -0
  161. package/lib/runs-controls.ts +213 -0
  162. package/lib/runs-retention.ts +38 -3
  163. package/lib/runs-start.ts +4 -2
  164. package/lib/runs-status.ts +11 -6
  165. package/lib/runs-trace.ts +136 -0
  166. package/lib/runtime-identity.ts +39 -0
  167. package/lib/runtime-notifier.ts +1 -1
  168. package/lib/runtime-triage.ts +120 -0
  169. package/lib/tool-review-scheduler.ts +7 -7
  170. package/lib/tools-inspect.ts +283 -900
  171. package/lib/tools-local.ts +2 -12
  172. package/lib/tools-message.ts +112 -520
  173. package/lib/tools-response.ts +5 -64
  174. package/lib/tools-spawn.ts +16 -32
  175. package/lib/tools.ts +5 -6
  176. package/lib/trace-projection.ts +244 -0
  177. package/package.json +2 -1
  178. package/recipes/draft-review.json +0 -10
  179. package/recipes/lens-swarm.json +0 -14
  180. package/recipes/music-player.json +10 -19
  181. package/recipes/pipeline-architect-coordinator.json +0 -11
  182. package/recipes/pipeline-artifact-bundle.json +1 -22
  183. package/recipes/pipeline-artifact-report.json +1 -18
  184. package/recipes/pipeline-artifact-write.json +1 -18
  185. package/recipes/pipeline-async-run-ops.json +0 -12
  186. package/recipes/pipeline-checkpoint-continuation.json +0 -14
  187. package/recipes/pipeline-development-tasking.json +0 -12
  188. package/recipes/pipeline-docs-maintenance.json +0 -12
  189. package/recipes/pipeline-media-library.json +0 -12
  190. package/recipes/pipeline-quorum-review.json +0 -12
  191. package/recipes/pipeline-release-readiness.json +0 -12
  192. package/recipes/pipeline-release-summary.json +0 -12
  193. package/recipes/pipeline-repo-health.json +0 -12
  194. package/recipes/pipeline-research-synthesis.json +0 -11
  195. package/recipes/pipeline-review-readiness.json +0 -12
  196. package/recipes/resource-locker.json +27 -0
  197. package/recipes/subagent-artifact.json +0 -9
  198. package/recipes/subagent-checkpoint.json +0 -10
  199. package/recipes/subagent-conflict-report.json +0 -11
  200. package/recipes/subagent-contradiction-map.json +0 -11
  201. package/recipes/subagent-critic.json +0 -11
  202. package/recipes/subagent-evidence-map.json +0 -11
  203. package/recipes/subagent-followup.json +0 -10
  204. package/recipes/subagent-judge.json +0 -11
  205. package/recipes/subagent-merge.json +0 -11
  206. package/recipes/subagent-normalize.json +0 -11
  207. package/recipes/subagent-plan.json +0 -11
  208. package/recipes/subagent-preflight.json +0 -11
  209. package/recipes/subagent-prompt.json +0 -10
  210. package/recipes/subagent-quorum.json +0 -10
  211. package/recipes/subagent-review-coordinator.json +0 -14
  212. package/recipes/subagent-review.json +0 -11
  213. package/recipes/subagent-task-card.json +0 -11
  214. package/recipes/subagent-tools.json +0 -10
  215. package/recipes/subagent-verify.json +0 -11
  216. package/recipes/subagents-prompts.json +0 -10
  217. package/recipes/tool-review.json +0 -10
  218. package/scripts/async-runner.mjs +25 -25
  219. package/scripts/conformance.mjs +4 -2
  220. package/scripts/locker.mjs +196 -69
  221. package/scripts/music-player.mjs +162 -159
  222. package/scripts/recipe-utils.mjs +6 -96
  223. package/scripts/release-gates.mjs +91 -0
  224. package/scripts/validate-recipe.mjs +8 -57
  225. package/skills/actors/SKILL.md +57 -265
  226. package/skills/swarm/SKILL.md +10 -34
  227. package/dist/fixtures/protocol/actor-message-branch.json +0 -13
  228. package/dist/fixtures/protocol/mailbox-contract.json +0 -15
  229. package/dist/fixtures/protocol/room-message.json +0 -11
  230. package/dist/fixtures/protocol/room-roster.json +0 -11
  231. package/dist/fixtures/protocol/run-inbox-message.json +0 -9
  232. package/dist/fixtures/protocol/run-outbox-event.json +0 -9
  233. package/dist/lib/mailbox-loop.d.ts +0 -41
  234. package/dist/lib/mailbox-loop.js +0 -60
  235. package/dist/lib/messages.d.ts +0 -25
  236. package/dist/lib/messages.js +0 -122
  237. package/dist/lib/rooms.d.ts +0 -104
  238. package/dist/lib/rooms.js +0 -647
  239. package/dist/lib/runs-mailbox.d.ts +0 -25
  240. package/dist/lib/runs-mailbox.js +0 -146
  241. package/dist/lib/runs-messages.d.ts +0 -15
  242. package/dist/lib/runs-messages.js +0 -179
  243. package/dist/lib/runs-outbox.d.ts +0 -41
  244. package/dist/lib/runs-outbox.js +0 -87
  245. package/dist/lib/tools-mailbox.d.ts +0 -8
  246. package/dist/lib/tools-mailbox.js +0 -48
  247. package/dist/recipes/actor-worker.json +0 -39
  248. package/dist/recipes/coordinator-locker.json +0 -45
  249. package/dist/recipes/locker.json +0 -45
  250. package/dist/recipes/pipeline-room-swarm.json +0 -50
  251. package/dist/recipes/subagent-message.json +0 -32
  252. package/dist/recipes/utility-actor-message.json +0 -23
  253. package/dist/scripts/actor-worker.mjs +0 -214
  254. package/dist/scripts/coordinator.mjs +0 -799
  255. package/docs/actor-messages.md +0 -225
  256. package/docs/actors-deep-reference.md +0 -66
  257. package/docs/component-recipes.md +0 -148
  258. package/docs/task-first-recipes.md +0 -263
  259. package/fixtures/protocol/actor-message-branch.json +0 -13
  260. package/fixtures/protocol/mailbox-contract.json +0 -15
  261. package/fixtures/protocol/room-message.json +0 -11
  262. package/fixtures/protocol/room-roster.json +0 -11
  263. package/fixtures/protocol/run-inbox-message.json +0 -9
  264. package/fixtures/protocol/run-outbox-event.json +0 -9
  265. package/lib/mailbox-loop.ts +0 -144
  266. package/lib/messages.ts +0 -151
  267. package/lib/rooms.ts +0 -939
  268. package/lib/runs-mailbox.ts +0 -208
  269. package/lib/runs-messages.ts +0 -252
  270. package/lib/runs-outbox.ts +0 -144
  271. package/lib/tools-mailbox.ts +0 -56
  272. package/recipes/actor-worker.json +0 -39
  273. package/recipes/coordinator-locker.json +0 -45
  274. package/recipes/locker.json +0 -45
  275. package/recipes/pipeline-room-swarm.json +0 -50
  276. package/recipes/subagent-message.json +0 -32
  277. package/recipes/utility-actor-message.json +0 -23
  278. package/scripts/actor-worker.mjs +0 -214
  279. package/scripts/coordinator.mjs +0 -799
@@ -1,357 +1,144 @@
1
- # Template Recipe Standard
1
+ # Template Recipes
2
2
 
3
- Template recipes are saved definitions around the synchronous [Command Template Standard](./command-templates.md). JSON remains the canonical precise format; Markdown is a literate authoring format that compiles into the same recipe model.
3
+ A Recipe stores a reusable command-template definition as JSON or Markdown.
4
4
 
5
- **Meta-contract:** a recipe stores a command-template graph plus defaults and run mode. It does not create a second execution language.
6
-
7
- **Scope:** reusable JSON/Markdown shape, recipe naming, file-backed recipes, co-located recipes, recipe-layer imports/references, call-time values, foreground execution, and the `async: true` handoff to the [Async Run Standard](./async-runs.md).
8
-
9
- ---
10
-
11
- ## Reading Model
12
-
13
- ```text
14
- command template = execution graph
15
- recipe = saved JSON definition
16
- run = one execution instance
17
- async: true = run through detached lifecycle
18
- ```
19
-
20
- A recipe wraps one command-template tree. The wrapped `template` keeps the normal command-template semantics: argv splitting, placeholders, defaults, typed args, sequence, `parallel: true`, `when`, delay, retry, failure propagation, recover cleanup, and output selection.
21
-
22
- Layer boundary: `imports`, `{ "name": "alias" }` imported-recipe nodes, `{alias.defaults.key}` references, fallback expressions, and recipe-local ternaries are recipe-loading features. They resolve before the command-template graph runs and do not extend the portable Command Template Standard. Typed imports are recipe definitions: they expose the imported recipe's command-template-shaped metadata (`template`, `args`, `defaults`, flags, and `values`), while async-run launch fields such as `async` and `retire_when` remain lifecycle configuration for starting a run, not part of the imported execution graph. Run state directories are runtime-owned and are not recipe or `register_tool` configuration; `{state_dir}` remains an injected run-local value for commands and artifact paths.
23
-
24
- Packaged recipes are the pi-actors recipe standard library: declarative actor config components that can be imported, launched, inspected, overridden, or composed by user recipes. Treat them as stable building blocks rather than user-local policy.
25
-
26
- ## Layer Ownership
27
-
28
- Template-recipe standard owns:
29
-
30
- - Saved JSON definitions around one command-template graph, plus Markdown-authored recipes that compile to that shape.
31
- - File-backed and co-located recipe shapes.
32
- - Recipe identity through file-backed filename or co-located tool id.
33
- - Recipe defaults, values, imports, import references, and import-node expansion.
34
- - Ordered named artifact declarations through `artifacts`.
35
- - Foreground-vs-detached selection through `async: true` when invoked by a recipe-aware host.
36
-
37
- Template-recipe standard does not own:
38
-
39
- - How command-template nodes execute internally.
40
- - Async state files, logs, run-local transports, status, cancellation, or observability.
41
- - Tool registry naming, button UX, package installation, or operator-specific policy.
42
- - Domain workflows such as swarm quorum, release policy, backlog parsing, or merge policy.
43
-
44
- A recipe can be synchronous or asynchronous:
45
-
46
- - Omitted or false `async`: a registered tool executes the recipe in the foreground and returns normal tool output.
47
- - `async: true`: a registered tool starts a detached async run and returns run metadata immediately.
48
-
49
- ## Minimal Shape
50
-
51
- Synchronous recipe:
52
-
53
- ```json
54
- {
55
- "template": "npm run check:docs"
56
- }
57
- ```
58
-
59
- Async recipe:
5
+ ## JSON
60
6
 
61
7
  ```json
62
8
  {
63
9
  "async": true,
64
- "template": "review docs/spec.md"
10
+ "description": "Create a repository health artifact",
11
+ "args": ["repo:path", "artifact_path:path", "model:string"],
12
+ "defaults": { "artifact_path": "{state_dir}/health.md" },
13
+ "imports": { "review": "subagent-review.json" },
14
+ "artifacts": { "report": "{artifact_path}" },
15
+ "template": {
16
+ "name": "review",
17
+ "values": { "input": "Inspect {repo}", "model": "{model}" }
18
+ }
65
19
  }
66
20
  ```
67
21
 
68
- A file-backed recipe's id comes from its filename, not a JSON `name` field. Legacy files may still contain `name`, but loaders ignore it for identity. `template` is the command-template tree. `async: true` selects detached run mode when the recipe is invoked through a registered tool.
69
-
70
- ## Markdown Authoring
22
+ ## Markdown
71
23
 
72
- Markdown recipes use `.md` files with YAML-like frontmatter for recipe metadata and one fenced executable block for the recipe/template body. Runtime behavior comes only from frontmatter plus the fenced block; surrounding prose is advisory for humans and future recipes-context use.
24
+ Markdown Recipes use YAML frontmatter and one executable fence:
73
25
 
74
26
  ````markdown
75
27
  ---
76
- description: Literate docs check
28
+ description: Summarize one file
77
29
  args:
78
- - scope:path
79
- defaults:
80
- scope: docs
81
- mailbox:
82
- accepts:
83
- - control.kill
30
+ - file:path
84
31
  ---
85
32
 
86
- Human notes can explain intent, examples, or review guidance.
33
+ Human notes remain advisory.
87
34
 
88
35
  ```template
89
- npm run check -- {scope}
36
+ summarize {file}
90
37
  ```
91
38
  ````
92
39
 
93
- Fenced blocks marked `template`, `command-template`, `json`, or `recipe` are executable. A `template` fence stores its text as the command-template string. A JSON fence can contain either a full recipe object with `template` or a raw command-template value. Frontmatter supports the recipe metadata used by JSON recipes, including `args`, `defaults`, `imports`, `mailbox`, `artifacts`, `async`, and command-template flags. For Markdown ergonomics, `args` may be either a YAML list or a comma-separated scalar, and `defaults` may be either a YAML object or a list of `key: value` entries; both normalize to the same JSON recipe shape.
94
-
95
- JSON remains the source-of-truth format for precise machine editing. If `<id>.json` and `<id>.md` exist in the same discovery priority layer, `<id>.json` wins and the Markdown recipe is reported as shadowed.
96
-
97
- ## Discovery Priority
98
-
99
- Recipe priority only matters when two discovered recipes have the same filename id. The conceptual ladder from lowest to highest priority is:
100
-
101
- 1. No recipe for that id.
102
- 2. Packaged pi-actors recipe components, acting as the standard library.
103
- 3. Explicitly referenced ad hoc user recipe files located outside `~/.pi/agent/recipes`.
104
- 4. User recipe files under `~/.pi/agent/recipes/*.json` or `*.md`.
105
-
106
- The high-priority user recipe directory is also the default tool set: recipes placed there are agent tools by location. This preserves the old advantage of a tool-only registry because listing `~/.pi/agent/recipes` shows the operator-managed tool surface. Packaged and ad hoc recipes are recipe components by default; they become tools only when copied or registered into the agent recipe root.
40
+ Fences marked `template`, `command-template`, `json`, or `recipe` can define execution. Frontmatter supports Recipe metadata and command-template flags.
107
41
 
108
- Higher-priority files shadow lower-priority files with the same basename. Within one priority layer, same-id JSON shadows Markdown because JSON is the canonical precise format. A highest-priority invalid recipe is still visible and blocks fallback so operators do not accidentally run packaged behavior when a user override is broken. A highest-priority recipe with `disabled: true` also blocks fallback, is not launchable, and intentionally disables that id. Healthy overrides are silent; failed bare-name launches caused by invalid or disabled shadowing include compact `reason=shadowed_invalid` or `reason=shadowed_disabled` diagnostics with the active path, blocked candidate, and recipe-doctor hint.
109
-
110
- ## Usage And Lineage Metadata
111
-
112
- User-owned recipe launches update extension-maintained lineage ledgers under `.usage/recipes/<recipe-name>.json` plus a path index. Authored recipes remain untouched. The ledger keeps lifetime and revision-local launch counts, executable fingerprints, former names and paths, bounded revision ancestry, transition events, and review epochs.
113
-
114
- Lifetime usage survives rename, promotion, demotion, and executable revision. Revision-local counters restart when executable content changes, making the new fingerprint eligible for portfolio review without erasing prior evidence. Discovery merges current lineage evidence into inspection; packaged standard-library recipes receive no mutable usage ledger. The unreleased format stays intentionally unversioned until a public compatibility boundary exists.
115
-
116
- There is intentionally no failure counter: a failed launch can reflect caller misuse, missing values, or environment state rather than recipe quality. Usage remains evidence, not an automatic usefulness verdict. Automatic review combines it with contract quality, portability, duplication, safety, and likely future value. `register_tool draft=...` is the preferred fenced single-draft override; a deliberate move/copy from `drafts/` into the recipe root also remains valid, though it may defer an already captured automatic batch.
117
-
118
- For object form, keep `template` last. Recipe metadata comes first; executable content stays last.
119
-
120
- ## Named Artifacts
121
-
122
- Use recipe-level `artifacts` to declare stable artifact names and paths for the whole recipe, ordered from most important to least important:
123
-
124
- ```json
125
- {
126
- "args": ["report_path:path"],
127
- "defaults": { "report_path": "artifacts/report.md" },
128
- "artifacts": {
129
- "report": "{report_path}",
130
- "summary": "artifacts/summary.json"
131
- },
132
- "template": "generate-report --out {report_path}"
133
- }
134
- ```
135
-
136
- `output` and `artifacts` are intentionally different. `output` is the command-template primary result selector and defaults to stdout; it participates in sequence/stdin flow. `artifacts` is recipe metadata: an ordered named artifact manifest for humans, async completion messages, and downstream tooling. `stdout` remains the default command result channel and is not renamed by `artifacts`.
137
-
138
- ## Mailbox
139
-
140
- Use recipe-level `mailbox` to document the semantic messages a recipe actor accepts and emits:
141
-
142
- ```json
143
- {
144
- "mailbox": {
145
- "accepts": [
146
- "control.continue",
147
- "control.revise",
148
- "control.approve",
149
- "control.kill"
150
- ],
151
- "emits": ["checkpoint.needs_scope", "branch.done", "run.done"]
152
- }
153
- }
154
- ```
155
-
156
- `mailbox` is contract metadata, not transport configuration. It should name semantic message types, not transport commands, file paths, or CLI fragments. Entries may be strings or typed objects such as `{ "type": "task.assign", "requires_response": true, "summary": "Assign work" }`; inspection normalizes both forms. Acceptance contracts are advisory by default: messages outside `mailbox.accepts` produce warnings rather than hard routing failures.
157
-
158
- ## Actor Recipe Context
159
-
160
- File-backed async recipes automatically build a bounded recipe context bundle for child LLM actor launches. The bundle is appended to child `pi -p` prompts as JSONL: each line is one recipe/context record containing filename-derived `name`, source file, role/depth, import path/alias, and the raw authored recipe JSON. The record whose command-template node launched the current child is marked with `"you_are_here": true` and path metadata.
161
-
162
- This context is provenance, not the task instruction. The authored prompt remains authoritative; the bundle explains the recipe/composition tree that produced the launch. A child actor can use it to give advisory feedback on whether its recipe, imports, mailbox metadata, and role boundaries fit the task, without needing a separate hand-written workflow explanation. Recipes that require a minimal child prompt may opt out:
163
-
164
- ```json
165
- {
166
- "async": true,
167
- "actor_context": false,
168
- "template": "pi -p --model {model} {prompt}"
169
- }
170
- ```
42
+ ## Fields
171
43
 
172
- `"actor_context": "off"` is equivalent. Bundle generation uses the same recipe file-size and import-depth safety limits as normal recipe loading.
44
+ Common Recipe fields:
173
45
 
174
- ## Actor Message Delivery
46
+ - `name`, `description`, `disabled`;
47
+ - `args`, typed arg declarations, and `defaults`;
48
+ - `imports` with optional binding defaults/values;
49
+ - `template`;
50
+ - `async`;
51
+ - `artifacts`;
52
+ - `control` for actual controlled services;
53
+ - command-template flags such as `parallel`, `concurrency`, `min_successful`, `when`, `timeout`, `delay`, `retry`, `failure`, `recover`, `repeat`, `accept_output`, and `output`;
54
+ - `retire_when: "children_terminal"` for opt-in supervisor retirement.
175
55
 
176
- Recipes do not declare a second event-delivery policy. A running actor emits addressed messages such as `command.done`, `run.done`, or `checkpoint.needs_input`; the coordinator/runtime decides whether a message stays diagnostic, becomes a notification, or re-enters the agent context. This keeps recipe metadata focused on the actor contract:
56
+ ## Imports
177
57
 
178
58
  ```json
179
59
  {
180
- "mailbox": {
181
- "accepts": ["control.kill"],
182
- "emits": ["command.done", "run.done", "run.failed"]
60
+ "imports": {
61
+ "review": "subagent-review.json",
62
+ "verify": {
63
+ "from": "subagent-verify.json",
64
+ "defaults": { "thinking": "medium" }
65
+ }
183
66
  },
184
- "template": "run-subtask {prompt}"
185
- }
186
- ```
187
-
188
- ## Command-Template Flags At Recipe Top Level
189
-
190
- Top-level command-template flags may sit beside recipe metadata such as `async`:
191
-
192
- ```json
193
- {
194
- "async": true,
195
- "parallel": true,
196
- "timeout": 300000,
197
- "failure": "branch",
198
- "template": ["review-a docs/spec.md", "review-b docs/spec.md"]
67
+ "template": [
68
+ { "name": "review", "values": { "input": "{input}" } },
69
+ { "name": "verify", "values": { "input": "Use prior output" } }
70
+ ]
199
71
  }
200
72
  ```
201
73
 
202
- Valid command-template flags include `args`, `defaults`, `parallel`, `concurrency`, `min_successful`, `when`, `label`, `timeout`, `delay`, `output`, `retry`, `failure`, `recover`, and `repeat`.
74
+ Imports are local definitions. Named nodes call imported templates inside the same execution graph and Run. Resolution enforces Recipe-root priority, file-size/depth bounds, and cycle rejection.
203
75
 
204
- Timeout is disabled by default. Set a positive `timeout` when a recipe should fail closed after a bounded runtime; omit it, or set `0`, for intentionally open-ended runs that will be stopped by async cancellation, such as background audio playback.
76
+ Direct delegation can use another Recipe as the entire template. The delegated Recipe remains the source of truth while the wrapper may narrow args/defaults or override selected lifecycle metadata.
205
77
 
206
- ## Valid Graph
78
+ ## Control
207
79
 
208
- The valid chain is:
209
-
210
- ```text
211
- tool → template reference → recipe → run → template
212
- ```
213
-
214
- A recipe must define `template` directly. Tool exposure comes from where the recipe is stored, so the same recipe remains transportable across user, ad hoc, and packaged roots.
215
-
216
- A recipe may live in a file or be co-located inside a registered tool entry. Both are storage variants of the same graph.
217
-
218
- ## File-Backed Recipes
219
-
220
- Reusable local recipes live in:
221
-
222
- ```text
223
- ~/.pi/agent/recipes/*.json
224
- ~/.pi/agent/recipes/*.md
225
- ```
226
-
227
- Bare recipe names resolve under that directory, so `file: "review-docs"` loads:
228
-
229
- ```text
230
- ~/.pi/agent/recipes/review-docs.json
231
- # or, when no same-id JSON file exists:
232
- ~/.pi/agent/recipes/review-docs.md
233
- ```
234
-
235
- Call-time params override file params. `values` are merged with file values; call-time values win. If a run id is omitted for an explicit async start, the file basename becomes the default run id.
236
-
237
- ## Registered Recipe Tools
238
-
239
- A registered tool is a recipe file exposed as an agent tool. User recipes under `~/.pi/agent/recipes/*.json` or `*.md` are tools by location; packaged/ad hoc recipes are components unless copied or registered into that user recipe root:
80
+ Only a process that consumes actor-local input declares actions:
240
81
 
241
82
  ```json
242
83
  {
243
- "description": "Start an async docs review actor",
244
84
  "async": true,
245
- "args": ["scope:path", "model:string"],
246
- "template": "review {scope} --model {model}"
85
+ "control": ["pause", "resume", "stop"],
86
+ "template": "{repo}/scripts/service.mjs --state-dir {state_dir}"
247
87
  }
248
88
  ```
249
89
 
250
- If a tool recipe contains `async: true`, calling the tool starts a detached actor run and returns metadata. If `async` is omitted or false, calling the tool executes the recipe foreground and returns normal tool output.
251
-
252
- ## Values And Public Args
253
-
254
- Recipe placeholders come from runtime values, recipe `defaults`, inline placeholder defaults, and registered-tool defaults. Pi tool launches also inject `{current_model}` and `{current_thinking}` when the active session exposes a selected model and thinking level; recipes that require those placeholders fail before fanout when the current value is unavailable unless the caller supplies an explicit override such as `model` or `thinking`. Async runs persist `model_policy` provenance in run status, progress, and terminal results so operators can tell whether model/thinking values were inherited, explicit, mixed, or unresolved.
255
-
256
- Recipe tools derive public arguments from the referenced or co-located command template when the recipe is available locally. Explicit `args` is still available when the public tool surface should be narrower than the recipe internals.
90
+ Actions must be lowercase ASCII, unique, non-reserved, and at most 64 characters. Serialized Control input is at most 380 bytes so every admitted wire record remains within 512 bytes on FIFO and named pipe. One-shot Recipes omit Control. Larger data belongs in a declared artifact/path; outputs belong in Trace, artifacts, execution evidence, or the command result.
257
91
 
258
- Example: a recipe may expose a private `repo` default for an example script, while the registered public tool only asks for `file`, `volume`, and `player`.
259
-
260
- ## Recipe Imports
261
-
262
- File-backed recipes may import other file-backed recipes at the recipe layer. Imports are resolved before the command-template graph is executed, so command-template core stays registry-free and synchronous. Recipe loading is intentionally bounded: a single recipe file larger than 1 MiB is rejected before JSON parsing, and import chains deeper than 32 are rejected before further resolution. Split very large prompts/data into explicit files or artifacts and keep recipe graphs shallow enough for operator review.
92
+ ## Artifacts
263
93
 
264
94
  ```json
265
95
  {
266
- "name": "parent",
267
- "imports": {
268
- "prepare": "prepare-worktree.json",
269
- "test": {
270
- "from": "run-tests.json",
271
- "values": { "suite": "unit" }
272
- }
273
- },
274
- "template": [{ "name": "prepare" }, { "name": "test" }]
96
+ "artifacts": {
97
+ "report": "{state_dir}/report.md",
98
+ "manifest": "{state_dir}/manifest.json"
99
+ }
275
100
  }
276
101
  ```
277
102
 
278
- An import binding may be either a string recipe path/name or an object with:
103
+ Artifact paths resolve under containment policy and appear in Run inspection. Recipes should write declared artifacts deterministically and fail when the requested write policy cannot be honored.
279
104
 
280
- - `from`: recipe path or bare recipe name. Import paths support static load-time placeholders: `{repo}` expands to the directory above the active recipe root, and `{agent}` expands to the pi agent directory. For a packaged recipe in `<repo>/recipes/name.json`, `{repo}/recipes/other.json` resolves to a sibling packaged recipe. For a user recipe in `~/.pi/agent/recipes/name.json`, `{repo}` and `{agent}` both resolve to `~/.pi/agent`. Bare names such as `utility-package-summary` resolve by recipe priority: first `~/.pi/agent/recipes`, then the importing recipe's directory, then the packaged standard library. This makes packaged recipes easy to reuse while preserving user/ad hoc overrides by filename identity.
281
- - `defaults`: extra default values exposed through the import.
282
- - `values`: explicit values for embedding that imported recipe.
105
+ ## Context and Provenance
283
106
 
284
- A template node of `{ "name": "alias" }` is replaced with the imported recipe's command-template graph. Imported recipe defaults are merged with import `defaults`, import `values`, node `defaults`, and node `values`; later layers win. This lets a parent recipe embed a reusable recipe in a sequence or `parallel: true` branch without inventing a workflow language.
107
+ File-backed Runs capture Recipe context records for the entry and imports. The captured bundle explains composition identity and remains generation-local evidence. It does not override the authored task prompt.
285
108
 
286
- Use imports as the default adapter for composed ready recipes. A user-root recipe such as `~/.pi/agent/recipes/repo_context_check.json` can import the maintained source recipe and call `{ "name": "alias" }` instead of duplicating the source recipe's script command. Skill scripts are the strongest version of this rule: when a skill provides `recipes/<name>.json` for its `scripts/*` entrypoint, local tools should delegate to or import the skill recipe instead of invoking the script path directly.
109
+ Recipes that need a minimal child prompt may opt out of injected Recipe context through the documented `actor_context` launch option.
287
110
 
288
- ## Direct Recipe Delegation
111
+ ## Current Policy
289
112
 
290
- A `template` string that resolves to a recipe name or recipe file path delegates to that recipe instead of executing the recipe file as a binary:
113
+ Defaults can inherit current Pi policy:
291
114
 
292
115
  ```json
293
116
  {
294
- "description": "Play music through the packaged player recipe.",
295
- "async": true,
296
- "defaults": { "source": "~/Music", "volume": "70" },
297
- "template": "music-player"
117
+ "defaults": {
118
+ "model": "{current_model}",
119
+ "thinking": "{current_thinking}"
120
+ }
298
121
  }
299
122
  ```
300
123
 
301
- Delegation is a one-to-one handoff for thin wrappers and simple reuse. It uses the same bare-name priority as imports: user-root recipes under `~/.pi/agent/recipes`, then the importing recipe's directory, then packaged standard-library recipes. A higher-priority invalid or disabled recipe still blocks lower-priority fallback so operator overrides fail closed.
124
+ Resolution fails before launch when required current policy is unavailable. The Run persists whether values were inherited or explicit.
302
125
 
303
- Delegated recipes remain the source of truth for their command template, async setting, args/defaults, mailbox, artifacts, and future fixes. Wrapper recipe fields may narrow args/defaults or override lifecycle metadata. Use imports plus `{ "name": "alias" }` when you need rich composition, multiple recipe nodes, import-specific values/defaults, or a pipeline where the reusable recipe is only one step.
126
+ ## Resolution and Shadowing
304
127
 
305
- Async composition stays explicit: importing or delegating to a recipe reuses its command-template-shaped definition. It does not start a nested async run. Put `async: true` on the parent recipe when the combined imported graph should run detached as one run with one state dir; thin delegation may inherit `async: true` from the delegated recipe. Ephemeral coordinator recipes may declare `retire_when: "children_terminal"` as an opt-in lifecycle hint for future graceful retirement handling; persistent services and implementer loops should omit it. For agent-callable fanout, prefer public inputs such as `prompts:array` plus `repeat: "{prompts.length}"`, then select each branch value with `{prompts[index]}` instead of baking concrete prompts or file names into the reusable recipe.
128
+ User Recipes under `~/.pi/agent/recipes` take priority over packaged Recipes. An invalid active file blocks fallback and reports both paths. Disabled Recipes cannot launch. Registry watchers converge after atomic changes without executing partial definitions.
306
129
 
307
- ```json
308
- {
309
- "async": true,
310
- "imports": {
311
- "review": "review-one.json"
312
- },
313
- "parallel": true,
314
- "failure": "branch",
315
- "template": [
316
- { "name": "review", "values": { "scope": "README.md" } },
317
- { "name": "review", "values": { "scope": "docs/template-recipes.md" } }
318
- ]
319
- }
320
- ```
321
-
322
- Recipes can also read imported metadata and value containers before command-template placeholder expansion. Each import alias acts like a recipe-local variable:
130
+ ## Validation
323
131
 
324
- ```json
325
- {
326
- "imports": {
327
- "base": {
328
- "from": "base.json",
329
- "values": { "target": "docs" }
330
- }
331
- },
332
- "defaults": {
333
- "profile": "{base.defaults.profile=safe}",
334
- "target": "{base.values.target}",
335
- "label": "{base.name}:{base.values.target}",
336
- "enabled_label": "{base.defaults.enabled?enabled:disabled}"
337
- },
338
- "template": "run {base.defaults.profile=safe} {base.values.target} {label}"
339
- }
132
+ ```bash
133
+ node scripts/validate-recipe.mjs recipes/example.json --qa
134
+ node scripts/validate-recipe.mjs recipes --all --qa --summary
340
135
  ```
341
136
 
342
- Supported references are:
343
-
344
- - `{alias.name}`
345
- - `{alias.file}`
346
- - `{alias.defaults.key}`
347
- - `{alias.values.key}`
348
- - `{alias.defaults.key=fallback}` for a missing/null import value fallback.
349
- - `{alias.values.key?truthy:falsy}` for a small recipe-layer ternary.
350
-
351
- Nested object keys are dot-separated. Import references are resolved before normal command-template placeholders, so ordinary values such as `{label}` still flow through command-template defaults and call-time values. Ternaries use simple falsy checks for missing, null, false, zero, and empty string. Missing imports, missing values without fallback, and import cycles fail during recipe loading.
352
-
353
- ## Recipe Shape
137
+ Validation checks JSON/Markdown compilation, imports, Control, artifacts, helper paths, and platform notes. Files exceed 1 MiB or import depth 32 fail closed.
354
138
 
355
- Use the filename for file-backed recipe ids, and use `async: true` for detached runs. Use `parallel: true` for fanout, `when` for node guards, and semantic public args such as `tools`, `all`, or `timeout_ms` instead of leaking CLI fragments or reusing node-control names. Local files belong under `~/.pi/agent/recipes/*.json` or `*.md` before relying on recipe launchers.
139
+ ## Related
356
140
 
357
- If a proposed recipe needs a scheduler, queue daemon, `goto`, or custom workflow syntax, stop. Keep the recipe as saved command-template JSON and put policy in the registered tool, script, or caller.
141
+ - [Command templates](./command-templates.md)
142
+ - [Runs](./async-runs.md)
143
+ - [Recipe library](./recipe-library.md)
144
+ - [Tool registry](./tool-registry.md)