cool-workflow 0.1.98 → 0.2.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 (306) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +11 -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/cli/dispatch.js +236 -0
  11. package/dist/cli/entry.js +120 -0
  12. package/dist/cli/io.js +21 -4
  13. package/dist/cli/parseargv.js +157 -0
  14. package/dist/cli.js +6 -33
  15. package/dist/core/capability-table.js +3534 -0
  16. package/dist/core/format/help.js +314 -0
  17. package/dist/{state-explosion/format.js → core/format/state-explosion-text.js} +10 -1
  18. package/dist/core/hash.js +137 -0
  19. package/dist/core/multi-agent/candidate-scoring.js +219 -0
  20. package/dist/core/multi-agent/collaboration.js +481 -0
  21. package/dist/core/multi-agent/coordinator.js +515 -0
  22. package/dist/core/multi-agent/eval-replay.js +306 -0
  23. package/dist/core/multi-agent/runtime.js +929 -0
  24. package/dist/core/multi-agent/topology.js +298 -0
  25. package/dist/core/multi-agent/trust-policy.js +197 -0
  26. package/dist/core/pipeline/commit-gate.js +320 -0
  27. package/dist/{pipeline-contract.js → core/pipeline/contract.js} +24 -37
  28. package/dist/core/pipeline/dispatch.js +103 -0
  29. package/dist/core/pipeline/drive-decide.js +227 -0
  30. package/dist/core/pipeline/error-feedback.js +161 -0
  31. package/dist/core/pipeline/loop-expansion.js +124 -0
  32. package/dist/{result-normalize.js → core/pipeline/result-normalize.js} +14 -37
  33. package/dist/core/pipeline/runner.js +230 -0
  34. package/dist/{contract-migration.js → core/state/contract-migration.js} +68 -92
  35. package/dist/{state-migrations.js → core/state/migrations.js} +103 -96
  36. package/dist/core/state/node-projection.js +95 -0
  37. package/dist/core/state/node-snapshot.js +230 -0
  38. package/dist/core/state/run-paths.js +93 -0
  39. package/dist/{schema-validate.js → core/state/schema-validate.js} +35 -28
  40. package/dist/core/state/schema.js +50 -0
  41. package/dist/core/state/state-explosion/digest.js +243 -0
  42. package/dist/core/state/state-explosion/graph.js +527 -0
  43. package/dist/{state-explosion → core/state/state-explosion}/helpers.js +34 -3
  44. package/dist/core/state/state-explosion/report.js +187 -0
  45. package/dist/{state-explosion → core/state/state-explosion}/size.js +25 -7
  46. package/dist/{state-node.js → core/state/state-node.js} +90 -113
  47. package/dist/core/state/types.js +19 -0
  48. package/dist/{validation.js → core/state/validation.js} +64 -131
  49. package/dist/core/trust/evidence-grounding.js +134 -0
  50. package/dist/core/trust/ledger.js +199 -0
  51. package/dist/{telemetry-attestation.js → core/trust/telemetry-attestation.js} +94 -68
  52. package/dist/core/trust/telemetry-ledger.js +127 -0
  53. package/dist/core/types.js +20 -0
  54. package/dist/core/version.js +16 -0
  55. package/dist/{workflow-app-framework.js → core/workflow-apps/app-schema.js} +337 -426
  56. package/dist/mcp/dispatch.js +104 -0
  57. package/dist/mcp/server.js +144 -0
  58. package/dist/mcp-server.js +6 -84
  59. package/dist/{agent-config.js → shell/agent-config.js} +118 -71
  60. package/dist/shell/app-run-cli.js +88 -0
  61. package/dist/shell/audit-cli.js +259 -0
  62. package/dist/shell/audit-provenance.js +83 -0
  63. package/dist/shell/candidate-scoring-io.js +459 -0
  64. package/dist/shell/collaboration-io.js +264 -0
  65. package/dist/shell/commit-summary.js +104 -0
  66. package/dist/shell/commit.js +290 -0
  67. package/dist/shell/coordinator-io.js +476 -0
  68. package/dist/shell/demo-cli.js +19 -0
  69. package/dist/shell/dispatch.js +162 -0
  70. package/dist/{doctor.js → shell/doctor.js} +123 -56
  71. package/dist/shell/drive.js +873 -0
  72. package/dist/shell/error-feedback-io.js +305 -0
  73. package/dist/shell/eval-io.js +473 -0
  74. package/dist/{multi-agent-eval/format.js → shell/eval-text.js} +78 -49
  75. package/dist/{evidence-reasoning.js → shell/evidence-reasoning.js} +124 -255
  76. package/dist/shell/exec-backend-cli.js +88 -0
  77. package/dist/shell/execution-backend/agent.js +475 -0
  78. package/dist/shell/execution-backend/ci.js +15 -0
  79. package/dist/shell/execution-backend/container.js +69 -0
  80. package/dist/shell/execution-backend/envelopes.js +55 -0
  81. package/dist/shell/execution-backend/local.js +113 -0
  82. package/dist/shell/execution-backend/probes.js +175 -0
  83. package/dist/shell/execution-backend/registry.js +402 -0
  84. package/dist/shell/execution-backend/remote.js +128 -0
  85. package/dist/shell/execution-backend/types.js +11 -0
  86. package/dist/shell/feedback-cli.js +81 -0
  87. package/dist/shell/feedback-operations.js +48 -0
  88. package/dist/shell/fs-atomic.js +276 -0
  89. package/dist/shell/harness.js +98 -0
  90. package/dist/shell/ledger-cli.js +212 -0
  91. package/dist/shell/ledger-io.js +169 -0
  92. package/dist/shell/man-cli.js +89 -0
  93. package/dist/shell/metrics-cli.js +98 -0
  94. package/dist/shell/multi-agent-cli.js +1002 -0
  95. package/dist/shell/multi-agent-host.js +563 -0
  96. package/dist/shell/multi-agent-io.js +387 -0
  97. package/dist/{multi-agent-operator-ux.js → shell/multi-agent-operator-ux.js} +234 -191
  98. package/dist/shell/node-store.js +124 -0
  99. package/dist/{observability/format.js → shell/observability-format.js} +7 -1
  100. package/dist/{observability/intake.js → shell/observability-intake.js} +79 -56
  101. package/dist/{observability.js → shell/observability.js} +159 -332
  102. package/dist/{onramp.js → shell/onramp.js} +11 -0
  103. package/dist/{operator-ux/format.js → shell/operator-ux-text.js} +250 -239
  104. package/dist/shell/operator-ux.js +431 -0
  105. package/dist/shell/orchestrator.js +231 -0
  106. package/dist/shell/pipeline-cli.js +667 -0
  107. package/dist/shell/pipeline.js +217 -0
  108. package/dist/shell/reclamation-io.js +1366 -0
  109. package/dist/shell/registry-cli.js +329 -0
  110. package/dist/{remote-source.js → shell/remote-source.js} +2 -2
  111. package/dist/shell/report-cli.js +101 -0
  112. package/dist/shell/report-view-cli.js +117 -0
  113. package/dist/{orchestrator → shell}/report.js +289 -282
  114. package/dist/shell/reporter.js +62 -0
  115. package/dist/shell/run-export-cli.js +106 -0
  116. package/dist/shell/run-export.js +680 -0
  117. package/dist/shell/run-registry-io.js +1014 -0
  118. package/dist/shell/run-store.js +164 -0
  119. package/dist/{sandbox-profile.js → shell/sandbox-profile.js} +134 -95
  120. package/dist/{scheduler.js → shell/scheduler-io.js} +248 -48
  121. package/dist/shell/scheduling-io.js +311 -0
  122. package/dist/shell/state-cli.js +181 -0
  123. package/dist/shell/state-explosion-cli.js +197 -0
  124. package/dist/shell/telemetry-cli.js +85 -0
  125. package/dist/{telemetry-demo.js → shell/telemetry-demo.js} +149 -119
  126. package/dist/shell/telemetry-ledger-io.js +132 -0
  127. package/dist/{term.js → shell/term.js} +36 -46
  128. package/dist/shell/topology-io.js +361 -0
  129. package/dist/shell/trust-audit.js +471 -0
  130. package/dist/{multi-agent-trust.js → shell/trust-policy-io.js} +67 -205
  131. package/dist/shell/verifier.js +48 -0
  132. package/dist/shell/workbench-host.js +250 -0
  133. package/dist/shell/workbench-text.js +18 -0
  134. package/dist/shell/workbench.js +175 -0
  135. package/dist/shell/worker-cli.js +124 -0
  136. package/dist/shell/worker-isolation.js +852 -0
  137. package/dist/shell/workflow-app-loader.js +650 -0
  138. package/docs/agent-delegation-drive.7.md +2 -0
  139. package/docs/cli-mcp-parity.7.md +280 -219
  140. package/docs/contract-migration-tooling.7.md +2 -0
  141. package/docs/control-plane-scheduling.7.md +2 -0
  142. package/docs/durable-state-and-locking.7.md +2 -0
  143. package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
  144. package/docs/execution-backends.7.md +2 -0
  145. package/docs/multi-agent-cli-mcp-surface.7.md +2 -0
  146. package/docs/multi-agent-eval-replay-harness.7.md +2 -0
  147. package/docs/multi-agent-operator-ux.7.md +2 -0
  148. package/docs/node-snapshot-diff-replay.7.md +2 -0
  149. package/docs/observability-cost-accounting.7.md +2 -0
  150. package/docs/project-index.md +132 -71
  151. package/docs/real-execution-backends.7.md +2 -0
  152. package/docs/release-and-migration.7.md +2 -0
  153. package/docs/release-tooling.7.md +2 -0
  154. package/docs/run-registry-control-plane.7.md +2 -0
  155. package/docs/run-retention-reclamation.7.md +23 -0
  156. package/docs/state-explosion-management.7.md +2 -0
  157. package/docs/team-collaboration.7.md +2 -0
  158. package/docs/web-desktop-workbench.7.md +2 -0
  159. package/manifest/plugin.manifest.json +1 -1
  160. package/manifest/source-context-profiles.json +9 -13
  161. package/package.json +1 -1
  162. package/scripts/agents/cw-attest-wrap.js +2 -2
  163. package/scripts/bump-version.js +4 -3
  164. package/scripts/canonical-apps.js +4 -4
  165. package/scripts/dogfood-architecture-review.js +2 -3
  166. package/scripts/dogfood-release.js +3 -3
  167. package/scripts/gen-parity-doc.js +15 -2
  168. package/scripts/golden-path.js +4 -4
  169. package/scripts/onramp-check.js +1 -1
  170. package/scripts/parity-check.js +38 -21
  171. package/scripts/release-flow.js +2 -2
  172. package/scripts/sync-project-index.js +51 -27
  173. package/scripts/validate-run-state-schema.js +2 -2
  174. package/scripts/version-sync-check.js +30 -30
  175. package/dist/candidate-scoring.js +0 -729
  176. package/dist/capability-core.js +0 -1189
  177. package/dist/capability-registry.js +0 -885
  178. package/dist/cli/command-surface.js +0 -494
  179. package/dist/cli/format.js +0 -56
  180. package/dist/cli/handlers/audit.js +0 -82
  181. package/dist/cli/handlers/blackboard.js +0 -81
  182. package/dist/cli/handlers/candidate.js +0 -40
  183. package/dist/cli/handlers/clones.js +0 -34
  184. package/dist/cli/handlers/collaboration.js +0 -61
  185. package/dist/cli/handlers/eval.js +0 -40
  186. package/dist/cli/handlers/ledger.js +0 -169
  187. package/dist/cli/handlers/maintenance.js +0 -107
  188. package/dist/cli/handlers/multi-agent.js +0 -165
  189. package/dist/cli/handlers/node.js +0 -41
  190. package/dist/cli/handlers/operational.js +0 -155
  191. package/dist/cli/handlers/operator.js +0 -146
  192. package/dist/cli/handlers/registry.js +0 -68
  193. package/dist/cli/handlers/run.js +0 -153
  194. package/dist/cli/handlers/scheduling.js +0 -132
  195. package/dist/cli/handlers/workbench.js +0 -41
  196. package/dist/cli/handlers/worker.js +0 -45
  197. package/dist/cli/run-summary.js +0 -45
  198. package/dist/clones.js +0 -162
  199. package/dist/collaboration.js +0 -726
  200. package/dist/commit.js +0 -592
  201. package/dist/compare.js +0 -18
  202. package/dist/coordinator/classify.js +0 -45
  203. package/dist/coordinator/paths.js +0 -42
  204. package/dist/coordinator/util.js +0 -126
  205. package/dist/coordinator.js +0 -990
  206. package/dist/daemon.js +0 -44
  207. package/dist/dispatch.js +0 -250
  208. package/dist/drive.js +0 -864
  209. package/dist/error-feedback.js +0 -419
  210. package/dist/evidence-grounding.js +0 -184
  211. package/dist/execution-backend/agent.js +0 -354
  212. package/dist/execution-backend/probes.js +0 -112
  213. package/dist/execution-backend/util.js +0 -47
  214. package/dist/execution-backend.js +0 -961
  215. package/dist/gates.js +0 -48
  216. package/dist/harness.js +0 -61
  217. package/dist/ledger.js +0 -313
  218. package/dist/loop-expansion.js +0 -60
  219. package/dist/mcp/tool-call.js +0 -470
  220. package/dist/mcp/tool-definitions.js +0 -1066
  221. package/dist/mcp-surface.js +0 -30
  222. package/dist/multi-agent/graph.js +0 -84
  223. package/dist/multi-agent/helpers.js +0 -141
  224. package/dist/multi-agent/ids.js +0 -20
  225. package/dist/multi-agent/paths.js +0 -22
  226. package/dist/multi-agent-eval/normalize.js +0 -51
  227. package/dist/multi-agent-eval.js +0 -678
  228. package/dist/multi-agent-host.js +0 -777
  229. package/dist/multi-agent.js +0 -984
  230. package/dist/node-projection.js +0 -59
  231. package/dist/node-snapshot.js +0 -260
  232. package/dist/operator-ux.js +0 -631
  233. package/dist/orchestrator/app-operations.js +0 -211
  234. package/dist/orchestrator/audit-operations.js +0 -182
  235. package/dist/orchestrator/candidate-operations.js +0 -117
  236. package/dist/orchestrator/cli-options.js +0 -294
  237. package/dist/orchestrator/collaboration-operations.js +0 -86
  238. package/dist/orchestrator/feedback-operations.js +0 -81
  239. package/dist/orchestrator/host-operations.js +0 -78
  240. package/dist/orchestrator/lifecycle-operations.js +0 -650
  241. package/dist/orchestrator/migration-operations.js +0 -44
  242. package/dist/orchestrator/multi-agent-operations.js +0 -362
  243. package/dist/orchestrator/topology-operations.js +0 -84
  244. package/dist/orchestrator.js +0 -925
  245. package/dist/pipeline-runner.js +0 -285
  246. package/dist/reclamation/hash.js +0 -72
  247. package/dist/reclamation.js +0 -812
  248. package/dist/reporter.js +0 -67
  249. package/dist/run-export.js +0 -815
  250. package/dist/run-registry/derive.js +0 -175
  251. package/dist/run-registry/format.js +0 -124
  252. package/dist/run-registry/gc.js +0 -251
  253. package/dist/run-registry/policy.js +0 -16
  254. package/dist/run-registry/queue.js +0 -115
  255. package/dist/run-registry.js +0 -850
  256. package/dist/run-state-schema.js +0 -68
  257. package/dist/scheduling.js +0 -184
  258. package/dist/state-explosion.js +0 -1014
  259. package/dist/state.js +0 -367
  260. package/dist/telemetry-ledger.js +0 -196
  261. package/dist/topology.js +0 -565
  262. package/dist/triggers.js +0 -184
  263. package/dist/trust-audit.js +0 -644
  264. package/dist/types/blackboard.js +0 -2
  265. package/dist/types/candidate.js +0 -2
  266. package/dist/types/collaboration.js +0 -2
  267. package/dist/types/core.js +0 -2
  268. package/dist/types/drive.js +0 -10
  269. package/dist/types/error-feedback.js +0 -2
  270. package/dist/types/evidence-reasoning.js +0 -2
  271. package/dist/types/execution-backend.js +0 -2
  272. package/dist/types/multi-agent.js +0 -2
  273. package/dist/types/observability.js +0 -2
  274. package/dist/types/pipeline.js +0 -2
  275. package/dist/types/reclamation.js +0 -8
  276. package/dist/types/report-bundle.js +0 -6
  277. package/dist/types/result.js +0 -2
  278. package/dist/types/run-registry.js +0 -2
  279. package/dist/types/run.js +0 -2
  280. package/dist/types/sandbox.js +0 -2
  281. package/dist/types/schedule.js +0 -2
  282. package/dist/types/state-node.js +0 -2
  283. package/dist/types/topology.js +0 -2
  284. package/dist/types/trust.js +0 -2
  285. package/dist/types/workbench.js +0 -2
  286. package/dist/types/worker.js +0 -2
  287. package/dist/types/workflow-app.js +0 -2
  288. package/dist/types.js +0 -44
  289. package/dist/util/fingerprint.js +0 -19
  290. package/dist/util/fingerprint.test.js +0 -27
  291. package/dist/verifier.js +0 -78
  292. package/dist/version.js +0 -8
  293. package/dist/workbench-host.js +0 -192
  294. package/dist/workbench.js +0 -192
  295. package/dist/worker-accept/acceptance.js +0 -114
  296. package/dist/worker-accept/blackboard-fanout.js +0 -80
  297. package/dist/worker-accept/blackboard-linkage.js +0 -19
  298. package/dist/worker-accept/context.js +0 -2
  299. package/dist/worker-accept/telemetry-ledger.js +0 -126
  300. package/dist/worker-accept/validation.js +0 -77
  301. package/dist/worker-accept/verifier-completion.js +0 -73
  302. package/dist/worker-isolation/helpers.js +0 -51
  303. package/dist/worker-isolation/paths.js +0 -46
  304. package/dist/worker-isolation.js +0 -656
  305. package/dist/workflow-api.js +0 -131
  306. /package/dist/{types → core/types}/boundary.js +0 -0
@@ -1,984 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.MULTI_AGENT_SCHEMA_VERSION = void 0;
7
- exports.ensureMultiAgentState = ensureMultiAgentState;
8
- exports.persistMultiAgentState = persistMultiAgentState;
9
- exports.createMultiAgentRun = createMultiAgentRun;
10
- exports.transitionMultiAgentRun = transitionMultiAgentRun;
11
- exports.createAgentRole = createAgentRole;
12
- exports.createAgentGroup = createAgentGroup;
13
- exports.assignAgentMembership = assignAgentMembership;
14
- exports.createAgentFanout = createAgentFanout;
15
- exports.attachDispatchToMultiAgent = attachDispatchToMultiAgent;
16
- exports.collectAgentFanin = collectAgentFanin;
17
- exports.recordMultiAgentWorkerOutput = recordMultiAgentWorkerOutput;
18
- exports.summarizeMultiAgent = summarizeMultiAgent;
19
- exports.buildMultiAgentGraph = buildMultiAgentGraph;
20
- exports.getMultiAgentRun = getMultiAgentRun;
21
- exports.getAgentRole = getAgentRole;
22
- exports.getAgentGroup = getAgentGroup;
23
- exports.getAgentMembership = getAgentMembership;
24
- exports.getAgentFanout = getAgentFanout;
25
- exports.getAgentFanin = getAgentFanin;
26
- const node_fs_1 = __importDefault(require("node:fs"));
27
- const node_path_1 = __importDefault(require("node:path"));
28
- const state_1 = require("./state");
29
- const pipeline_contract_1 = require("./pipeline-contract");
30
- const state_node_1 = require("./state-node");
31
- const trust_audit_1 = require("./trust-audit");
32
- const multi_agent_trust_1 = require("./multi-agent-trust");
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; } });
37
- function ensureMultiAgentState(run) {
38
- run.paths.multiAgentDir = (0, paths_1.multiAgentRoot)(run);
39
- node_fs_1.default.mkdirSync(run.paths.multiAgentDir, { recursive: true });
40
- for (const dir of ["runs", "roles", "groups", "memberships", "fanouts", "fanins"]) {
41
- node_fs_1.default.mkdirSync(node_path_1.default.join(run.paths.multiAgentDir, dir), { recursive: true });
42
- }
43
- if (!run.multiAgent) {
44
- run.multiAgent = {
45
- schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
46
- runs: [],
47
- roles: [],
48
- groups: [],
49
- memberships: [],
50
- fanouts: [],
51
- fanins: []
52
- };
53
- }
54
- run.multiAgent.schemaVersion = helpers_1.MULTI_AGENT_SCHEMA_VERSION;
55
- run.multiAgent.runs = run.multiAgent.runs || [];
56
- run.multiAgent.roles = run.multiAgent.roles || [];
57
- run.multiAgent.groups = run.multiAgent.groups || [];
58
- run.multiAgent.memberships = run.multiAgent.memberships || [];
59
- run.multiAgent.fanouts = run.multiAgent.fanouts || [];
60
- run.multiAgent.fanins = run.multiAgent.fanins || [];
61
- return run.multiAgent;
62
- }
63
- function persistMultiAgentState(run) {
64
- const state = ensureMultiAgentState(run);
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);
72
- (0, state_1.writeJson)(node_path_1.default.join(root, "index.json"), {
73
- schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
74
- runId: run.id,
75
- counts: {
76
- runs: state.runs.length,
77
- roles: state.roles.length,
78
- groups: state.groups.length,
79
- memberships: state.memberships.length,
80
- fanouts: state.fanouts.length,
81
- fanins: state.fanins.length
82
- },
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)
89
- });
90
- for (const record of state.runs)
91
- writeRecord(run, "runs", record);
92
- for (const record of state.roles)
93
- writeRecord(run, "roles", record);
94
- for (const record of state.groups)
95
- writeRecord(run, "groups", record);
96
- for (const record of state.memberships)
97
- writeRecord(run, "memberships", record);
98
- for (const record of state.fanouts)
99
- writeRecord(run, "fanouts", record);
100
- for (const record of state.fanins)
101
- writeRecord(run, "fanins", record);
102
- }
103
- function createMultiAgentRun(run, input = {}) {
104
- const state = ensureMultiAgentState(run);
105
- const id = input.id || (0, helpers_1.createId)("mar", state.runs.length + 1);
106
- if (state.runs.some((record) => record.id === id))
107
- throw new Error(`Duplicate MultiAgentRun id: ${id}`);
108
- const now = new Date().toISOString();
109
- const status = input.status || "planned";
110
- const record = {
111
- schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
112
- id,
113
- runId: run.id,
114
- createdAt: now,
115
- updatedAt: now,
116
- status,
117
- title: input.title || id,
118
- objective: input.objective,
119
- parentMultiAgentRunId: input.parentMultiAgentRunId,
120
- childMultiAgentRunIds: [],
121
- roleIds: [],
122
- groupIds: [],
123
- fanoutIds: [],
124
- faninIds: [],
125
- blackboardId: input.blackboardId,
126
- topicIds: (0, helpers_1.unique)(input.topicIds || []),
127
- lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, status, "created")],
128
- links: {
129
- workflowRunId: run.id,
130
- phase: input.phase,
131
- phaseId: input.phaseId,
132
- blackboardId: input.blackboardId,
133
- blackboardTopicIds: (0, helpers_1.unique)(input.topicIds || [])
134
- },
135
- policy: {
136
- schemaVersion: 1,
137
- id: `${id}-policy`,
138
- policyRef: `multiAgent.runs.${id}.policy`,
139
- subjectKind: "multi-agent-run",
140
- subjectId: id,
141
- allowedBlackboardTopicIds: (0, helpers_1.unique)(input.topicIds || ["*"]),
142
- allowedWriteOperations: ["message", "context", "artifact", "snapshot", "topic", "coordinator-decision"],
143
- allowedCandidateOperations: ["register", "score", "select"],
144
- allowedJudgeOperations: ["verdict", "rationale", "panel-decision"],
145
- sandboxProfileHints: [],
146
- requiredEvidenceRefs: [],
147
- deniedOperations: [],
148
- metadata: { title: input.title }
149
- },
150
- metadata: (0, helpers_1.compact)(input.metadata)
151
- };
152
- if (record.parentMultiAgentRunId) {
153
- const parent = requireMultiAgentRun(run, record.parentMultiAgentRunId);
154
- parent.childMultiAgentRunIds = (0, helpers_1.unique)([...parent.childMultiAgentRunIds, record.id]);
155
- (0, helpers_1.touch)(parent);
156
- }
157
- state.runs.push(record);
158
- appendMultiAgentNode(run, "multi-agent-run", record.id, (0, helpers_1.statusToNodeStatus)(status), {
159
- title: record.title,
160
- objective: record.objective,
161
- phase: record.links.phase
162
- });
163
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
164
- kind: "multi-agent.run",
165
- decision: "recorded",
166
- source: "runtime-derived",
167
- multiAgentRunId: record.id,
168
- metadata: { status: record.status, objective: record.objective }
169
- });
170
- persistMultiAgentState(run);
171
- return record;
172
- }
173
- function transitionMultiAgentRun(run, multiAgentRunId, status, options = {}) {
174
- ensureMultiAgentState(run);
175
- const record = requireMultiAgentRun(run, multiAgentRunId);
176
- (0, helpers_1.assertLifecycleTransition)(record.status, status);
177
- if (status === "completed")
178
- assertMultiAgentRunCompletionReady(run, record);
179
- const before = record.status;
180
- record.status = status;
181
- record.updatedAt = new Date().toISOString();
182
- record.lifecycle.push((0, helpers_1.lifecycleEvent)(before, status, options.reason, options.actor, options.metadata));
183
- if (status === "completed")
184
- completeOwnedMultiAgentRecords(run, record, options.reason);
185
- appendMultiAgentNode(run, "multi-agent-run", record.id, (0, helpers_1.statusToNodeStatus)(status), {
186
- status,
187
- reason: options.reason
188
- });
189
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
190
- kind: "multi-agent.lifecycle",
191
- decision: status === "failed" ? "failed" : "validated",
192
- source: "cw-validated",
193
- multiAgentRunId: record.id,
194
- metadata: { from: before, to: status, reason: options.reason }
195
- });
196
- persistMultiAgentState(run);
197
- return record;
198
- }
199
- function assertMultiAgentRunCompletionReady(run, multiAgentRun) {
200
- const state = ensureMultiAgentState(run);
201
- const groups = state.groups.filter((record) => record.multiAgentRunId === multiAgentRun.id);
202
- const fanins = state.fanins.filter((record) => record.multiAgentRunId === multiAgentRun.id);
203
- const blocked = fanins.flatMap((fanin) => {
204
- const reasons = [...fanin.blockedReasons];
205
- if (fanin.status === "blocked" || fanin.status === "failed")
206
- reasons.push(`fanin ${fanin.id} status is ${fanin.status}`);
207
- if (!fanin.verifierReady)
208
- reasons.push(`fanin ${fanin.id} is not verifier-ready`);
209
- return reasons.map((reason) => `${fanin.id}: ${reason}`);
210
- });
211
- for (const group of groups) {
212
- if ((group.membershipIds.length || group.fanoutIds.length) && !group.faninIds.length) {
213
- blocked.push(`group ${group.id} has no fanin record`);
214
- }
215
- }
216
- if (blocked.length) {
217
- throw new Error(`Cannot complete MultiAgentRun ${multiAgentRun.id}: ${blocked.join("; ")}`);
218
- }
219
- }
220
- function completeOwnedMultiAgentRecords(run, multiAgentRun, reason) {
221
- const state = ensureMultiAgentState(run);
222
- for (const role of state.roles.filter((record) => record.multiAgentRunId === multiAgentRun.id)) {
223
- if (role.status === "completed" || role.status === "cancelled")
224
- continue;
225
- const before = role.status;
226
- role.status = "completed";
227
- role.updatedAt = multiAgentRun.updatedAt;
228
- role.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "completed", reason || "multi-agent run completed"));
229
- }
230
- for (const group of state.groups.filter((record) => record.multiAgentRunId === multiAgentRun.id)) {
231
- if (group.status === "completed" || group.status === "failed" || group.status === "cancelled")
232
- continue;
233
- const before = group.status;
234
- group.status = "completed";
235
- group.updatedAt = multiAgentRun.updatedAt;
236
- group.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "completed", reason || "multi-agent run completed"));
237
- }
238
- for (const fanout of state.fanouts.filter((record) => record.multiAgentRunId === multiAgentRun.id)) {
239
- if (fanout.status === "completed" || fanout.status === "failed" || fanout.status === "cancelled")
240
- continue;
241
- const before = fanout.status;
242
- fanout.status = "completed";
243
- fanout.updatedAt = multiAgentRun.updatedAt;
244
- fanout.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "completed", reason || "multi-agent run completed"));
245
- }
246
- for (const fanin of state.fanins.filter((record) => record.multiAgentRunId === multiAgentRun.id)) {
247
- if (fanin.status === "completed" || fanin.status === "failed")
248
- continue;
249
- const before = fanin.status;
250
- fanin.status = "completed";
251
- fanin.updatedAt = multiAgentRun.updatedAt;
252
- fanin.lifecycle.push((0, helpers_1.lifecycleEvent)(before, "completed", reason || "multi-agent run completed"));
253
- }
254
- }
255
- function createAgentRole(run, input) {
256
- const state = ensureMultiAgentState(run);
257
- const multiAgentRun = requireMultiAgentRun(run, input.multiAgentRunId);
258
- const id = input.id || (0, helpers_1.createId)("role", state.roles.length + 1);
259
- if (state.roles.some((record) => record.id === id))
260
- throw new Error(`Duplicate AgentRole id: ${id}`);
261
- if (input.parentRoleId)
262
- requireAgentRole(run, input.parentRoleId);
263
- const now = new Date().toISOString();
264
- const role = {
265
- schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
266
- id,
267
- runId: run.id,
268
- multiAgentRunId: multiAgentRun.id,
269
- createdAt: now,
270
- updatedAt: now,
271
- status: "planned",
272
- title: input.title || id,
273
- responsibilities: input.responsibilities || [],
274
- requiredEvidence: input.requiredEvidence || [],
275
- sandboxProfileHints: input.sandboxProfileHints || [],
276
- expectedArtifacts: input.expectedArtifacts || [],
277
- faninObligations: input.faninObligations || [],
278
- blackboardId: input.blackboardId || multiAgentRun.blackboardId,
279
- topicIds: (0, helpers_1.unique)([...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
280
- lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, "planned", "created")],
281
- parentRoleId: input.parentRoleId,
282
- childRoleIds: [],
283
- policy: undefined,
284
- metadata: (0, helpers_1.compact)(input.metadata)
285
- };
286
- role.policy = (0, multi_agent_trust_1.policyForRole)(role);
287
- if (role.parentRoleId) {
288
- const parent = requireAgentRole(run, role.parentRoleId);
289
- parent.childRoleIds = (0, helpers_1.unique)([...parent.childRoleIds, role.id]);
290
- (0, helpers_1.touch)(parent);
291
- }
292
- state.roles.push(role);
293
- multiAgentRun.roleIds = (0, helpers_1.unique)([...multiAgentRun.roleIds, role.id]);
294
- (0, helpers_1.touch)(multiAgentRun);
295
- appendMultiAgentNode(run, "agent-role", role.id, "pending", {
296
- multiAgentRunId: role.multiAgentRunId,
297
- title: role.title,
298
- responsibilities: role.responsibilities,
299
- requiredEvidence: role.requiredEvidence
300
- }, [`${run.id}:multi-agent:${role.multiAgentRunId}`]);
301
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
302
- kind: "multi-agent.role",
303
- decision: "recorded",
304
- source: "runtime-derived",
305
- multiAgentRunId: role.multiAgentRunId,
306
- agentRoleId: role.id,
307
- metadata: {
308
- responsibilities: role.responsibilities,
309
- requiredEvidence: role.requiredEvidence,
310
- sandboxProfileHints: role.sandboxProfileHints,
311
- faninObligations: role.faninObligations
312
- }
313
- });
314
- (0, multi_agent_trust_1.recordRolePolicyAudit)(run, role);
315
- persistMultiAgentState(run);
316
- return role;
317
- }
318
- function createAgentGroup(run, input) {
319
- const state = ensureMultiAgentState(run);
320
- const multiAgentRun = requireMultiAgentRun(run, input.multiAgentRunId);
321
- const id = input.id || (0, helpers_1.createId)("group", state.groups.length + 1);
322
- if (state.groups.some((record) => record.id === id))
323
- throw new Error(`Duplicate AgentGroup id: ${id}`);
324
- if (input.parentGroupId)
325
- requireAgentGroup(run, input.parentGroupId);
326
- for (const taskId of input.taskIds || [])
327
- requireRunTask(run, taskId);
328
- const now = new Date().toISOString();
329
- const group = {
330
- schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
331
- id,
332
- runId: run.id,
333
- multiAgentRunId: multiAgentRun.id,
334
- createdAt: now,
335
- updatedAt: now,
336
- status: "forming",
337
- title: input.title || id,
338
- phase: input.phase,
339
- phaseId: input.phaseId,
340
- taskIds: (0, helpers_1.unique)(input.taskIds || []),
341
- roleIds: [],
342
- membershipIds: [],
343
- workerIds: [],
344
- fanoutIds: [],
345
- faninIds: [],
346
- blackboardId: input.blackboardId || multiAgentRun.blackboardId,
347
- topicIds: (0, helpers_1.unique)([...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
348
- lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, "forming", "created")],
349
- parentGroupId: input.parentGroupId,
350
- childGroupIds: [],
351
- policy: undefined,
352
- metadata: (0, helpers_1.compact)(input.metadata)
353
- };
354
- group.policy = (0, multi_agent_trust_1.policyForGroup)(group);
355
- if (group.parentGroupId) {
356
- const parent = requireAgentGroup(run, group.parentGroupId);
357
- parent.childGroupIds = (0, helpers_1.unique)([...parent.childGroupIds, group.id]);
358
- (0, helpers_1.touch)(parent);
359
- }
360
- state.groups.push(group);
361
- multiAgentRun.groupIds = (0, helpers_1.unique)([...multiAgentRun.groupIds, group.id]);
362
- (0, helpers_1.touch)(multiAgentRun);
363
- appendMultiAgentNode(run, "agent-group", group.id, "running", {
364
- multiAgentRunId: group.multiAgentRunId,
365
- phase: group.phase,
366
- taskIds: group.taskIds
367
- }, [`${run.id}:multi-agent:${group.multiAgentRunId}`]);
368
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
369
- kind: "multi-agent.group",
370
- decision: "recorded",
371
- source: "runtime-derived",
372
- multiAgentRunId: group.multiAgentRunId,
373
- agentGroupId: group.id,
374
- metadata: { phase: group.phase, taskIds: group.taskIds }
375
- });
376
- persistMultiAgentState(run);
377
- return group;
378
- }
379
- function assignAgentMembership(run, input) {
380
- const state = ensureMultiAgentState(run);
381
- const group = requireAgentGroup(run, input.groupId);
382
- const role = requireAgentRole(run, input.roleId);
383
- if (role.multiAgentRunId !== group.multiAgentRunId) {
384
- throw new Error(`AgentRole ${role.id} belongs to ${role.multiAgentRunId}, not group run ${group.multiAgentRunId}`);
385
- }
386
- if (input.multiAgentRunId && input.multiAgentRunId !== group.multiAgentRunId) {
387
- throw new Error(`Membership multiAgentRunId ${input.multiAgentRunId} does not match group ${group.id}`);
388
- }
389
- const task = requireRunTask(run, input.taskId);
390
- if (input.workerId && !(run.workers || []).some((worker) => worker.id === input.workerId)) {
391
- throw new Error(`Unknown worker id for membership: ${input.workerId}`);
392
- }
393
- const duplicate = state.memberships.find((membership) => membership.groupId === group.id &&
394
- membership.roleId === role.id &&
395
- membership.taskId === task.id &&
396
- (input.workerId ? membership.workerId === input.workerId : !membership.workerId));
397
- if (duplicate) {
398
- throw new Error(`Duplicate AgentMembership for group=${group.id}, role=${role.id}, task=${task.id}, worker=${input.workerId || "none"}`);
399
- }
400
- const id = input.id || (0, helpers_1.createId)("membership", state.memberships.length + 1);
401
- if (state.memberships.some((record) => record.id === id))
402
- throw new Error(`Duplicate AgentMembership id: ${id}`);
403
- const now = new Date().toISOString();
404
- const status = input.status || (input.workerId ? "running" : "assigned");
405
- const membership = {
406
- schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
407
- id,
408
- runId: run.id,
409
- multiAgentRunId: group.multiAgentRunId,
410
- groupId: group.id,
411
- roleId: role.id,
412
- taskId: task.id,
413
- workerId: input.workerId,
414
- dispatchId: input.dispatchId,
415
- fanoutId: input.fanoutId,
416
- createdAt: now,
417
- updatedAt: now,
418
- status,
419
- lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, status, "assigned")],
420
- evidenceRefs: [],
421
- artifactPaths: [],
422
- blackboardId: input.blackboardId || group.blackboardId || role.blackboardId,
423
- topicIds: (0, helpers_1.unique)([...(group.topicIds || []), ...(role.topicIds || []), ...(input.topicIds || [])]),
424
- blackboardMessageIds: [],
425
- blackboardArtifactRefIds: [],
426
- policy: undefined,
427
- metadata: (0, helpers_1.compact)(input.metadata)
428
- };
429
- membership.policy = (0, multi_agent_trust_1.policyForMembership)(membership, role);
430
- state.memberships.push(membership);
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]);
434
- if (membership.workerId)
435
- group.workerIds = (0, helpers_1.unique)([...group.workerIds, membership.workerId]);
436
- (0, helpers_1.touch)(group);
437
- const roleStatusBefore = role.status;
438
- role.status = "active";
439
- role.updatedAt = now;
440
- role.lifecycle.push((0, helpers_1.lifecycleEvent)(roleStatusBefore, "active", "membership assigned"));
441
- if (membership.workerId)
442
- attachWorkerMetadata(run, membership);
443
- appendMultiAgentNode(run, "agent-membership", membership.id, (0, helpers_1.statusToNodeStatus)(membership.status), {
444
- multiAgentRunId: membership.multiAgentRunId,
445
- groupId: membership.groupId,
446
- roleId: membership.roleId,
447
- taskId: membership.taskId,
448
- workerId: membership.workerId,
449
- dispatchId: membership.dispatchId,
450
- fanoutId: membership.fanoutId
451
- }, [`${run.id}:multi-agent:group:${membership.groupId}`, `${run.id}:multi-agent:role:${membership.roleId}`]);
452
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
453
- kind: "multi-agent.membership",
454
- decision: "recorded",
455
- source: "runtime-derived",
456
- workerId: membership.workerId,
457
- taskId: membership.taskId,
458
- multiAgentRunId: membership.multiAgentRunId,
459
- agentRoleId: membership.roleId,
460
- agentGroupId: membership.groupId,
461
- agentMembershipId: membership.id,
462
- agentFanoutId: membership.fanoutId,
463
- metadata: { status: membership.status, dispatchId: membership.dispatchId }
464
- });
465
- persistMultiAgentState(run);
466
- return membership;
467
- }
468
- function createAgentFanout(run, input) {
469
- const state = ensureMultiAgentState(run);
470
- const group = requireAgentGroup(run, input.groupId);
471
- const multiAgentRun = requireMultiAgentRun(run, input.multiAgentRunId || group.multiAgentRunId);
472
- if (group.multiAgentRunId !== multiAgentRun.id)
473
- throw new Error(`AgentGroup ${group.id} does not belong to ${multiAgentRun.id}`);
474
- const id = input.id || (0, helpers_1.createId)("fanout", state.fanouts.length + 1);
475
- if (state.fanouts.some((record) => record.id === id))
476
- throw new Error(`Duplicate AgentFanout id: ${id}`);
477
- for (const roleId of input.roleIds || [])
478
- requireAgentRole(run, roleId);
479
- for (const taskId of input.taskIds || [])
480
- requireRunTask(run, taskId);
481
- const now = new Date().toISOString();
482
- const fanout = {
483
- schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
484
- id,
485
- runId: run.id,
486
- multiAgentRunId: multiAgentRun.id,
487
- groupId: group.id,
488
- createdAt: now,
489
- updatedAt: now,
490
- status: "planned",
491
- reason: input.reason,
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 || []),
497
- concurrencyLimit: input.concurrencyLimit,
498
- sandboxProfileChoices: input.sandboxProfileChoices || {},
499
- expectedReturnShape: input.expectedReturnShape || "Each member writes a Markdown result with a cw:result JSON fence containing summary, findings, and evidence.",
500
- blackboardId: input.blackboardId || group.blackboardId || multiAgentRun.blackboardId,
501
- topicIds: (0, helpers_1.unique)([...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
502
- lifecycle: [(0, helpers_1.lifecycleEvent)(undefined, "planned", "created")],
503
- policy: {
504
- schemaVersion: 1,
505
- id: `${id}-policy`,
506
- policyRef: `multiAgent.fanouts.${id}.policy`,
507
- subjectKind: "fanout",
508
- subjectId: id,
509
- allowedBlackboardTopicIds: (0, helpers_1.unique)(fanoutTopicIds(group, multiAgentRun, input)),
510
- allowedWriteOperations: ["message", "context", "artifact"],
511
- allowedCandidateOperations: ["register"],
512
- allowedJudgeOperations: [],
513
- sandboxProfileHints: (0, helpers_1.unique)(Object.values(input.sandboxProfileChoices || {}).map(String)),
514
- requiredEvidenceRefs: [],
515
- deniedOperations: [],
516
- metadata: { reason: input.reason }
517
- },
518
- metadata: (0, helpers_1.compact)(input.metadata)
519
- };
520
- state.fanouts.push(fanout);
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);
527
- appendMultiAgentNode(run, "agent-fanout", fanout.id, "pending", {
528
- multiAgentRunId: fanout.multiAgentRunId,
529
- groupId: fanout.groupId,
530
- reason: fanout.reason,
531
- roleIds: fanout.roleIds,
532
- taskIds: fanout.taskIds,
533
- concurrencyLimit: fanout.concurrencyLimit,
534
- sandboxProfileChoices: fanout.sandboxProfileChoices
535
- }, [`${run.id}:multi-agent:group:${fanout.groupId}`]);
536
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
537
- kind: "multi-agent.fanout",
538
- decision: "recorded",
539
- source: "runtime-derived",
540
- multiAgentRunId: fanout.multiAgentRunId,
541
- agentGroupId: fanout.groupId,
542
- agentFanoutId: fanout.id,
543
- metadata: {
544
- reason: fanout.reason,
545
- roleIds: fanout.roleIds,
546
- taskIds: fanout.taskIds,
547
- concurrencyLimit: fanout.concurrencyLimit,
548
- sandboxProfileChoices: fanout.sandboxProfileChoices
549
- }
550
- });
551
- persistMultiAgentState(run);
552
- return fanout;
553
- }
554
- function attachDispatchToMultiAgent(run, input) {
555
- if (!input.multiAgentRunId && !input.groupId && !input.roleId && !input.fanoutId)
556
- return { membershipIds: [] };
557
- const state = ensureMultiAgentState(run);
558
- let fanout = input.fanoutId ? requireAgentFanout(run, input.fanoutId) : undefined;
559
- let group = input.groupId ? requireAgentGroup(run, input.groupId) : undefined;
560
- if (!group && fanout)
561
- group = requireAgentGroup(run, fanout.groupId);
562
- const multiAgentRun = requireMultiAgentRun(run, input.multiAgentRunId || group?.multiAgentRunId || fanout?.multiAgentRunId || "");
563
- if (!group)
564
- throw new Error("Dispatch multi-agent attach requires --multi-agent-group or --multiAgentGroup");
565
- if (group.multiAgentRunId !== multiAgentRun.id)
566
- throw new Error(`Group ${group.id} does not belong to MultiAgentRun ${multiAgentRun.id}`);
567
- const roleIds = input.roleId ? [input.roleId] : (0, helpers_1.unique)([...(fanout ? fanout.roleIds : [])]);
568
- if (roleIds.length !== 1) {
569
- throw new Error(`Dispatch multi-agent attach requires exactly one role for deterministic membership; found ${roleIds.length || 0}`);
570
- }
571
- const role = requireAgentRole(run, roleIds[0]);
572
- if (role.multiAgentRunId !== multiAgentRun.id)
573
- throw new Error(`Role ${role.id} does not belong to MultiAgentRun ${multiAgentRun.id}`);
574
- if (!fanout) {
575
- fanout = createAgentFanout(run, {
576
- multiAgentRunId: multiAgentRun.id,
577
- groupId: group.id,
578
- reason: "dispatch attachment",
579
- roleIds: [role.id],
580
- taskIds: input.tasks.map((task) => task.id),
581
- dispatchIds: [input.dispatchId],
582
- concurrencyLimit: input.concurrencyLimit,
583
- sandboxProfileChoices: input.sandboxProfileId ? { dispatch: input.sandboxProfileId } : {}
584
- });
585
- }
586
- if (fanout.multiAgentRunId !== multiAgentRun.id || fanout.groupId !== group.id) {
587
- throw new Error(`Fanout ${fanout.id} does not match MultiAgentRun ${multiAgentRun.id} and group ${group.id}`);
588
- }
589
- const membershipIds = [];
590
- for (const task of input.tasks) {
591
- if (!task.workerId)
592
- throw new Error(`Task ${task.id} has no worker id for multi-agent membership`);
593
- const membership = assignAgentMembership(run, {
594
- multiAgentRunId: multiAgentRun.id,
595
- groupId: group.id,
596
- roleId: role.id,
597
- taskId: task.id,
598
- workerId: task.workerId,
599
- dispatchId: input.dispatchId,
600
- fanoutId: fanout.id,
601
- status: "running"
602
- });
603
- task.multiAgent = {
604
- runId: multiAgentRun.id,
605
- groupId: group.id,
606
- roleId: role.id,
607
- membershipId: membership.id,
608
- fanoutId: fanout.id
609
- };
610
- membershipIds.push(membership.id);
611
- }
612
- fanout.status = "dispatched";
613
- fanout.updatedAt = new Date().toISOString();
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]);
619
- if (input.sandboxProfileId)
620
- fanout.sandboxProfileChoices.dispatch = input.sandboxProfileId;
621
- const groupStatusBefore = group.status;
622
- group.status = "running";
623
- group.updatedAt = fanout.updatedAt;
624
- group.lifecycle.push((0, helpers_1.lifecycleEvent)(groupStatusBefore, "running", "dispatch created"));
625
- multiAgentRun.status = multiAgentRun.status === "planned" || multiAgentRun.status === "forming" ? "running" : multiAgentRun.status;
626
- (0, helpers_1.touch)(multiAgentRun);
627
- appendMultiAgentNode(run, "agent-fanout", fanout.id, "running", {
628
- status: fanout.status,
629
- dispatchIds: fanout.dispatchIds,
630
- workerIds: fanout.workerIds,
631
- membershipIds: fanout.membershipIds
632
- }, [`${run.id}:dispatch:${input.dispatchId}`]);
633
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
634
- kind: "multi-agent.fanout.dispatch",
635
- decision: "validated",
636
- source: "cw-validated",
637
- multiAgentRunId: multiAgentRun.id,
638
- agentRoleId: role.id,
639
- agentGroupId: group.id,
640
- agentFanoutId: fanout.id,
641
- metadata: { dispatchId: input.dispatchId, membershipIds, workerIds: fanout.workerIds }
642
- });
643
- persistMultiAgentState(run);
644
- return {
645
- multiAgent: {
646
- runId: multiAgentRun.id,
647
- groupId: group.id,
648
- roleId: role.id,
649
- fanoutId: fanout.id
650
- },
651
- membershipIds
652
- };
653
- }
654
- function collectAgentFanin(run, input) {
655
- const state = ensureMultiAgentState(run);
656
- const fanout = input.fanoutId ? requireAgentFanout(run, input.fanoutId) : undefined;
657
- const group = requireAgentGroup(run, input.groupId || fanout?.groupId || "");
658
- const multiAgentRun = requireMultiAgentRun(run, input.multiAgentRunId || group.multiAgentRunId);
659
- if (group.multiAgentRunId !== multiAgentRun.id)
660
- throw new Error(`Group ${group.id} does not belong to MultiAgentRun ${multiAgentRun.id}`);
661
- if (fanout && fanout.groupId !== group.id)
662
- throw new Error(`Fanout ${fanout.id} does not belong to group ${group.id}`);
663
- const id = input.id || (0, helpers_1.createId)("fanin", state.fanins.length + 1);
664
- if (state.fanins.some((record) => record.id === id))
665
- throw new Error(`Duplicate AgentFanin id: ${id}`);
666
- const requiredRoleIds = (0, helpers_1.unique)(input.requiredRoleIds?.length ? input.requiredRoleIds : group.roleIds);
667
- for (const roleId of requiredRoleIds)
668
- requireAgentRole(run, roleId);
669
- const scopedMemberships = state.memberships.filter((membership) => membership.groupId === group.id && (!fanout || membership.fanoutId === fanout.id));
670
- const coverage = scopedMemberships.map((membership) => ({
671
- membershipId: membership.id,
672
- roleId: membership.roleId,
673
- taskId: membership.taskId,
674
- workerId: membership.workerId,
675
- evidenceRefs: membership.evidenceRefs,
676
- blackboardMessageIds: membership.blackboardMessageIds || [],
677
- blackboardArtifactRefIds: membership.blackboardArtifactRefIds || [],
678
- resultNodeId: membership.resultNodeId,
679
- verifierNodeId: membership.verifierNodeId,
680
- complete: (0, helpers_1.isMembershipReported)(membership)
681
- }));
682
- const missingRoleIds = requiredRoleIds.filter((roleId) => !scopedMemberships.some((membership) => membership.roleId === roleId));
683
- const missingMembershipIds = scopedMemberships
684
- .filter((membership) => requiredRoleIds.includes(membership.roleId) && !(0, helpers_1.isMembershipReported)(membership))
685
- .map((membership) => membership.id);
686
- const blockedReasons = [
687
- ...missingRoleIds.map((roleId) => `required role ${roleId} has no membership`),
688
- ...missingMembershipIds.map((membershipId) => `membership ${membershipId} has not reported required evidence`)
689
- ];
690
- const requiredMemberships = scopedMemberships.filter((membership) => requiredRoleIds.includes(membership.roleId));
691
- const blackboardId = input.blackboardId || group.blackboardId || multiAgentRun.blackboardId;
692
- const requiresBlackboardEvidence = Boolean(blackboardId || requiredMemberships.some((membership) => membership.blackboardId));
693
- if (requiresBlackboardEvidence) {
694
- for (const membership of requiredMemberships) {
695
- const indexedEvidence = [
696
- ...((membership.blackboardArtifactRefIds || [])),
697
- ...((membership.blackboardMessageIds || []))
698
- ];
699
- if (!indexedEvidence.length)
700
- blockedReasons.push(`membership ${membership.id} has no indexed blackboard evidence`);
701
- }
702
- }
703
- const verifierReady = blockedReasons.length === 0;
704
- const status = verifierReady ? "ready" : "blocked";
705
- const now = new Date().toISOString();
706
- const fanin = {
707
- schemaVersion: helpers_1.MULTI_AGENT_SCHEMA_VERSION,
708
- id,
709
- runId: run.id,
710
- multiAgentRunId: multiAgentRun.id,
711
- groupId: group.id,
712
- fanoutId: fanout?.id,
713
- createdAt: now,
714
- updatedAt: now,
715
- status,
716
- strategy: input.strategy || "required-role-evidence",
717
- requiredRoleIds,
718
- reportedMembershipIds: coverage.filter((entry) => entry.complete).map((entry) => entry.membershipId),
719
- missingMembershipIds,
720
- missingRoleIds,
721
- evidenceCoverage: coverage,
722
- verifierReady,
723
- blockedReasons,
724
- blackboardId,
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")],
729
- policy: {
730
- schemaVersion: 1,
731
- id: `${id}-policy`,
732
- policyRef: `multiAgent.fanins.${id}.policy`,
733
- subjectKind: "fanin",
734
- subjectId: id,
735
- allowedBlackboardTopicIds: (0, helpers_1.unique)([...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])]),
736
- allowedWriteOperations: ["message", "context", "artifact", "snapshot", "coordinator-decision"],
737
- allowedCandidateOperations: verifierReady ? ["register", "score", "select"] : [],
738
- allowedJudgeOperations: verifierReady ? ["panel-decision", "rationale"] : [],
739
- sandboxProfileHints: [],
740
- requiredEvidenceRefs: (0, helpers_1.unique)(coverage.flatMap((entry) => entry.evidenceRefs)),
741
- deniedOperations: verifierReady ? [] : blockedReasons.map((reason) => ({ operation: "candidate.select", reason })),
742
- metadata: { verifierReady, strategy: input.strategy || "required-role-evidence" }
743
- },
744
- metadata: (0, helpers_1.compact)(input.metadata)
745
- };
746
- state.fanins.push(fanin);
747
- group.faninIds = (0, helpers_1.unique)([...group.faninIds, fanin.id]);
748
- group.status = verifierReady ? "verifying" : "collecting";
749
- (0, helpers_1.touch)(group);
750
- multiAgentRun.faninIds = (0, helpers_1.unique)([...multiAgentRun.faninIds, fanin.id]);
751
- multiAgentRun.status = verifierReady ? "verifying" : "collecting";
752
- (0, helpers_1.touch)(multiAgentRun);
753
- appendMultiAgentNode(run, "agent-fanin", fanin.id, verifierReady ? "verified" : "blocked", {
754
- multiAgentRunId: fanin.multiAgentRunId,
755
- groupId: fanin.groupId,
756
- fanoutId: fanin.fanoutId,
757
- requiredRoleIds,
758
- missingRoleIds,
759
- missingMembershipIds,
760
- verifierReady
761
- }, [
762
- `${run.id}:multi-agent:group:${fanin.groupId}`,
763
- ...(fanin.fanoutId ? [`${run.id}:multi-agent:fanout:${fanin.fanoutId}`] : []),
764
- ...fanin.evidenceCoverage.map((entry) => `${run.id}:multi-agent:membership:${entry.membershipId}`)
765
- ]);
766
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
767
- kind: "multi-agent.fanin",
768
- decision: verifierReady ? "validated" : "failed",
769
- source: "cw-validated",
770
- multiAgentRunId: fanin.multiAgentRunId,
771
- agentGroupId: fanin.groupId,
772
- agentFanoutId: fanin.fanoutId,
773
- agentFaninId: fanin.id,
774
- evidenceRefs: fanin.evidenceCoverage.flatMap((entry) => entry.evidenceRefs),
775
- metadata: {
776
- verifierReady,
777
- requiredRoleIds,
778
- missingRoleIds,
779
- missingMembershipIds,
780
- blockedReasons
781
- }
782
- });
783
- persistMultiAgentState(run);
784
- return fanin;
785
- }
786
- function recordMultiAgentWorkerOutput(run, input) {
787
- const state = ensureMultiAgentState(run);
788
- const memberships = state.memberships.filter((membership) => membership.workerId === input.workerId && membership.taskId === input.taskId);
789
- if (!memberships.length)
790
- return [];
791
- const evidenceRefs = input.evidence.map((entry) => entry.locator || entry.path || entry.summary || entry.id).filter(Boolean);
792
- for (const membership of memberships) {
793
- const before = membership.status;
794
- membership.status = "reported";
795
- membership.updatedAt = new Date().toISOString();
796
- membership.resultNodeId = input.resultNodeId || membership.resultNodeId;
797
- membership.verifierNodeId = input.verifierNodeId || membership.verifierNodeId;
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"));
803
- appendMultiAgentNode(run, "agent-membership", membership.id, "completed", {
804
- resultNodeId: membership.resultNodeId,
805
- verifierNodeId: membership.verifierNodeId,
806
- evidenceRefs: membership.evidenceRefs
807
- }, [membership.resultNodeId, membership.verifierNodeId].filter(Boolean));
808
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
809
- kind: "multi-agent.membership.output",
810
- decision: "accepted",
811
- source: "cw-validated",
812
- workerId: input.workerId,
813
- taskId: input.taskId,
814
- nodeId: input.resultNodeId,
815
- multiAgentRunId: membership.multiAgentRunId,
816
- agentRoleId: membership.roleId,
817
- agentGroupId: membership.groupId,
818
- agentMembershipId: membership.id,
819
- agentFanoutId: membership.fanoutId,
820
- evidence: input.evidence,
821
- metadata: { verifierNodeId: input.verifierNodeId }
822
- });
823
- }
824
- persistMultiAgentState(run);
825
- return memberships;
826
- }
827
- function summarizeMultiAgent(run) {
828
- const state = ensureMultiAgentState(run);
829
- const blockedReasons = [];
830
- for (const fanin of state.fanins)
831
- blockedReasons.push(...fanin.blockedReasons.map((reason) => `${fanin.id}: ${reason}`));
832
- for (const membership of state.memberships) {
833
- if (membership.status === "failed")
834
- blockedReasons.push(`${membership.id}: failed membership`);
835
- }
836
- const groupsDetail = state.groups.map((group) => {
837
- const roleIds = (0, helpers_1.unique)([...group.roleIds, ...state.memberships.filter((membership) => membership.groupId === group.id).map((membership) => membership.roleId)]);
838
- return {
839
- id: group.id,
840
- multiAgentRunId: group.multiAgentRunId,
841
- status: group.status,
842
- phase: group.phase,
843
- roles: roleIds.map((roleId) => {
844
- const role = state.roles.find((entry) => entry.id === roleId);
845
- const memberships = state.memberships.filter((membership) => membership.groupId === group.id && membership.roleId === roleId);
846
- const reported = memberships.filter(helpers_1.isMembershipReported).length;
847
- return {
848
- roleId,
849
- requiredEvidence: role?.requiredEvidence.length || 0,
850
- memberships: memberships.length,
851
- reported,
852
- missing: Math.max(0, memberships.length - reported)
853
- };
854
- }),
855
- fanouts: group.fanoutIds,
856
- fanins: group.faninIds
857
- };
858
- });
859
- return {
860
- totalRuns: state.runs.length,
861
- runsByStatus: (0, helpers_1.countBy)(state.runs, (record) => record.status),
862
- roles: state.roles.length,
863
- groups: state.groups.length,
864
- memberships: state.memberships.length,
865
- fanouts: state.fanouts.length,
866
- fanins: state.fanins.length,
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),
870
- blockedReasons,
871
- groupsDetail,
872
- nextAction: nextMultiAgentAction(run, blockedReasons)
873
- };
874
- }
875
- function buildMultiAgentGraph(run) {
876
- const state = ensureMultiAgentState(run);
877
- return (0, graph_1.buildMultiAgentGraphFromState)(run, state);
878
- }
879
- function getMultiAgentRun(run, id) {
880
- return ensureMultiAgentState(run).runs.find((record) => record.id === id);
881
- }
882
- function getAgentRole(run, id) {
883
- return ensureMultiAgentState(run).roles.find((record) => record.id === id);
884
- }
885
- function getAgentGroup(run, id) {
886
- return ensureMultiAgentState(run).groups.find((record) => record.id === id);
887
- }
888
- function getAgentMembership(run, id) {
889
- return ensureMultiAgentState(run).memberships.find((record) => record.id === id);
890
- }
891
- function getAgentFanout(run, id) {
892
- return ensureMultiAgentState(run).fanouts.find((record) => record.id === id);
893
- }
894
- function getAgentFanin(run, id) {
895
- return ensureMultiAgentState(run).fanins.find((record) => record.id === id);
896
- }
897
- function requireMultiAgentRun(run, id) {
898
- const record = getMultiAgentRun(run, id);
899
- if (!record)
900
- throw new Error(`Unknown MultiAgentRun id: ${id}`);
901
- return record;
902
- }
903
- function requireAgentRole(run, id) {
904
- const record = getAgentRole(run, id);
905
- if (!record)
906
- throw new Error(`Unknown AgentRole id: ${id}`);
907
- return record;
908
- }
909
- function requireAgentGroup(run, id) {
910
- const record = getAgentGroup(run, id);
911
- if (!record)
912
- throw new Error(`Unknown AgentGroup id: ${id}`);
913
- return record;
914
- }
915
- function requireAgentFanout(run, id) {
916
- const record = getAgentFanout(run, id);
917
- if (!record)
918
- throw new Error(`Unknown AgentFanout id: ${id}`);
919
- return record;
920
- }
921
- function requireRunTask(run, id) {
922
- const task = run.tasks.find((record) => record.id === id);
923
- if (!task)
924
- throw new Error(`Unknown task id for multi-agent record: ${id}`);
925
- return task;
926
- }
927
- function fanoutTopicIds(group, multiAgentRun, input) {
928
- return [...(group.topicIds || []), ...(multiAgentRun.topicIds || []), ...(input.topicIds || [])];
929
- }
930
- function writeRecord(run, kind, record) {
931
- (0, state_1.writeJson)((0, paths_1.recordPath)(run, kind, record.id), record);
932
- }
933
- function appendMultiAgentNode(run, kind, id, status, metadata, parents = []) {
934
- const nodeId = kind === "multi-agent-run" ? `${run.id}:multi-agent:${id}` : `${run.id}:multi-agent:${kind.replace("agent-", "")}:${id}`;
935
- (0, state_node_1.appendRunNode)(run, (0, state_node_1.createStateNode)({
936
- id: nodeId,
937
- kind,
938
- status,
939
- loopStage: run.loopStage,
940
- outputs: metadata,
941
- artifacts: [{ id: kind, kind: "json", path: (0, paths_1.recordPath)(run, (0, helpers_1.pluralKind)(kind), id) }],
942
- parents,
943
- contractId: pipeline_contract_1.DEFAULT_PIPELINE_CONTRACT_ID,
944
- metadata
945
- }));
946
- }
947
- function attachWorkerMetadata(run, membership) {
948
- const workers = run.workers || [];
949
- const index = workers.findIndex((worker) => worker.id === membership.workerId);
950
- if (index < 0)
951
- return;
952
- const worker = workers[index];
953
- const multiAgent = {
954
- runId: membership.multiAgentRunId,
955
- groupId: membership.groupId,
956
- roleId: membership.roleId,
957
- membershipId: membership.id,
958
- fanoutId: membership.fanoutId
959
- };
960
- const updated = {
961
- ...worker,
962
- updatedAt: new Date().toISOString(),
963
- multiAgent,
964
- metadata: {
965
- ...(worker.metadata || {}),
966
- multiAgent
967
- }
968
- };
969
- run.workers = workers.map((candidate) => (candidate.id === worker.id ? updated : candidate));
970
- }
971
- function nextMultiAgentAction(run, blockedReasons) {
972
- const state = ensureMultiAgentState(run);
973
- if (!state.runs.length)
974
- return `node scripts/cw.js multi-agent run ${run.id} --id <multi-agent-run-id>`;
975
- if (blockedReasons.length)
976
- return `node scripts/cw.js multi-agent fanin ${run.id} --group <group-id> --fanout <fanout-id>`;
977
- const running = state.memberships.find((membership) => membership.status === "running");
978
- if (running?.workerId)
979
- return `node scripts/cw.js worker manifest ${run.id} ${running.workerId}`;
980
- const groupWithoutFanin = state.groups.find((group) => group.membershipIds.length && !group.faninIds.length);
981
- if (groupWithoutFanin)
982
- return `node scripts/cw.js multi-agent fanin ${run.id} --group ${groupWithoutFanin.id}`;
983
- return undefined;
984
- }