@llblab/pi-actors 0.25.0 → 0.26.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 (89) hide show
  1. package/BACKLOG.md +4 -8
  2. package/CHANGELOG.md +7 -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/recipes/actor-worker.json +10 -6
  7. package/dist/recipes/lens-swarm.json +0 -2
  8. package/dist/recipes/pipeline-architect-coordinator.json +0 -2
  9. package/dist/recipes/pipeline-artifact-bundle.json +0 -2
  10. package/dist/recipes/pipeline-artifact-report.json +0 -2
  11. package/dist/recipes/pipeline-artifact-write.json +0 -2
  12. package/dist/recipes/pipeline-async-run-ops.json +0 -2
  13. package/dist/recipes/pipeline-checkpoint-continuation.json +0 -2
  14. package/dist/recipes/pipeline-development-tasking.json +0 -2
  15. package/dist/recipes/pipeline-docs-maintenance.json +0 -2
  16. package/dist/recipes/pipeline-media-library.json +0 -2
  17. package/dist/recipes/pipeline-quorum-review.json +0 -2
  18. package/dist/recipes/pipeline-release-readiness.json +0 -2
  19. package/dist/recipes/pipeline-release-summary.json +0 -2
  20. package/dist/recipes/pipeline-repo-health.json +0 -2
  21. package/dist/recipes/pipeline-research-synthesis.json +0 -2
  22. package/dist/recipes/pipeline-review-readiness.json +0 -2
  23. package/dist/recipes/pipeline-room-swarm.json +0 -2
  24. package/dist/recipes/subagent-artifact.json +0 -2
  25. package/dist/recipes/subagent-checkpoint.json +0 -2
  26. package/dist/recipes/subagent-conflict-report.json +0 -2
  27. package/dist/recipes/subagent-contradiction-map.json +0 -2
  28. package/dist/recipes/subagent-critic.json +0 -2
  29. package/dist/recipes/subagent-evidence-map.json +0 -2
  30. package/dist/recipes/subagent-followup.json +0 -2
  31. package/dist/recipes/subagent-judge.json +0 -2
  32. package/dist/recipes/subagent-merge.json +0 -2
  33. package/dist/recipes/subagent-message.json +0 -2
  34. package/dist/recipes/subagent-normalize.json +0 -2
  35. package/dist/recipes/subagent-plan.json +0 -2
  36. package/dist/recipes/subagent-prompt.json +0 -2
  37. package/dist/recipes/subagent-quorum.json +0 -2
  38. package/dist/recipes/subagent-review-coordinator.json +0 -2
  39. package/dist/recipes/subagent-review.json +0 -2
  40. package/dist/recipes/subagent-task-card.json +0 -2
  41. package/dist/recipes/subagent-tools.json +0 -2
  42. package/dist/recipes/subagent-verify.json +0 -2
  43. package/dist/recipes/subagents-prompts.json +0 -2
  44. package/dist/skills/actors/SKILL.md +2 -2
  45. package/dist/skills/swarm/SKILL.md +1 -1
  46. package/docs/actor-messages.md +1 -1
  47. package/docs/template-recipes.md +2 -2
  48. package/lib/actor-worker.ts +62 -6
  49. package/package.json +1 -1
  50. package/recipes/actor-worker.json +10 -6
  51. package/recipes/lens-swarm.json +0 -2
  52. package/recipes/pipeline-architect-coordinator.json +0 -2
  53. package/recipes/pipeline-artifact-bundle.json +0 -2
  54. package/recipes/pipeline-artifact-report.json +0 -2
  55. package/recipes/pipeline-artifact-write.json +0 -2
  56. package/recipes/pipeline-async-run-ops.json +0 -2
  57. package/recipes/pipeline-checkpoint-continuation.json +0 -2
  58. package/recipes/pipeline-development-tasking.json +0 -2
  59. package/recipes/pipeline-docs-maintenance.json +0 -2
  60. package/recipes/pipeline-media-library.json +0 -2
  61. package/recipes/pipeline-quorum-review.json +0 -2
  62. package/recipes/pipeline-release-readiness.json +0 -2
  63. package/recipes/pipeline-release-summary.json +0 -2
  64. package/recipes/pipeline-repo-health.json +0 -2
  65. package/recipes/pipeline-research-synthesis.json +0 -2
  66. package/recipes/pipeline-review-readiness.json +0 -2
  67. package/recipes/pipeline-room-swarm.json +0 -2
  68. package/recipes/subagent-artifact.json +0 -2
  69. package/recipes/subagent-checkpoint.json +0 -2
  70. package/recipes/subagent-conflict-report.json +0 -2
  71. package/recipes/subagent-contradiction-map.json +0 -2
  72. package/recipes/subagent-critic.json +0 -2
  73. package/recipes/subagent-evidence-map.json +0 -2
  74. package/recipes/subagent-followup.json +0 -2
  75. package/recipes/subagent-judge.json +0 -2
  76. package/recipes/subagent-merge.json +0 -2
  77. package/recipes/subagent-message.json +0 -2
  78. package/recipes/subagent-normalize.json +0 -2
  79. package/recipes/subagent-plan.json +0 -2
  80. package/recipes/subagent-prompt.json +0 -2
  81. package/recipes/subagent-quorum.json +0 -2
  82. package/recipes/subagent-review-coordinator.json +0 -2
  83. package/recipes/subagent-review.json +0 -2
  84. package/recipes/subagent-task-card.json +0 -2
  85. package/recipes/subagent-tools.json +0 -2
  86. package/recipes/subagent-verify.json +0 -2
  87. package/recipes/subagents-prompts.json +0 -2
  88. package/skills/actors/SKILL.md +2 -2
  89. package/skills/swarm/SKILL.md +1 -1
@@ -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
  }
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.0",
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": [
@@ -14,8 +14,6 @@
14
14
  },
15
15
  "mailbox": {
16
16
  "accepts": [
17
- "control.stop",
18
- "control.cancel",
19
17
  "control.kill"
20
18
  ],
21
19
  "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": [
@@ -36,8 +36,6 @@
36
36
  },
37
37
  "mailbox": {
38
38
  "accepts": [
39
- "control.stop",
40
- "control.cancel",
41
39
  "control.kill"
42
40
  ],
43
41
  "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": [
@@ -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.0
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.0
6
6
  ---
7
7
 
8
8
  # Swarm