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,777 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hostRun = hostRun;
4
- exports.hostStatus = hostStatus;
5
- exports.hostStep = hostStep;
6
- exports.hostBlackboard = hostBlackboard;
7
- exports.hostScore = hostScore;
8
- exports.hostSelect = hostSelect;
9
- // Multi-Agent Host — the high-level orchestrator for topology-backed multi-agent
10
- // workflows. Delegates common lifecycle steps (plan, dispatch, commit) to
11
- // orchestrator/lifecycle-operations.ts; handles ONLY multi-agent-specific steps
12
- // here (fanin collection, judge rationale, topology application). Adding a new
13
- // lifecycle step: prefer adding it to lifecycle-operations.ts and calling it
14
- // from here — keep the single-agent and multi-agent paths sharing one mechanism.
15
- // See P2-2 (v0.1.48) and src/orchestrator/lifecycle-operations.ts.
16
- const dispatch_1 = require("./dispatch");
17
- const coordinator_1 = require("./coordinator");
18
- const multi_agent_1 = require("./multi-agent");
19
- const topology_1 = require("./topology");
20
- const operator_ux_1 = require("./operator-ux");
21
- const multi_agent_operator_ux_1 = require("./multi-agent-operator-ux");
22
- const candidate_scoring_1 = require("./candidate-scoring");
23
- const trust_audit_1 = require("./trust-audit");
24
- const multi_agent_trust_1 = require("./multi-agent-trust");
25
- function hostRun(run, options = {}) {
26
- const topologyId = stringOption(options.topology || options.topologyId || options.id);
27
- if (!topologyId)
28
- return hostStatus(run, "run");
29
- const existing = activeTopologies(run).find((entry) => entry.topologyId === topologyId && !isTerminalTopology(entry));
30
- const topologyRun = existing || (0, topology_1.applyTopology)(run, topologyId, {
31
- id: stringOption(options.topologyRun || options.topologyRunId || options["topology-run"] || options["topology-run-id"] || options.name),
32
- title: stringOption(options.title),
33
- multiAgentRunId: stringOption(options.multiAgentRun || options.multiAgentRunId),
34
- blackboardId: stringOption(options.blackboard || options.blackboardId),
35
- taskIds: arrayOption(options.task || options.taskId || options.tasks).map(String),
36
- mapperCount: numberOption(options.mapperCount || options["mapper-count"] || options.mappers || options.mapper),
37
- judgeCount: numberOption(options.judgeCount || options["judge-count"] || options.judges || options.judge),
38
- debateRounds: numberOption(options.debateRounds || options["debate-rounds"] || options.rounds),
39
- collectInitialFanin: Boolean(options.collectInitialFanin || options["collect-initial-fanin"]),
40
- metadata: { hostSurface: "multi-agent.run" }
41
- });
42
- return envelope(run, "run", {
43
- performed: existing ? "attached-topology" : "applied-topology",
44
- data: {
45
- topologyRun,
46
- dispatchCreated: false,
47
- note: "Workers are not dispatched by multi-agent run; call multi-agent step or dispatch explicitly."
48
- }
49
- });
50
- }
51
- function hostStatus(run, command = "status") {
52
- return envelope(run, command);
53
- }
54
- function hostStep(run, options = {}) {
55
- const state = classifyHostState(run);
56
- if (state === "complete") {
57
- return envelope(run, "step", {
58
- performed: "none",
59
- requiredHostAction: "Review the completed run report; no further host step is available."
60
- });
61
- }
62
- if (state === "ready-for-commit") {
63
- return envelope(run, "step", {
64
- performed: "none",
65
- requiredHostAction: "Run the recommended verifier-gated commit command before taking more steps."
66
- });
67
- }
68
- if (state === "needs-run") {
69
- return envelope(run, "step", {
70
- performed: "none",
71
- requiredHostAction: "Create or attach a multi-agent run before stepping."
72
- });
73
- }
74
- if (state === "blocked" || state === "failed")
75
- return envelope(run, "step", { performed: "none", requiredHostAction: "Resolve blocked reasons, then rerun multi-agent status." });
76
- const topology = requireSingleActiveTopology(run);
77
- const runningWorkers = (run.workers || []).filter((worker) => worker.status === "allocated" || worker.status === "running");
78
- if (runningWorkers.length) {
79
- return envelope(run, "step", {
80
- performed: "none",
81
- requiredHostAction: `Execute ${runningWorkers.length} worker(s), write result.md, then record output with worker output or result.`,
82
- extraBlockedReasons: runningWorkers.map((worker) => `worker ${worker.id} is ${worker.status}`)
83
- });
84
- }
85
- const faninPlan = nextFaninPlan(run, topology);
86
- if (faninPlan) {
87
- const fanin = (0, multi_agent_1.collectAgentFanin)(run, faninPlan);
88
- linkTopologyRecord(topology, { faninIds: [fanin.id] });
89
- return envelope(run, "step", {
90
- performed: fanin.status === "ready" ? "collected-fanin" : "collected-blocked-fanin",
91
- data: fanin,
92
- requiredHostAction: fanin.status === "ready" ? undefined : "Add missing worker evidence or blackboard artifacts before continuing.",
93
- extraBlockedReasons: fanin.status === "ready" ? [] : fanin.blockedReasons
94
- });
95
- }
96
- const dispatchPlan = nextDispatchPlan(run, topology, options);
97
- if (dispatchPlan) {
98
- const manifest = (0, dispatch_1.createDispatchManifest)(run, dispatchPlan.limit, {
99
- sandboxProfileId: dispatchPlan.sandboxProfileId,
100
- backendId: dispatchPlan.backendId,
101
- multiAgentRunId: topology.multiAgentRunId,
102
- multiAgentGroupId: dispatchPlan.groupId,
103
- multiAgentRoleId: dispatchPlan.roleId,
104
- multiAgentFanoutId: dispatchPlan.fanoutId
105
- });
106
- return envelope(run, "step", {
107
- performed: manifest.dispatchId ? "created-dispatch-manifest" : "none",
108
- data: manifest,
109
- requiredHostAction: manifest.dispatchId ? "Spawn the worker described by the manifest and record its result." : "No runnable pending task is available for dispatch."
110
- });
111
- }
112
- const snapshotPlan = activeBlackboardId(run, topology);
113
- if (snapshotPlan && !(run.blackboard?.snapshots || []).some((snapshot) => snapshot.blackboardId === snapshotPlan)) {
114
- const snapshot = (0, coordinator_1.createBlackboardSnapshot)(run, snapshotPlan);
115
- return envelope(run, "step", { performed: "created-blackboard-snapshot", data: snapshot });
116
- }
117
- const candidatePlan = nextCandidatePlan(run);
118
- if (candidatePlan) {
119
- const candidate = (0, candidate_scoring_1.registerCandidate)(run, {
120
- id: stringOption(options.candidate || options.candidateId),
121
- kind: "worker-output",
122
- workerId: candidatePlan.id,
123
- taskId: candidatePlan.taskId,
124
- resultNodeId: candidatePlan.resultNodeId,
125
- verifierNodeId: candidatePlan.output?.verifierNodeId,
126
- resultPath: candidatePlan.resultPath,
127
- metadata: { hostSurface: "multi-agent.step" }
128
- }, { persist: false });
129
- linkTopologyRecord(topology, { candidateIds: [candidate.id] });
130
- return envelope(run, "step", { performed: "registered-candidate", data: candidate });
131
- }
132
- const scorePlan = nextScorePlan(run, options);
133
- if (scorePlan) {
134
- const score = (0, candidate_scoring_1.scoreCandidate)(run, scorePlan.candidate.id, {
135
- scorer: stringOption(options.scorer) || "multi-agent-host",
136
- criteria: parseCriteria(options, { correctness: 1, evidence: 1, fit: 1 }),
137
- maxTotal: numberOption(options.maxTotal || options.max) || 3,
138
- verdict: stringOption(options.verdict),
139
- evidence: scorePlan.evidence,
140
- notes: stringOption(options.notes) || "Host step scored candidate with existing verifier evidence.",
141
- metadata: { hostSurface: "multi-agent.step", topologyRunId: topology.id }
142
- }, { persist: false });
143
- (0, coordinator_1.recordCoordinatorDecision)(run, {
144
- blackboardId: topology.blackboardId,
145
- topicId: topology.topicIds[0],
146
- kind: "candidate-synthesis",
147
- outcome: score.verdict === "fail" ? "blocked" : "ready",
148
- reason: `Candidate ${score.candidateId} scored ${score.total}/${score.maxTotal}.`,
149
- subjectIds: [score.candidateId, score.id],
150
- evidenceRefs: score.evidence.map((entry) => entry.locator || entry.summary || entry.id).filter(Boolean),
151
- metadata: { hostSurface: "multi-agent.step", scoreId: score.id }
152
- });
153
- return envelope(run, "step", { performed: "scored-candidate", data: score });
154
- }
155
- const selectionPlan = nextSelectionPlan(run, options);
156
- if (selectionPlan) {
157
- const selection = (0, candidate_scoring_1.selectCandidate)(run, selectionPlan.candidate.id, {
158
- selectedBy: stringOption(options.by || options.selectedBy) || "multi-agent-host",
159
- reason: stringOption(options.reason) || "Selected by high-level multi-agent host step after scoring and verifier evidence.",
160
- scoreId: selectionPlan.scoreId,
161
- allowUnverified: Boolean(options.allowUnverified)
162
- }, { persist: false });
163
- linkTopologyRecord(topology, { selectionIds: [selection.id] });
164
- (0, coordinator_1.recordCoordinatorDecision)(run, {
165
- blackboardId: topology.blackboardId,
166
- topicId: topology.topicIds.at(-1),
167
- kind: "candidate-synthesis",
168
- outcome: "accepted",
169
- reason: selection.reason,
170
- subjectIds: [selection.candidateId, selection.id],
171
- evidenceRefs: selection.evidence.map((entry) => entry.locator || entry.summary || entry.id).filter(Boolean),
172
- metadata: { hostSurface: "multi-agent.step", selectionId: selection.id }
173
- });
174
- return envelope(run, "step", { performed: "selected-candidate", data: selection });
175
- }
176
- return envelope(run, "step", {
177
- performed: "none",
178
- requiredHostAction: "No safe deterministic step is available. Use multi-agent status for the next explicit command."
179
- });
180
- }
181
- function hostBlackboard(run, action, options = {}) {
182
- const topology = optionalSingleActiveTopology(run);
183
- const blackboardId = resolveHostBlackboardId(run, topology, options);
184
- const topicId = stringOption(options.topic || options.topicId) || resolveHostTopicId(run, blackboardId, options, action);
185
- let data;
186
- let performed = "read-blackboard";
187
- switch (action || "summary") {
188
- case "summary":
189
- case "board":
190
- data = (0, coordinator_1.summarizeBlackboard)(run, blackboardId);
191
- break;
192
- case "topics":
193
- case "list-topics":
194
- data = (run.blackboard?.topics || []).filter((topic) => topic.blackboardId === blackboardId);
195
- break;
196
- case "messages":
197
- case "list-messages":
198
- data = (0, coordinator_1.listBlackboardMessages)(run, { blackboardId, topicId });
199
- break;
200
- case "post":
201
- case "message":
202
- data = (0, coordinator_1.postBlackboardMessage)(run, {
203
- topicId: requireString(topicId, "topic id"),
204
- blackboardId,
205
- body: requireString(options.body || options.message, "message body"),
206
- evidenceRefs: arrayOption(options.evidence || options.evidenceRef).map(String),
207
- artifactRefIds: arrayOption(options.artifact || options.artifactRef || options.artifactRefId).map(String),
208
- metadata: { hostSurface: "multi-agent.blackboard" }
209
- });
210
- performed = "posted-message";
211
- break;
212
- case "artifacts":
213
- case "list-artifacts":
214
- data = (0, coordinator_1.listBlackboardArtifacts)(run, { blackboardId, topicId });
215
- break;
216
- case "add-artifact":
217
- case "artifact":
218
- data = (0, coordinator_1.addBlackboardArtifact)(run, {
219
- id: stringOption(options.id),
220
- blackboardId,
221
- topicId,
222
- kind: requireString(options.kind, "artifact kind"),
223
- path: stringOption(options.path),
224
- locator: stringOption(options.locator),
225
- source: stringOption(options.source) || "multi-agent-host",
226
- evidenceRefs: arrayOption(options.evidence || options.evidenceRef).map(String),
227
- metadata: { hostSurface: "multi-agent.blackboard" }
228
- });
229
- performed = "added-artifact";
230
- break;
231
- case "context":
232
- case "put-context":
233
- data = (0, coordinator_1.putBlackboardContext)(run, {
234
- blackboardId,
235
- topicId: requireString(topicId, "topic id"),
236
- kind: requireString(options.kind, "context kind"),
237
- key: stringOption(options.key),
238
- value: requireString(options.value || options.body, "context value"),
239
- evidenceRefs: arrayOption(options.evidence || options.evidenceRef).map(String),
240
- artifactRefIds: arrayOption(options.artifact || options.artifactRef || options.artifactRefId).map(String),
241
- metadata: { hostSurface: "multi-agent.blackboard" }
242
- });
243
- performed = "put-context";
244
- break;
245
- case "snapshot":
246
- data = (0, coordinator_1.createBlackboardSnapshot)(run, blackboardId);
247
- performed = "created-snapshot";
248
- break;
249
- default:
250
- throw new Error("Usage: multi-agent blackboard <run-id> [summary|topics|messages|post|artifacts|add-artifact|context|snapshot]");
251
- }
252
- return envelope(run, "blackboard", { performed, data });
253
- }
254
- function hostScore(run, options = {}) {
255
- const topology = optionalSingleActiveTopology(run);
256
- let candidate = resolveCandidate(run, options);
257
- if (!candidate && stringOption(options.worker || options.workerId)) {
258
- candidate = (0, candidate_scoring_1.registerCandidate)(run, {
259
- id: stringOption(options.candidate || options.candidateId || options.id),
260
- kind: "worker-output",
261
- workerId: requireString(options.worker || options.workerId, "worker id"),
262
- metadata: { hostSurface: "multi-agent.score" }
263
- }, { persist: false });
264
- }
265
- if (!candidate)
266
- throw new Error("multi-agent score requires --candidate or --worker when a single candidate cannot be inferred");
267
- const evidence = explicitEvidence(options);
268
- if (!evidence.length)
269
- throw new Error(`Candidate ${candidate.id} score requires evidence`);
270
- const authority = authorityOptions(options);
271
- if (authority.agentRoleId || authority.agentMembershipId) {
272
- const rationale = stringOption(options.rationale || options.notes || options.reason);
273
- if (!rationale)
274
- throw new Error(`Candidate ${candidate.id} judge score requires rationale`);
275
- const permission = (0, multi_agent_trust_1.assertMultiAgentActionAllowed)(run, {
276
- operation: "judge.rationale",
277
- actor: authority.actor,
278
- multiAgentRunId: authority.multiAgentRunId || topology?.multiAgentRunId,
279
- agentRoleId: authority.agentRoleId,
280
- agentGroupId: authority.agentGroupId,
281
- agentMembershipId: authority.agentMembershipId,
282
- blackboardId: topology?.blackboardId,
283
- blackboardTopicId: topology?.topicIds[0],
284
- candidateId: candidate.id,
285
- evidenceRefs: evidence.map((entry) => entry.locator || entry.summary || entry.id).filter(Boolean)
286
- });
287
- (0, multi_agent_trust_1.recordJudgeRationaleAudit)(run, {
288
- kind: "judge.rationale",
289
- actor: authority.actor,
290
- multiAgentRunId: authority.multiAgentRunId || topology?.multiAgentRunId,
291
- agentRoleId: authority.agentRoleId,
292
- agentGroupId: authority.agentGroupId,
293
- agentMembershipId: authority.agentMembershipId,
294
- blackboardId: topology?.blackboardId,
295
- blackboardTopicId: topology?.topicIds[0],
296
- candidateId: candidate.id,
297
- evidenceRefs: evidence.map((entry) => entry.locator || entry.summary || entry.id).filter(Boolean),
298
- rationale,
299
- policyRef: permission.policyRef,
300
- parentEventIds: [permission.event.id]
301
- });
302
- }
303
- const score = (0, candidate_scoring_1.scoreCandidate)(run, candidate.id, {
304
- id: stringOption(options.score || options.scoreId),
305
- scorer: stringOption(options.scorer) || "multi-agent-host",
306
- criteria: parseCriteria(options),
307
- maxTotal: numberOption(options.maxTotal || options.max),
308
- verdict: stringOption(options.verdict),
309
- evidence,
310
- notes: stringOption(options.notes),
311
- metadata: { hostSurface: "multi-agent.score", topologyRunId: topology?.id }
312
- }, { persist: false });
313
- if (topology) {
314
- linkTopologyRecord(topology, { candidateIds: [candidate.id] });
315
- (0, coordinator_1.recordCoordinatorDecision)(run, {
316
- blackboardId: topology.blackboardId,
317
- topicId: topology.topicIds[0],
318
- kind: "candidate-synthesis",
319
- outcome: score.verdict === "fail" ? "blocked" : "ready",
320
- reason: `Host scored candidate ${candidate.id} with score ${score.id}.`,
321
- subjectIds: [candidate.id, score.id],
322
- evidenceRefs: score.evidence.map((entry) => entry.locator || entry.summary || entry.id).filter(Boolean),
323
- metadata: { hostSurface: "multi-agent.score", scoreId: score.id }
324
- });
325
- }
326
- return envelope(run, "score", { performed: "scored-candidate", data: score });
327
- }
328
- function hostSelect(run, options = {}) {
329
- const topology = optionalSingleActiveTopology(run);
330
- const candidate = resolveCandidate(run, options) || topRankedCandidate(run);
331
- if (!candidate)
332
- throw new Error("multi-agent select requires a scored candidate");
333
- const authority = authorityOptions(options);
334
- if (authority.agentRoleId || authority.agentMembershipId) {
335
- const scoreId = stringOption(options.score || options.scoreId) || candidate.scores.at(-1);
336
- if (!(0, multi_agent_trust_1.hasAcceptedJudgeRationale)(run, { multiAgentRunId: authority.multiAgentRunId || topology?.multiAgentRunId, candidateId: candidate.id, scoreId })) {
337
- throw new Error(`Candidate ${candidate.id} selection requires accepted judge rationale with evidence`);
338
- }
339
- (0, multi_agent_trust_1.assertMultiAgentActionAllowed)(run, {
340
- operation: "candidate.select",
341
- actor: authority.actor,
342
- multiAgentRunId: authority.multiAgentRunId || topology?.multiAgentRunId,
343
- agentRoleId: authority.agentRoleId,
344
- agentGroupId: authority.agentGroupId,
345
- agentMembershipId: authority.agentMembershipId,
346
- blackboardId: topology?.blackboardId,
347
- blackboardTopicId: topology?.topicIds.at(-1),
348
- candidateId: candidate.id,
349
- scoreId,
350
- evidenceRefs: explicitEvidence(options).map((entry) => entry.locator || entry.summary || entry.id).filter(Boolean)
351
- });
352
- }
353
- const selection = (0, candidate_scoring_1.selectCandidate)(run, candidate.id, {
354
- selectedBy: stringOption(options.by || options.selectedBy) || "multi-agent-host",
355
- reason: requireString(options.reason || "Selected by high-level multi-agent host surface.", "selection reason"),
356
- scoreId: stringOption(options.score || options.scoreId),
357
- allowUnverified: Boolean(options.allowUnverified)
358
- }, {
359
- persist: false,
360
- policy: {
361
- requireVerifierGate: options.requireVerifierGate === undefined ? undefined : Boolean(options.requireVerifierGate),
362
- minNormalized: numberOption(options.minNormalized)
363
- }
364
- });
365
- if (topology) {
366
- linkTopologyRecord(topology, { candidateIds: [candidate.id], selectionIds: [selection.id] });
367
- (0, coordinator_1.recordCoordinatorDecision)(run, {
368
- blackboardId: topology.blackboardId,
369
- topicId: topology.topicIds.at(-1),
370
- kind: "candidate-synthesis",
371
- outcome: "accepted",
372
- reason: selection.reason,
373
- subjectIds: [selection.candidateId, selection.id],
374
- evidenceRefs: selection.evidence.map((entry) => entry.locator || entry.summary || entry.id).filter(Boolean),
375
- author: authority.actor,
376
- links: {
377
- multiAgentRunId: authority.multiAgentRunId || topology.multiAgentRunId,
378
- agentGroupId: authority.agentGroupId,
379
- agentRoleId: authority.agentRoleId,
380
- agentMembershipId: authority.agentMembershipId
381
- },
382
- metadata: { hostSurface: "multi-agent.select", selectionId: selection.id }
383
- });
384
- }
385
- return envelope(run, "select", { performed: "selected-candidate", data: selection });
386
- }
387
- function memoize(compute) {
388
- let cached;
389
- return (run) => (cached ??= { value: compute(run) }).value;
390
- }
391
- function createHostSummaryCache(run) {
392
- const topologies = memoize(topology_1.summarizeTopologies);
393
- const multiAgent = memoize(multi_agent_1.summarizeMultiAgent);
394
- const blackboard = memoize(coordinator_1.summarizeBlackboard);
395
- const workers = memoize(operator_ux_1.summarizeOperatorWorkers);
396
- const candidates = memoize(operator_ux_1.summarizeOperatorCandidates);
397
- const feedback = memoize(operator_ux_1.summarizeOperatorFeedback);
398
- const commits = memoize(operator_ux_1.summarizeOperatorCommits);
399
- const trust = memoize(trust_audit_1.summarizeTrustAudit);
400
- const operator = memoize(operator_ux_1.summarizeOperatorRun);
401
- const multiAgentOperator = memoize(multi_agent_operator_ux_1.summarizeMultiAgentOperator);
402
- const active = memoize(activeTopologies);
403
- return {
404
- run,
405
- topologies: () => topologies(run),
406
- multiAgent: () => multiAgent(run),
407
- blackboard: () => blackboard(run),
408
- workers: () => workers(run),
409
- candidates: () => candidates(run),
410
- feedback: () => feedback(run),
411
- commits: () => commits(run),
412
- trust: () => trust(run),
413
- operator: () => operator(run),
414
- multiAgentOperator: () => multiAgentOperator(run),
415
- active: () => active(run)
416
- };
417
- }
418
- function envelope(run, command, options = {}) {
419
- const cache = createHostSummaryCache(run);
420
- const topologies = cache.topologies();
421
- const multiAgent = cache.multiAgent();
422
- const blackboard = cache.blackboard();
423
- const workers = cache.workers();
424
- const candidates = cache.candidates();
425
- const feedback = cache.feedback();
426
- const commits = cache.commits();
427
- const trust = cache.trust();
428
- const operator = cache.operator();
429
- const multiAgentOperator = cache.multiAgentOperator();
430
- const active = cache.active();
431
- const blockedReasons = unique([...operator.blockedReasons, ...(options.extraBlockedReasons || [])]);
432
- const state = blockedReasons.length ? "blocked" : classifyHostState(run, cache);
433
- const ids = activeIds(run, active);
434
- const nextActions = hostNextActions(run, state, active, options.requiredHostAction, cache);
435
- return {
436
- schemaVersion: 1,
437
- surface: "multi-agent-host",
438
- command,
439
- runId: run.id,
440
- state,
441
- performed: options.performed,
442
- nextAction: nextActions[0]?.command,
443
- nextActions,
444
- blockedReasons,
445
- requiredHostAction: options.requiredHostAction,
446
- evidenceRequirements: evidenceRequirements(active, multiAgent.blockedReasons),
447
- ids,
448
- paths: {
449
- statePath: run.paths.state,
450
- reportPath: run.paths.report,
451
- blackboardIndexPath: blackboard.indexPath,
452
- auditSummaryPath: run.audit?.summaryPath,
453
- auditEventLogPath: run.audit?.eventLogPath,
454
- candidateRankingPath: candidates.latestRankingPath,
455
- workerManifestPaths: workers.manifestPaths,
456
- workerResultPaths: workers.resultPaths
457
- },
458
- summaries: { topologies, multiAgent, multiAgentOperator, blackboard, workers, candidates, feedback, commits, trust },
459
- data: options.data
460
- };
461
- }
462
- function classifyHostState(run, cache = createHostSummaryCache(run)) {
463
- const active = cache.active();
464
- const feedback = cache.feedback();
465
- const workers = cache.workers();
466
- const candidates = cache.candidates();
467
- const commits = cache.commits();
468
- if (!active.length && !(run.multiAgent?.runs || []).length)
469
- return "needs-run";
470
- if (feedback.open.some((entry) => !entry.retryable))
471
- return "failed";
472
- if (feedback.open.length)
473
- return "blocked";
474
- if (commits.verifierGated > 0 && candidates.readyForCommit.length === 0)
475
- return "complete";
476
- if (candidates.readyForCommit.length)
477
- return "ready-for-commit";
478
- if ((run.candidateSelections || []).length === 0 && (run.candidates || []).some((candidate) => candidate.status === "scored" || candidate.status === "verified")) {
479
- return "ready-for-selection";
480
- }
481
- if ((run.candidates || []).some((candidate) => candidate.status === "registered"))
482
- return "ready-for-scoring";
483
- if (workers.workers.some((worker) => worker.status === "allocated" || worker.status === "running"))
484
- return "awaiting-worker-output";
485
- if (nextCandidatePlan(run))
486
- return "ready-for-scoring";
487
- if (nextFaninPlan(run, active[0]))
488
- return "ready-for-fanin";
489
- if (nextDispatchPlan(run, active[0], {}))
490
- return "ready-for-dispatch";
491
- return "blocked";
492
- }
493
- function activeIds(run, active) {
494
- return {
495
- topologyRunIds: active.map((entry) => entry.id),
496
- topologyIds: active.map((entry) => entry.topologyId),
497
- multiAgentRunIds: unique([...active.map((entry) => entry.multiAgentRunId), ...(run.multiAgent?.runs || []).map((entry) => entry.id)]),
498
- blackboardIds: unique([...active.map((entry) => entry.blackboardId), ...(run.blackboard?.boards || []).map((entry) => entry.id)]),
499
- topicIds: unique(active.flatMap((entry) => entry.topicIds)),
500
- groupIds: unique(active.flatMap((entry) => entry.groupIds)),
501
- roleIds: unique(active.flatMap((entry) => entry.roleIds)),
502
- fanoutIds: unique(active.flatMap((entry) => entry.fanoutIds)),
503
- faninIds: unique(active.flatMap((entry) => entry.faninIds)),
504
- candidateIds: unique([...(run.candidates || []).map((entry) => entry.id), ...active.flatMap((entry) => entry.candidateIds)]),
505
- selectionIds: unique([...(run.candidateSelections || []).map((entry) => entry.id), ...active.flatMap((entry) => entry.selectionIds)]),
506
- commitIds: (run.commits || []).map((entry) => entry.id),
507
- auditEventIds: unique(active.flatMap((entry) => entry.links.auditEventIds))
508
- };
509
- }
510
- function hostNextActions(run, state, active, requiredHostAction, cache = createHostSummaryCache(run)) {
511
- if (requiredHostAction)
512
- return [{ command: "host-action", reason: requiredHostAction, priority: "high" }];
513
- const runId = run.id;
514
- switch (state) {
515
- case "needs-run":
516
- return [{ command: `node scripts/cw.js multi-agent run ${runId} --topology map-reduce`, reason: "Materialize a host-facing multi-agent topology.", priority: "high" }];
517
- case "ready-for-dispatch":
518
- return [{ command: `node scripts/cw.js multi-agent step ${runId}`, reason: "Create the next dispatch manifest without spawning workers.", priority: "high" }];
519
- case "awaiting-worker-output":
520
- return [{ command: `node scripts/cw.js worker output ${runId} <worker-id> <result.md>`, reason: "A host-executed worker must report result evidence.", priority: "high" }];
521
- case "ready-for-fanin":
522
- return [{ command: `node scripts/cw.js multi-agent step ${runId}`, reason: "Collect fanin once required worker evidence is present.", priority: "high" }];
523
- case "ready-for-scoring":
524
- return [{ command: `node scripts/cw.js multi-agent score ${runId} --candidate <candidate-id> --criterion correctness=1 --evidence <path-or-ref>`, reason: "Score a candidate with explicit evidence.", priority: "high" }];
525
- case "ready-for-selection":
526
- return [{ command: `node scripts/cw.js multi-agent select ${runId} --candidate <candidate-id> --reason "<rationale>"`, reason: "Select a scored candidate after verifier gates pass.", priority: "high" }];
527
- case "ready-for-commit": {
528
- const ready = cache.candidates().readyForCommit[0];
529
- return [{ command: `node scripts/cw.js commit ${runId} --selection ${ready.selectionId} --reason "<verified rationale>"`, reason: "Create a verifier-gated CW state commit.", priority: "high" }];
530
- }
531
- case "complete":
532
- return [{ command: `node scripts/cw.js report ${runId} --show`, reason: "Review the completed run report.", priority: "normal" }];
533
- case "failed":
534
- case "blocked":
535
- default:
536
- return [{ command: `node scripts/cw.js multi-agent status ${runId}`, reason: active.length > 1 ? "Resolve ambiguous active topology state." : "Inspect specific blocked reasons.", priority: "high" }];
537
- }
538
- }
539
- function nextDispatchPlan(run, topology, options) {
540
- if (!topology)
541
- return undefined;
542
- if (topology.faninIds.length)
543
- return undefined;
544
- const fanout = (run.multiAgent?.fanouts || []).find((entry) => topology.fanoutIds.includes(entry.id));
545
- const group = (run.multiAgent?.groups || []).find((entry) => topology.groupIds.includes(entry.id));
546
- if (!fanout || !group)
547
- return undefined;
548
- const pending = run.tasks.filter((task) => task.status === "pending");
549
- if (!pending.length)
550
- return undefined;
551
- const membershipRoleIds = new Set((run.multiAgent?.memberships || []).filter((entry) => entry.fanoutId === fanout.id).map((entry) => entry.roleId));
552
- const roleId = fanout.roleIds.find((id) => !membershipRoleIds.has(id));
553
- if (!roleId)
554
- return undefined;
555
- return {
556
- limit: numberOption(options.limit) || 1,
557
- sandboxProfileId: stringOption(options.sandbox || options.sandboxProfile || options.sandboxProfileId) || "readonly",
558
- backendId: stringOption(options.backend || options.backendId || options.executionBackend),
559
- groupId: group.id,
560
- fanoutId: fanout.id,
561
- roleId
562
- };
563
- }
564
- function nextFaninPlan(run, topology) {
565
- if (!topology || topology.faninIds.length)
566
- return undefined;
567
- const fanout = (run.multiAgent?.fanouts || []).find((entry) => topology.fanoutIds.includes(entry.id));
568
- const group = (run.multiAgent?.groups || []).find((entry) => topology.groupIds.includes(entry.id));
569
- if (!fanout || !group || !fanout.membershipIds.length)
570
- return undefined;
571
- const memberships = (run.multiAgent?.memberships || []).filter((entry) => entry.fanoutId === fanout.id);
572
- if (!memberships.length || memberships.some((entry) => entry.status !== "reported" && !entry.verifierNodeId))
573
- return undefined;
574
- const membershipRoleIds = new Set(memberships.map((entry) => entry.roleId));
575
- if (fanout.roleIds.some((roleId) => !membershipRoleIds.has(roleId)))
576
- return undefined;
577
- return {
578
- id: `${topology.id}-fanin`,
579
- multiAgentRunId: topology.multiAgentRunId,
580
- groupId: group.id,
581
- fanoutId: fanout.id,
582
- requiredRoleIds: fanout.roleIds,
583
- strategy: "host step fanin requires all dispatched role evidence",
584
- blackboardId: topology.blackboardId,
585
- topicIds: topology.topicIds,
586
- metadata: { hostSurface: "multi-agent.step", topologyRunId: topology.id }
587
- };
588
- }
589
- function nextCandidatePlan(run) {
590
- const candidateWorkerIds = new Set((run.candidates || []).map((entry) => entry.workerId).filter(Boolean));
591
- return (run.workers || []).find((worker) => worker.status === "verified" &&
592
- worker.id &&
593
- !candidateWorkerIds.has(worker.id) &&
594
- worker.output?.verifierNodeId);
595
- }
596
- function nextScorePlan(run, options) {
597
- const explicit = resolveCandidate(run, options);
598
- const candidate = explicit || (run.candidates || []).filter((entry) => entry.status === "registered").at(0);
599
- if (!candidate || candidate.scores.length)
600
- return undefined;
601
- const evidence = explicitEvidence(options);
602
- return { candidate, evidence: evidence.length ? evidence : candidateEvidence(candidate) };
603
- }
604
- function nextSelectionPlan(run, options) {
605
- const candidate = resolveCandidate(run, options) || topRankedCandidate(run);
606
- if (!candidate || (run.candidateSelections || []).some((entry) => entry.candidateId === candidate.id))
607
- return undefined;
608
- if (!candidate.scores.length)
609
- return undefined;
610
- return { candidate, scoreId: stringOption(options.score || options.scoreId) };
611
- }
612
- function resolveCandidate(run, options) {
613
- const id = stringOption(options.candidate || options.candidateId || options.id);
614
- if (id) {
615
- const candidate = (run.candidates || []).find((entry) => entry.id === id);
616
- if (!candidate)
617
- throw new Error(`Unknown candidate id for run ${run.id}: ${id}`);
618
- return candidate;
619
- }
620
- const candidates = (run.candidates || []).filter((entry) => entry.status !== "rejected" && entry.status !== "failed");
621
- return candidates.length === 1 ? candidates[0] : undefined;
622
- }
623
- function topRankedCandidate(run) {
624
- const ranking = (0, candidate_scoring_1.rankCandidates)(run);
625
- const first = ranking.candidates.find((entry) => entry.scoreCount > 0 && entry.verdict !== "fail");
626
- return first ? (run.candidates || []).find((candidate) => candidate.id === first.candidateId) : undefined;
627
- }
628
- function activeTopologies(run) {
629
- return [...(run.topologies?.runs || [])].filter((entry) => !isTerminalTopology(entry));
630
- }
631
- function optionalSingleActiveTopology(run) {
632
- const active = activeTopologies(run);
633
- if (active.length > 1)
634
- throw new Error(`Ambiguous active topology state: ${active.map((entry) => entry.id).join(", ")}`);
635
- return active[0];
636
- }
637
- function requireSingleActiveTopology(run) {
638
- const active = activeTopologies(run);
639
- if (!active.length)
640
- throw new Error(`Run ${run.id} has no active multi-agent topology. Use multi-agent run --topology <id>.`);
641
- if (active.length > 1)
642
- throw new Error(`Ambiguous active topology state: ${active.map((entry) => entry.id).join(", ")}`);
643
- return active[0];
644
- }
645
- function resolveHostBlackboardId(run, topology, options) {
646
- const explicit = stringOption(options.blackboard || options.blackboardId);
647
- if (explicit)
648
- return explicit;
649
- if (topology?.blackboardId)
650
- return topology.blackboardId;
651
- const boards = run.blackboard?.boards || [];
652
- if (boards.length === 1)
653
- return boards[0].id;
654
- if (!boards.length)
655
- throw new Error(`Run ${run.id} has no blackboard. Use multi-agent run --topology <id> first.`);
656
- throw new Error(`Ambiguous blackboard state: ${boards.map((board) => board.id).join(", ")}`);
657
- }
658
- function resolveHostTopicId(run, blackboardId, options, action) {
659
- const explicit = stringOption(options.topic || options.topicId);
660
- if (explicit)
661
- return explicit;
662
- if (action === "summary" || action === "board" || action === "topics" || action === "artifacts" || action === "list-artifacts" || action === "snapshot") {
663
- return undefined;
664
- }
665
- const topics = (run.blackboard?.topics || []).filter((topic) => topic.blackboardId === blackboardId);
666
- if (topics.length === 1)
667
- return topics[0].id;
668
- if (!topics.length)
669
- throw new Error(`Blackboard ${blackboardId} has no topics`);
670
- throw new Error(`Ambiguous blackboard topic state: ${topics.map((topic) => topic.id).join(", ")}`);
671
- }
672
- function activeBlackboardId(run, topology) {
673
- const board = (run.blackboard?.boards || []).find((entry) => entry.id === topology.blackboardId);
674
- return board?.id;
675
- }
676
- function linkTopologyRecord(topology, links) {
677
- const faninIds = links.faninIds || [];
678
- const candidateIds = links.candidateIds || [];
679
- const selectionIds = links.selectionIds || [];
680
- topology.faninIds = unique([...topology.faninIds, ...faninIds]);
681
- topology.candidateIds = unique([...topology.candidateIds, ...candidateIds]);
682
- topology.selectionIds = unique([...topology.selectionIds, ...selectionIds]);
683
- topology.links.agentFaninIds = unique([...topology.links.agentFaninIds, ...faninIds]);
684
- topology.links.candidateIds = unique([...topology.links.candidateIds, ...candidateIds]);
685
- topology.links.selectionIds = unique([...topology.links.selectionIds, ...selectionIds]);
686
- topology.updatedAt = new Date().toISOString();
687
- }
688
- function evidenceRequirements(active, extra) {
689
- return unique([...active.flatMap((entry) => entry.missingEvidence), ...extra]);
690
- }
691
- function isTerminalTopology(topology) {
692
- return topology.status === "completed" || topology.status === "failed";
693
- }
694
- function parseCriteria(options, fallback) {
695
- const criteria = {};
696
- const structured = options.criteria;
697
- if (structured && typeof structured === "object" && !Array.isArray(structured)) {
698
- for (const [key, value] of Object.entries(structured)) {
699
- const parsed = Number(value);
700
- if (key && Number.isFinite(parsed))
701
- criteria[key] = parsed;
702
- }
703
- }
704
- for (const entry of arrayOption(options.criterion || (typeof structured === "string" ? structured : undefined) || options.score)) {
705
- const [key, value] = String(entry).split("=");
706
- if (!key || value === undefined)
707
- continue;
708
- const parsed = Number(value);
709
- if (Number.isFinite(parsed))
710
- criteria[key] = parsed;
711
- }
712
- if (!Object.keys(criteria).length && options.total !== undefined)
713
- criteria.total = Number(options.total);
714
- if (!Object.keys(criteria).length && fallback)
715
- return fallback;
716
- if (!Object.keys(criteria).length)
717
- throw new Error("Missing score criteria. Use --criterion name=value");
718
- return criteria;
719
- }
720
- function explicitEvidence(options) {
721
- return arrayOption(options.evidence || options.evidenceRef || options["evidence-ref"]).map((entry, index) => ({
722
- id: `host-score:${index + 1}`,
723
- source: "multi-agent-host",
724
- locator: String(entry),
725
- summary: String(entry)
726
- }));
727
- }
728
- function authorityOptions(options) {
729
- const agentRoleId = stringOption(options.role || options.roleId || options["multi-agent-role"]);
730
- const agentGroupId = stringOption(options.group || options.groupId || options["multi-agent-group"]);
731
- const agentMembershipId = stringOption(options.membership || options.membershipId || options["multi-agent-membership"]);
732
- const actor = agentMembershipId
733
- ? { kind: "membership", id: agentMembershipId }
734
- : agentRoleId
735
- ? { kind: "role", id: agentRoleId }
736
- : agentGroupId
737
- ? { kind: "group", id: agentGroupId }
738
- : undefined;
739
- return {
740
- actor,
741
- multiAgentRunId: stringOption(options.multiAgentRun || options.multiAgentRunId || options["multi-agent-run"]),
742
- agentRoleId,
743
- agentGroupId,
744
- agentMembershipId
745
- };
746
- }
747
- function candidateEvidence(candidate) {
748
- return (candidate.evidence || []).map((entry, index) => ({
749
- ...entry,
750
- id: entry.id || `candidate:${index + 1}`
751
- }));
752
- }
753
- function numberOption(value) {
754
- if (value === undefined || value === null || value === true)
755
- return undefined;
756
- const parsed = Number(value);
757
- return Number.isFinite(parsed) ? parsed : undefined;
758
- }
759
- function stringOption(value) {
760
- if (value === undefined || value === null || value === true)
761
- return undefined;
762
- return String(value);
763
- }
764
- function requireString(value, label) {
765
- const parsed = stringOption(value);
766
- if (!parsed)
767
- throw new Error(`Missing ${label}`);
768
- return parsed;
769
- }
770
- function arrayOption(value) {
771
- if (value === undefined || value === null || value === true)
772
- return [];
773
- return Array.isArray(value) ? value : [value];
774
- }
775
- function unique(values) {
776
- return [...new Set(values.filter((value) => value !== undefined && value !== null))];
777
- }