@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
@@ -26,7 +26,6 @@ function usage() {
26
26
  recipe-utils.mjs changelog-section <file> <version>
27
27
  recipe-utils.mjs artifact-manifest <artifact-path> <title> <status> [summary]
28
28
  recipe-utils.mjs artifact-write <artifact-path> [create|overwrite|append]
29
- recipe-utils.mjs actor-message <type> [to] [from] [summary] [metadata-json] [correlation-id] [reply-to]
30
29
  recipe-utils.mjs package-summary <package-json>
31
30
  recipe-utils.mjs skill-summary <skill-md> [package-json]`);
32
31
  }
@@ -36,41 +35,6 @@ function fail(message) {
36
35
  process.exit(1);
37
36
  }
38
37
 
39
- const ADDRESS_PATTERN = /^[A-Za-z0-9_.-]+$/;
40
- const MESSAGE_TYPE_PATTERN = /^[A-Za-z][A-Za-z0-9_.:-]*$/;
41
- function assertToken(value, label) {
42
- const normalized = String(value ?? "").trim();
43
- if (!normalized) fail(`${label} is required`);
44
- if (!ADDRESS_PATTERN.test(normalized))
45
- fail(`${label} contains unsupported characters: ${value}`);
46
- return normalized;
47
- }
48
-
49
- function validateActorAddress(address, label) {
50
- const value = String(address ?? "").trim();
51
- if (value === "coordinator") return value;
52
- const separator = value.indexOf(":");
53
- if (separator < 0) fail(`${label} must include an actor kind: ${address}`);
54
- const kind = value.slice(0, separator);
55
- const rest = value.slice(separator + 1);
56
- if (kind === "branch") {
57
- const [run, branch, ...extra] = rest.split("/");
58
- if (extra.length > 0)
59
- fail(`${label} branch address has too many parts: ${address}`);
60
- return `branch:${assertToken(run, `${label} branch run`)}/${assertToken(branch, `${label} branch id`)}`;
61
- }
62
- if (["run", "session", "tool"].includes(kind))
63
- return `${kind}:${assertToken(rest, label)}`;
64
- fail(`${label} has unsupported actor kind: ${kind}`);
65
- }
66
-
67
- function validateMessageType(type) {
68
- const value = String(type ?? "").trim();
69
- if (!MESSAGE_TYPE_PATTERN.test(value))
70
- fail(`Invalid actor message type: ${type}`);
71
- return value;
72
- }
73
-
74
38
  function walkFiles(dir, maxDepth = 2, depth = 0, out = []) {
75
39
  if (depth > maxDepth || !existsSync(dir)) return out;
76
40
  for (const entry of readdirSync(dir)) {
@@ -172,7 +136,7 @@ function runOpsSnapshot(
172
136
  rootValue.replace(/^~(?=\/|$)/, process.env.HOME ?? "~"),
173
137
  );
174
138
  const inspectedRun = String(runIdValue || "music");
175
- const messageFile = join(root, inspectedRun, "outbox.jsonl");
139
+ const traceFile = join(root, inspectedRun, "trace.jsonl");
176
140
  const staleMs = Number(staleMinutesValue) * 60 * 1000;
177
141
  const now = Date.now();
178
142
  const recommendations = runs.flatMap((run) => {
@@ -186,10 +150,9 @@ function runOpsSnapshot(
186
150
  {
187
151
  run: run.run,
188
152
  reason: "running-stale",
189
- suggested_message: {
190
- to: `run:${run.run}`,
191
- type: "control.stop",
192
- body: "stop",
153
+ suggested_inspect: {
154
+ target: `run:${run.run}`,
155
+ view: "control",
193
156
  },
194
157
  },
195
158
  ];
@@ -199,7 +162,7 @@ function runOpsSnapshot(
199
162
  {
200
163
  run: run.run,
201
164
  reason: `terminal-${run.status}`,
202
- suggested_inspect: { target: `run:${run.run}`, view: "tail" },
165
+ suggested_inspect: { target: `run:${run.run}`, view: "trace" },
203
166
  },
204
167
  ];
205
168
  }
@@ -210,7 +173,7 @@ function runOpsSnapshot(
210
173
  {
211
174
  runs,
212
175
  inspectedRun,
213
- messages: tailJsonl(messageFile, linesValue),
176
+ trace: tailJsonl(traceFile, linesValue),
214
177
  recommendations,
215
178
  },
216
179
  null,
@@ -291,57 +254,6 @@ function artifactWrite(pathValue, mode = "create") {
291
254
  );
292
255
  }
293
256
 
294
- function actorMessage(
295
- type = "event",
296
- to = "coordinator",
297
- from = "run:{run_id}",
298
- summary = "",
299
- metadataValue = "",
300
- correlationId = "",
301
- replyTo = "",
302
- ) {
303
- const messageType = validateMessageType(type);
304
- const messageTo = validateActorAddress(to, "message.to");
305
- const messageFrom = validateActorAddress(from, "message.from");
306
- let metadata = {};
307
- if (metadataValue) {
308
- try {
309
- const parsed = JSON.parse(metadataValue);
310
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
311
- metadata = parsed;
312
- else fail("Actor message metadata must be a JSON object");
313
- } catch (error) {
314
- fail(`Invalid actor message metadata JSON: ${error.message}`);
315
- }
316
- }
317
- const bodyText = readFileSync(0, "utf8");
318
- const trimmed = bodyText.trim();
319
- let body = bodyText;
320
- if (trimmed) {
321
- try {
322
- body = JSON.parse(trimmed);
323
- } catch {
324
- body = bodyText;
325
- }
326
- }
327
- console.log(
328
- JSON.stringify(
329
- {
330
- to: messageTo,
331
- from: messageFrom,
332
- type: messageType,
333
- summary: summary || messageType,
334
- body,
335
- ...(correlationId ? { correlation_id: correlationId } : {}),
336
- ...(replyTo ? { reply_to: replyTo } : {}),
337
- metadata,
338
- },
339
- null,
340
- 2,
341
- ),
342
- );
343
- }
344
-
345
257
  function packageSummary(fileValue = "package.json") {
346
258
  const file = resolve(
347
259
  fileValue.replace(/^~(?=\/|$)/, process.env.HOME ?? "~"),
@@ -475,8 +387,6 @@ else if (command === "artifact-manifest")
475
387
  artifactManifest(args[0] ?? "artifact.md", args[1], args[2], args[3]);
476
388
  else if (command === "artifact-write")
477
389
  artifactWrite(args[0] ?? "artifact.md", args[1] ?? "create");
478
- else if (command === "actor-message")
479
- actorMessage(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
480
390
  else if (command === "package-summary")
481
391
  packageSummary(args[0] ?? "package.json");
482
392
  else if (command === "skill-summary")
@@ -93,6 +93,66 @@ try {
93
93
  }
94
94
  console.log("[release] bounded secret and public-path hygiene checked");
95
95
 
96
+ const removedPaths = [
97
+ "lib/messages.ts",
98
+ "lib/rooms.ts",
99
+ "lib/mailbox-loop.ts",
100
+ "lib/runs-mailbox.ts",
101
+ "lib/runs-messages.ts",
102
+ "lib/runs-outbox.ts",
103
+ "lib/tools-mailbox.ts",
104
+ "scripts/actor-worker.mjs",
105
+ "scripts/coordinator.mjs",
106
+ "recipes/actor-worker.json",
107
+ "recipes/pipeline-room-swarm.json",
108
+ "recipes/subagent-message.json",
109
+ "recipes/utility-actor-message.json",
110
+ "docs/actor-messages.md",
111
+ "docs/run-inspector.md",
112
+ "lib/run-inspector.ts",
113
+ "lib/run-inspector-overlay.ts",
114
+ ];
115
+ for (const path of removedPaths) check(!fileSet.has(path), `removed surface returned: ${path}`);
116
+
117
+ const currentSurface = /^(?:lib\/|scripts\/|recipes\/|fixtures\/|skills\/|docs\/|README\.md|AGENTS\.md)/u;
118
+ const forbiddenPatterns = [
119
+ [/room:</u, "room address"],
120
+ [/branch:</u, "branch address"],
121
+ [/communication\.json/u, "communication snapshot"],
122
+ [/\bActor(?:Address|Message)\b/u, "legacy actor type"],
123
+ [/\b(?:actor_address|default_room)\b/u, "legacy spawn placeholder"],
124
+ [/inbox\.jsonl/u, "legacy inbox state"],
125
+ ];
126
+ for (const path of files.filter((candidate) => currentSurface.test(candidate))) {
127
+ if (path === "BACKLOG.md" || path === "CHANGELOG.md" || path === "scripts/release-gates.mjs") continue;
128
+ const text = stagedText(path) ?? "";
129
+ for (const [pattern, label] of forbiddenPatterns) {
130
+ check(!pattern.test(text), `${label} in current surface: ${path}`);
131
+ }
132
+ }
133
+ const legacyFallbacks = new Map([
134
+ ["lib/observability.ts", "outbox.jsonl"],
135
+ ["lib/runs-status.ts", "events.jsonl"],
136
+ ["lib/runs-start.ts", "events.jsonl"],
137
+ ]);
138
+ for (const path of files.filter((candidate) => currentSurface.test(candidate))) {
139
+ if (path === "BACKLOG.md" || path === "CHANGELOG.md" || path === "scripts/release-gates.mjs") continue;
140
+ const text = stagedText(path) ?? "";
141
+ for (const term of ["outbox.jsonl", "events.jsonl"]) {
142
+ if (!text.includes(term)) continue;
143
+ check(legacyFallbacks.get(path) === term, `legacy state reference outside read-only fallback: ${path} (${term})`);
144
+ }
145
+ }
146
+ console.log("[release] removed-surface and legacy-fallback allowlists checked");
147
+
148
+ const baselineShippedLines = 35_077;
149
+ const shippedPath = /^(?:lib\/|scripts\/|recipes\/|docs\/|skills\/)/u;
150
+ const shippedLines = files
151
+ .filter((path) => shippedPath.test(path))
152
+ .reduce((total, path) => total + (((stagedText(path) ?? "").match(/\n/gu) ?? []).length + 1), 0);
153
+ check(shippedLines < baselineShippedLines, `shipped lines ${shippedLines} are not below baseline ${baselineShippedLines}`);
154
+ console.log(`[release] shipped lines ${shippedLines} < frozen baseline ${baselineShippedLines}`);
155
+
96
156
  const sources = files.filter((path) => path === "index.ts" || (path.startsWith("lib/") && path.endsWith(".ts")));
97
157
  const sourceSet = new Set(sources);
98
158
  const graph = new Map();
@@ -63,13 +63,6 @@ function recipeFiles(target, all) {
63
63
  .map((file) => resolve(target, file));
64
64
  }
65
65
 
66
- function mailboxType(value) {
67
- if (typeof value === "string") return value;
68
- if (value && typeof value === "object" && typeof value.type === "string")
69
- return value.type;
70
- return undefined;
71
- }
72
-
73
66
  function collectTemplateStrings(value, out = []) {
74
67
  if (typeof value === "string") out.push(value);
75
68
  else if (Array.isArray(value)) value.forEach((item) => collectTemplateStrings(item, out));
@@ -124,46 +117,13 @@ function validateHelperPaths(file, config) {
124
117
  return diagnostics;
125
118
  }
126
119
 
127
- function validateMailboxContract(file, config) {
128
- const diagnostics = [];
129
- const mailbox = config.mailbox;
130
- const accepts = Array.isArray(mailbox?.accepts) ? mailbox.accepts : [];
131
- const emits = Array.isArray(mailbox?.emits) ? mailbox.emits : [];
132
- if (config.async === true && !mailbox)
133
- diagnostics.push("mailbox: async recipes must declare mailbox metadata");
134
- if (config.async === true && !accepts.map(mailboxType).includes("control.kill"))
135
- diagnostics.push("mailbox.accepts: async recipes must include control.kill");
136
- const allowedLegacyTypes = new Set(["awaiting_assignment"]);
137
- for (const [key, entries] of Object.entries({ accepts, emits })) {
138
- entries.forEach((entry, index) => {
139
- const type = mailboxType(entry);
140
- if (!type) diagnostics.push(`mailbox.${key}[${index}]: must be a string or object with type`);
141
- else if (
142
- !allowedLegacyTypes.has(type) &&
143
- !/^[a-z][a-z0-9_-]*\.(?:[a-z][a-z0-9_-]*|\*)$/.test(type)
144
- )
145
- diagnostics.push(`mailbox.${key}[${index}]: message type must use channel.action form`);
146
- });
147
- }
148
- const allowedDomainTermination = new Set([
149
- "coordinator-locker.json",
150
- "locker.json",
151
- "music-player.json",
152
- ]);
153
- const hasDomainTermination = accepts
154
- .map(mailboxType)
155
- .some((type) => type === "control.stop" || type === "control.cancel");
156
- if (hasDomainTermination && !allowedDomainTermination.has(file.split(/[\\/]/).pop()))
157
- diagnostics.push("mailbox.accepts: control.stop/control.cancel are reserved for actor-domain handlers");
158
- return diagnostics;
159
- }
160
-
161
120
  function qaDiagnostics(file, config) {
162
121
  const diagnostics = [];
163
122
  const warnings = [];
164
123
  if (typeof config.description !== "string" || !config.description.trim())
165
124
  warnings.push("description: missing or empty");
166
- diagnostics.push(...validateMailboxContract(file, config));
125
+ if (config.mailbox !== undefined)
126
+ diagnostics.push("recipe.mailbox was removed; use control actions and Trace events");
167
127
  diagnostics.push(...validateArtifactDeclarations(config));
168
128
  diagnostics.push(...validateHelperPaths(file, config));
169
129
  const platformSpecificTemplate = collectTemplateStrings(config.template).some(
@@ -201,17 +161,7 @@ function validateFile(file, qa = false) {
201
161
  config.imports && typeof config.imports === "object"
202
162
  ? Object.keys(config.imports).sort()
203
163
  : [],
204
- mailbox:
205
- config.mailbox && typeof config.mailbox === "object"
206
- ? {
207
- accepts: Array.isArray(config.mailbox.accepts)
208
- ? config.mailbox.accepts
209
- : [],
210
- emits: Array.isArray(config.mailbox.emits)
211
- ? config.mailbox.emits
212
- : [],
213
- }
214
- : undefined,
164
+ control: Array.isArray(config.control) ? config.control : undefined,
215
165
  ...(qa
216
166
  ? {
217
167
  qa: {