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,25 +1,95 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
2
+ // shell/multi-agent-operator-ux.ts the "Multi-Agent Operator UX" family
3
+ // (v0.1.21 + v0.1.27): the dependency / failure / evidence panels that the
4
+ // `multi-agent status|dependencies|failures|evidence` surfaces render.
5
+ //
6
+ // GAP #17. Port of the old build's src/multi-agent-operator-ux.ts data layer
7
+ // (summarizeMultiAgentOperator + deriveDependencies/deriveFailures/
8
+ // deriveEvidence + the three text formatters + graph). Byte-behavior
9
+ // preserved; adapted to v2's core/shell split:
10
+ // - StateEvidence lives in core/state/types;
11
+ // - CandidateScore lives in core/multi-agent/candidate-scoring;
12
+ // - scores are read from disk the same way candidate-scoring-io.ts's
13
+ // private readScores does (there is no validateCandidateScore in v2 —
14
+ // the on-disk record is trusted, matching the io reader).
15
+ //
16
+ // Evidence: SPEC/multi-agent.md "Multi-Agent Operator UX";
17
+ // plugins/cool-workflow/src/multi-agent-operator-ux.ts (byte-exact source).
18
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
19
+ if (k2 === undefined) k2 = k;
20
+ var desc = Object.getOwnPropertyDescriptor(m, k);
21
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
22
+ desc = { enumerable: true, get: function() { return m[k]; } };
23
+ }
24
+ Object.defineProperty(o, k2, desc);
25
+ }) : (function(o, m, k, k2) {
26
+ if (k2 === undefined) k2 = k;
27
+ o[k2] = m[k];
28
+ }));
29
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
30
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
31
+ }) : function(o, v) {
32
+ o["default"] = v;
33
+ });
34
+ var __importStar = (this && this.__importStar) || (function () {
35
+ var ownKeys = function(o) {
36
+ ownKeys = Object.getOwnPropertyNames || function (o) {
37
+ var ar = [];
38
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
39
+ return ar;
40
+ };
41
+ return ownKeys(o);
42
+ };
43
+ return function (mod) {
44
+ if (mod && mod.__esModule) return mod;
45
+ var result = {};
46
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
47
+ __setModuleDefault(result, mod);
48
+ return result;
49
+ };
50
+ })();
5
51
  Object.defineProperty(exports, "__esModule", { value: true });
6
52
  exports.summarizeMultiAgentOperator = summarizeMultiAgentOperator;
53
+ exports.operatorDigestInput = operatorDigestInput;
7
54
  exports.buildMultiAgentOperatorGraph = buildMultiAgentOperatorGraph;
8
55
  exports.formatMultiAgentOperatorStatus = formatMultiAgentOperatorStatus;
9
56
  exports.formatMultiAgentDependencies = formatMultiAgentDependencies;
10
57
  exports.formatMultiAgentFailures = formatMultiAgentFailures;
11
58
  exports.formatMultiAgentEvidence = formatMultiAgentEvidence;
12
- const node_fs_1 = __importDefault(require("node:fs"));
13
- const node_path_1 = __importDefault(require("node:path"));
14
- const coordinator_1 = require("./coordinator");
15
- const multi_agent_1 = require("./multi-agent");
16
- const topology_1 = require("./topology");
59
+ const fs = __importStar(require("node:fs"));
60
+ const path = __importStar(require("node:path"));
61
+ const coordinator_io_1 = require("./coordinator-io");
62
+ const multi_agent_io_1 = require("./multi-agent-io");
63
+ const topology_io_1 = require("./topology-io");
17
64
  const trust_audit_1 = require("./trust-audit");
18
- const validation_1 = require("./validation");
65
+ function maOf(run) {
66
+ return run.multiAgent || {};
67
+ }
68
+ function candidatesOf(run) {
69
+ return (run.candidates || []);
70
+ }
71
+ function selectionsOf(run) {
72
+ return (run.candidateSelections || []);
73
+ }
74
+ function commitsOf(run) {
75
+ return (run.commits || []);
76
+ }
77
+ function workersOf(run) {
78
+ return (run.workers || []);
79
+ }
80
+ function feedbackOf(run) {
81
+ return (run.feedback || []);
82
+ }
83
+ function topologyRunsOf(run) {
84
+ return (run.topologies?.runs || []);
85
+ }
86
+ function blackboardOf(run) {
87
+ return (run.blackboard || {});
88
+ }
19
89
  function summarizeMultiAgentOperator(run) {
20
- const topologies = (0, topology_1.summarizeTopologies)(run);
21
- const multiAgent = (0, multi_agent_1.summarizeMultiAgent)(run);
22
- const blackboard = (0, coordinator_1.summarizeBlackboard)(run);
90
+ const topologies = (0, topology_io_1.summarizeTopologies)(run);
91
+ const multiAgent = (0, multi_agent_io_1.summarizeMultiAgent)(run);
92
+ const blackboard = (0, coordinator_io_1.summarizeBlackboard)(run);
23
93
  const trust = (0, trust_audit_1.summarizeTrustAudit)(run);
24
94
  const dependencies = deriveDependencies(run);
25
95
  const failures = deriveFailures(run, dependencies);
@@ -29,7 +99,7 @@ function summarizeMultiAgentOperator(run) {
29
99
  const inspectableEvidence = missingEvidence.filter((entry) => entry.disposition === "inspectable");
30
100
  const activeTopologyIds = new Set(topologies.active.map((entry) => entry.id));
31
101
  const activeMultiAgentRunIds = new Set(topologies.active.map((entry) => entry.multiAgentRunId));
32
- const state = run.multiAgent;
102
+ const state = maOf(run);
33
103
  const nextAction = failures[0]?.nextCommand ||
34
104
  topologies.nextAction ||
35
105
  multiAgent.nextAction ||
@@ -39,14 +109,14 @@ function summarizeMultiAgentOperator(run) {
39
109
  return {
40
110
  schemaVersion: 1,
41
111
  runId: run.id,
42
- activeMultiAgentRunIds: [...activeMultiAgentRunIds, ...((state?.runs || []).filter((entry) => !isTerminal(entry.status)).map((entry) => entry.id))].filter(uniqueFilter),
112
+ activeMultiAgentRunIds: [...activeMultiAgentRunIds, ...((state.runs || []).filter((entry) => !isTerminal(entry.status)).map((entry) => entry.id))].filter(uniqueFilter),
43
113
  topologyRunIds: [...activeTopologyIds],
44
114
  topologyIds: topologies.active.map((entry) => entry.topologyId).filter(uniqueFilter),
45
- groups: (state?.groups || []).map((entry) => entry.id).sort(),
46
- roles: (state?.roles || []).map((entry) => entry.id).sort(),
47
- memberships: (state?.memberships || []).map((entry) => entry.id).sort(),
48
- fanouts: (state?.fanouts || []).map((entry) => entry.id).sort(),
49
- fanins: (state?.fanins || []).map((entry) => entry.id).sort(),
115
+ groups: (state.groups || []).map((entry) => entry.id).sort(),
116
+ roles: (state.roles || []).map((entry) => entry.id).sort(),
117
+ memberships: (state.memberships || []).map((entry) => entry.id).sort(),
118
+ fanouts: (state.fanouts || []).map((entry) => entry.id).sort(),
119
+ fanins: (state.fanins || []).map((entry) => entry.id).sort(),
50
120
  blocked: failures.length > 0,
51
121
  dependencies,
52
122
  failures,
@@ -55,87 +125,60 @@ function summarizeMultiAgentOperator(run) {
55
125
  adoptedEvidence,
56
126
  inspectableEvidence,
57
127
  nextAction,
58
- summaries: { topologies, multiAgent, blackboard, trust }
128
+ summaries: { topologies, multiAgent, blackboard, trust },
129
+ };
130
+ }
131
+ /** Adapt the operator status into the structural input `buildOperatorDigest`
132
+ * (core) folds into the state-explosion digest — the shell-side bridge that
133
+ * lets core stay free of `summarizeMultiAgentOperator`. */
134
+ function operatorDigestInput(run) {
135
+ const status = summarizeMultiAgentOperator(run);
136
+ return {
137
+ failures: status.failures.map((f) => ({ id: f.id, kind: f.kind, status: f.status, reason: f.reason, nextCommand: f.nextCommand })),
138
+ evidence: status.evidence.map((e) => ({ id: e.id, ref: e.ref, status: e.status, sourceId: e.sourceId })),
139
+ nextAction: status.nextAction,
140
+ trustEvents: status.summaries.trust?.eventCount || 0,
59
141
  };
60
142
  }
61
143
  function buildMultiAgentOperatorGraph(run) {
62
144
  const nodes = new Map();
63
145
  const edges = [];
64
- const addNode = (id, kind, status, label, pathValue) => {
146
+ const addNode = (id, kind, status, label, filePath) => {
65
147
  if (!id)
66
148
  return;
67
- nodes.set(id, { id, kind, status, label, path: pathValue });
68
- };
69
- const addEdge = (from, to, label) => {
70
- if (!from || !to)
71
- return;
72
- edges.push({ from, to, label });
73
- };
74
- addNode(`${run.id}:run`, "multi-agent-run-root", run.loopStage, run.id, run.paths.state);
75
- for (const graph of [(0, topology_1.buildTopologyGraph)(run), (0, multi_agent_1.buildMultiAgentGraph)(run), (0, coordinator_1.buildBlackboardGraph)(run)]) {
76
- for (const node of graph.nodes)
77
- addNode(node.id, node.kind, node.status, node.label, node.path);
78
- for (const edge of graph.edges)
79
- addEdge(edge.from, edge.to, relabel(edge.label));
80
- }
81
- for (const task of run.tasks || []) {
82
- addNode(`${run.id}:task:${task.id}`, "task", task.status, task.id, task.taskPath);
83
- addEdge(`${run.id}:run`, `${run.id}:task:${task.id}`, "owns");
84
- addEdge(`${run.id}:task:${task.id}`, task.dispatchId ? `${run.id}:dispatch:${task.dispatchId}` : undefined, "dispatches");
85
- addEdge(`${run.id}:task:${task.id}`, task.resultNodeId, "reports");
86
- addEdge(`${run.id}:task:${task.id}`, task.verifierNodeId, "gates");
87
- }
88
- for (const dispatch of run.dispatches || []) {
89
- addNode(`${run.id}:dispatch:${dispatch.id}`, "dispatch", "completed", dispatch.id, dispatch.manifestPath);
90
- for (const workerId of dispatch.workerIds || [])
91
- addEdge(`${run.id}:dispatch:${dispatch.id}`, `${run.id}:worker:${workerId}`, "dispatches");
92
- }
93
- for (const worker of run.workers || []) {
94
- addNode(`${run.id}:worker:${worker.id}`, "worker", worker.status, worker.id, worker.inputPath);
95
- addEdge(`${run.id}:worker:${worker.id}`, worker.resultNodeId, "reports");
96
- addEdge(`${run.id}:worker:${worker.id}`, worker.output?.verifierNodeId, "gates");
97
- for (const feedbackId of worker.feedbackIds || [])
98
- addEdge(`${run.id}:worker:${worker.id}`, `${run.id}:feedback:${feedbackId}`, "blocks");
99
- }
100
- for (const candidate of run.candidates || []) {
101
- const candidateId = `${run.id}:candidate:${candidate.id}`;
102
- addNode(candidateId, "candidate", candidate.status, candidate.id, candidate.resultPath);
103
- addEdge(candidate.workerId ? `${run.id}:worker:${candidate.workerId}` : candidate.resultNodeId, candidateId, "reports");
104
- addEdge(candidate.verifierNodeId, candidateId, "gates");
105
- for (const scoreId of candidate.scores || []) {
106
- const nodeId = `${run.id}:score:${scoreId}`;
107
- addNode(nodeId, "score", "completed", scoreId, scorePath(run, candidate.id, scoreId));
108
- addEdge(candidateId, nodeId, "scores");
109
- }
110
- for (const feedbackId of candidate.feedbackIds || [])
111
- addEdge(candidateId, `${run.id}:feedback:${feedbackId}`, "blocks");
112
- }
113
- for (const selection of run.candidateSelections || []) {
114
- const nodeId = `${run.id}:selection:${selection.id}`;
115
- addNode(nodeId, "selection", "accepted", selection.id, selection.rankingPath);
116
- addEdge(`${run.id}:candidate:${selection.candidateId}`, nodeId, "selects");
117
- if (selection.scoreId)
118
- addEdge(`${run.id}:score:${selection.scoreId}`, nodeId, "selects");
119
- addEdge(selection.verifierNodeId, nodeId, "gates");
120
- }
121
- for (const commit of run.commits || []) {
122
- const nodeId = commit.stateNodeId || `${run.id}:commit:${commit.id}`;
123
- addNode(nodeId, "commit", commit.verifierGated ? "committed" : "checkpoint", commit.id, commit.snapshotPath);
124
- addEdge(commit.selectionId ? `${run.id}:selection:${commit.selectionId}` : undefined, nodeId, "commits");
125
- addEdge(commit.verifierNodeId, nodeId, "gates");
126
- }
127
- for (const feedback of run.feedback || []) {
128
- addNode(`${run.id}:feedback:${feedback.id}`, "feedback", feedback.status, `${feedback.severity} ${feedback.classification}`);
129
- addEdge(feedback.nodeId, `${run.id}:feedback:${feedback.id}`, "blocks");
130
- addEdge(feedback.taskId ? `${run.id}:task:${feedback.taskId}` : undefined, `${run.id}:feedback:${feedback.id}`, "blocks");
131
- }
132
- for (const dep of deriveDependencies(run))
133
- addEdge(dep.from, dep.to, dep.label);
134
- return {
135
- runId: run.id,
136
- nodes: [...nodes.values()].sort((left, right) => left.kind.localeCompare(right.kind) || left.id.localeCompare(right.id)),
137
- edges: uniqueEdges(edges).sort((left, right) => left.from.localeCompare(right.from) || left.to.localeCompare(right.to) || (left.label || "").localeCompare(right.label || ""))
149
+ if (!nodes.has(id))
150
+ nodes.set(id, { id, kind, status, label, path: filePath });
138
151
  };
152
+ const state = maOf(run);
153
+ for (const topology of topologyRunsOf(run)) {
154
+ const id = String(topology.id);
155
+ addNode(`${run.id}:topology:${id}`, "topology-run", String(topology.status), `topology ${topology.topologyId}`);
156
+ }
157
+ for (const group of state.groups || [])
158
+ addNode(`${run.id}:multi-agent:group:${group.id}`, "agent-group", "running", `group ${group.id}`);
159
+ for (const role of state.roles || [])
160
+ addNode(`${run.id}:multi-agent:role:${role.id}`, "agent-role", role.status, `role ${role.id}`);
161
+ for (const membership of state.memberships || [])
162
+ addNode(`${run.id}:multi-agent:membership:${membership.id}`, "agent-membership", membership.status, `membership ${membership.id}`);
163
+ for (const fanout of state.fanouts || [])
164
+ addNode(`${run.id}:multi-agent:fanout:${fanout.id}`, "agent-fanout", "running", `fanout ${fanout.id}`);
165
+ for (const fanin of state.fanins || [])
166
+ addNode(`${run.id}:multi-agent:fanin:${fanin.id}`, "agent-fanin", fanin.status, `fanin ${fanin.id}`);
167
+ for (const candidate of candidatesOf(run))
168
+ addNode(`${run.id}:candidate:${candidate.id}`, "candidate", String(candidate.status), `candidate ${candidate.id}`);
169
+ for (const candidate of candidatesOf(run))
170
+ for (const scoreId of candidate.scores || [])
171
+ addNode(`${run.id}:score:${scoreId}`, "score", "completed", `score ${scoreId}`);
172
+ for (const selection of selectionsOf(run))
173
+ addNode(`${run.id}:selection:${selection.id}`, "selection", "accepted", `selection ${selection.id}`);
174
+ for (const commit of commitsOf(run))
175
+ addNode(String(commit.stateNodeId || `${run.id}:commit:${commit.id}`), "commit", commit.verifierGated ? "committed" : "checkpoint", `commit ${commit.id}`);
176
+ for (const artifact of blackboardOf(run).artifacts || [])
177
+ addNode(`${run.id}:blackboard:artifact:${artifact.id}`, "blackboard-artifact", String(artifact.status || "pending"), `artifact ${artifact.id}`, artifact.path);
178
+ for (const dependency of deriveDependencies(run)) {
179
+ edges.push({ from: dependency.from, to: dependency.to, label: relabel(dependency.label) });
180
+ }
181
+ return { runId: run.id, nodes: [...nodes.values()], edges: uniqueEdges(edges) };
139
182
  }
140
183
  function formatMultiAgentOperatorStatus(status) {
141
184
  return [
@@ -158,7 +201,7 @@ function formatMultiAgentOperatorStatus(status) {
158
201
  : "Missing Evidence", status.missingEvidence),
159
202
  "",
160
203
  "Next Action",
161
- ` ${status.nextAction}`
204
+ ` ${status.nextAction}`,
162
205
  ].join("\n");
163
206
  }
164
207
  function formatMultiAgentDependencies(rows) {
@@ -177,32 +220,33 @@ function deriveDependencies(run) {
177
220
  return;
178
221
  rows.push({ id: `${from}->${to}:${label}`, from, to, label, status, reason, nextCommand });
179
222
  };
180
- const state = run.multiAgent;
181
- for (const topology of run.topologies?.runs || []) {
182
- add(`${run.id}:topology:${topology.id}`, `${run.id}:multi-agent:${topology.multiAgentRunId}`, "owns");
183
- add(`${run.id}:topology:${topology.id}`, `${run.id}:blackboard:${topology.blackboardId}`, "owns");
184
- for (const fanoutId of topology.fanoutIds)
185
- add(`${run.id}:topology:${topology.id}`, `${run.id}:multi-agent:fanout:${fanoutId}`, "fanout");
186
- for (const faninId of topology.faninIds)
187
- add(`${run.id}:multi-agent:fanin:${faninId}`, `${run.id}:topology:${topology.id}`, "reports");
188
- for (const candidateId of topology.candidateIds)
189
- add(`${run.id}:topology:${topology.id}`, `${run.id}:candidate:${candidateId}`, "candidate");
190
- for (const selectionId of topology.selectionIds)
191
- add(`${run.id}:selection:${selectionId}`, `${run.id}:topology:${topology.id}`, "selects");
192
- }
193
- for (const group of state?.groups || []) {
223
+ const state = maOf(run);
224
+ for (const topology of topologyRunsOf(run)) {
225
+ const id = String(topology.id);
226
+ add(`${run.id}:topology:${id}`, `${run.id}:multi-agent:${topology.multiAgentRunId}`, "owns");
227
+ add(`${run.id}:topology:${id}`, `${run.id}:blackboard:${topology.blackboardId}`, "owns");
228
+ for (const fanoutId of topology.fanoutIds || [])
229
+ add(`${run.id}:topology:${id}`, `${run.id}:multi-agent:fanout:${fanoutId}`, "fanout");
230
+ for (const faninId of topology.faninIds || [])
231
+ add(`${run.id}:multi-agent:fanin:${faninId}`, `${run.id}:topology:${id}`, "reports");
232
+ for (const candidateId of topology.candidateIds || [])
233
+ add(`${run.id}:topology:${id}`, `${run.id}:candidate:${candidateId}`, "candidate");
234
+ for (const selectionId of topology.selectionIds || [])
235
+ add(`${run.id}:selection:${selectionId}`, `${run.id}:topology:${id}`, "selects");
236
+ }
237
+ for (const group of state.groups || []) {
194
238
  add(`${run.id}:multi-agent:${group.multiAgentRunId}`, `${run.id}:multi-agent:group:${group.id}`, "owns");
195
- for (const taskId of group.taskIds)
239
+ for (const taskId of group.taskIds || [])
196
240
  add(`${run.id}:multi-agent:group:${group.id}`, `${run.id}:task:${taskId}`, "depends-on");
197
241
  }
198
- for (const fanout of state?.fanouts || []) {
242
+ for (const fanout of state.fanouts || []) {
199
243
  add(`${run.id}:multi-agent:group:${fanout.groupId}`, `${run.id}:multi-agent:fanout:${fanout.id}`, "fanout");
200
- for (const roleId of fanout.roleIds)
244
+ for (const roleId of fanout.roleIds || [])
201
245
  add(`${run.id}:multi-agent:fanout:${fanout.id}`, `${run.id}:multi-agent:role:${roleId}`, "depends-on");
202
- for (const dispatchId of fanout.dispatchIds)
246
+ for (const dispatchId of fanout.dispatchIds || [])
203
247
  add(`${run.id}:multi-agent:fanout:${fanout.id}`, `${run.id}:dispatch:${dispatchId}`, "dispatches");
204
248
  }
205
- for (const membership of state?.memberships || []) {
249
+ for (const membership of state.memberships || []) {
206
250
  add(`${run.id}:multi-agent:role:${membership.roleId}`, `${run.id}:multi-agent:membership:${membership.id}`, "owns");
207
251
  add(`${run.id}:multi-agent:membership:${membership.id}`, `${run.id}:task:${membership.taskId}`, "depends-on");
208
252
  add(`${run.id}:multi-agent:membership:${membership.id}`, membership.workerId ? `${run.id}:worker:${membership.workerId}` : undefined, "dispatches");
@@ -213,23 +257,23 @@ function deriveDependencies(run) {
213
257
  for (const messageId of membership.blackboardMessageIds || [])
214
258
  add(`${run.id}:blackboard:message:${messageId}`, `${run.id}:multi-agent:membership:${membership.id}`, "cites");
215
259
  }
216
- for (const fanin of state?.fanins || []) {
260
+ for (const fanin of state.fanins || []) {
217
261
  add(fanin.fanoutId ? `${run.id}:multi-agent:fanout:${fanin.fanoutId}` : `${run.id}:multi-agent:group:${fanin.groupId}`, `${run.id}:multi-agent:fanin:${fanin.id}`, "fanin");
218
- for (const coverage of fanin.evidenceCoverage) {
262
+ for (const coverage of fanin.evidenceCoverage || []) {
219
263
  add(`${run.id}:multi-agent:membership:${coverage.membershipId}`, `${run.id}:multi-agent:fanin:${fanin.id}`, coverage.complete ? "adopted-by" : "blocks", coverage.complete ? "ready" : "blocked", coverage.complete ? undefined : "membership has not reported required evidence", `node scripts/cw.js worker manifest ${run.id} ${coverage.workerId || "<worker-id>"}`);
220
264
  }
221
265
  }
222
- for (const candidate of run.candidates || []) {
223
- add(candidate.workerId ? `${run.id}:worker:${candidate.workerId}` : candidate.resultNodeId, `${run.id}:candidate:${candidate.id}`, "reports", candidate.status);
266
+ for (const candidate of candidatesOf(run)) {
267
+ add(candidate.workerId ? `${run.id}:worker:${candidate.workerId}` : candidate.resultNodeId, `${run.id}:candidate:${candidate.id}`, "reports", String(candidate.status));
224
268
  for (const scoreId of candidate.scores || [])
225
269
  add(`${run.id}:candidate:${candidate.id}`, `${run.id}:score:${scoreId}`, "scores", "completed");
226
270
  }
227
- for (const selection of run.candidateSelections || []) {
271
+ for (const selection of selectionsOf(run)) {
228
272
  add(`${run.id}:candidate:${selection.candidateId}`, `${run.id}:selection:${selection.id}`, "selects", "accepted");
229
273
  add(selection.scoreId ? `${run.id}:score:${selection.scoreId}` : undefined, `${run.id}:selection:${selection.id}`, "scores", "accepted");
230
274
  }
231
- for (const commit of run.commits || []) {
232
- add(commit.selectionId ? `${run.id}:selection:${commit.selectionId}` : undefined, commit.stateNodeId || `${run.id}:commit:${commit.id}`, "commits", commit.verifierGated ? "committed" : "checkpoint");
275
+ for (const commit of commitsOf(run)) {
276
+ add(commit.selectionId ? `${run.id}:selection:${commit.selectionId}` : undefined, String(commit.stateNodeId || `${run.id}:commit:${commit.id}`), "commits", commit.verifierGated ? "committed" : "checkpoint");
233
277
  }
234
278
  return rows.filter(uniqueById).sort((left, right) => left.from.localeCompare(right.from) || left.to.localeCompare(right.to));
235
279
  }
@@ -238,60 +282,61 @@ function deriveFailures(run, dependencies) {
238
282
  const add = (id, kind, status, reason, nextCommand, owner, linked) => {
239
283
  rows.push({ id, kind, status, owner, linked, reason, nextCommand });
240
284
  };
241
- const state = run.multiAgent;
242
- for (const role of state?.roles || []) {
243
- const memberships = (state?.memberships || []).filter((entry) => entry.roleId === role.id);
285
+ const state = maOf(run);
286
+ for (const role of state.roles || []) {
287
+ const memberships = (state.memberships || []).filter((entry) => entry.roleId === role.id);
244
288
  if (!memberships.length && role.status !== "completed" && role.status !== "cancelled") {
245
289
  add(role.id, "missing-role-coverage", role.status, `role ${role.id} has no membership`, `node scripts/cw.js multi-agent step ${run.id}`, role.id);
246
290
  }
247
291
  if (role.status === "blocked" || role.status === "cancelled")
248
292
  add(role.id, "agent-role", role.status, `role ${role.id} is ${role.status}`, `node scripts/cw.js multi-agent status ${run.id} --json`, role.id);
249
293
  }
250
- for (const membership of state?.memberships || []) {
251
- const worker = membership.workerId ? (run.workers || []).find((entry) => entry.id === membership.workerId) : undefined;
294
+ for (const membership of state.memberships || []) {
295
+ const worker = membership.workerId ? workersOf(run).find((entry) => entry.id === membership.workerId) : undefined;
252
296
  if (membership.status === "failed" || membership.status === "cancelled")
253
297
  add(membership.id, "agent-membership", membership.status, `membership ${membership.id} is ${membership.status}`, `node scripts/cw.js multi-agent membership ${run.id} ${membership.id}`, membership.roleId, membership.workerId);
254
298
  if (!membership.workerId)
255
299
  add(membership.id, "missing-worker", membership.status, `membership ${membership.id} has no worker`, `node scripts/cw.js multi-agent step ${run.id}`, membership.roleId, membership.taskId);
256
300
  if (worker && (worker.status === "failed" || worker.status === "rejected"))
257
- add(worker.id, "worker", worker.status, worker.errors[0]?.message || `worker ${worker.id} is ${worker.status}`, `node scripts/cw.js worker show ${run.id} ${worker.id}`, membership.roleId, membership.id);
301
+ add(String(worker.id), "worker", String(worker.status), worker.errors?.[0]?.message || `worker ${worker.id} is ${worker.status}`, `node scripts/cw.js worker show ${run.id} ${worker.id}`, membership.roleId, membership.id);
258
302
  if (worker && (worker.status === "allocated" || worker.status === "running"))
259
- add(worker.id, "worker-output", worker.status, `worker ${worker.id} has not reported output`, `node scripts/cw.js worker manifest ${run.id} ${worker.id}`, membership.roleId, membership.id);
303
+ add(String(worker.id), "worker-output", String(worker.status), `worker ${worker.id} has not reported output`, `node scripts/cw.js worker manifest ${run.id} ${worker.id}`, membership.roleId, membership.id);
260
304
  }
261
- for (const fanin of state?.fanins || []) {
262
- for (const reason of fanin.blockedReasons)
305
+ for (const fanin of state.fanins || []) {
306
+ for (const reason of fanin.blockedReasons || [])
263
307
  add(fanin.id, "fanin", fanin.status, reason, `node scripts/cw.js multi-agent failures ${run.id}`, fanin.groupId, fanin.fanoutId);
264
- for (const roleId of fanin.missingRoleIds)
308
+ for (const roleId of fanin.missingRoleIds || [])
265
309
  add(`${fanin.id}:${roleId}`, "missing-role-evidence", "missing", `fanin ${fanin.id} is missing role ${roleId}`, `node scripts/cw.js multi-agent step ${run.id}`, roleId, fanin.id);
266
- for (const membershipId of fanin.missingMembershipIds)
310
+ for (const membershipId of fanin.missingMembershipIds || [])
267
311
  add(`${fanin.id}:${membershipId}`, "missing-membership-evidence", "missing", `fanin ${fanin.id} is missing membership ${membershipId}`, `node scripts/cw.js multi-agent membership ${run.id} ${membershipId}`, membershipId, fanin.id);
268
312
  }
269
- for (const topology of run.topologies?.runs || []) {
313
+ for (const topology of topologyRunsOf(run)) {
270
314
  for (const missing of topology.missingEvidence || [])
271
- add(`${topology.id}:${missing}`, "missing-topology-evidence", "missing", missing, topology.nextActions[0] || `node scripts/cw.js topology summary ${run.id}`, topology.id);
315
+ add(`${topology.id}:${missing}`, "missing-topology-evidence", "missing", missing, topology.nextActions?.[0] || `node scripts/cw.js topology summary ${run.id}`, String(topology.id));
272
316
  if (topology.status === "blocked" || topology.status === "failed")
273
- add(topology.id, "topology", topology.status, `topology ${topology.id} is ${topology.status}`, `node scripts/cw.js topology summary ${run.id}`, topology.id);
317
+ add(String(topology.id), "topology", String(topology.status), `topology ${topology.id} is ${topology.status}`, `node scripts/cw.js topology summary ${run.id}`, String(topology.id));
274
318
  }
275
- for (const feedback of run.feedback || []) {
319
+ for (const feedback of feedbackOf(run)) {
276
320
  if (feedback.status === "open" || feedback.status === "tasked")
277
- add(feedback.id, feedback.classification, feedback.status, feedback.message, `node scripts/cw.js feedback show ${run.id} ${feedback.id}`, feedback.taskId, feedback.nodeId);
321
+ add(String(feedback.id), String(feedback.classification), String(feedback.status), String(feedback.message), `node scripts/cw.js feedback show ${run.id} ${feedback.id}`, feedback.taskId, feedback.nodeId);
278
322
  }
279
- for (const candidate of run.candidates || []) {
323
+ for (const candidate of candidatesOf(run)) {
324
+ const scores = candidate.scores || [];
280
325
  if (candidate.status === "rejected" || candidate.status === "failed")
281
- add(candidate.id, "candidate", candidate.status, candidate.feedbackIds[0] || `candidate ${candidate.id} is ${candidate.status}`, `node scripts/cw.js candidate show ${run.id} ${candidate.id}`, candidate.workerId, candidate.taskId);
282
- if (!candidate.scores.length && candidate.status !== "rejected" && candidate.status !== "failed")
283
- add(candidate.id, "candidate-score-gap", candidate.status, `candidate ${candidate.id} has no score`, `node scripts/cw.js multi-agent score ${run.id} --candidate ${candidate.id} --evidence <path-or-ref>`, candidate.workerId, candidate.taskId);
326
+ add(String(candidate.id), "candidate", String(candidate.status), candidate.feedbackIds?.[0] || `candidate ${candidate.id} is ${candidate.status}`, `node scripts/cw.js candidate show ${run.id} ${candidate.id}`, candidate.workerId, candidate.taskId);
327
+ if (!scores.length && candidate.status !== "rejected" && candidate.status !== "failed")
328
+ add(String(candidate.id), "candidate-score-gap", String(candidate.status), `candidate ${candidate.id} has no score`, `node scripts/cw.js multi-agent score ${run.id} --candidate ${candidate.id} --evidence <path-or-ref>`, candidate.workerId, candidate.taskId);
284
329
  if (!candidate.verifierNodeId)
285
- add(`${candidate.id}:verifier`, "candidate-verifier-gap", candidate.status, `candidate ${candidate.id} has no verifier gate`, `node scripts/cw.js candidate show ${run.id} ${candidate.id}`, candidate.workerId, candidate.taskId);
330
+ add(`${candidate.id}:verifier`, "candidate-verifier-gap", String(candidate.status), `candidate ${candidate.id} has no verifier gate`, `node scripts/cw.js candidate show ${run.id} ${candidate.id}`, candidate.workerId, candidate.taskId);
286
331
  }
287
- if ((run.candidates || []).some((candidate) => candidate.scores.length) && !(run.candidateSelections || []).length) {
332
+ if (candidatesOf(run).some((candidate) => (candidate.scores || []).length) && !selectionsOf(run).length) {
288
333
  add("selection-gap", "selection", "missing", "scored candidates exist but no selection is recorded", `node scripts/cw.js multi-agent select ${run.id} --candidate <candidate-id> --reason "<rationale>"`);
289
334
  }
290
335
  for (const dep of dependencies.filter((entry) => entry.status === "blocked"))
291
336
  add(dep.id, "ambiguous-dependency", dep.status, dep.reason || "dependency is blocked", dep.nextCommand || `node scripts/cw.js multi-agent status ${run.id} --json`);
292
- const readySelection = (run.candidateSelections || []).find((selection) => !(run.commits || []).some((commit) => commit.selectionId === selection.id && commit.verifierGated));
337
+ const readySelection = selectionsOf(run).find((selection) => !commitsOf(run).some((commit) => commit.selectionId === selection.id && commit.verifierGated));
293
338
  if (readySelection)
294
- add(readySelection.id, "commit-gate", "not-ready", `selection ${readySelection.id} has no verifier-gated commit`, `node scripts/cw.js commit ${run.id} --selection ${readySelection.id} --reason "<verified rationale>"`, readySelection.candidateId);
339
+ add(String(readySelection.id), "commit-gate", "not-ready", `selection ${readySelection.id} has no verifier-gated commit`, `node scripts/cw.js commit ${run.id} --selection ${readySelection.id} --reason "<verified rationale>"`, readySelection.candidateId);
295
340
  return rows.filter(uniqueByFailure).sort((left, right) => left.kind.localeCompare(right.kind) || left.id.localeCompare(right.id));
296
341
  }
297
342
  function deriveEvidence(run) {
@@ -308,7 +353,7 @@ function deriveEvidence(run) {
308
353
  scoreIds: [],
309
354
  selectionIds: [],
310
355
  commitIds: [],
311
- status: "pending"
356
+ status: "pending",
312
357
  };
313
358
  Object.assign(next, patch);
314
359
  next.adoptedBy = unique([...(next.adoptedBy || []), ...(patch.adoptedBy || [])]);
@@ -329,17 +374,18 @@ function deriveEvidence(run) {
329
374
  path: item.path,
330
375
  locator: item.locator,
331
376
  provenanceSource: item.provenance?.source,
332
- sourceId: item.provenance?.workerId || item.provenance?.candidateId || item.provenance?.selectionId || item.provenance?.commitId || patch.sourceId,
377
+ sourceId: provenanceSourceId(item) || patch.sourceId,
333
378
  sourceKind: sourceKindFromEvidence(item, patch.sourceKind),
334
- ...patch
379
+ ...patch,
335
380
  });
336
381
  }
337
382
  };
338
- for (const worker of run.workers || []) {
339
- if (worker.output?.resultPath)
340
- ensure(worker.output.resultPath, { path: worker.output.resultPath, sourceKind: "worker", sourceId: worker.id, status: worker.status === "verified" ? "adopted" : "pending", adoptedBy: worker.status === "verified" ? [worker.id] : [], pendingConsumers: worker.status === "verified" ? [] : [worker.id] });
383
+ for (const worker of workersOf(run)) {
384
+ const output = worker.output;
385
+ if (output?.resultPath)
386
+ ensure(output.resultPath, { path: output.resultPath, sourceKind: "worker", sourceId: String(worker.id), status: worker.status === "verified" ? "adopted" : "pending", adoptedBy: worker.status === "verified" ? [String(worker.id)] : [], pendingConsumers: worker.status === "verified" ? [] : [String(worker.id)] });
341
387
  }
342
- for (const membership of run.multiAgent?.memberships || []) {
388
+ for (const membership of maOf(run).memberships || []) {
343
389
  for (const ref of membership.evidenceRefs || [])
344
390
  ensure(ref, { ref, sourceKind: "worker", sourceId: membership.workerId || membership.id, status: membership.status === "reported" || membership.status === "verified" ? "adopted" : "pending", adoptedBy: membership.status === "reported" || membership.status === "verified" ? [membership.id] : [], pendingConsumers: membership.status === "reported" || membership.status === "verified" ? [] : [membership.id] });
345
391
  for (const artifactId of membership.blackboardArtifactRefIds || [])
@@ -347,56 +393,51 @@ function deriveEvidence(run) {
347
393
  for (const messageId of membership.blackboardMessageIds || [])
348
394
  ensure(messageId, { ref: messageId, sourceKind: "blackboard", sourceId: membership.id, status: "adopted", adoptedBy: [membership.id] });
349
395
  }
350
- for (const artifact of run.blackboard?.artifacts || []) {
351
- ensure(artifact.id, { ref: artifact.locator || artifact.path || artifact.id, path: artifact.path, locator: artifact.locator, sourceKind: "blackboard", sourceId: artifact.source, provenanceSource: artifact.provenance.auditEventIds?.[0], status: artifact.status === "rejected" ? "rejected" : artifact.status === "superseded" ? "superseded" : artifact.status === "conflicting" ? "conflicting" : "pending" });
396
+ for (const artifact of blackboardOf(run).artifacts || []) {
397
+ ensure(String(artifact.id), { ref: artifact.locator || artifact.path || String(artifact.id), path: artifact.path, locator: artifact.locator, sourceKind: "blackboard", sourceId: artifact.source, provenanceSource: artifact.provenance?.auditEventIds?.[0], status: artifact.status === "rejected" ? "rejected" : artifact.status === "superseded" ? "superseded" : artifact.status === "conflicting" ? "conflicting" : "pending" });
352
398
  for (const ref of artifact.evidenceRefs || [])
353
- ensure(ref, { ref, sourceKind: "blackboard", sourceId: artifact.id, status: "pending", pendingConsumers: [artifact.id] });
399
+ ensure(ref, { ref, sourceKind: "blackboard", sourceId: String(artifact.id), status: "pending", pendingConsumers: [String(artifact.id)] });
354
400
  }
355
- for (const message of run.blackboard?.messages || []) {
356
- ensure(message.id, { ref: message.id, sourceKind: "blackboard", sourceId: message.author.id, status: message.status === "rejected" ? "rejected" : message.status === "superseded" ? "superseded" : "pending" });
401
+ for (const message of blackboardOf(run).messages || []) {
402
+ ensure(String(message.id), { ref: String(message.id), sourceKind: "blackboard", sourceId: message.author?.id, status: message.status === "rejected" ? "rejected" : message.status === "superseded" ? "superseded" : "pending" });
357
403
  for (const ref of message.linkedEvidenceRefs || [])
358
- ensure(ref, { ref, sourceKind: "blackboard", sourceId: message.id, status: "pending", pendingConsumers: [message.id] });
404
+ ensure(ref, { ref, sourceKind: "blackboard", sourceId: String(message.id), status: "pending", pendingConsumers: [String(message.id)] });
359
405
  }
360
- for (const decision of run.blackboard?.decisions || []) {
406
+ for (const decision of blackboardOf(run).decisions || []) {
361
407
  for (const ref of [...(decision.evidenceRefs || []), ...(decision.artifactRefIds || []), ...(decision.messageIds || [])]) {
362
- ensure(ref, { ref, sourceKind: "coordinator", sourceId: decision.id, status: evidenceStatusForDecision(decision.outcome), adoptedBy: decision.outcome === "accepted" || decision.outcome === "ready" ? [decision.id] : [], rejectedBy: decision.outcome === "rejected" ? [decision.id] : [] });
408
+ ensure(ref, { ref, sourceKind: "coordinator", sourceId: String(decision.id), status: evidenceStatusForDecision(String(decision.outcome)), adoptedBy: decision.outcome === "accepted" || decision.outcome === "ready" ? [String(decision.id)] : [], rejectedBy: decision.outcome === "rejected" ? [String(decision.id)] : [] });
363
409
  }
364
410
  }
365
- for (const fanin of run.multiAgent?.fanins || []) {
366
- for (const coverage of fanin.evidenceCoverage) {
411
+ for (const fanin of maOf(run).fanins || []) {
412
+ for (const coverage of fanin.evidenceCoverage || []) {
367
413
  for (const ref of [...coverage.evidenceRefs, ...(coverage.blackboardArtifactRefIds || []), ...(coverage.blackboardMessageIds || [])])
368
414
  ensure(ref, { ref, sourceKind: "worker", sourceId: coverage.workerId || coverage.membershipId, status: coverage.complete && fanin.verifierReady ? "adopted" : "pending", adoptedBy: coverage.complete ? [fanin.id] : [], pendingConsumers: coverage.complete ? [] : [fanin.id] });
369
415
  }
370
- for (const roleId of fanin.missingRoleIds)
416
+ for (const roleId of fanin.missingRoleIds || [])
371
417
  ensure(`${fanin.id}:missing-role:${roleId}`, { ref: roleId, sourceKind: "runtime", sourceId: fanin.id, status: "missing", pendingConsumers: [fanin.id], reason: `fanin ${fanin.id} requires role ${roleId}` });
372
- for (const membershipId of fanin.missingMembershipIds)
418
+ for (const membershipId of fanin.missingMembershipIds || [])
373
419
  ensure(`${fanin.id}:missing-membership:${membershipId}`, { ref: membershipId, sourceKind: "runtime", sourceId: fanin.id, status: "missing", pendingConsumers: [fanin.id], reason: `fanin ${fanin.id} requires membership ${membershipId}` });
374
420
  }
375
- for (const candidate of run.candidates || []) {
376
- addEvidence(candidate.evidence, { status: candidate.status === "rejected" || candidate.status === "failed" ? "rejected" : "pending", sourceKind: "worker", sourceId: candidate.workerId || candidate.id, candidateIds: [candidate.id], rejectedBy: candidate.status === "rejected" || candidate.status === "failed" ? [candidate.id] : [] });
377
- for (const score of readScores(run, candidate.id))
378
- addEvidence(score.evidence, { status: score.verdict === "fail" ? "rejected" : "adopted", sourceKind: "operator", sourceId: score.scorer, candidateIds: [candidate.id], scoreIds: [score.id], adoptedBy: score.verdict === "fail" ? [] : [score.id], rejectedBy: score.verdict === "fail" ? [score.id] : [] });
421
+ for (const candidate of candidatesOf(run)) {
422
+ addEvidence(candidate.evidence || [], { status: candidate.status === "rejected" || candidate.status === "failed" ? "rejected" : "pending", sourceKind: "worker", sourceId: candidate.workerId || String(candidate.id), candidateIds: [String(candidate.id)], rejectedBy: candidate.status === "rejected" || candidate.status === "failed" ? [String(candidate.id)] : [] });
423
+ for (const score of readScores(run, String(candidate.id)))
424
+ addEvidence(score.evidence, { status: score.verdict === "fail" ? "rejected" : "adopted", sourceKind: "operator", sourceId: score.scorer, candidateIds: [String(candidate.id)], scoreIds: [score.id], adoptedBy: score.verdict === "fail" ? [] : [score.id], rejectedBy: score.verdict === "fail" ? [score.id] : [] });
379
425
  }
380
- for (const selection of run.candidateSelections || []) {
381
- addEvidence(selection.evidence, { status: "adopted", sourceKind: "verifier", sourceId: selection.verifierNodeId || selection.id, candidateIds: [selection.candidateId], selectionIds: [selection.id], scoreIds: selection.scoreId ? [selection.scoreId] : [], adoptedBy: [selection.id] });
426
+ for (const selection of selectionsOf(run)) {
427
+ addEvidence(selection.evidence || [], { status: "adopted", sourceKind: "verifier", sourceId: selection.verifierNodeId || String(selection.id), candidateIds: [String(selection.candidateId)], selectionIds: [String(selection.id)], scoreIds: selection.scoreId ? [String(selection.scoreId)] : [], adoptedBy: [String(selection.id)] });
382
428
  }
383
- for (const commit of run.commits || []) {
384
- addEvidence(commit.evidence || [], { status: commit.verifierGated ? "adopted" : "pending", sourceKind: "runtime", sourceId: commit.id, selectionIds: commit.selectionId ? [commit.selectionId] : [], candidateIds: commit.candidateId ? [commit.candidateId] : [], commitIds: [commit.id], adoptedBy: commit.verifierGated ? [commit.id] : [], pendingConsumers: commit.verifierGated ? [] : [commit.id] });
429
+ for (const commit of commitsOf(run)) {
430
+ addEvidence(commit.evidence || [], { status: commit.verifierGated ? "adopted" : "pending", sourceKind: "runtime", sourceId: String(commit.id), selectionIds: commit.selectionId ? [String(commit.selectionId)] : [], candidateIds: commit.candidateId ? [String(commit.candidateId)] : [], commitIds: [String(commit.id)], adoptedBy: commit.verifierGated ? [String(commit.id)] : [], pendingConsumers: commit.verifierGated ? [] : [String(commit.id)] });
385
431
  }
386
- for (const topology of run.topologies?.runs || []) {
432
+ for (const topology of topologyRunsOf(run)) {
387
433
  for (const missing of topology.missingEvidence || [])
388
- ensure(`${topology.id}:missing:${missing}`, { ref: missing, sourceKind: "runtime", sourceId: topology.id, status: "missing", pendingConsumers: [topology.id], reason: missing });
434
+ ensure(`${topology.id}:missing:${missing}`, { ref: missing, sourceKind: "runtime", sourceId: String(topology.id), status: "missing", pendingConsumers: [String(topology.id)], reason: missing });
389
435
  }
390
- // Once any verifier-gated commit exists the selected path is decided; rows
391
- // that still read missing/pending/conflicting are then inspectable operator
392
- // state (e.g. sibling judge-panel roles never driven as separate workers),
393
- // not blocking failures. Before a verifier-gated commit, those same rows
394
- // genuinely block. `disposition` is the operator-facing reading of `status`.
395
- const committed = (run.commits || []).some((commit) => commit.verifierGated);
436
+ const committed = commitsOf(run).some((commit) => commit.verifierGated);
396
437
  const blocks = (status) => status === "missing" || status === "pending" || status === "conflicting";
397
438
  const withDisposition = (row) => ({
398
439
  ...row,
399
- disposition: row.status === "adopted" ? "adopted" : blocks(row.status) && !committed ? "blocking" : "inspectable"
440
+ disposition: row.status === "adopted" ? "adopted" : blocks(row.status) && !committed ? "blocking" : "inspectable",
400
441
  });
401
442
  return [...rows.values()]
402
443
  .map(normalizeEvidenceStatus)
@@ -441,21 +482,18 @@ function formatEvidence(title, rows) {
441
482
  return lines.join("\n");
442
483
  }
443
484
  function readScores(run, candidateId) {
444
- const dir = node_path_1.default.join(run.paths.candidatesDir || node_path_1.default.join(run.paths.runDir, "candidates"), safeFileName(candidateId), "scores");
445
- if (!node_fs_1.default.existsSync(dir))
485
+ const candidatesDir = run.paths.candidatesDir || path.join(run.paths.runDir, "candidates");
486
+ const dir = path.join(candidatesDir, safeFileName(candidateId), "scores");
487
+ if (!fs.existsSync(dir))
446
488
  return [];
447
- return node_fs_1.default
489
+ return fs
448
490
  .readdirSync(dir)
449
491
  .filter((file) => file.endsWith(".json"))
450
492
  .sort()
451
- .map((file) => (0, validation_1.validateCandidateScore)(JSON.parse(node_fs_1.default.readFileSync(node_path_1.default.join(dir, file), "utf8"))));
452
- }
453
- function scorePath(run, candidateId, scoreId) {
454
- const file = node_path_1.default.join(run.paths.candidatesDir || node_path_1.default.join(run.paths.runDir, "candidates"), safeFileName(candidateId), "scores", `${safeFileName(scoreId)}.json`);
455
- return node_fs_1.default.existsSync(file) ? file : undefined;
493
+ .map((file) => JSON.parse(fs.readFileSync(path.join(dir, file), "utf8")));
456
494
  }
457
495
  function readyCommitCommand(run) {
458
- const selection = (run.candidateSelections || []).find((entry) => !(run.commits || []).some((commit) => commit.selectionId === entry.id && commit.verifierGated));
496
+ const selection = selectionsOf(run).find((entry) => !commitsOf(run).some((commit) => commit.selectionId === entry.id && commit.verifierGated));
459
497
  return selection ? `node scripts/cw.js commit ${run.id} --selection ${selection.id} --reason "<verified rationale>"` : undefined;
460
498
  }
461
499
  function normalizeEvidenceStatus(row) {
@@ -470,14 +508,19 @@ function normalizeEvidenceStatus(row) {
470
508
  function evidenceKey(evidence) {
471
509
  return evidence.id || evidence.locator || evidence.path || evidence.summary || "evidence";
472
510
  }
511
+ function provenanceSourceId(item) {
512
+ const provenance = item.provenance;
513
+ return provenance?.workerId || provenance?.candidateId || provenance?.selectionId || provenance?.commitId;
514
+ }
473
515
  function sourceKindFromEvidence(evidence, fallback) {
474
516
  if (fallback)
475
517
  return fallback;
476
- if (evidence.provenance?.workerId)
518
+ const provenance = evidence.provenance;
519
+ if (provenance?.workerId)
477
520
  return "worker";
478
- if (evidence.provenance?.verifierNodeId)
521
+ if (provenance?.verifierNodeId)
479
522
  return "verifier";
480
- if (evidence.provenance?.source === "operator-recorded")
523
+ if (provenance?.source === "operator-recorded")
481
524
  return "operator";
482
525
  return "runtime";
483
526
  }