@llblab/pi-actors 0.42.2 → 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 (254) hide show
  1. package/AGENTS.md +121 -175
  2. package/CHANGELOG.md +16 -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 +17 -17
  26. package/dist/lib/observability.js +45 -84
  27. package/dist/lib/pi.d.ts +1 -1
  28. package/dist/lib/prompts.d.ts +1 -1
  29. package/dist/lib/prompts.js +2 -2
  30. package/dist/lib/recipe-control.d.ts +7 -0
  31. package/dist/lib/recipe-control.js +39 -0
  32. package/dist/lib/recipes-discovery.js +2 -0
  33. package/dist/lib/recipes-references.d.ts +1 -14
  34. package/dist/lib/recipes-references.js +6 -21
  35. package/dist/lib/review-projection.js +1 -5
  36. package/dist/lib/run-ui-runtime.js +2 -2
  37. package/dist/lib/runs-control-delivery.d.ts +21 -0
  38. package/dist/lib/runs-control-delivery.js +127 -0
  39. package/dist/lib/runs-controls.d.ts +35 -0
  40. package/dist/lib/runs-controls.js +144 -0
  41. package/dist/lib/runs-retention.d.ts +7 -0
  42. package/dist/lib/runs-retention.js +27 -3
  43. package/dist/lib/runs-start.js +4 -2
  44. package/dist/lib/runs-status.js +11 -6
  45. package/dist/lib/runs-trace.d.ts +24 -0
  46. package/dist/lib/runs-trace.js +98 -0
  47. package/dist/lib/runtime-notifier.d.ts +1 -1
  48. package/dist/lib/runtime-notifier.js +1 -1
  49. package/dist/lib/tools-inspect.d.ts +3 -3
  50. package/dist/lib/tools-inspect.js +203 -708
  51. package/dist/lib/tools-local.js +2 -10
  52. package/dist/lib/tools-message.d.ts +7 -7
  53. package/dist/lib/tools-message.js +95 -396
  54. package/dist/lib/tools-response.d.ts +1 -4
  55. package/dist/lib/tools-response.js +5 -39
  56. package/dist/lib/tools-spawn.js +16 -28
  57. package/dist/lib/tools.js +1 -2
  58. package/dist/lib/trace-projection.d.ts +22 -0
  59. package/dist/lib/trace-projection.js +165 -0
  60. package/dist/recipes/draft-review.json +0 -10
  61. package/dist/recipes/lens-swarm.json +0 -14
  62. package/dist/recipes/music-player.json +10 -19
  63. package/dist/recipes/pipeline-architect-coordinator.json +0 -11
  64. package/dist/recipes/pipeline-artifact-bundle.json +1 -22
  65. package/dist/recipes/pipeline-artifact-report.json +1 -18
  66. package/dist/recipes/pipeline-artifact-write.json +1 -18
  67. package/dist/recipes/pipeline-async-run-ops.json +0 -12
  68. package/dist/recipes/pipeline-checkpoint-continuation.json +0 -14
  69. package/dist/recipes/pipeline-development-tasking.json +0 -12
  70. package/dist/recipes/pipeline-docs-maintenance.json +0 -12
  71. package/dist/recipes/pipeline-media-library.json +0 -12
  72. package/dist/recipes/pipeline-quorum-review.json +0 -12
  73. package/dist/recipes/pipeline-release-readiness.json +0 -12
  74. package/dist/recipes/pipeline-release-summary.json +0 -12
  75. package/dist/recipes/pipeline-repo-health.json +0 -12
  76. package/dist/recipes/pipeline-research-synthesis.json +0 -11
  77. package/dist/recipes/pipeline-review-readiness.json +0 -12
  78. package/dist/recipes/resource-locker.json +27 -0
  79. package/dist/recipes/subagent-artifact.json +0 -9
  80. package/dist/recipes/subagent-checkpoint.json +0 -10
  81. package/dist/recipes/subagent-conflict-report.json +0 -11
  82. package/dist/recipes/subagent-contradiction-map.json +0 -11
  83. package/dist/recipes/subagent-critic.json +0 -11
  84. package/dist/recipes/subagent-evidence-map.json +0 -11
  85. package/dist/recipes/subagent-followup.json +0 -10
  86. package/dist/recipes/subagent-judge.json +0 -11
  87. package/dist/recipes/subagent-merge.json +0 -11
  88. package/dist/recipes/subagent-normalize.json +0 -11
  89. package/dist/recipes/subagent-plan.json +0 -11
  90. package/dist/recipes/subagent-preflight.json +0 -11
  91. package/dist/recipes/subagent-prompt.json +0 -10
  92. package/dist/recipes/subagent-quorum.json +0 -10
  93. package/dist/recipes/subagent-review-coordinator.json +0 -14
  94. package/dist/recipes/subagent-review.json +0 -11
  95. package/dist/recipes/subagent-task-card.json +0 -11
  96. package/dist/recipes/subagent-tools.json +0 -10
  97. package/dist/recipes/subagent-verify.json +0 -11
  98. package/dist/recipes/subagents-prompts.json +0 -10
  99. package/dist/recipes/tool-review.json +0 -10
  100. package/dist/scripts/async-runner.mjs +25 -25
  101. package/dist/scripts/conformance.mjs +4 -2
  102. package/dist/scripts/locker.mjs +200 -66
  103. package/dist/scripts/music-player.mjs +159 -150
  104. package/dist/scripts/recipe-utils.mjs +6 -96
  105. package/dist/scripts/release-gates.mjs +60 -0
  106. package/dist/scripts/validate-recipe.mjs +3 -53
  107. package/dist/skills/actors/SKILL.md +53 -266
  108. package/dist/skills/swarm/SKILL.md +11 -33
  109. package/docs/0.43-baseline.md +44 -0
  110. package/docs/README.md +3 -3
  111. package/docs/actor-inspector.md +26 -64
  112. package/docs/actors-deep-reference.md +92 -50
  113. package/docs/async-runs.md +81 -328
  114. package/docs/command-templates.md +2 -2
  115. package/docs/component-recipes.md +30 -133
  116. package/docs/recipe-library.md +57 -182
  117. package/docs/task-first-recipes.md +10 -12
  118. package/docs/template-recipes.md +76 -289
  119. package/docs/tool-registry.md +41 -161
  120. package/fixtures/protocol/control-endpoint.json +6 -0
  121. package/fixtures/protocol/control-record.json +9 -0
  122. package/fixtures/protocol/recipe-summary.json +4 -12
  123. package/fixtures/protocol/trace-event.json +9 -0
  124. package/lib/async-runs.ts +202 -201
  125. package/lib/control.ts +102 -0
  126. package/lib/execution-sessions.ts +111 -0
  127. package/lib/file-state.ts +17 -4
  128. package/lib/inspector-actions.ts +2 -2
  129. package/lib/inspector-command.ts +3 -3
  130. package/lib/inspector-overlay.ts +577 -1121
  131. package/lib/inspector.ts +46 -979
  132. package/lib/limits.ts +4 -2
  133. package/lib/observability.ts +63 -104
  134. package/lib/pi.ts +1 -1
  135. package/lib/prompts.ts +2 -2
  136. package/lib/recipe-control.ts +45 -0
  137. package/lib/recipes-discovery.ts +2 -0
  138. package/lib/recipes-references.ts +9 -45
  139. package/lib/review-projection.ts +1 -5
  140. package/lib/run-ui-runtime.ts +2 -2
  141. package/lib/runs-control-delivery.ts +181 -0
  142. package/lib/runs-controls.ts +204 -0
  143. package/lib/runs-retention.ts +38 -3
  144. package/lib/runs-start.ts +4 -2
  145. package/lib/runs-status.ts +11 -6
  146. package/lib/runs-trace.ts +132 -0
  147. package/lib/runtime-notifier.ts +1 -1
  148. package/lib/tools-inspect.ts +240 -901
  149. package/lib/tools-local.ts +2 -12
  150. package/lib/tools-message.ts +112 -519
  151. package/lib/tools-response.ts +5 -52
  152. package/lib/tools-spawn.ts +16 -32
  153. package/lib/tools.ts +1 -2
  154. package/lib/trace-projection.ts +221 -0
  155. package/package.json +2 -1
  156. package/recipes/draft-review.json +0 -10
  157. package/recipes/lens-swarm.json +0 -14
  158. package/recipes/music-player.json +10 -19
  159. package/recipes/pipeline-architect-coordinator.json +0 -11
  160. package/recipes/pipeline-artifact-bundle.json +1 -22
  161. package/recipes/pipeline-artifact-report.json +1 -18
  162. package/recipes/pipeline-artifact-write.json +1 -18
  163. package/recipes/pipeline-async-run-ops.json +0 -12
  164. package/recipes/pipeline-checkpoint-continuation.json +0 -14
  165. package/recipes/pipeline-development-tasking.json +0 -12
  166. package/recipes/pipeline-docs-maintenance.json +0 -12
  167. package/recipes/pipeline-media-library.json +0 -12
  168. package/recipes/pipeline-quorum-review.json +0 -12
  169. package/recipes/pipeline-release-readiness.json +0 -12
  170. package/recipes/pipeline-release-summary.json +0 -12
  171. package/recipes/pipeline-repo-health.json +0 -12
  172. package/recipes/pipeline-research-synthesis.json +0 -11
  173. package/recipes/pipeline-review-readiness.json +0 -12
  174. package/recipes/resource-locker.json +27 -0
  175. package/recipes/subagent-artifact.json +0 -9
  176. package/recipes/subagent-checkpoint.json +0 -10
  177. package/recipes/subagent-conflict-report.json +0 -11
  178. package/recipes/subagent-contradiction-map.json +0 -11
  179. package/recipes/subagent-critic.json +0 -11
  180. package/recipes/subagent-evidence-map.json +0 -11
  181. package/recipes/subagent-followup.json +0 -10
  182. package/recipes/subagent-judge.json +0 -11
  183. package/recipes/subagent-merge.json +0 -11
  184. package/recipes/subagent-normalize.json +0 -11
  185. package/recipes/subagent-plan.json +0 -11
  186. package/recipes/subagent-preflight.json +0 -11
  187. package/recipes/subagent-prompt.json +0 -10
  188. package/recipes/subagent-quorum.json +0 -10
  189. package/recipes/subagent-review-coordinator.json +0 -14
  190. package/recipes/subagent-review.json +0 -11
  191. package/recipes/subagent-task-card.json +0 -11
  192. package/recipes/subagent-tools.json +0 -10
  193. package/recipes/subagent-verify.json +0 -11
  194. package/recipes/subagents-prompts.json +0 -10
  195. package/recipes/tool-review.json +0 -10
  196. package/scripts/async-runner.mjs +25 -25
  197. package/scripts/conformance.mjs +4 -2
  198. package/scripts/locker.mjs +200 -66
  199. package/scripts/music-player.mjs +159 -150
  200. package/scripts/recipe-utils.mjs +6 -96
  201. package/scripts/release-gates.mjs +60 -0
  202. package/scripts/validate-recipe.mjs +3 -53
  203. package/skills/actors/SKILL.md +53 -266
  204. package/skills/swarm/SKILL.md +11 -33
  205. package/dist/fixtures/protocol/actor-message-branch.json +0 -13
  206. package/dist/fixtures/protocol/mailbox-contract.json +0 -15
  207. package/dist/fixtures/protocol/room-message.json +0 -11
  208. package/dist/fixtures/protocol/room-roster.json +0 -11
  209. package/dist/fixtures/protocol/run-inbox-message.json +0 -9
  210. package/dist/fixtures/protocol/run-outbox-event.json +0 -9
  211. package/dist/lib/mailbox-loop.d.ts +0 -41
  212. package/dist/lib/mailbox-loop.js +0 -60
  213. package/dist/lib/messages.d.ts +0 -25
  214. package/dist/lib/messages.js +0 -122
  215. package/dist/lib/rooms.d.ts +0 -104
  216. package/dist/lib/rooms.js +0 -647
  217. package/dist/lib/runs-mailbox.d.ts +0 -25
  218. package/dist/lib/runs-mailbox.js +0 -146
  219. package/dist/lib/runs-messages.d.ts +0 -15
  220. package/dist/lib/runs-messages.js +0 -179
  221. package/dist/lib/runs-outbox.d.ts +0 -41
  222. package/dist/lib/runs-outbox.js +0 -87
  223. package/dist/lib/tools-mailbox.d.ts +0 -8
  224. package/dist/lib/tools-mailbox.js +0 -48
  225. package/dist/recipes/actor-worker.json +0 -39
  226. package/dist/recipes/coordinator-locker.json +0 -45
  227. package/dist/recipes/locker.json +0 -45
  228. package/dist/recipes/pipeline-room-swarm.json +0 -50
  229. package/dist/recipes/subagent-message.json +0 -32
  230. package/dist/recipes/utility-actor-message.json +0 -23
  231. package/dist/scripts/actor-worker.mjs +0 -214
  232. package/dist/scripts/coordinator.mjs +0 -799
  233. package/docs/actor-messages.md +0 -225
  234. package/fixtures/protocol/actor-message-branch.json +0 -13
  235. package/fixtures/protocol/mailbox-contract.json +0 -15
  236. package/fixtures/protocol/room-message.json +0 -11
  237. package/fixtures/protocol/room-roster.json +0 -11
  238. package/fixtures/protocol/run-inbox-message.json +0 -9
  239. package/fixtures/protocol/run-outbox-event.json +0 -9
  240. package/lib/mailbox-loop.ts +0 -144
  241. package/lib/messages.ts +0 -151
  242. package/lib/rooms.ts +0 -939
  243. package/lib/runs-mailbox.ts +0 -208
  244. package/lib/runs-messages.ts +0 -252
  245. package/lib/runs-outbox.ts +0 -144
  246. package/lib/tools-mailbox.ts +0 -56
  247. package/recipes/actor-worker.json +0 -39
  248. package/recipes/coordinator-locker.json +0 -45
  249. package/recipes/locker.json +0 -45
  250. package/recipes/pipeline-room-swarm.json +0 -50
  251. package/recipes/subagent-message.json +0 -32
  252. package/recipes/utility-actor-message.json +0 -23
  253. package/scripts/actor-worker.mjs +0 -214
  254. 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: {