@llblab/pi-actors 0.25.0 → 0.26.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 (91) hide show
  1. package/BACKLOG.md +4 -8
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +1 -1
  4. package/dist/lib/actor-worker.d.ts +3 -0
  5. package/dist/lib/actor-worker.js +54 -6
  6. package/dist/lib/coordinator.js +31 -4
  7. package/dist/recipes/actor-worker.json +10 -6
  8. package/dist/recipes/lens-swarm.json +0 -2
  9. package/dist/recipes/pipeline-architect-coordinator.json +0 -2
  10. package/dist/recipes/pipeline-artifact-bundle.json +0 -2
  11. package/dist/recipes/pipeline-artifact-report.json +0 -2
  12. package/dist/recipes/pipeline-artifact-write.json +0 -2
  13. package/dist/recipes/pipeline-async-run-ops.json +0 -2
  14. package/dist/recipes/pipeline-checkpoint-continuation.json +0 -2
  15. package/dist/recipes/pipeline-development-tasking.json +0 -2
  16. package/dist/recipes/pipeline-docs-maintenance.json +0 -2
  17. package/dist/recipes/pipeline-media-library.json +0 -2
  18. package/dist/recipes/pipeline-quorum-review.json +0 -2
  19. package/dist/recipes/pipeline-release-readiness.json +0 -2
  20. package/dist/recipes/pipeline-release-summary.json +0 -2
  21. package/dist/recipes/pipeline-repo-health.json +0 -2
  22. package/dist/recipes/pipeline-research-synthesis.json +0 -2
  23. package/dist/recipes/pipeline-review-readiness.json +0 -2
  24. package/dist/recipes/pipeline-room-swarm.json +0 -2
  25. package/dist/recipes/subagent-artifact.json +0 -2
  26. package/dist/recipes/subagent-checkpoint.json +0 -2
  27. package/dist/recipes/subagent-conflict-report.json +0 -2
  28. package/dist/recipes/subagent-contradiction-map.json +0 -2
  29. package/dist/recipes/subagent-critic.json +0 -2
  30. package/dist/recipes/subagent-evidence-map.json +0 -2
  31. package/dist/recipes/subagent-followup.json +0 -2
  32. package/dist/recipes/subagent-judge.json +0 -2
  33. package/dist/recipes/subagent-merge.json +0 -2
  34. package/dist/recipes/subagent-message.json +0 -2
  35. package/dist/recipes/subagent-normalize.json +0 -2
  36. package/dist/recipes/subagent-plan.json +0 -2
  37. package/dist/recipes/subagent-prompt.json +0 -2
  38. package/dist/recipes/subagent-quorum.json +0 -2
  39. package/dist/recipes/subagent-review-coordinator.json +0 -2
  40. package/dist/recipes/subagent-review.json +0 -2
  41. package/dist/recipes/subagent-task-card.json +0 -2
  42. package/dist/recipes/subagent-tools.json +0 -2
  43. package/dist/recipes/subagent-verify.json +0 -2
  44. package/dist/recipes/subagents-prompts.json +0 -2
  45. package/dist/skills/actors/SKILL.md +2 -2
  46. package/dist/skills/swarm/SKILL.md +1 -1
  47. package/docs/actor-messages.md +1 -1
  48. package/docs/template-recipes.md +2 -2
  49. package/lib/actor-worker.ts +62 -6
  50. package/lib/coordinator.ts +33 -4
  51. package/package.json +1 -1
  52. package/recipes/actor-worker.json +10 -6
  53. package/recipes/lens-swarm.json +0 -2
  54. package/recipes/pipeline-architect-coordinator.json +0 -2
  55. package/recipes/pipeline-artifact-bundle.json +0 -2
  56. package/recipes/pipeline-artifact-report.json +0 -2
  57. package/recipes/pipeline-artifact-write.json +0 -2
  58. package/recipes/pipeline-async-run-ops.json +0 -2
  59. package/recipes/pipeline-checkpoint-continuation.json +0 -2
  60. package/recipes/pipeline-development-tasking.json +0 -2
  61. package/recipes/pipeline-docs-maintenance.json +0 -2
  62. package/recipes/pipeline-media-library.json +0 -2
  63. package/recipes/pipeline-quorum-review.json +0 -2
  64. package/recipes/pipeline-release-readiness.json +0 -2
  65. package/recipes/pipeline-release-summary.json +0 -2
  66. package/recipes/pipeline-repo-health.json +0 -2
  67. package/recipes/pipeline-research-synthesis.json +0 -2
  68. package/recipes/pipeline-review-readiness.json +0 -2
  69. package/recipes/pipeline-room-swarm.json +0 -2
  70. package/recipes/subagent-artifact.json +0 -2
  71. package/recipes/subagent-checkpoint.json +0 -2
  72. package/recipes/subagent-conflict-report.json +0 -2
  73. package/recipes/subagent-contradiction-map.json +0 -2
  74. package/recipes/subagent-critic.json +0 -2
  75. package/recipes/subagent-evidence-map.json +0 -2
  76. package/recipes/subagent-followup.json +0 -2
  77. package/recipes/subagent-judge.json +0 -2
  78. package/recipes/subagent-merge.json +0 -2
  79. package/recipes/subagent-message.json +0 -2
  80. package/recipes/subagent-normalize.json +0 -2
  81. package/recipes/subagent-plan.json +0 -2
  82. package/recipes/subagent-prompt.json +0 -2
  83. package/recipes/subagent-quorum.json +0 -2
  84. package/recipes/subagent-review-coordinator.json +0 -2
  85. package/recipes/subagent-review.json +0 -2
  86. package/recipes/subagent-task-card.json +0 -2
  87. package/recipes/subagent-tools.json +0 -2
  88. package/recipes/subagent-verify.json +0 -2
  89. package/recipes/subagents-prompts.json +0 -2
  90. package/skills/actors/SKILL.md +2 -2
  91. package/skills/swarm/SKILL.md +1 -1
@@ -20,8 +20,6 @@
20
20
  },
21
21
  "mailbox": {
22
22
  "accepts": [
23
- "control.stop",
24
- "control.cancel",
25
23
  "control.kill"
26
24
  ],
27
25
  "emits": [
@@ -13,8 +13,6 @@
13
13
  },
14
14
  "mailbox": {
15
15
  "accepts": [
16
- "control.stop",
17
- "control.cancel",
18
16
  "control.kill"
19
17
  ],
20
18
  "emits": [
@@ -19,8 +19,6 @@
19
19
  },
20
20
  "mailbox": {
21
21
  "accepts": [
22
- "control.stop",
23
- "control.cancel",
24
22
  "control.kill"
25
23
  ],
26
24
  "emits": [
@@ -25,8 +25,6 @@
25
25
  },
26
26
  "mailbox": {
27
27
  "accepts": [
28
- "control.stop",
29
- "control.cancel",
30
28
  "control.kill"
31
29
  ],
32
30
  "emits": [
@@ -2,7 +2,7 @@
2
2
  name: actors
3
3
  description: Highest-density practical guide for pi-actors. Read this skill whenever prompt and tools are not enough for spawn, message, inspect, actor runs, tools, recipes, command templates, async lifecycle, mailboxes, artifacts, and local orchestration mechanics.
4
4
  metadata:
5
- version: 0.25.0
5
+ version: 0.26.1
6
6
  ---
7
7
 
8
8
  # Actors (pi-actors)
@@ -277,7 +277,7 @@ Use packaged recipes by name with `spawn file=<name>` for async actors, or regis
277
277
  - [`locker`](../../recipes/locker.json): modular queue + acquire/renew/release lease locks + journaled locker messages + platform-adapted control metadata.
278
278
  - [`utility-coordinator-lock-snapshot`](../../recipes/utility-coordinator-lock-snapshot.json): one-shot JSON snapshot of a coordinator-locker state directory.
279
279
  - [`music-player`](../../recipes/music-player.json): background local/URL/directory/playlist playback actor controlled by messages.
280
- - [`actor-worker`](../../recipes/actor-worker.json): canonical mailbox-backed branch worker demo that claims branch inbox work, emits room-visible task lifecycle messages, and stops on standard control messages.
280
+ - [`actor-worker`](../../recipes/actor-worker.json): canonical mailbox-backed branch worker reference that claims branch inbox work, emits room-visible task lifecycle messages, writes compact `worker-status.json`, optionally writes per-task result artifacts under `worker-artifacts/`, surfaces stale-claim counts when `stale_claim_ms` is set, and terminates on `control.kill`.
281
281
 
282
282
  ### Subagent Atoms
283
283
 
@@ -2,7 +2,7 @@
2
2
  name: swarm
3
3
  description: Subagent orchestration with scoped locks and quorum consensus. Use for multi-model review, parallel scoped work, delegated audit, and coordinated subagent execution.
4
4
  metadata:
5
- version: 0.25.0
5
+ version: 0.26.1
6
6
  ---
7
7
 
8
8
  # Swarm
@@ -164,7 +164,7 @@ Recipes can declare their conversational surface:
164
164
  "control.continue",
165
165
  "control.revise",
166
166
  "control.approve",
167
- "control.stop"
167
+ "control.kill"
168
168
  ],
169
169
  "emits": ["checkpoint.needs_scope", "branch.done", "run.done"]
170
170
  }
@@ -80,7 +80,7 @@ defaults:
80
80
  scope: docs
81
81
  mailbox:
82
82
  accepts:
83
- - control.stop
83
+ - control.kill
84
84
  ---
85
85
 
86
86
  Human notes can explain intent, examples, or review guidance.
@@ -155,7 +155,7 @@ Use recipe-level `mailbox` to document the semantic messages a recipe actor acce
155
155
  "control.continue",
156
156
  "control.revise",
157
157
  "control.approve",
158
- "control.stop"
158
+ "control.kill"
159
159
  ],
160
160
  "emits": ["checkpoint.needs_scope", "branch.done", "run.done"]
161
161
  }
@@ -3,17 +3,20 @@
3
3
  * Zones: worker demo, mailbox loop recipe runtime
4
4
  */
5
5
 
6
- import { appendFileSync } from "node:fs";
6
+ import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
7
7
  import { join } from "node:path";
8
8
 
9
- import { appendRoomMessage, ensureRoomMember } from "./actor-rooms.ts";
9
+ import { appendRoomMessage, ensureRoomMember, readBranchInboxMessages } from "./actor-rooms.ts";
10
10
  import { handleMailboxLoopOnce, isMailboxLoopStopMessage } from "./mailbox-loop.ts";
11
11
 
12
12
  interface ActorWorkerArgs {
13
+ artifact_dir?: string;
13
14
  branch?: string;
14
15
  poll_ms?: string | number;
15
16
  run?: string;
17
+ stale_claim_ms?: string | number;
16
18
  state_dir?: string;
19
+ write_artifacts?: string | boolean;
17
20
  }
18
21
 
19
22
  export function parseActorWorkerArgs(argv: string[]): ActorWorkerArgs {
@@ -41,12 +44,23 @@ function text(value: unknown): string {
41
44
  return typeof value === "string" ? value : JSON.stringify(value);
42
45
  }
43
46
 
47
+ function enabled(value: unknown): boolean {
48
+ return value !== false && value !== "false" && value !== "0";
49
+ }
50
+
51
+ function safeName(value: unknown): string {
52
+ return String(value ?? "unknown").replaceAll(/[^A-Za-z0-9_.-]+/g, "_");
53
+ }
54
+
44
55
  export async function runActorWorker(argv = process.argv.slice(2)): Promise<void> {
45
56
  const args = parseActorWorkerArgs(argv);
46
57
  const stateDir = String(args.state_dir ?? "");
47
58
  const run = String(args.run ?? "");
48
59
  const branch = String(args.branch ?? "worker");
49
60
  const pollMs = Math.max(50, Number(args.poll_ms ?? 1000));
61
+ const staleClaimMs = Math.max(0, Number(args.stale_claim_ms ?? 0));
62
+ const artifactDir = String(args.artifact_dir ?? join(stateDir, "worker-artifacts"));
63
+ const writeArtifacts = enabled(args.write_artifacts ?? true);
50
64
 
51
65
  if (!stateDir || !run) {
52
66
  throw new Error("usage: actor-worker.mjs --state-dir <dir> --run <id> [--branch worker] [--poll-ms 1000]");
@@ -55,6 +69,8 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
55
69
  const branchAddress = `branch:${run}/${branch}`;
56
70
  const roomAddress = `room:${run}`;
57
71
  const journalPath = join(stateDir, "worker-events.jsonl");
72
+ const statusPath = join(stateDir, "worker-status.json");
73
+ if (writeArtifacts) mkdirSync(artifactDir, { recursive: true });
58
74
 
59
75
  function journal(event: string, data: Record<string, unknown> = {}): void {
60
76
  appendFileSync(
@@ -63,6 +79,30 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
63
79
  );
64
80
  }
65
81
 
82
+ function staleClaims(): number {
83
+ if (staleClaimMs <= 0) return 0;
84
+ const cutoff = Date.now() - staleClaimMs;
85
+ return readBranchInboxMessages(stateDir, run, branchAddress).filter((record) => {
86
+ if (record.status !== "claimed" || !record.claimed_at) return false;
87
+ const claimedAt = Date.parse(record.claimed_at);
88
+ return Number.isFinite(claimedAt) && claimedAt < cutoff;
89
+ }).length;
90
+ }
91
+
92
+ function status(state: string, data: Record<string, unknown> = {}): void {
93
+ writeFileSync(
94
+ statusPath,
95
+ `${JSON.stringify({ artifact_dir: artifactDir, branch, run, stale_claims: staleClaims(), state, ts: new Date().toISOString(), ...data }, null, 2)}\n`,
96
+ );
97
+ }
98
+
99
+ function writeResultArtifact(id: unknown, result: string): string | undefined {
100
+ if (!writeArtifacts) return undefined;
101
+ const path = join(artifactDir, `${safeName(id)}.txt`);
102
+ writeFileSync(path, `${result}\n`);
103
+ return path;
104
+ }
105
+
66
106
  function room(type: string, summary: string, body: Record<string, unknown> = {}): void {
67
107
  appendRoomMessage(stateDir, "main", {
68
108
  body,
@@ -82,7 +122,10 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
82
122
  `${branch} joined as mailbox worker`,
83
123
  );
84
124
  room("awaiting_assignment", `${branch} awaiting assignment`, { branch });
85
- journal("worker.started", { branch, run });
125
+ journal("worker.started", { artifact_dir: artifactDir, branch, run, stale_claim_ms: staleClaimMs });
126
+ status("awaiting_assignment", { handled: 0, stale_claim_ms: staleClaimMs });
127
+
128
+ let handled = 0;
86
129
 
87
130
  let stopping = false;
88
131
  while (!stopping) {
@@ -93,6 +136,7 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
93
136
  stopping = true;
94
137
  room("actor.leave", `${branch} stopping`, { branch, reason: message.type });
95
138
  journal("worker.stopping", { id: message.id, type: message.type });
139
+ status("stopping", { handled, reason: message.type });
96
140
  return;
97
141
  }
98
142
  room("task.claim", `${branch} claimed ${message.type}`, {
@@ -100,19 +144,31 @@ export async function runActorWorker(argv = process.argv.slice(2)): Promise<void
100
144
  id: message.id,
101
145
  type: message.type,
102
146
  });
147
+ const result = text(message.body);
148
+ const artifact = writeResultArtifact(message.id, result);
149
+ handled += 1;
103
150
  room("task.result", `${branch} handled ${message.type}`, {
151
+ artifact,
104
152
  branch,
105
153
  id: message.id,
106
- result: text(message.body),
154
+ result,
107
155
  type: message.type,
108
156
  });
109
157
  room("awaiting_assignment", `${branch} awaiting assignment`, { branch });
110
- journal("task.handled", { id: message.id, type: message.type });
158
+ journal("task.handled", { artifact, id: message.id, type: message.type });
159
+ status("awaiting_assignment", {
160
+ handled,
161
+ last_artifact: artifact,
162
+ last_id: message.id,
163
+ last_type: message.type,
164
+ stale_claim_ms: staleClaimMs,
165
+ });
111
166
  },
112
167
  { owner: branchAddress },
113
168
  );
114
169
  if (!result.handled) await sleep(pollMs);
115
170
  }
116
171
 
117
- journal("worker.done", { branch, run });
172
+ journal("worker.done", { branch, handled, run });
173
+ status("done", { handled });
118
174
  }
@@ -285,7 +285,7 @@ async function readRoomTranscript(config) {
285
285
  }
286
286
 
287
287
  async function synthesize(config, locker) {
288
- if (!config.artifactPath) return;
288
+ if (!config.artifactPath) return { code: 0, empty: false };
289
289
  if (locker) {
290
290
  await writeLockerMessage(locker, {
291
291
  type: "lock.claim",
@@ -295,11 +295,15 @@ async function synthesize(config, locker) {
295
295
  const transcript = await readRoomTranscript(config);
296
296
  const prompt = `Synthesize this transcript into a concise Markdown artifact. Mission: ${config.mission}. Include: Title, Consensus, Roles, Protocol, Final Artifact Shape, Next Actions, Open Questions. Use only the transcript evidence below.\n\nTRANSCRIPT:\n${transcript.slice(-24000)}`;
297
297
  const result = await runPi(prompt, config.model, config.thinking);
298
+ const output = result.stdout.trim();
299
+ const diagnostics = config.stats
300
+ ? `\n\n## Diagnostics\n\nparticipant_attempts=${config.stats.participantAttempts}\nparticipant_success=${config.stats.participantSuccess}\nparticipant_failures=${config.stats.participantFailures}\nsynthesis_code=${result.code}\ntranscript_messages=${transcript.trim() ? transcript.split("\n").length : 0}\n`
301
+ : "";
298
302
  await writeFile(
299
303
  config.artifactPath,
300
- result.stdout.trim()
304
+ output
301
305
  ? result.stdout
302
- : "# Synthesis Artifact\n\nNo synthesis output.\n",
306
+ : `# Synthesis Artifact\n\nNo synthesis output.${diagnostics}\n`,
303
307
  "utf8",
304
308
  );
305
309
  if (locker) {
@@ -314,6 +318,7 @@ async function synthesize(config, locker) {
314
318
  });
315
319
  }
316
320
  process.stdout.write(`artifact=${config.artifactPath}\n`);
321
+ return { code: result.code, empty: !output };
317
322
  }
318
323
 
319
324
  async function readInboxLines(inboxPath) {
@@ -432,11 +437,17 @@ async function participantRound(role, round, config) {
432
437
  const address = `branch:${config.runId}/${role.name}`;
433
438
  const prompt = `You are ${displayName} (${address}), ${role.persona}. Mission: ${config.mission}. Round ${round}/${config.rounds}. First call inspect target=${config.room} view=previews lines=30 and inspect target=${config.room} view=contacts. Then call message once to ${config.room} from ${address} type=chat.message. Body: 2-4 sentences that react to a named participant, propose the next coordination step, and refine the shared artifact. Use contacts for peer names and addresses. End stdout with summary <=160 chars.`;
434
439
  const result = await executeParticipantPrompt(role, prompt, config);
440
+ if (config.stats) {
441
+ config.stats.participantAttempts += 1;
442
+ if (result.code === 0) config.stats.participantSuccess += 1;
443
+ else config.stats.participantFailures += 1;
444
+ }
435
445
  process.stdout.write(
436
446
  `[${role.name} round ${round}] code=${result.code}\n${result.stdout}\n`,
437
447
  );
438
448
  if (result.stderr.trim())
439
449
  process.stderr.write(`[${role.name} round ${round}] ${result.stderr}\n`);
450
+ return result;
440
451
  }
441
452
 
442
453
  async function participantJoin(role, config) {
@@ -635,6 +646,11 @@ const config = {
635
646
  artifactPath: arg("artifact-path", ""),
636
647
  locker: boolArg("locker", false),
637
648
  lockerLeaseMs: numberArg("locker-lease-ms", 600000),
649
+ stats: {
650
+ participantAttempts: 0,
651
+ participantSuccess: 0,
652
+ participantFailures: 0,
653
+ },
638
654
  };
639
655
 
640
656
  if (!config.model) {
@@ -650,7 +666,20 @@ try {
650
666
  const runMode = coordinatorModes[config.mode];
651
667
  if (!runMode) throw new Error(`Unknown coordinator mode: ${config.mode}`);
652
668
  await runMode(config, locker);
653
- await synthesize(config, locker);
669
+ const synthesis = await synthesize(config, locker);
670
+ if (config.stats.participantAttempts > 0 && config.stats.participantSuccess === 0) {
671
+ failures.push(
672
+ `All participant rounds failed: attempts=${config.stats.participantAttempts}`,
673
+ );
674
+ }
675
+ if (synthesis?.empty && config.stats.participantFailures > 0) {
676
+ failures.push(
677
+ `Synthesis output was empty after participant failures: failures=${config.stats.participantFailures}`,
678
+ );
679
+ }
680
+ if (synthesis && synthesis.code !== 0) {
681
+ failures.push(`Synthesis command failed: code=${synthesis.code}`);
682
+ }
654
683
  } catch (globalError) {
655
684
  failures.push(`Global coordinator error: ${globalError.message}`);
656
685
  } finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llblab/pi-actors",
3
- "version": "0.25.0",
3
+ "version": "0.26.1",
4
4
  "private": false,
5
5
  "description": "Local Actor Kernel for Pi",
6
6
  "keywords": [
@@ -4,18 +4,20 @@
4
4
  "args": [
5
5
  "repo:path",
6
6
  "branch:string",
7
- "poll_ms:int"
7
+ "poll_ms:int",
8
+ "stale_claim_ms:int",
9
+ "write_artifacts:bool"
8
10
  ],
9
11
  "defaults": {
10
12
  "repo": "~/.pi/agent/extensions/pi-actors",
11
13
  "branch": "worker",
12
- "poll_ms": "1000"
14
+ "poll_ms": "1000",
15
+ "stale_claim_ms": "0",
16
+ "write_artifacts": "true"
13
17
  },
14
18
  "mailbox": {
15
19
  "accepts": [
16
20
  "task.assign",
17
- "control.stop",
18
- "control.cancel",
19
21
  "control.kill"
20
22
  ],
21
23
  "emits": [
@@ -29,7 +31,9 @@
29
31
  ]
30
32
  },
31
33
  "artifacts": {
32
- "journal": "{state_dir}/worker-events.jsonl"
34
+ "journal": "{state_dir}/worker-events.jsonl",
35
+ "status": "{state_dir}/worker-status.json",
36
+ "results": "{state_dir}/worker-artifacts"
33
37
  },
34
- "template": "{repo}/scripts/actor-worker.mjs --state-dir {state_dir} --run {run_id} --branch {branch} --poll-ms {poll_ms}"
38
+ "template": "{repo}/scripts/actor-worker.mjs --state-dir {state_dir} --run {run_id} --branch {branch} --poll-ms {poll_ms} --stale-claim-ms {stale_claim_ms} --write-artifacts {write_artifacts}"
35
39
  }
@@ -30,8 +30,6 @@
30
30
  },
31
31
  "mailbox": {
32
32
  "accepts": [
33
- "control.stop",
34
- "control.cancel",
35
33
  "control.kill"
36
34
  ],
37
35
  "emits": [
@@ -26,8 +26,6 @@
26
26
  },
27
27
  "mailbox": {
28
28
  "accepts": [
29
- "control.stop",
30
- "control.cancel",
31
29
  "control.kill"
32
30
  ],
33
31
  "emits": [
@@ -35,8 +35,6 @@
35
35
  },
36
36
  "mailbox": {
37
37
  "accepts": [
38
- "control.stop",
39
- "control.cancel",
40
38
  "control.kill"
41
39
  ],
42
40
  "emits": [
@@ -18,8 +18,6 @@
18
18
  },
19
19
  "mailbox": {
20
20
  "accepts": [
21
- "control.stop",
22
- "control.cancel",
23
21
  "control.kill"
24
22
  ],
25
23
  "emits": [
@@ -21,8 +21,6 @@
21
21
  },
22
22
  "mailbox": {
23
23
  "accepts": [
24
- "control.stop",
25
- "control.cancel",
26
24
  "control.kill"
27
25
  ],
28
26
  "emits": [
@@ -24,8 +24,6 @@
24
24
  },
25
25
  "mailbox": {
26
26
  "accepts": [
27
- "control.stop",
28
- "control.cancel",
29
27
  "control.kill"
30
28
  ],
31
29
  "emits": [
@@ -22,8 +22,6 @@
22
22
  "accepts": [
23
23
  "control.reply",
24
24
  "control.revise",
25
- "control.stop",
26
- "control.cancel",
27
25
  "control.kill"
28
26
  ],
29
27
  "emits": [
@@ -24,8 +24,6 @@
24
24
  },
25
25
  "mailbox": {
26
26
  "accepts": [
27
- "control.stop",
28
- "control.cancel",
29
27
  "control.kill"
30
28
  ],
31
29
  "emits": [
@@ -23,8 +23,6 @@
23
23
  },
24
24
  "mailbox": {
25
25
  "accepts": [
26
- "control.stop",
27
- "control.cancel",
28
26
  "control.kill"
29
27
  ],
30
28
  "emits": [
@@ -23,8 +23,6 @@
23
23
  },
24
24
  "mailbox": {
25
25
  "accepts": [
26
- "control.stop",
27
- "control.cancel",
28
26
  "control.kill"
29
27
  ],
30
28
  "emits": [
@@ -20,8 +20,6 @@
20
20
  },
21
21
  "mailbox": {
22
22
  "accepts": [
23
- "control.stop",
24
- "control.cancel",
25
23
  "control.kill"
26
24
  ],
27
25
  "emits": [
@@ -40,8 +40,6 @@
40
40
  },
41
41
  "mailbox": {
42
42
  "accepts": [
43
- "control.stop",
44
- "control.cancel",
45
43
  "control.kill"
46
44
  ],
47
45
  "emits": [
@@ -29,8 +29,6 @@
29
29
  },
30
30
  "mailbox": {
31
31
  "accepts": [
32
- "control.stop",
33
- "control.cancel",
34
32
  "control.kill"
35
33
  ],
36
34
  "emits": [
@@ -25,8 +25,6 @@
25
25
  },
26
26
  "mailbox": {
27
27
  "accepts": [
28
- "control.stop",
29
- "control.cancel",
30
28
  "control.kill"
31
29
  ],
32
30
  "emits": [
@@ -22,8 +22,6 @@
22
22
  },
23
23
  "mailbox": {
24
24
  "accepts": [
25
- "control.stop",
26
- "control.cancel",
27
25
  "control.kill"
28
26
  ],
29
27
  "emits": [
@@ -25,8 +25,6 @@
25
25
  },
26
26
  "mailbox": {
27
27
  "accepts": [
28
- "control.stop",
29
- "control.cancel",
30
28
  "control.kill"
31
29
  ],
32
30
  "emits": [
@@ -34,8 +34,6 @@
34
34
  },
35
35
  "mailbox": {
36
36
  "accepts": [
37
- "control.stop",
38
- "control.cancel",
39
37
  "control.kill"
40
38
  ],
41
39
  "emits": [
@@ -19,8 +19,6 @@
19
19
  },
20
20
  "mailbox": {
21
21
  "accepts": [
22
- "control.stop",
23
- "control.cancel",
24
22
  "control.kill"
25
23
  ],
26
24
  "emits": [
@@ -21,8 +21,6 @@
21
21
  "accepts": [
22
22
  "control.continue",
23
23
  "control.revise",
24
- "control.stop",
25
- "control.cancel",
26
24
  "control.kill"
27
25
  ],
28
26
  "emits": [
@@ -17,8 +17,6 @@
17
17
  },
18
18
  "mailbox": {
19
19
  "accepts": [
20
- "control.stop",
21
- "control.cancel",
22
20
  "control.kill"
23
21
  ],
24
22
  "emits": [
@@ -18,8 +18,6 @@
18
18
  },
19
19
  "mailbox": {
20
20
  "accepts": [
21
- "control.stop",
22
- "control.cancel",
23
21
  "control.kill"
24
22
  ],
25
23
  "emits": [
@@ -20,8 +20,6 @@
20
20
  },
21
21
  "mailbox": {
22
22
  "accepts": [
23
- "control.stop",
24
- "control.cancel",
25
23
  "control.kill"
26
24
  ],
27
25
  "emits": [
@@ -18,8 +18,6 @@
18
18
  },
19
19
  "mailbox": {
20
20
  "accepts": [
21
- "control.stop",
22
- "control.cancel",
23
21
  "control.kill"
24
22
  ],
25
23
  "emits": [
@@ -21,8 +21,6 @@
21
21
  "accepts": [
22
22
  "control.reply",
23
23
  "control.revise",
24
- "control.stop",
25
- "control.cancel",
26
24
  "control.kill"
27
25
  ],
28
26
  "emits": [
@@ -18,8 +18,6 @@
18
18
  },
19
19
  "mailbox": {
20
20
  "accepts": [
21
- "control.stop",
22
- "control.cancel",
23
21
  "control.kill"
24
22
  ],
25
23
  "emits": [
@@ -18,8 +18,6 @@
18
18
  },
19
19
  "mailbox": {
20
20
  "accepts": [
21
- "control.stop",
22
- "control.cancel",
23
21
  "control.kill"
24
22
  ],
25
23
  "emits": [
@@ -22,8 +22,6 @@
22
22
  },
23
23
  "mailbox": {
24
24
  "accepts": [
25
- "control.stop",
26
- "control.cancel",
27
25
  "control.kill"
28
26
  ],
29
27
  "emits": [
@@ -16,8 +16,6 @@
16
16
  },
17
17
  "mailbox": {
18
18
  "accepts": [
19
- "control.stop",
20
- "control.cancel",
21
19
  "control.kill"
22
20
  ],
23
21
  "emits": [
@@ -18,8 +18,6 @@
18
18
  },
19
19
  "mailbox": {
20
20
  "accepts": [
21
- "control.stop",
22
- "control.cancel",
23
21
  "control.kill"
24
22
  ],
25
23
  "emits": [