cool-workflow 0.1.80 → 0.1.81

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 (110) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +42 -2
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +1 -1
  6. package/apps/end-to-end-golden-path/app.json +1 -1
  7. package/apps/pr-review-fix-ci/app.json +1 -1
  8. package/apps/release-cut/app.json +1 -1
  9. package/apps/research-synthesis/app.json +1 -1
  10. package/dist/agent-config.js +21 -7
  11. package/dist/candidate-scoring.js +42 -22
  12. package/dist/capability-core.js +94 -17
  13. package/dist/capability-registry.js +138 -171
  14. package/dist/cli.js +90 -100
  15. package/dist/collaboration.js +5 -6
  16. package/dist/commit.js +20 -6
  17. package/dist/compare.js +18 -0
  18. package/dist/coordinator/classify.js +45 -0
  19. package/dist/coordinator/paths.js +42 -0
  20. package/dist/coordinator/util.js +129 -0
  21. package/dist/coordinator.js +127 -300
  22. package/dist/dispatch.js +35 -0
  23. package/dist/drive.js +7 -7
  24. package/dist/error-feedback.js +8 -4
  25. package/dist/evidence-reasoning.js +1 -1
  26. package/dist/execution-backend/agent.js +331 -0
  27. package/dist/execution-backend/probes.js +96 -0
  28. package/dist/execution-backend/util.js +47 -0
  29. package/dist/execution-backend.js +67 -420
  30. package/dist/mcp-server.js +34 -173
  31. package/dist/multi-agent/graph.js +84 -0
  32. package/dist/multi-agent/helpers.js +145 -0
  33. package/dist/multi-agent/paths.js +22 -0
  34. package/dist/multi-agent-eval/format.js +194 -0
  35. package/dist/multi-agent-eval/normalize.js +51 -0
  36. package/dist/multi-agent-eval.js +39 -244
  37. package/dist/multi-agent-host.js +0 -19
  38. package/dist/multi-agent.js +125 -314
  39. package/dist/node-snapshot.js +3 -3
  40. package/dist/observability/format.js +61 -0
  41. package/dist/observability/intake.js +98 -0
  42. package/dist/observability.js +14 -160
  43. package/dist/operator-ux/format.js +364 -0
  44. package/dist/operator-ux.js +22 -363
  45. package/dist/orchestrator/report.js +8 -0
  46. package/dist/orchestrator.js +25 -8
  47. package/dist/reclamation.js +26 -21
  48. package/dist/run-export.js +138 -14
  49. package/dist/run-registry/derive.js +172 -0
  50. package/dist/run-registry/format.js +124 -0
  51. package/dist/run-registry/gc.js +251 -0
  52. package/dist/run-registry/policy.js +16 -0
  53. package/dist/run-registry/queue.js +116 -0
  54. package/dist/run-registry.js +78 -593
  55. package/dist/run-state-schema.js +1 -0
  56. package/dist/sandbox-profile.js +43 -2
  57. package/dist/state-explosion/format.js +159 -0
  58. package/dist/state-explosion/helpers.js +82 -0
  59. package/dist/state-explosion.js +65 -283
  60. package/dist/state-node.js +19 -4
  61. package/dist/telemetry-attestation.js +55 -0
  62. package/dist/telemetry-demo.js +15 -3
  63. package/dist/telemetry-ledger.js +60 -15
  64. package/dist/topology.js +25 -8
  65. package/dist/triggers.js +33 -14
  66. package/dist/trust-audit.js +145 -33
  67. package/dist/version.js +1 -1
  68. package/dist/worker-isolation/helpers.js +51 -0
  69. package/dist/worker-isolation/paths.js +46 -0
  70. package/dist/worker-isolation.js +39 -115
  71. package/docs/agent-delegation-drive.7.md +13 -0
  72. package/docs/cli-mcp-parity.7.md +4 -0
  73. package/docs/contract-migration-tooling.7.md +2 -0
  74. package/docs/control-plane-scheduling.7.md +2 -0
  75. package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +40 -0
  76. package/docs/durable-state-and-locking.7.md +4 -0
  77. package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
  78. package/docs/execution-backends.7.md +2 -0
  79. package/docs/index.md +1 -0
  80. package/docs/launch/launch-kit.md +46 -23
  81. package/docs/launch/pre-launch-checklist.md +14 -14
  82. package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
  83. package/docs/multi-agent-eval-replay-harness.7.md +2 -0
  84. package/docs/multi-agent-operator-ux.7.md +2 -0
  85. package/docs/multi-agent-trust-policy-audit.7.md +27 -0
  86. package/docs/node-snapshot-diff-replay.7.md +2 -0
  87. package/docs/observability-cost-accounting.7.md +2 -0
  88. package/docs/project-index.md +18 -5
  89. package/docs/real-execution-backends.7.md +2 -0
  90. package/docs/release-and-migration.7.md +4 -0
  91. package/docs/release-tooling.7.md +2 -0
  92. package/docs/run-registry-control-plane.7.md +54 -8
  93. package/docs/run-retention-reclamation.7.md +4 -0
  94. package/docs/state-explosion-management.7.md +2 -0
  95. package/docs/team-collaboration.7.md +2 -0
  96. package/docs/trust-model.md +267 -0
  97. package/docs/vendor-manifest-loadability.7.md +43 -0
  98. package/docs/web-desktop-workbench.7.md +2 -0
  99. package/manifest/plugin.manifest.json +1 -1
  100. package/package.json +4 -2
  101. package/scripts/agents/builtin-templates.json +7 -0
  102. package/scripts/bump-version.js +5 -11
  103. package/scripts/canonical-apps-list.js +64 -0
  104. package/scripts/canonical-apps.js +19 -4
  105. package/scripts/dogfood-release.js +1 -1
  106. package/scripts/golden-path.js +4 -4
  107. package/scripts/parity-check.js +5 -0
  108. package/scripts/release-check.js +5 -1
  109. package/scripts/version-sync-check.js +5 -8
  110. package/dist/capability-dispatcher.js +0 -86
@@ -30,16 +30,19 @@ const pipeline_contract_1 = require("./pipeline-contract");
30
30
  const state_node_1 = require("./state-node");
31
31
  const trust_audit_1 = require("./trust-audit");
32
32
  const multi_agent_trust_1 = require("./multi-agent-trust");
33
- exports.MULTI_AGENT_SCHEMA_VERSION = 1;
33
+ const paths_1 = require("./multi-agent/paths");
34
+ const graph_1 = require("./multi-agent/graph");
35
+ const helpers_1 = require("./multi-agent/helpers");
36
+ Object.defineProperty(exports, "MULTI_AGENT_SCHEMA_VERSION", { enumerable: true, get: function () { return helpers_1.MULTI_AGENT_SCHEMA_VERSION; } });
34
37
  function ensureMultiAgentState(run) {
35
- run.paths.multiAgentDir = multiAgentRoot(run);
38
+ run.paths.multiAgentDir = (0, paths_1.multiAgentRoot)(run);
36
39
  node_fs_1.default.mkdirSync(run.paths.multiAgentDir, { recursive: true });
37
40
  for (const dir of ["runs", "roles", "groups", "memberships", "fanouts", "fanins"]) {
38
41
  node_fs_1.default.mkdirSync(node_path_1.default.join(run.paths.multiAgentDir, dir), { recursive: true });
39
42
  }
40
43
  if (!run.multiAgent) {
41
44
  run.multiAgent = {
42
- schemaVersion: exports.MULTI_AGENT_SCHEMA_VERSION,
45
+ schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
43
46
  runs: [],
44
47
  roles: [],
45
48
  groups: [],
@@ -48,7 +51,7 @@ function ensureMultiAgentState(run) {
48
51
  fanins: []
49
52
  };
50
53
  }
51
- run.multiAgent.schemaVersion = exports.MULTI_AGENT_SCHEMA_VERSION;
54
+ run.multiAgent.schemaVersion = helpers_1.MULTI_AGENT_SCHEMA_VERSION;
52
55
  run.multiAgent.runs = run.multiAgent.runs || [];
53
56
  run.multiAgent.roles = run.multiAgent.roles || [];
54
57
  run.multiAgent.groups = run.multiAgent.groups || [];
@@ -59,15 +62,15 @@ function ensureMultiAgentState(run) {
59
62
  }
60
63
  function persistMultiAgentState(run) {
61
64
  const state = ensureMultiAgentState(run);
62
- const root = multiAgentRoot(run);
63
- assertNoRecordPathCollisions("MultiAgentRun", state.runs);
64
- assertNoRecordPathCollisions("AgentRole", state.roles);
65
- assertNoRecordPathCollisions("AgentGroup", state.groups);
66
- assertNoRecordPathCollisions("AgentMembership", state.memberships);
67
- assertNoRecordPathCollisions("AgentFanout", state.fanouts);
68
- assertNoRecordPathCollisions("AgentFanin", state.fanins);
65
+ const root = (0, paths_1.multiAgentRoot)(run);
66
+ (0, helpers_1.assertNoRecordPathCollisions)("MultiAgentRun", state.runs);
67
+ (0, helpers_1.assertNoRecordPathCollisions)("AgentRole", state.roles);
68
+ (0, helpers_1.assertNoRecordPathCollisions)("AgentGroup", state.groups);
69
+ (0, helpers_1.assertNoRecordPathCollisions)("AgentMembership", state.memberships);
70
+ (0, helpers_1.assertNoRecordPathCollisions)("AgentFanout", state.fanouts);
71
+ (0, helpers_1.assertNoRecordPathCollisions)("AgentFanin", state.fanins);
69
72
  (0, state_1.writeJson)(node_path_1.default.join(root, "index.json"), {
70
- schemaVersion: exports.MULTI_AGENT_SCHEMA_VERSION,
73
+ schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
71
74
  runId: run.id,
72
75
  counts: {
73
76
  runs: state.runs.length,
@@ -77,12 +80,12 @@ function persistMultiAgentState(run) {
77
80
  fanouts: state.fanouts.length,
78
81
  fanins: state.fanins.length
79
82
  },
80
- runs: state.runs.map(indexRow),
81
- roles: state.roles.map(indexRow),
82
- groups: state.groups.map(indexRow),
83
- memberships: state.memberships.map(indexRow),
84
- fanouts: state.fanouts.map(indexRow),
85
- fanins: state.fanins.map(indexRow)
83
+ runs: state.runs.map(helpers_1.indexRow),
84
+ roles: state.roles.map(helpers_1.indexRow),
85
+ groups: state.groups.map(helpers_1.indexRow),
86
+ memberships: state.memberships.map(helpers_1.indexRow),
87
+ fanouts: state.fanouts.map(helpers_1.indexRow),
88
+ fanins: state.fanins.map(helpers_1.indexRow)
86
89
  });
87
90
  for (const record of state.runs)
88
91
  writeRecord(run, "runs", record);
@@ -99,13 +102,13 @@ function persistMultiAgentState(run) {
99
102
  }
100
103
  function createMultiAgentRun(run, input = {}) {
101
104
  const state = ensureMultiAgentState(run);
102
- const id = input.id || createId("mar");
105
+ const id = input.id || (0, helpers_1.createId)("mar", state.runs.length + 1);
103
106
  if (state.runs.some((record) => record.id === id))
104
107
  throw new Error(`Duplicate MultiAgentRun id: ${id}`);
105
108
  const now = new Date().toISOString();
106
109
  const status = input.status || "planned";
107
110
  const record = {
108
- schemaVersion: exports.MULTI_AGENT_SCHEMA_VERSION,
111
+ schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
109
112
  id,
110
113
  runId: run.id,
111
114
  createdAt: now,
@@ -120,14 +123,14 @@ function createMultiAgentRun(run, input = {}) {
120
123
  fanoutIds: [],
121
124
  faninIds: [],
122
125
  blackboardId: input.blackboardId,
123
- topicIds: unique(input.topicIds || []),
124
- lifecycle: [lifecycleEvent(undefined, status, "created")],
126
+ topicIds: (0, helpers_1.unique)(input.topicIds || []),
127
+ lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, status, "created")],
125
128
  links: {
126
129
  workflowRunId: run.id,
127
130
  phase: input.phase,
128
131
  phaseId: input.phaseId,
129
132
  blackboardId: input.blackboardId,
130
- blackboardTopicIds: unique(input.topicIds || [])
133
+ blackboardTopicIds: (0, helpers_1.unique)(input.topicIds || [])
131
134
  },
132
135
  policy: {
133
136
  schemaVersion: 1,
@@ -135,7 +138,7 @@ function createMultiAgentRun(run, input = {}) {
135
138
  policyRef: `multiAgent.runs.${id}.policy`,
136
139
  subjectKind: "multi-agent-run",
137
140
  subjectId: id,
138
- allowedBlackboardTopicIds: unique(input.topicIds || ["*"]),
141
+ allowedBlackboardTopicIds: (0, helpers_1.unique)(input.topicIds || ["*"]),
139
142
  allowedWriteOperations: ["message", "context", "artifact", "snapshot", "topic", "coordinator-decision"],
140
143
  allowedCandidateOperations: ["register", "score", "select"],
141
144
  allowedJudgeOperations: ["verdict", "rationale", "panel-decision"],
@@ -144,15 +147,15 @@ function createMultiAgentRun(run, input = {}) {
144
147
  deniedOperations: [],
145
148
  metadata: { title: input.title }
146
149
  },
147
- metadata: compact(input.metadata)
150
+ metadata: (0, helpers_1.compact)(input.metadata)
148
151
  };
149
152
  if (record.parentMultiAgentRunId) {
150
153
  const parent = requireMultiAgentRun(run, record.parentMultiAgentRunId);
151
- parent.childMultiAgentRunIds = unique([...parent.childMultiAgentRunIds, record.id]);
152
- touch(parent);
154
+ parent.childMultiAgentRunIds = (0, helpers_1.unique)([...parent.childMultiAgentRunIds, record.id]);
155
+ (0, helpers_1.touch)(parent);
153
156
  }
154
157
  state.runs.push(record);
155
- appendMultiAgentNode(run, "multi-agent-run", record.id, statusToNodeStatus(status), {
158
+ appendMultiAgentNode(run, "multi-agent-run", record.id, (0, helpers_1.statusToNodeStatus)(status), {
156
159
  title: record.title,
157
160
  objective: record.objective,
158
161
  phase: record.links.phase
@@ -170,16 +173,16 @@ function createMultiAgentRun(run, input = {}) {
170
173
  function transitionMultiAgentRun(run, multiAgentRunId, status, options = {}) {
171
174
  ensureMultiAgentState(run);
172
175
  const record = requireMultiAgentRun(run, multiAgentRunId);
173
- assertLifecycleTransition(record.status, status);
176
+ (0, helpers_1.assertLifecycleTransition)(record.status, status);
174
177
  if (status === "completed")
175
178
  assertMultiAgentRunCompletionReady(run, record);
176
179
  const before = record.status;
177
180
  record.status = status;
178
181
  record.updatedAt = new Date().toISOString();
179
- record.lifecycle.push(lifecycleEvent(before, status, options.reason, options.actor, options.metadata));
182
+ record.lifecycle.push((0, helpers_1.lifecycleEvent)(before, status, options.reason, options.actor, options.metadata));
180
183
  if (status === "completed")
181
184
  completeOwnedMultiAgentRecords(run, record, options.reason);
182
- appendMultiAgentNode(run, "multi-agent-run", record.id, statusToNodeStatus(status), {
185
+ appendMultiAgentNode(run, "multi-agent-run", record.id, (0, helpers_1.statusToNodeStatus)(status), {
183
186
  status,
184
187
  reason: options.reason
185
188
  });
@@ -222,7 +225,7 @@ function completeOwnedMultiAgentRecords(run, multiAgentRun, reason) {
222
225
  const before = role.status;
223
226
  role.status = "completed";
224
227
  role.updatedAt = multiAgentRun.updatedAt;
225
- role.lifecycle.push(lifecycleEvent(before, "completed", reason || "multi-agent run completed"));
228
+ role.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "completed", reason || "multi-agent run completed"));
226
229
  }
227
230
  for (const group of state.groups.filter((record) => record.multiAgentRunId === multiAgentRun.id)) {
228
231
  if (group.status === "completed" || group.status === "failed" || group.status === "cancelled")
@@ -230,7 +233,7 @@ function completeOwnedMultiAgentRecords(run, multiAgentRun, reason) {
230
233
  const before = group.status;
231
234
  group.status = "completed";
232
235
  group.updatedAt = multiAgentRun.updatedAt;
233
- group.lifecycle.push(lifecycleEvent(before, "completed", reason || "multi-agent run completed"));
236
+ group.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "completed", reason || "multi-agent run completed"));
234
237
  }
235
238
  for (const fanout of state.fanouts.filter((record) => record.multiAgentRunId === multiAgentRun.id)) {
236
239
  if (fanout.status === "completed" || fanout.status === "failed" || fanout.status === "cancelled")
@@ -238,7 +241,7 @@ function completeOwnedMultiAgentRecords(run, multiAgentRun, reason) {
238
241
  const before = fanout.status;
239
242
  fanout.status = "completed";
240
243
  fanout.updatedAt = multiAgentRun.updatedAt;
241
- fanout.lifecycle.push(lifecycleEvent(before, "completed", reason || "multi-agent run completed"));
244
+ fanout.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "completed", reason || "multi-agent run completed"));
242
245
  }
243
246
  for (const fanin of state.fanins.filter((record) => record.multiAgentRunId === multiAgentRun.id)) {
244
247
  if (fanin.status === "completed" || fanin.status === "failed")
@@ -246,20 +249,20 @@ function completeOwnedMultiAgentRecords(run, multiAgentRun, reason) {
246
249
  const before = fanin.status;
247
250
  fanin.status = "completed";
248
251
  fanin.updatedAt = multiAgentRun.updatedAt;
249
- fanin.lifecycle.push(lifecycleEvent(before, "completed", reason || "multi-agent run completed"));
252
+ fanin.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "completed", reason || "multi-agent run completed"));
250
253
  }
251
254
  }
252
255
  function createAgentRole(run, input) {
253
256
  const state = ensureMultiAgentState(run);
254
257
  const multiAgentRun = requireMultiAgentRun(run, input.multiAgentRunId);
255
- const id = input.id || createId("role");
258
+ const id = input.id || (0, helpers_1.createId)("role", state.roles.length + 1);
256
259
  if (state.roles.some((record) => record.id === id))
257
260
  throw new Error(`Duplicate AgentRole id: ${id}`);
258
261
  if (input.parentRoleId)
259
262
  requireAgentRole(run, input.parentRoleId);
260
263
  const now = new Date().toISOString();
261
264
  const role = {
262
- schemaVersion: exports.MULTI_AGENT_SCHEMA_VERSION,
265
+ schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
263
266
  id,
264
267
  runId: run.id,
265
268
  multiAgentRunId: multiAgentRun.id,
@@ -273,22 +276,22 @@ function createAgentRole(run, input) {
273
276
  expectedArtifacts: input.expectedArtifacts || [],
274
277
  faninObligations: input.faninObligations || [],
275
278
  blackboardId: input.blackboardId || multiAgentRun.blackboardId,
276
- topicIds: unique([...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
277
- lifecycle: [lifecycleEvent(undefined, "planned", "created")],
279
+ topicIds: (0, helpers_1.unique)([...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
280
+ lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, "planned", "created")],
278
281
  parentRoleId: input.parentRoleId,
279
282
  childRoleIds: [],
280
283
  policy: undefined,
281
- metadata: compact(input.metadata)
284
+ metadata: (0, helpers_1.compact)(input.metadata)
282
285
  };
283
286
  role.policy = (0, multi_agent_trust_1.policyForRole)(role);
284
287
  if (role.parentRoleId) {
285
288
  const parent = requireAgentRole(run, role.parentRoleId);
286
- parent.childRoleIds = unique([...parent.childRoleIds, role.id]);
287
- touch(parent);
289
+ parent.childRoleIds = (0, helpers_1.unique)([...parent.childRoleIds, role.id]);
290
+ (0, helpers_1.touch)(parent);
288
291
  }
289
292
  state.roles.push(role);
290
- multiAgentRun.roleIds = unique([...multiAgentRun.roleIds, role.id]);
291
- touch(multiAgentRun);
293
+ multiAgentRun.roleIds = (0, helpers_1.unique)([...multiAgentRun.roleIds, role.id]);
294
+ (0, helpers_1.touch)(multiAgentRun);
292
295
  appendMultiAgentNode(run, "agent-role", role.id, "pending", {
293
296
  multiAgentRunId: role.multiAgentRunId,
294
297
  title: role.title,
@@ -315,7 +318,7 @@ function createAgentRole(run, input) {
315
318
  function createAgentGroup(run, input) {
316
319
  const state = ensureMultiAgentState(run);
317
320
  const multiAgentRun = requireMultiAgentRun(run, input.multiAgentRunId);
318
- const id = input.id || createId("group");
321
+ const id = input.id || (0, helpers_1.createId)("group", state.groups.length + 1);
319
322
  if (state.groups.some((record) => record.id === id))
320
323
  throw new Error(`Duplicate AgentGroup id: ${id}`);
321
324
  if (input.parentGroupId)
@@ -324,7 +327,7 @@ function createAgentGroup(run, input) {
324
327
  requireRunTask(run, taskId);
325
328
  const now = new Date().toISOString();
326
329
  const group = {
327
- schemaVersion: exports.MULTI_AGENT_SCHEMA_VERSION,
330
+ schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
328
331
  id,
329
332
  runId: run.id,
330
333
  multiAgentRunId: multiAgentRun.id,
@@ -334,29 +337,29 @@ function createAgentGroup(run, input) {
334
337
  title: input.title || id,
335
338
  phase: input.phase,
336
339
  phaseId: input.phaseId,
337
- taskIds: unique(input.taskIds || []),
340
+ taskIds: (0, helpers_1.unique)(input.taskIds || []),
338
341
  roleIds: [],
339
342
  membershipIds: [],
340
343
  workerIds: [],
341
344
  fanoutIds: [],
342
345
  faninIds: [],
343
346
  blackboardId: input.blackboardId || multiAgentRun.blackboardId,
344
- topicIds: unique([...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
345
- lifecycle: [lifecycleEvent(undefined, "forming", "created")],
347
+ topicIds: (0, helpers_1.unique)([...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
348
+ lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, "forming", "created")],
346
349
  parentGroupId: input.parentGroupId,
347
350
  childGroupIds: [],
348
351
  policy: undefined,
349
- metadata: compact(input.metadata)
352
+ metadata: (0, helpers_1.compact)(input.metadata)
350
353
  };
351
354
  group.policy = (0, multi_agent_trust_1.policyForGroup)(group);
352
355
  if (group.parentGroupId) {
353
356
  const parent = requireAgentGroup(run, group.parentGroupId);
354
- parent.childGroupIds = unique([...parent.childGroupIds, group.id]);
355
- touch(parent);
357
+ parent.childGroupIds = (0, helpers_1.unique)([...parent.childGroupIds, group.id]);
358
+ (0, helpers_1.touch)(parent);
356
359
  }
357
360
  state.groups.push(group);
358
- multiAgentRun.groupIds = unique([...multiAgentRun.groupIds, group.id]);
359
- touch(multiAgentRun);
361
+ multiAgentRun.groupIds = (0, helpers_1.unique)([...multiAgentRun.groupIds, group.id]);
362
+ (0, helpers_1.touch)(multiAgentRun);
360
363
  appendMultiAgentNode(run, "agent-group", group.id, "running", {
361
364
  multiAgentRunId: group.multiAgentRunId,
362
365
  phase: group.phase,
@@ -394,13 +397,13 @@ function assignAgentMembership(run, input) {
394
397
  if (duplicate) {
395
398
  throw new Error(`Duplicate AgentMembership for group=${group.id}, role=${role.id}, task=${task.id}, worker=${input.workerId || "none"}`);
396
399
  }
397
- const id = input.id || createId("membership");
400
+ const id = input.id || (0, helpers_1.createId)("membership", state.memberships.length + 1);
398
401
  if (state.memberships.some((record) => record.id === id))
399
402
  throw new Error(`Duplicate AgentMembership id: ${id}`);
400
403
  const now = new Date().toISOString();
401
404
  const status = input.status || (input.workerId ? "running" : "assigned");
402
405
  const membership = {
403
- schemaVersion: exports.MULTI_AGENT_SCHEMA_VERSION,
406
+ schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
404
407
  id,
405
408
  runId: run.id,
406
409
  multiAgentRunId: group.multiAgentRunId,
@@ -413,31 +416,31 @@ function assignAgentMembership(run, input) {
413
416
  createdAt: now,
414
417
  updatedAt: now,
415
418
  status,
416
- lifecycle: [lifecycleEvent(undefined, status, "assigned")],
419
+ lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, status, "assigned")],
417
420
  evidenceRefs: [],
418
421
  artifactPaths: [],
419
422
  blackboardId: input.blackboardId || group.blackboardId || role.blackboardId,
420
- topicIds: unique([...(group.topicIds || []), ...(role.topicIds || []), ...(input.topicIds || [])]),
423
+ topicIds: (0, helpers_1.unique)([...(group.topicIds || []), ...(role.topicIds || []), ...(input.topicIds || [])]),
421
424
  blackboardMessageIds: [],
422
425
  blackboardArtifactRefIds: [],
423
426
  policy: undefined,
424
- metadata: compact(input.metadata)
427
+ metadata: (0, helpers_1.compact)(input.metadata)
425
428
  };
426
429
  membership.policy = (0, multi_agent_trust_1.policyForMembership)(membership, role);
427
430
  state.memberships.push(membership);
428
- group.membershipIds = unique([...group.membershipIds, membership.id]);
429
- group.roleIds = unique([...group.roleIds, role.id]);
430
- group.taskIds = unique([...group.taskIds, task.id]);
431
+ group.membershipIds = (0, helpers_1.unique)([...group.membershipIds, membership.id]);
432
+ group.roleIds = (0, helpers_1.unique)([...group.roleIds, role.id]);
433
+ group.taskIds = (0, helpers_1.unique)([...group.taskIds, task.id]);
431
434
  if (membership.workerId)
432
- group.workerIds = unique([...group.workerIds, membership.workerId]);
433
- touch(group);
435
+ group.workerIds = (0, helpers_1.unique)([...group.workerIds, membership.workerId]);
436
+ (0, helpers_1.touch)(group);
434
437
  const roleStatusBefore = role.status;
435
438
  role.status = "active";
436
439
  role.updatedAt = now;
437
- role.lifecycle.push(lifecycleEvent(roleStatusBefore, "active", "membership assigned"));
440
+ role.lifecycle.push((0, helpers_1.lifecycleEvent)(roleStatusBefore, "active", "membership assigned"));
438
441
  if (membership.workerId)
439
442
  attachWorkerMetadata(run, membership);
440
- appendMultiAgentNode(run, "agent-membership", membership.id, statusToNodeStatus(membership.status), {
443
+ appendMultiAgentNode(run, "agent-membership", membership.id, (0, helpers_1.statusToNodeStatus)(membership.status), {
441
444
  multiAgentRunId: membership.multiAgentRunId,
442
445
  groupId: membership.groupId,
443
446
  roleId: membership.roleId,
@@ -468,7 +471,7 @@ function createAgentFanout(run, input) {
468
471
  const multiAgentRun = requireMultiAgentRun(run, input.multiAgentRunId || group.multiAgentRunId);
469
472
  if (group.multiAgentRunId !== multiAgentRun.id)
470
473
  throw new Error(`AgentGroup ${group.id} does not belong to ${multiAgentRun.id}`);
471
- const id = input.id || createId("fanout");
474
+ const id = input.id || (0, helpers_1.createId)("fanout", state.fanouts.length + 1);
472
475
  if (state.fanouts.some((record) => record.id === id))
473
476
  throw new Error(`Duplicate AgentFanout id: ${id}`);
474
477
  for (const roleId of input.roleIds || [])
@@ -477,7 +480,7 @@ function createAgentFanout(run, input) {
477
480
  requireRunTask(run, taskId);
478
481
  const now = new Date().toISOString();
479
482
  const fanout = {
480
- schemaVersion: exports.MULTI_AGENT_SCHEMA_VERSION,
483
+ schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
481
484
  id,
482
485
  runId: run.id,
483
486
  multiAgentRunId: multiAgentRun.id,
@@ -486,41 +489,41 @@ function createAgentFanout(run, input) {
486
489
  updatedAt: now,
487
490
  status: "planned",
488
491
  reason: input.reason,
489
- roleIds: unique(input.roleIds || group.roleIds),
490
- taskIds: unique(input.taskIds || group.taskIds),
491
- workerIds: unique(input.workerIds || []),
492
- membershipIds: unique(input.membershipIds || []),
493
- dispatchIds: unique(input.dispatchIds || []),
492
+ roleIds: (0, helpers_1.unique)(input.roleIds || group.roleIds),
493
+ taskIds: (0, helpers_1.unique)(input.taskIds || group.taskIds),
494
+ workerIds: (0, helpers_1.unique)(input.workerIds || []),
495
+ membershipIds: (0, helpers_1.unique)(input.membershipIds || []),
496
+ dispatchIds: (0, helpers_1.unique)(input.dispatchIds || []),
494
497
  concurrencyLimit: input.concurrencyLimit,
495
498
  sandboxProfileChoices: input.sandboxProfileChoices || {},
496
499
  expectedReturnShape: input.expectedReturnShape || "Each member writes a Markdown result with a cw:result JSON fence containing summary, findings, and evidence.",
497
500
  blackboardId: input.blackboardId || group.blackboardId || multiAgentRun.blackboardId,
498
- topicIds: unique([...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
499
- lifecycle: [lifecycleEvent(undefined, "planned", "created")],
501
+ topicIds: (0, helpers_1.unique)([...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
502
+ lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, "planned", "created")],
500
503
  policy: {
501
504
  schemaVersion: 1,
502
505
  id: `${id}-policy`,
503
506
  policyRef: `multiAgent.fanouts.${id}.policy`,
504
507
  subjectKind: "fanout",
505
508
  subjectId: id,
506
- allowedBlackboardTopicIds: unique(fanoutTopicIds(group, multiAgentRun, input)),
509
+ allowedBlackboardTopicIds: (0, helpers_1.unique)(fanoutTopicIds(group, multiAgentRun, input)),
507
510
  allowedWriteOperations: ["message", "context", "artifact"],
508
511
  allowedCandidateOperations: ["register"],
509
512
  allowedJudgeOperations: [],
510
- sandboxProfileHints: unique(Object.values(input.sandboxProfileChoices || {}).map(String)),
513
+ sandboxProfileHints: (0, helpers_1.unique)(Object.values(input.sandboxProfileChoices || {}).map(String)),
511
514
  requiredEvidenceRefs: [],
512
515
  deniedOperations: [],
513
516
  metadata: { reason: input.reason }
514
517
  },
515
- metadata: compact(input.metadata)
518
+ metadata: (0, helpers_1.compact)(input.metadata)
516
519
  };
517
520
  state.fanouts.push(fanout);
518
- group.fanoutIds = unique([...group.fanoutIds, fanout.id]);
519
- group.roleIds = unique([...group.roleIds, ...fanout.roleIds]);
520
- group.taskIds = unique([...group.taskIds, ...fanout.taskIds]);
521
- touch(group);
522
- multiAgentRun.fanoutIds = unique([...multiAgentRun.fanoutIds, fanout.id]);
523
- touch(multiAgentRun);
521
+ group.fanoutIds = (0, helpers_1.unique)([...group.fanoutIds, fanout.id]);
522
+ group.roleIds = (0, helpers_1.unique)([...group.roleIds, ...fanout.roleIds]);
523
+ group.taskIds = (0, helpers_1.unique)([...group.taskIds, ...fanout.taskIds]);
524
+ (0, helpers_1.touch)(group);
525
+ multiAgentRun.fanoutIds = (0, helpers_1.unique)([...multiAgentRun.fanoutIds, fanout.id]);
526
+ (0, helpers_1.touch)(multiAgentRun);
524
527
  appendMultiAgentNode(run, "agent-fanout", fanout.id, "pending", {
525
528
  multiAgentRunId: fanout.multiAgentRunId,
526
529
  groupId: fanout.groupId,
@@ -561,7 +564,7 @@ function attachDispatchToMultiAgent(run, input) {
561
564
  throw new Error("Dispatch multi-agent attach requires --multi-agent-group or --multiAgentGroup");
562
565
  if (group.multiAgentRunId !== multiAgentRun.id)
563
566
  throw new Error(`Group ${group.id} does not belong to MultiAgentRun ${multiAgentRun.id}`);
564
- const roleIds = input.roleId ? [input.roleId] : unique([...(fanout ? fanout.roleIds : [])]);
567
+ const roleIds = input.roleId ? [input.roleId] : (0, helpers_1.unique)([...(fanout ? fanout.roleIds : [])]);
565
568
  if (roleIds.length !== 1) {
566
569
  throw new Error(`Dispatch multi-agent attach requires exactly one role for deterministic membership; found ${roleIds.length || 0}`);
567
570
  }
@@ -608,19 +611,19 @@ function attachDispatchToMultiAgent(run, input) {
608
611
  }
609
612
  fanout.status = "dispatched";
610
613
  fanout.updatedAt = new Date().toISOString();
611
- fanout.lifecycle.push(lifecycleEvent("planned", "dispatched", "dispatch created"));
612
- fanout.dispatchIds = unique([...fanout.dispatchIds, input.dispatchId]);
613
- fanout.taskIds = unique([...fanout.taskIds, ...input.tasks.map((task) => task.id)]);
614
- fanout.workerIds = unique([...fanout.workerIds, ...input.tasks.map((task) => task.workerId || "").filter(Boolean)]);
615
- fanout.membershipIds = unique([...fanout.membershipIds, ...membershipIds]);
614
+ fanout.lifecycle.push((0, helpers_1.lifecycleEvent)("planned", "dispatched", "dispatch created"));
615
+ fanout.dispatchIds = (0, helpers_1.unique)([...fanout.dispatchIds, input.dispatchId]);
616
+ fanout.taskIds = (0, helpers_1.unique)([...fanout.taskIds, ...input.tasks.map((task) => task.id)]);
617
+ fanout.workerIds = (0, helpers_1.unique)([...fanout.workerIds, ...input.tasks.map((task) => task.workerId || "").filter(Boolean)]);
618
+ fanout.membershipIds = (0, helpers_1.unique)([...fanout.membershipIds, ...membershipIds]);
616
619
  if (input.sandboxProfileId)
617
620
  fanout.sandboxProfileChoices.dispatch = input.sandboxProfileId;
618
621
  const groupStatusBefore = group.status;
619
622
  group.status = "running";
620
623
  group.updatedAt = fanout.updatedAt;
621
- group.lifecycle.push(lifecycleEvent(groupStatusBefore, "running", "dispatch created"));
624
+ group.lifecycle.push((0, helpers_1.lifecycleEvent)(groupStatusBefore, "running", "dispatch created"));
622
625
  multiAgentRun.status = multiAgentRun.status === "planned" || multiAgentRun.status === "forming" ? "running" : multiAgentRun.status;
623
- touch(multiAgentRun);
626
+ (0, helpers_1.touch)(multiAgentRun);
624
627
  appendMultiAgentNode(run, "agent-fanout", fanout.id, "running", {
625
628
  status: fanout.status,
626
629
  dispatchIds: fanout.dispatchIds,
@@ -657,10 +660,10 @@ function collectAgentFanin(run, input) {
657
660
  throw new Error(`Group ${group.id} does not belong to MultiAgentRun ${multiAgentRun.id}`);
658
661
  if (fanout && fanout.groupId !== group.id)
659
662
  throw new Error(`Fanout ${fanout.id} does not belong to group ${group.id}`);
660
- const id = input.id || createId("fanin");
663
+ const id = input.id || (0, helpers_1.createId)("fanin", state.fanins.length + 1);
661
664
  if (state.fanins.some((record) => record.id === id))
662
665
  throw new Error(`Duplicate AgentFanin id: ${id}`);
663
- const requiredRoleIds = unique(input.requiredRoleIds?.length ? input.requiredRoleIds : group.roleIds);
666
+ const requiredRoleIds = (0, helpers_1.unique)(input.requiredRoleIds?.length ? input.requiredRoleIds : group.roleIds);
664
667
  for (const roleId of requiredRoleIds)
665
668
  requireAgentRole(run, roleId);
666
669
  const scopedMemberships = state.memberships.filter((membership) => membership.groupId === group.id && (!fanout || membership.fanoutId === fanout.id));
@@ -674,11 +677,11 @@ function collectAgentFanin(run, input) {
674
677
  blackboardArtifactRefIds: membership.blackboardArtifactRefIds || [],
675
678
  resultNodeId: membership.resultNodeId,
676
679
  verifierNodeId: membership.verifierNodeId,
677
- complete: isMembershipReported(membership)
680
+ complete: (0, helpers_1.isMembershipReported)(membership)
678
681
  }));
679
682
  const missingRoleIds = requiredRoleIds.filter((roleId) => !scopedMemberships.some((membership) => membership.roleId === roleId));
680
683
  const missingMembershipIds = scopedMemberships
681
- .filter((membership) => requiredRoleIds.includes(membership.roleId) && !isMembershipReported(membership))
684
+ .filter((membership) => requiredRoleIds.includes(membership.roleId) && !(0, helpers_1.isMembershipReported)(membership))
682
685
  .map((membership) => membership.id);
683
686
  const blockedReasons = [
684
687
  ...missingRoleIds.map((roleId) => `required role ${roleId} has no membership`),
@@ -701,7 +704,7 @@ function collectAgentFanin(run, input) {
701
704
  const status = verifierReady ? "ready" : "blocked";
702
705
  const now = new Date().toISOString();
703
706
  const fanin = {
704
- schemaVersion: exports.MULTI_AGENT_SCHEMA_VERSION,
707
+ schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
705
708
  id,
706
709
  runId: run.id,
707
710
  multiAgentRunId: multiAgentRun.id,
@@ -719,34 +722,34 @@ function collectAgentFanin(run, input) {
719
722
  verifierReady,
720
723
  blockedReasons,
721
724
  blackboardId,
722
- topicIds: unique([...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
723
- blackboardArtifactRefIds: unique(coverage.flatMap((entry) => entry.blackboardArtifactRefIds || [])),
724
- blackboardMessageIds: unique(coverage.flatMap((entry) => entry.blackboardMessageIds || [])),
725
- lifecycle: [lifecycleEvent(undefined, status, "collected")],
725
+ topicIds: (0, helpers_1.unique)([...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
726
+ blackboardArtifactRefIds: (0, helpers_1.unique)(coverage.flatMap((entry) => entry.blackboardArtifactRefIds || [])),
727
+ blackboardMessageIds: (0, helpers_1.unique)(coverage.flatMap((entry) => entry.blackboardMessageIds || [])),
728
+ lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, status, "collected")],
726
729
  policy: {
727
730
  schemaVersion: 1,
728
731
  id: `${id}-policy`,
729
732
  policyRef: `multiAgent.fanins.${id}.policy`,
730
733
  subjectKind: "fanin",
731
734
  subjectId: id,
732
- allowedBlackboardTopicIds: unique([...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
735
+ allowedBlackboardTopicIds: (0, helpers_1.unique)([...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
733
736
  allowedWriteOperations: ["message", "context", "artifact", "snapshot", "coordinator-decision"],
734
737
  allowedCandidateOperations: verifierReady ? ["register", "score", "select"] : [],
735
738
  allowedJudgeOperations: verifierReady ? ["panel-decision", "rationale"] : [],
736
739
  sandboxProfileHints: [],
737
- requiredEvidenceRefs: unique(coverage.flatMap((entry) => entry.evidenceRefs)),
740
+ requiredEvidenceRefs: (0, helpers_1.unique)(coverage.flatMap((entry) => entry.evidenceRefs)),
738
741
  deniedOperations: verifierReady ? [] : blockedReasons.map((reason) => ({ operation: "candidate.select", reason })),
739
742
  metadata: { verifierReady, strategy: input.strategy || "required-role-evidence" }
740
743
  },
741
- metadata: compact(input.metadata)
744
+ metadata: (0, helpers_1.compact)(input.metadata)
742
745
  };
743
746
  state.fanins.push(fanin);
744
- group.faninIds = unique([...group.faninIds, fanin.id]);
747
+ group.faninIds = (0, helpers_1.unique)([...group.faninIds, fanin.id]);
745
748
  group.status = verifierReady ? "verifying" : "collecting";
746
- touch(group);
747
- multiAgentRun.faninIds = unique([...multiAgentRun.faninIds, fanin.id]);
749
+ (0, helpers_1.touch)(group);
750
+ multiAgentRun.faninIds = (0, helpers_1.unique)([...multiAgentRun.faninIds, fanin.id]);
748
751
  multiAgentRun.status = verifierReady ? "verifying" : "collecting";
749
- touch(multiAgentRun);
752
+ (0, helpers_1.touch)(multiAgentRun);
750
753
  appendMultiAgentNode(run, "agent-fanin", fanin.id, verifierReady ? "verified" : "blocked", {
751
754
  multiAgentRunId: fanin.multiAgentRunId,
752
755
  groupId: fanin.groupId,
@@ -792,11 +795,11 @@ function recordMultiAgentWorkerOutput(run, input) {
792
795
  membership.updatedAt = new Date().toISOString();
793
796
  membership.resultNodeId = input.resultNodeId || membership.resultNodeId;
794
797
  membership.verifierNodeId = input.verifierNodeId || membership.verifierNodeId;
795
- membership.evidenceRefs = unique([...membership.evidenceRefs, ...evidenceRefs]);
796
- membership.artifactPaths = unique([...(membership.artifactPaths || []), ...(input.artifactPaths || [])]);
797
- membership.blackboardMessageIds = unique([...(membership.blackboardMessageIds || []), ...(input.blackboardMessageIds || [])]);
798
- membership.blackboardArtifactRefIds = unique([...(membership.blackboardArtifactRefIds || []), ...(input.blackboardArtifactRefIds || [])]);
799
- membership.lifecycle.push(lifecycleEvent(before, "reported", "worker output accepted"));
798
+ membership.evidenceRefs = (0, helpers_1.unique)([...membership.evidenceRefs, ...evidenceRefs]);
799
+ membership.artifactPaths = (0, helpers_1.unique)([...(membership.artifactPaths || []), ...(input.artifactPaths || [])]);
800
+ membership.blackboardMessageIds = (0, helpers_1.unique)([...(membership.blackboardMessageIds || []), ...(input.blackboardMessageIds || [])]);
801
+ membership.blackboardArtifactRefIds = (0, helpers_1.unique)([...(membership.blackboardArtifactRefIds || []), ...(input.blackboardArtifactRefIds || [])]);
802
+ membership.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "reported", "worker output accepted"));
800
803
  appendMultiAgentNode(run, "agent-membership", membership.id, "completed", {
801
804
  resultNodeId: membership.resultNodeId,
802
805
  verifierNodeId: membership.verifierNodeId,
@@ -831,7 +834,7 @@ function summarizeMultiAgent(run) {
831
834
  blockedReasons.push(`${membership.id}: failed membership`);
832
835
  }
833
836
  const groupsDetail = state.groups.map((group) => {
834
- const roleIds = unique([...group.roleIds, ...state.memberships.filter((membership) => membership.groupId === group.id).map((membership) => membership.roleId)]);
837
+ const roleIds = (0, helpers_1.unique)([...group.roleIds, ...state.memberships.filter((membership) => membership.groupId === group.id).map((membership) => membership.roleId)]);
835
838
  return {
836
839
  id: group.id,
837
840
  multiAgentRunId: group.multiAgentRunId,
@@ -840,7 +843,7 @@ function summarizeMultiAgent(run) {
840
843
  roles: roleIds.map((roleId) => {
841
844
  const role = state.roles.find((entry) => entry.id === roleId);
842
845
  const memberships = state.memberships.filter((membership) => membership.groupId === group.id && membership.roleId === roleId);
843
- const reported = memberships.filter(isMembershipReported).length;
846
+ const reported = memberships.filter(helpers_1.isMembershipReported).length;
844
847
  return {
845
848
  roleId,
846
849
  requiredEvidence: role?.requiredEvidence.length || 0,
@@ -855,15 +858,15 @@ function summarizeMultiAgent(run) {
855
858
  });
856
859
  return {
857
860
  totalRuns: state.runs.length,
858
- runsByStatus: countBy(state.runs, (record) => record.status),
861
+ runsByStatus: (0, helpers_1.countBy)(state.runs, (record) => record.status),
859
862
  roles: state.roles.length,
860
863
  groups: state.groups.length,
861
864
  memberships: state.memberships.length,
862
865
  fanouts: state.fanouts.length,
863
866
  fanins: state.fanins.length,
864
- groupsByStatus: countBy(state.groups, (record) => record.status),
865
- membershipsByStatus: countBy(state.memberships, (record) => record.status),
866
- faninsByStatus: countBy(state.fanins, (record) => record.status),
867
+ groupsByStatus: (0, helpers_1.countBy)(state.groups, (record) => record.status),
868
+ membershipsByStatus: (0, helpers_1.countBy)(state.memberships, (record) => record.status),
869
+ faninsByStatus: (0, helpers_1.countBy)(state.fanins, (record) => record.status),
867
870
  blockedReasons,
868
871
  groupsDetail,
869
872
  nextAction: nextMultiAgentAction(run, blockedReasons)
@@ -871,70 +874,7 @@ function summarizeMultiAgent(run) {
871
874
  }
872
875
  function buildMultiAgentGraph(run) {
873
876
  const state = ensureMultiAgentState(run);
874
- const root = multiAgentRoot(run);
875
- const nodes = [];
876
- const edges = [];
877
- for (const record of state.runs) {
878
- nodes.push({ id: `${run.id}:multi-agent:${record.id}`, kind: "multi-agent-run", status: record.status, label: record.title || record.id, path: recordPath(run, "runs", record.id) });
879
- edges.push({ from: `${run.id}:run`, to: `${run.id}:multi-agent:${record.id}` });
880
- if (record.blackboardId)
881
- edges.push({ from: `${run.id}:multi-agent:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
882
- if (record.parentMultiAgentRunId)
883
- edges.push({ from: `${run.id}:multi-agent:${record.parentMultiAgentRunId}`, to: `${run.id}:multi-agent:${record.id}`, label: "child" });
884
- }
885
- for (const record of state.roles) {
886
- nodes.push({ id: `${run.id}:multi-agent:role:${record.id}`, kind: "agent-role", status: record.status, label: record.title, path: recordPath(run, "roles", record.id) });
887
- edges.push({ from: `${run.id}:multi-agent:${record.multiAgentRunId}`, to: `${run.id}:multi-agent:role:${record.id}` });
888
- if (record.blackboardId)
889
- edges.push({ from: `${run.id}:multi-agent:role:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
890
- }
891
- for (const record of state.groups) {
892
- nodes.push({ id: `${run.id}:multi-agent:group:${record.id}`, kind: "agent-group", status: record.status, label: record.title || record.id, path: recordPath(run, "groups", record.id) });
893
- edges.push({ from: `${run.id}:multi-agent:${record.multiAgentRunId}`, to: `${run.id}:multi-agent:group:${record.id}` });
894
- if (record.blackboardId)
895
- edges.push({ from: `${run.id}:multi-agent:group:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
896
- for (const taskId of record.taskIds)
897
- edges.push({ from: `${run.id}:multi-agent:group:${record.id}`, to: `${run.id}:task:${taskId}`, label: "task" });
898
- }
899
- for (const record of state.fanouts) {
900
- nodes.push({ id: `${run.id}:multi-agent:fanout:${record.id}`, kind: "agent-fanout", status: record.status, label: record.reason, path: recordPath(run, "fanouts", record.id) });
901
- edges.push({ from: `${run.id}:multi-agent:group:${record.groupId}`, to: `${run.id}:multi-agent:fanout:${record.id}` });
902
- for (const dispatchId of record.dispatchIds)
903
- edges.push({ from: `${run.id}:multi-agent:fanout:${record.id}`, to: `${run.id}:dispatch:${dispatchId}`, label: "dispatch" });
904
- }
905
- for (const record of state.memberships) {
906
- nodes.push({ id: `${run.id}:multi-agent:membership:${record.id}`, kind: "agent-membership", status: record.status, label: `${record.roleId}/${record.taskId}`, path: recordPath(run, "memberships", record.id) });
907
- edges.push({ from: `${run.id}:multi-agent:group:${record.groupId}`, to: `${run.id}:multi-agent:membership:${record.id}` });
908
- edges.push({ from: `${run.id}:multi-agent:role:${record.roleId}`, to: `${run.id}:multi-agent:membership:${record.id}` });
909
- edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:task:${record.taskId}`, label: "task" });
910
- if (record.workerId)
911
- edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:worker:${record.workerId}`, label: "worker" });
912
- if (record.resultNodeId)
913
- edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: record.resultNodeId, label: "result" });
914
- if (record.verifierNodeId)
915
- edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: record.verifierNodeId, label: "verifier" });
916
- if (record.blackboardId)
917
- edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
918
- for (const artifactId of record.blackboardArtifactRefIds || [])
919
- edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:blackboard:artifact:${artifactId}`, label: "evidence" });
920
- for (const messageId of record.blackboardMessageIds || [])
921
- edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:blackboard:message:${messageId}`, label: "message" });
922
- }
923
- for (const record of state.fanins) {
924
- nodes.push({ id: `${run.id}:multi-agent:fanin:${record.id}`, kind: "agent-fanin", status: record.status, label: record.strategy, path: recordPath(run, "fanins", record.id) });
925
- edges.push({ from: `${run.id}:multi-agent:group:${record.groupId}`, to: `${run.id}:multi-agent:fanin:${record.id}` });
926
- if (record.fanoutId)
927
- edges.push({ from: `${run.id}:multi-agent:fanout:${record.fanoutId}`, to: `${run.id}:multi-agent:fanin:${record.id}` });
928
- for (const membershipId of record.reportedMembershipIds)
929
- edges.push({ from: `${run.id}:multi-agent:membership:${membershipId}`, to: `${run.id}:multi-agent:fanin:${record.id}`, label: "reported" });
930
- for (const membershipId of record.missingMembershipIds)
931
- edges.push({ from: `${run.id}:multi-agent:membership:${membershipId}`, to: `${run.id}:multi-agent:fanin:${record.id}`, label: "missing" });
932
- if (record.blackboardId)
933
- edges.push({ from: `${run.id}:multi-agent:fanin:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
934
- }
935
- if (!node_fs_1.default.existsSync(root))
936
- node_fs_1.default.mkdirSync(root, { recursive: true });
937
- return { nodes, edges: uniqueEdges(edges) };
877
+ return (0, graph_1.buildMultiAgentGraphFromState)(run, state);
938
878
  }
939
879
  function getMultiAgentRun(run, id) {
940
880
  return ensureMultiAgentState(run).runs.find((record) => record.id === id);
@@ -984,31 +924,11 @@ function requireRunTask(run, id) {
984
924
  throw new Error(`Unknown task id for multi-agent record: ${id}`);
985
925
  return task;
986
926
  }
987
- function multiAgentRoot(run) {
988
- return run.paths.multiAgentDir || node_path_1.default.join(run.paths.runDir, "multi-agent");
989
- }
990
- function recordPath(run, kind, id) {
991
- return node_path_1.default.join(multiAgentRoot(run), kind, `${(0, state_1.safeFileName)(id)}.json`);
992
- }
993
927
  function fanoutTopicIds(group, multiAgentRun, input) {
994
928
  return [...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])];
995
929
  }
996
930
  function writeRecord(run, kind, record) {
997
- (0, state_1.writeJson)(recordPath(run, kind, record.id), record);
998
- }
999
- function assertNoRecordPathCollisions(label, records) {
1000
- const seen = new Map();
1001
- for (const record of records) {
1002
- const safe = (0, state_1.safeFileName)(record.id);
1003
- const existing = seen.get(safe);
1004
- if (existing && existing !== record.id) {
1005
- throw new Error(`${label} ids ${existing} and ${record.id} collide on safe file name ${safe}`);
1006
- }
1007
- seen.set(safe, record.id);
1008
- }
1009
- }
1010
- function indexRow(record) {
1011
- return { id: record.id, status: record.status, updatedAt: record.updatedAt };
931
+ (0, state_1.writeJson)((0, paths_1.recordPath)(run, kind, record.id), record);
1012
932
  }
1013
933
  function appendMultiAgentNode(run, kind, id, status, metadata, parents = []) {
1014
934
  const nodeId = kind === "multi-agent-run" ? `${run.id}:multi-agent:${id}` : `${run.id}:multi-agent:${kind.replace("agent-", "")}:${id}`;
@@ -1018,81 +938,12 @@ function appendMultiAgentNode(run, kind, id, status, metadata, parents = []) {
1018
938
  status,
1019
939
  loopStage: run.loopStage,
1020
940
  outputs: metadata,
1021
- artifacts: [{ id: kind, kind: "json", path: recordPath(run, pluralKind(kind), id) }],
941
+ artifacts: [{ id: kind, kind: "json", path: (0, paths_1.recordPath)(run, (0, helpers_1.pluralKind)(kind), id) }],
1022
942
  parents,
1023
943
  contractId: pipeline_contract_1.DEFAULT_PIPELINE_CONTRACT_ID,
1024
944
  metadata
1025
945
  }));
1026
946
  }
1027
- function pluralKind(kind) {
1028
- switch (kind) {
1029
- case "multi-agent-run":
1030
- return "runs";
1031
- case "agent-role":
1032
- return "roles";
1033
- case "agent-group":
1034
- return "groups";
1035
- case "agent-membership":
1036
- return "memberships";
1037
- case "agent-fanout":
1038
- return "fanouts";
1039
- case "agent-fanin":
1040
- return "fanins";
1041
- default:
1042
- return `${kind}s`;
1043
- }
1044
- }
1045
- function statusToNodeStatus(status) {
1046
- switch (status) {
1047
- case "completed":
1048
- case "reported":
1049
- case "ready":
1050
- return "completed";
1051
- case "running":
1052
- case "forming":
1053
- case "collecting":
1054
- case "verifying":
1055
- case "assigned":
1056
- case "active":
1057
- case "dispatched":
1058
- return "running";
1059
- case "blocked":
1060
- return "blocked";
1061
- case "failed":
1062
- return "failed";
1063
- case "cancelled":
1064
- case "rejected":
1065
- return "rejected";
1066
- default:
1067
- return "pending";
1068
- }
1069
- }
1070
- function assertLifecycleTransition(from, to) {
1071
- const allowed = {
1072
- planned: ["forming", "running", "failed", "cancelled"],
1073
- forming: ["running", "failed", "cancelled"],
1074
- running: ["collecting", "completed", "failed", "cancelled"],
1075
- collecting: ["verifying", "completed", "failed", "cancelled"],
1076
- verifying: ["completed", "failed", "cancelled"],
1077
- completed: [],
1078
- failed: [],
1079
- cancelled: []
1080
- };
1081
- if (from === to)
1082
- return;
1083
- if (!allowed[from].includes(to))
1084
- throw new Error(`Invalid MultiAgentRun lifecycle transition: ${from} -> ${to}`);
1085
- }
1086
- function lifecycleEvent(from, to, reason, actor = "cw", metadata) {
1087
- return {
1088
- at: new Date().toISOString(),
1089
- from,
1090
- to,
1091
- actor,
1092
- reason,
1093
- metadata: compact(metadata)
1094
- };
1095
- }
1096
947
  function attachWorkerMetadata(run, membership) {
1097
948
  const workers = run.workers || [];
1098
949
  const index = workers.findIndex((worker) => worker.id === membership.workerId);
@@ -1117,9 +968,6 @@ function attachWorkerMetadata(run, membership) {
1117
968
  };
1118
969
  run.workers = workers.map((candidate) => (candidate.id === worker.id ? updated : candidate));
1119
970
  }
1120
- function isMembershipReported(membership) {
1121
- return (membership.status === "reported" || membership.status === "verified") && membership.evidenceRefs.length > 0;
1122
- }
1123
971
  function nextMultiAgentAction(run, blockedReasons) {
1124
972
  const state = ensureMultiAgentState(run);
1125
973
  if (!state.runs.length)
@@ -1134,40 +982,3 @@ function nextMultiAgentAction(run, blockedReasons) {
1134
982
  return `node scripts/cw.js multi-agent fanin ${run.id} --group ${groupWithoutFanin.id}`;
1135
983
  return undefined;
1136
984
  }
1137
- function touch(record) {
1138
- record.updatedAt = new Date().toISOString();
1139
- return record;
1140
- }
1141
- function createId(prefix) {
1142
- const stamp = new Date().toISOString().replace(/[-:]/g, "").replace(/\..+/, "Z");
1143
- return `${prefix}-${stamp}-${Math.random().toString(36).slice(2, 8)}`;
1144
- }
1145
- function compact(value) {
1146
- if (!value)
1147
- return undefined;
1148
- const entries = Object.entries(value).filter(([, entry]) => entry !== undefined);
1149
- return entries.length ? Object.fromEntries(entries) : undefined;
1150
- }
1151
- function unique(values) {
1152
- return Array.from(new Set(values.filter(Boolean))).sort();
1153
- }
1154
- function countBy(items, key) {
1155
- const counts = {};
1156
- for (const item of items) {
1157
- const value = key(item);
1158
- counts[value] = (counts[value] || 0) + 1;
1159
- }
1160
- return counts;
1161
- }
1162
- function uniqueEdges(edges) {
1163
- const seen = new Set();
1164
- const result = [];
1165
- for (const edge of edges) {
1166
- const key = `${edge.from}\0${edge.to}\0${edge.label || ""}`;
1167
- if (seen.has(key))
1168
- continue;
1169
- seen.add(key);
1170
- result.push(edge);
1171
- }
1172
- return result;
1173
- }