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,1014 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.stateExplosionReportLines = exports.formatBlackboardDigest = exports.formatCompactGraph = exports.formatStateExplosionReport = exports.fingerprintStrings = exports.GRAPH_VIEWS = exports.STATE_EXPLOSION_SCHEMA_VERSION = exports.DEFAULT_STATE_EXPLOSION_THRESHOLDS = exports.computeStateSizeWithGraph = exports.computeStateSize = void 0;
7
- exports.summarizeBlackboardDigest = summarizeBlackboardDigest;
8
- exports.buildCompactGraph = buildCompactGraph;
9
- exports.buildStateExplosionReport = buildStateExplosionReport;
10
- exports.maybeCompactRun = maybeCompactRun;
11
- exports.refreshStateExplosionSummaries = refreshStateExplosionSummaries;
12
- exports.loadStateExplosionSummaryIndex = loadStateExplosionSummaryIndex;
13
- exports.showStateExplosionSummary = showStateExplosionSummary;
14
- exports.normalizeStateExplosionForEval = normalizeStateExplosionForEval;
15
- const node_fs_1 = __importDefault(require("node:fs"));
16
- const node_path_1 = __importDefault(require("node:path"));
17
- const state_1 = require("./state");
18
- const coordinator_1 = require("./coordinator");
19
- const multi_agent_operator_ux_1 = require("./multi-agent-operator-ux");
20
- const trust_audit_1 = require("./trust-audit");
21
- const evidence_reasoning_1 = require("./evidence-reasoning");
22
- const helpers_1 = require("./state-explosion/helpers");
23
- const size_1 = require("./state-explosion/size");
24
- Object.defineProperty(exports, "computeStateSize", { enumerable: true, get: function () { return size_1.computeStateSize; } });
25
- Object.defineProperty(exports, "computeStateSizeWithGraph", { enumerable: true, get: function () { return size_1.computeStateSizeWithGraph; } });
26
- Object.defineProperty(exports, "DEFAULT_STATE_EXPLOSION_THRESHOLDS", { enumerable: true, get: function () { return size_1.DEFAULT_STATE_EXPLOSION_THRESHOLDS; } });
27
- Object.defineProperty(exports, "STATE_EXPLOSION_SCHEMA_VERSION", { enumerable: true, get: function () { return size_1.STATE_EXPLOSION_SCHEMA_VERSION; } });
28
- exports.GRAPH_VIEWS = [
29
- "full",
30
- "compact",
31
- "critical-path",
32
- "failures",
33
- "evidence",
34
- "trust",
35
- "topology",
36
- "blackboard",
37
- "candidate",
38
- "commit-gate"
39
- ];
40
- function createStateExplosionBuildContext() {
41
- return {
42
- stateSizes: new Map(),
43
- blackboardDigests: new Map(),
44
- graphRecords: new Map()
45
- };
46
- }
47
- function fullGraphFor(run, context) {
48
- if (!context.fullGraph)
49
- context.fullGraph = (0, multi_agent_operator_ux_1.buildMultiAgentOperatorGraph)(run);
50
- return context.fullGraph;
51
- }
52
- function operatorFor(run, context) {
53
- if (!context.operator)
54
- context.operator = (0, multi_agent_operator_ux_1.summarizeMultiAgentOperator)(run);
55
- return context.operator;
56
- }
57
- function reasoningCriticalIdsFor(run, context) {
58
- if (!context.reasoningCriticalIds)
59
- context.reasoningCriticalIds = (0, evidence_reasoning_1.reasoningCriticalNodeIds)(run, operatorFor(run, context));
60
- return context.reasoningCriticalIds;
61
- }
62
- function thresholdsKey(thresholds) {
63
- return [
64
- thresholds.graphNodes,
65
- thresholds.graphEdges,
66
- thresholds.blackboardMessages,
67
- thresholds.blackboardRecords,
68
- thresholds.collapseBucket,
69
- thresholds.totalRecords
70
- ].join(":");
71
- }
72
- function graphKey(view, options) {
73
- return [
74
- view,
75
- options.focus || "",
76
- options.depth === undefined ? "" : String(options.depth),
77
- thresholdsKey(options.thresholds || size_1.DEFAULT_STATE_EXPLOSION_THRESHOLDS)
78
- ].join("\0");
79
- }
80
- // ---------------------------------------------------------------------------
81
- // State size (implementation in state-explosion/size.ts)
82
- // ---------------------------------------------------------------------------
83
- function stateSizeFor(run, thresholds, context) {
84
- const key = thresholdsKey(thresholds);
85
- let size = context.stateSizes.get(key);
86
- if (!size) {
87
- size = (0, size_1.computeStateSizeWithGraph)(run, thresholds, fullGraphFor(run, context));
88
- context.stateSizes.set(key, size);
89
- }
90
- return size;
91
- }
92
- // ---------------------------------------------------------------------------
93
- // Blackboard digest (deterministic structural summary)
94
- // ---------------------------------------------------------------------------
95
- function summarizeBlackboardDigest(run, blackboardId) {
96
- const bb = run.blackboard || {
97
- boards: [],
98
- topics: [],
99
- messages: [],
100
- contexts: [],
101
- artifacts: [],
102
- snapshots: [],
103
- decisions: []
104
- };
105
- const board = blackboardId ? (bb.boards || []).find((b) => b.id === blackboardId) : (bb.boards || [])[0];
106
- const boardId = board?.id;
107
- const inBoard = (items) => boardId ? items.filter((item) => item.blackboardId === boardId) : items;
108
- const topics = inBoard(bb.topics || []);
109
- const messages = inBoard(bb.messages || []);
110
- const contexts = inBoard(bb.contexts || []);
111
- const artifacts = inBoard(bb.artifacts || []);
112
- const decisions = inBoard(bb.decisions || []);
113
- const summary = (0, coordinator_1.summarizeBlackboard)(run, boardId);
114
- const topicRollups = topics
115
- .map((topic) => {
116
- const topicMessages = messages.filter((m) => m.topicId === topic.id);
117
- return {
118
- id: topic.id,
119
- label: `${topic.title} (${topicMessages.length} messages, ${topic.contextIds.length} contexts, ${topic.artifactRefIds.length} artifacts)`,
120
- status: topic.status,
121
- sourceIds: [topic.id, ...topicMessages.map((m) => m.id)],
122
- evidenceRefs: (0, helpers_1.unique)(topicMessages.flatMap((m) => m.linkedEvidenceRefs || [])),
123
- expansionCommand: `node scripts/cw.js blackboard message list ${run.id} --topic ${topic.id}`
124
- };
125
- })
126
- .sort(helpers_1.byId);
127
- const threadSummaries = topics
128
- .map((topic) => {
129
- const topicMessages = messages
130
- .filter((m) => m.topicId === topic.id)
131
- .sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
132
- const last = topicMessages[topicMessages.length - 1];
133
- return {
134
- id: `thread:${topic.id}`,
135
- label: `${topic.title}: ${topicMessages.length} messages${last ? `; latest by ${last.author.kind}:${last.author.id}` : ""}`,
136
- status: topic.status,
137
- sourceIds: topicMessages.map((m) => m.id),
138
- evidenceRefs: (0, helpers_1.unique)(topicMessages.flatMap((m) => m.linkedEvidenceRefs || [])),
139
- expansionCommand: `node scripts/cw.js blackboard message list ${run.id} --topic ${topic.id}`
140
- };
141
- })
142
- .filter((entry) => entry.sourceIds.length)
143
- .sort(helpers_1.byId);
144
- const unresolvedQuestions = contexts
145
- .filter((c) => c.kind === "question" && c.status === "open")
146
- .map((c) => ({
147
- id: c.id,
148
- label: `${c.key}: ${(0, helpers_1.truncate)(c.value)}`,
149
- status: c.status,
150
- sourceIds: [c.id],
151
- evidenceRefs: (0, helpers_1.unique)([...(c.evidenceRefs || []), ...(c.artifactRefIds || [])]),
152
- expansionCommand: `node scripts/cw.js blackboard message post ${run.id} --topic ${c.topicId} --body "<answer with evidence>"`
153
- }))
154
- .sort(helpers_1.byId);
155
- const conflicts = contexts
156
- .filter((c) => c.status === "conflicting" || (c.conflictingContextIds || []).length)
157
- .map((c) => ({
158
- id: c.id,
159
- label: `${c.key} conflicts with ${(c.conflictingContextIds || []).join(", ") || "another value"}`,
160
- status: c.status,
161
- sourceIds: [c.id, ...(c.conflictingContextIds || [])],
162
- evidenceRefs: (0, helpers_1.unique)([...(c.evidenceRefs || []), ...(c.artifactRefIds || [])]),
163
- expansionCommand: `node scripts/cw.js coordinator decision ${run.id} --kind conflict-resolution --outcome accepted --subject ${c.id} --reason "<reason>"`
164
- }))
165
- .sort(helpers_1.byId);
166
- const decisionEntries = decisions
167
- .map((d) => ({
168
- id: d.id,
169
- label: `${d.kind}:${d.outcome} ${(0, helpers_1.truncate)(d.reason)}`,
170
- status: d.status,
171
- sourceIds: [d.id, ...(d.subjectIds || [])],
172
- evidenceRefs: (0, helpers_1.unique)([...(d.evidenceRefs || []), ...(d.artifactRefIds || [])]),
173
- expansionCommand: `node scripts/cw.js node show ${run.id} ${run.id}:coordinator:decision:${d.id}`
174
- }))
175
- .sort(helpers_1.byId);
176
- const artifactEntries = artifacts
177
- .map((a) => ({
178
- id: a.id,
179
- label: `${a.kind} ${a.locator || a.path || a.id}`,
180
- status: a.status,
181
- sourceIds: [a.id],
182
- evidenceRefs: (0, helpers_1.unique)(a.evidenceRefs || []),
183
- expansionCommand: `node scripts/cw.js blackboard artifact list ${run.id}`
184
- }))
185
- .sort(helpers_1.byId);
186
- const adoptedEvidence = artifacts
187
- .filter((a) => a.status === "active")
188
- .map((a) => ({
189
- id: `evidence:${a.id}`,
190
- label: `${a.kind} ${a.locator || a.path || a.id}`,
191
- status: a.status,
192
- sourceIds: [a.id],
193
- evidenceRefs: (0, helpers_1.unique)([a.locator || a.path || a.id, ...(a.evidenceRefs || [])]),
194
- expansionCommand: `node scripts/cw.js audit blackboard ${run.id} --json`
195
- }))
196
- .sort(helpers_1.byId);
197
- const missingEvidence = (summary.missingEvidence || [])
198
- .map((reason, index) => ({
199
- id: `missing:${index}:${(0, helpers_1.slug)(reason)}`,
200
- label: reason,
201
- status: "missing",
202
- sourceIds: [],
203
- evidenceRefs: [],
204
- expansionCommand: `node scripts/cw.js multi-agent failures ${run.id}`
205
- }))
206
- .sort(helpers_1.byId);
207
- const policyViolations = decisions
208
- .filter((d) => d.outcome === "rejected" || d.outcome === "blocked" || d.outcome === "conflicting")
209
- .map((d) => ({
210
- id: `policy:${d.id}`,
211
- label: `${d.kind}:${d.outcome} ${(0, helpers_1.truncate)(d.reason)}`,
212
- status: d.status,
213
- sourceIds: [d.id],
214
- evidenceRefs: (0, helpers_1.unique)(d.evidenceRefs || []),
215
- expansionCommand: `node scripts/cw.js audit policy ${run.id} --json`
216
- }))
217
- .sort(helpers_1.byId);
218
- const judgeRationale = messages
219
- .filter((m) => (m.tags || []).includes("judge-rationale") || Boolean(m.metadata?.judgeRationale))
220
- .map((m) => ({
221
- id: `judge:${m.id}`,
222
- label: `${m.author.kind}:${m.author.id} ${(0, helpers_1.truncate)(m.body)}`,
223
- status: m.status,
224
- sourceIds: [m.id],
225
- evidenceRefs: (0, helpers_1.unique)(m.linkedEvidenceRefs || []),
226
- expansionCommand: `node scripts/cw.js audit judge ${run.id} --json`
227
- }))
228
- .sort(helpers_1.byId);
229
- const recentChanges = [...messages, ...contexts, ...artifacts, ...decisions]
230
- .map((record) => ({
231
- id: record.id,
232
- kind: record.kind,
233
- updatedAt: record.updatedAt,
234
- status: record.status
235
- }))
236
- .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt) || a.id.localeCompare(b.id))
237
- .slice(0, 10)
238
- .map((record) => ({
239
- id: `recent:${record.id}`,
240
- label: `${record.id} (${record.status})`,
241
- status: record.status,
242
- sourceIds: [record.id],
243
- evidenceRefs: [],
244
- expansionCommand: `node scripts/cw.js node show ${run.id} ${record.id}`
245
- }))
246
- .sort(helpers_1.byId);
247
- const highSignal = [
248
- ...conflicts,
249
- ...unresolvedQuestions,
250
- ...policyViolations,
251
- ...missingEvidence
252
- ].sort(helpers_1.byId);
253
- const sourceRecordIds = (0, helpers_1.unique)([
254
- ...topics.map((t) => t.id),
255
- ...messages.map((m) => m.id),
256
- ...contexts.map((c) => c.id),
257
- ...artifacts.map((a) => a.id),
258
- ...decisions.map((d) => d.id)
259
- ]);
260
- const evidenceRefs = (0, helpers_1.unique)([
261
- ...messages.flatMap((m) => m.linkedEvidenceRefs || []),
262
- ...artifacts.flatMap((a) => [a.locator || a.path || a.id, ...(a.evidenceRefs || [])]),
263
- ...contexts.flatMap((c) => c.evidenceRefs || [])
264
- ]);
265
- const trustAuditEventRefs = (0, helpers_1.unique)([
266
- ...messages.flatMap((m) => m.linkedAuditEventIds || []),
267
- ...artifacts.flatMap((a) => a.trustAuditEventIds || [])
268
- ]);
269
- const fingerprint = (0, helpers_1.fingerprintRecords)([...topics, ...messages, ...contexts, ...artifacts, ...decisions]);
270
- return {
271
- schemaVersion: size_1.STATE_EXPLOSION_SCHEMA_VERSION,
272
- runId: run.id,
273
- id: `blackboard-digest${boardId ? `:${boardId}` : ""}`,
274
- scope: "blackboard",
275
- blackboardId: boardId,
276
- sourceRecordIds,
277
- sourceFingerprint: fingerprint,
278
- includedCount: topicRollups.length + conflicts.length + unresolvedQuestions.length + decisionEntries.length + artifactEntries.length,
279
- omittedCount: Math.max(0, messages.length - threadSummaries.length),
280
- importantRefs: (0, helpers_1.unique)([
281
- ...conflicts.map((c) => c.id),
282
- ...unresolvedQuestions.map((q) => q.id),
283
- ...policyViolations.map((p) => p.id)
284
- ]),
285
- evidenceRefs,
286
- trustAuditEventRefs,
287
- generatedAt: new Date().toISOString(),
288
- status: "valid",
289
- deterministic: true,
290
- nextAction: summary.nextAction || `node scripts/cw.js blackboard summary ${run.id}`,
291
- topicRollups,
292
- threadSummaries,
293
- unresolvedQuestions,
294
- conflicts,
295
- decisions: decisionEntries,
296
- artifacts: artifactEntries,
297
- adoptedEvidence,
298
- missingEvidence,
299
- policyViolations,
300
- judgeRationale,
301
- recentChanges,
302
- highSignal
303
- };
304
- }
305
- function blackboardDigestFor(run, context, blackboardId) {
306
- const key = blackboardId || "";
307
- let digest = context.blackboardDigests.get(key);
308
- if (!digest) {
309
- digest = summarizeBlackboardDigest(run, blackboardId);
310
- context.blackboardDigests.set(key, digest);
311
- }
312
- return digest;
313
- }
314
- function buildCompactGraph(run, view = "compact", options = {}) {
315
- return buildCompactGraphWithContext(run, view, options, createStateExplosionBuildContext());
316
- }
317
- function buildCompactGraphWithContext(run, view, options, context) {
318
- const thresholds = options.thresholds || size_1.DEFAULT_STATE_EXPLOSION_THRESHOLDS;
319
- const key = graphKey(view, { ...options, thresholds });
320
- const cached = context.graphRecords.get(key);
321
- if (cached)
322
- return cached;
323
- const full = fullGraphFor(run, context);
324
- const operator = operatorFor(run, context);
325
- const critical = criticalPathNodeIds(run, operator);
326
- const protectedIds = new Set(critical);
327
- // Failures, blocked, rejected, conflicting nodes are always preserved.
328
- for (const node of full.nodes) {
329
- if ((0, helpers_1.isProtectedStatus)(node.status))
330
- protectedIds.add(node.id);
331
- }
332
- // v0.1.26: reasoning steps are on the critical path and must never be collapsed
333
- // into a synthetic summary node — protect every decision-gate node backing an
334
- // adopted reasoning chain (notably score nodes, which are otherwise collapsed).
335
- for (const id of reasoningCriticalIdsFor(run, context))
336
- protectedIds.add(id);
337
- for (const failure of operator.failures) {
338
- if (failure.linked)
339
- protectedIds.add(failure.linked);
340
- }
341
- const parents = (0, helpers_1.parentMap)(full.edges);
342
- const parentOf = (id) => parents.get(id);
343
- let scopeNodes = full.nodes;
344
- let scopeEdges = full.edges;
345
- if (view !== "full" && view !== "compact" && view !== "critical-path") {
346
- const filtered = filterByView(run, view, full, operator, protectedIds);
347
- scopeNodes = filtered.nodes;
348
- scopeEdges = filtered.edges;
349
- }
350
- // Focus + depth: keep nodes within BFS depth of focus; collapse the rest.
351
- let focusKeep;
352
- if (options.focus) {
353
- focusKeep = bfsNeighborhood(options.focus, scopeNodes, scopeEdges, options.depth ?? 1);
354
- for (const id of focusKeep)
355
- protectedIds.add(id);
356
- }
357
- const collapseEnabled = view === "compact" || view === "critical-path" || Boolean(options.focus);
358
- if (view === "full" || !collapseEnabled) {
359
- // No collapse: emit scoped graph verbatim (still records provenance + critical path).
360
- const record = finalizeGraphRecord(run, view, options, full, {
361
- nodes: scopeNodes.map((node) => ({ ...node })),
362
- edges: scopeEdges.map((edge) => ({ ...edge })),
363
- syntheticNodes: [],
364
- critical,
365
- operator
366
- });
367
- context.graphRecords.set(key, record);
368
- return record;
369
- }
370
- // Determine collapse buckets per node.
371
- const rule = collapseRuleFor(view);
372
- const keep = new Set();
373
- const buckets = new Map();
374
- for (const node of scopeNodes) {
375
- if (protectedIds.has(node.id) || (focusKeep && focusKeep.has(node.id))) {
376
- keep.add(node.id);
377
- continue;
378
- }
379
- if (view === "critical-path") {
380
- // Collapse everything not on the critical path into one bucket per kind.
381
- const key = `critical-context:${node.kind}`;
382
- buckets.set(key, [...(buckets.get(key) || []), node.id]);
383
- continue;
384
- }
385
- if (!shouldCollapseKind(node.kind, rule)) {
386
- keep.add(node.id);
387
- continue;
388
- }
389
- const key = rule.bucketBy(node, parentOf);
390
- buckets.set(key, [...(buckets.get(key) || []), node.id]);
391
- }
392
- // Buckets smaller than the collapse threshold stay expanded (unless critical-path).
393
- const synthetic = [];
394
- const collapsedNodeIds = new Map(); // sourceNodeId -> syntheticId
395
- for (const [key, ids] of [...buckets.entries()].sort((a, b) => a[0].localeCompare(b[0]))) {
396
- if (view !== "critical-path" && ids.length < thresholds.collapseBucket) {
397
- for (const id of ids)
398
- keep.add(id);
399
- continue;
400
- }
401
- const members = scopeNodes.filter((node) => ids.includes(node.id));
402
- const internalEdges = scopeEdges.filter((edge) => ids.includes(edge.from) && ids.includes(edge.to));
403
- const syntheticId = `${run.id}:summary:${(0, helpers_1.slug)(key)}`;
404
- const dominant = (0, helpers_1.dominantStatus)(members.map((m) => m.status));
405
- const blocked = members.find((m) => (0, helpers_1.isProtectedStatus)(m.status));
406
- synthetic.push({
407
- id: syntheticId,
408
- kind: "summary",
409
- label: `${key} (${ids.length} collapsed)`,
410
- status: dominant,
411
- collapsedNodeCount: ids.length,
412
- collapsedEdgeCount: internalEdges.length,
413
- sourceIds: [...ids].sort(),
414
- dominantStatus: dominant,
415
- blockedReason: blocked ? `${blocked.kind} ${blocked.id} is ${blocked.status}` : undefined,
416
- expansionCommand: expansionCommandFor(run, view, key)
417
- });
418
- for (const id of ids)
419
- collapsedNodeIds.set(id, syntheticId);
420
- }
421
- const redirect = (id) => collapsedNodeIds.get(id) || id;
422
- const nodes = [];
423
- for (const node of scopeNodes) {
424
- if (keep.has(node.id))
425
- nodes.push({ ...node });
426
- }
427
- for (const syn of synthetic) {
428
- nodes.push({
429
- id: syn.id,
430
- kind: "summary",
431
- label: syn.label,
432
- status: syn.status,
433
- synthetic: syn
434
- });
435
- }
436
- const edgeSeen = new Set();
437
- const edges = [];
438
- for (const edge of scopeEdges) {
439
- const from = redirect(edge.from);
440
- const to = redirect(edge.to);
441
- if (from === to)
442
- continue; // edge fully internal to a synthetic node
443
- const key = `${from}\0${to}\0${edge.label || ""}`;
444
- if (edgeSeen.has(key))
445
- continue;
446
- edgeSeen.add(key);
447
- edges.push({ from, to, label: edge.label });
448
- }
449
- const record = finalizeGraphRecord(run, view, options, full, {
450
- nodes: nodes.sort((a, b) => a.kind.localeCompare(b.kind) || a.id.localeCompare(b.id)),
451
- edges: edges.sort((a, b) => a.from.localeCompare(b.from) || a.to.localeCompare(b.to) || (a.label || "").localeCompare(b.label || "")),
452
- syntheticNodes: synthetic.sort((a, b) => a.id.localeCompare(b.id)),
453
- critical,
454
- operator
455
- });
456
- context.graphRecords.set(key, record);
457
- return record;
458
- }
459
- function finalizeGraphRecord(run, view, options, full, built) {
460
- const collapsedNodeCount = built.syntheticNodes.reduce((acc, syn) => acc + syn.collapsedNodeCount, 0);
461
- const collapsedEdgeCount = built.syntheticNodes.reduce((acc, syn) => acc + syn.collapsedEdgeCount, 0);
462
- const blockedReasons = (0, helpers_1.unique)([
463
- ...built.operator.failures.map((f) => `${f.kind} ${f.id}: ${f.reason}`),
464
- ...built.syntheticNodes.filter((s) => s.blockedReason).map((s) => s.blockedReason)
465
- ]);
466
- return {
467
- schemaVersion: size_1.STATE_EXPLOSION_SCHEMA_VERSION,
468
- runId: run.id,
469
- id: `graph-${view}${options.focus ? `:focus:${(0, helpers_1.slug)(options.focus)}` : ""}`,
470
- scope: "run",
471
- view,
472
- focus: options.focus,
473
- depth: options.depth,
474
- fullNodeCount: full.nodes.length,
475
- fullEdgeCount: full.edges.length,
476
- compactNodeCount: built.nodes.length,
477
- compactEdgeCount: built.edges.length,
478
- collapsedNodeCount,
479
- collapsedEdgeCount,
480
- syntheticNodes: built.syntheticNodes,
481
- criticalPath: built.critical,
482
- blockedReasons,
483
- nodes: built.nodes,
484
- edges: built.edges,
485
- sourceRecordIds: full.nodes.map((n) => n.id).sort(),
486
- sourceFingerprint: (0, helpers_1.fingerprintStrings)(full.nodes.map((n) => `${n.id}:${n.status}`)),
487
- includedCount: built.nodes.length,
488
- omittedCount: collapsedNodeCount,
489
- importantRefs: built.critical,
490
- evidenceRefs: [],
491
- trustAuditEventRefs: [],
492
- generatedAt: new Date().toISOString(),
493
- status: "valid",
494
- deterministic: true,
495
- nextAction: collapsedNodeCount > 0
496
- ? `node scripts/cw.js multi-agent graph ${run.id} --view full --json`
497
- : `node scripts/cw.js multi-agent graph ${run.id} --view ${view} --json`
498
- };
499
- }
500
- function collapseRuleFor(view) {
501
- return {
502
- bucketBy: (node, parentOf) => {
503
- switch (node.kind) {
504
- case "blackboard-message":
505
- return "messages";
506
- case "blackboard-context":
507
- return "contexts";
508
- case "agent-membership": {
509
- const parent = parentOf(node.id);
510
- return `memberships:${parent ? parent.split(":").pop() : "unscoped"}`;
511
- }
512
- case "worker":
513
- return "workers";
514
- case "score":
515
- return "scores";
516
- case "blackboard-snapshot":
517
- return "snapshots";
518
- default:
519
- return `${node.kind}`;
520
- }
521
- }
522
- };
523
- }
524
- function shouldCollapseKind(kind, _rule) {
525
- // Collapsible kinds (high-volume, low-individual-signal). Decisions, artifacts,
526
- // fanins, candidates, selections, commits and feedback are NEVER collapsed so
527
- // failures, evidence, policy and judge rationale stay visible.
528
- return [
529
- "blackboard-message",
530
- "blackboard-context",
531
- "agent-membership",
532
- "worker",
533
- "score",
534
- "blackboard-snapshot",
535
- "agent-role"
536
- ].includes(kind);
537
- }
538
- function filterByView(run, view, full, operator, protectedIds) {
539
- const keepKinds = (kinds) => {
540
- const ids = new Set();
541
- for (const node of full.nodes) {
542
- if (kinds.includes(node.kind) || protectedIds.has(node.id))
543
- ids.add(node.id);
544
- }
545
- return ids;
546
- };
547
- let ids;
548
- switch (view) {
549
- case "failures": {
550
- ids = new Set();
551
- for (const failure of operator.failures) {
552
- if (failure.linked)
553
- ids.add(failure.linked);
554
- }
555
- for (const node of full.nodes)
556
- if ((0, helpers_1.isProtectedStatus)(node.status))
557
- ids.add(node.id);
558
- ids.add(`${run.id}:run`);
559
- break;
560
- }
561
- case "evidence":
562
- ids = keepKinds([
563
- "multi-agent-run-root",
564
- "blackboard",
565
- "blackboard-topic",
566
- "blackboard-artifact",
567
- "blackboard-message",
568
- "agent-membership",
569
- "agent-fanin",
570
- "candidate",
571
- "selection",
572
- "commit"
573
- ]);
574
- break;
575
- case "trust":
576
- ids = keepKinds([
577
- "multi-agent-run-root",
578
- "blackboard",
579
- "coordinator-decision",
580
- "agent-fanin",
581
- "candidate",
582
- "selection",
583
- "commit"
584
- ]);
585
- break;
586
- case "topology":
587
- ids = keepKinds([
588
- "multi-agent-run-root",
589
- "topology",
590
- "multi-agent-run",
591
- "agent-group",
592
- "agent-role",
593
- "agent-fanout",
594
- "agent-fanin"
595
- ]);
596
- break;
597
- case "blackboard":
598
- ids = keepKinds([
599
- "multi-agent-run-root",
600
- "blackboard",
601
- "blackboard-topic",
602
- "blackboard-message",
603
- "blackboard-context",
604
- "blackboard-artifact",
605
- "blackboard-snapshot",
606
- "coordinator-decision"
607
- ]);
608
- break;
609
- case "candidate":
610
- ids = keepKinds(["multi-agent-run-root", "candidate", "score", "selection", "worker", "agent-fanin"]);
611
- break;
612
- case "commit-gate":
613
- ids = keepKinds(["multi-agent-run-root", "selection", "commit", "candidate", "agent-fanin"]);
614
- break;
615
- default:
616
- ids = new Set(full.nodes.map((n) => n.id));
617
- }
618
- const nodes = full.nodes.filter((node) => ids.has(node.id));
619
- const edges = full.edges.filter((edge) => ids.has(edge.from) && ids.has(edge.to));
620
- return { nodes, edges };
621
- }
622
- function criticalPathNodeIds(run, operator) {
623
- const ids = [`${run.id}:run`];
624
- const ma = run.multiAgent;
625
- for (const record of ma?.runs || [])
626
- ids.push(`${run.id}:multi-agent:${record.id}`);
627
- for (const group of ma?.groups || [])
628
- ids.push(`${run.id}:multi-agent:group:${group.id}`);
629
- for (const fanout of ma?.fanouts || [])
630
- ids.push(`${run.id}:multi-agent:fanout:${fanout.id}`);
631
- for (const fanin of ma?.fanins || [])
632
- ids.push(`${run.id}:multi-agent:fanin:${fanin.id}`);
633
- for (const selection of run.candidateSelections || []) {
634
- ids.push(`${run.id}:selection:${selection.id}`);
635
- ids.push(`${run.id}:candidate:${selection.candidateId}`);
636
- }
637
- for (const commit of run.commits || []) {
638
- if (commit.verifierGated)
639
- ids.push(commit.stateNodeId || `${run.id}:commit:${commit.id}`);
640
- }
641
- // Blocked dependencies live on the critical path because they gate completion.
642
- for (const failure of operator.failures) {
643
- if (failure.linked)
644
- ids.push(failure.linked);
645
- }
646
- return (0, helpers_1.unique)(ids);
647
- }
648
- function bfsNeighborhood(focus, nodes, edges, depth) {
649
- const adjacency = new Map();
650
- for (const edge of edges) {
651
- if (!adjacency.has(edge.from))
652
- adjacency.set(edge.from, new Set());
653
- if (!adjacency.has(edge.to))
654
- adjacency.set(edge.to, new Set());
655
- adjacency.get(edge.from).add(edge.to);
656
- adjacency.get(edge.to).add(edge.from);
657
- }
658
- const keep = new Set([focus]);
659
- let frontier = new Set([focus]);
660
- for (let level = 0; level < Math.max(0, depth); level += 1) {
661
- const next = new Set();
662
- for (const id of frontier) {
663
- for (const neighbor of adjacency.get(id) || []) {
664
- if (!keep.has(neighbor)) {
665
- keep.add(neighbor);
666
- next.add(neighbor);
667
- }
668
- }
669
- }
670
- frontier = next;
671
- }
672
- return keep;
673
- }
674
- function expansionCommandFor(run, view, key) {
675
- if (key === "messages" || key.startsWith("thread"))
676
- return `node scripts/cw.js blackboard message list ${run.id}`;
677
- if (key.startsWith("memberships"))
678
- return `node scripts/cw.js multi-agent graph ${run.id} --view full --json`;
679
- return `node scripts/cw.js multi-agent graph ${run.id} --view full --focus ${key} --json`;
680
- }
681
- function buildOperatorDigestWithContext(run, thresholds, context) {
682
- const stateSize = stateSizeFor(run, thresholds, context);
683
- const operator = operatorFor(run, context);
684
- const compact = buildCompactGraphWithContext(run, "compact", { thresholds }, context);
685
- const blackboard = blackboardDigestFor(run, context);
686
- const evidence = operator.evidence;
687
- const adopted = evidence.filter((e) => e.status === "adopted");
688
- const missing = evidence.filter((e) => e.status === "missing" || e.status === "pending" || e.status === "conflicting");
689
- const rejected = evidence.filter((e) => e.status === "rejected");
690
- const trust = operator.summaries.trust;
691
- const hiddenSourceRecords = compact.syntheticNodes.map((syn) => ({
692
- kind: syn.id.split(":summary:")[1] || syn.kind,
693
- count: syn.collapsedNodeCount,
694
- expansionCommand: syn.expansionCommand
695
- }));
696
- const expansionCommands = (0, helpers_1.unique)([
697
- `node scripts/cw.js multi-agent graph ${run.id} --view full --json`,
698
- `node scripts/cw.js blackboard message list ${run.id} --topic <topic-id>`,
699
- `node scripts/cw.js multi-agent graph ${run.id} --view critical-path`,
700
- `node scripts/cw.js multi-agent failures ${run.id} --json`,
701
- ...compact.syntheticNodes.map((syn) => syn.expansionCommand)
702
- ]);
703
- return {
704
- schemaVersion: size_1.STATE_EXPLOSION_SCHEMA_VERSION,
705
- runId: run.id,
706
- id: "operator-digest",
707
- scope: "run",
708
- sourceRecordIds: compact.sourceRecordIds,
709
- sourceFingerprint: (0, helpers_1.fingerprintStrings)([
710
- compact.sourceFingerprint,
711
- blackboard.sourceFingerprint,
712
- String(stateSize.total)
713
- ]),
714
- includedCount: compact.compactNodeCount,
715
- omittedCount: compact.collapsedNodeCount,
716
- importantRefs: compact.criticalPath,
717
- evidenceRefs: (0, helpers_1.unique)(adopted.map((e) => e.ref || e.id)),
718
- trustAuditEventRefs: (0, helpers_1.unique)(blackboard.trustAuditEventRefs),
719
- generatedAt: new Date().toISOString(),
720
- status: "valid",
721
- deterministic: true,
722
- nextAction: operator.nextAction,
723
- stateSize,
724
- compactGraphRef: compact.id,
725
- blackboardDigestRef: blackboard.id,
726
- criticalPath: compact.criticalPath,
727
- failures: operator.failures.map((f) => ({
728
- id: f.id,
729
- kind: f.kind,
730
- status: f.status,
731
- reason: f.reason,
732
- nextCommand: f.nextCommand
733
- })),
734
- evidenceDigest: {
735
- adopted: adopted.length,
736
- missing: missing.length,
737
- rejected: rejected.length,
738
- entries: [...adopted, ...missing].slice(0, 40).map((e) => ({
739
- id: e.id,
740
- label: `${e.ref || e.id} (${e.status})`,
741
- status: e.status,
742
- sourceIds: [e.sourceId || e.id].filter(Boolean),
743
- evidenceRefs: [e.ref || e.id].filter(Boolean),
744
- expansionCommand: `node scripts/cw.js multi-agent evidence ${run.id} --json`
745
- }))
746
- },
747
- trustDigest: {
748
- events: trust?.totalEvents || 0,
749
- policyViolations: blackboard.policyViolations.length,
750
- judgeRationales: blackboard.judgeRationale.length,
751
- entries: (0, helpers_1.unique)([
752
- ...blackboard.policyViolations.map((p) => p.id),
753
- ...blackboard.judgeRationale.map((j) => j.id)
754
- ])
755
- },
756
- hiddenSourceRecords,
757
- expansionCommands
758
- };
759
- }
760
- // ---------------------------------------------------------------------------
761
- // State explosion report (combines all derived indexes)
762
- // ---------------------------------------------------------------------------
763
- function buildStateExplosionReport(run, options = {}) {
764
- return buildStateExplosionReportWithContext(run, options, createStateExplosionBuildContext());
765
- }
766
- function buildStateExplosionReportWithContext(run, options, context) {
767
- const thresholds = options.thresholds || size_1.DEFAULT_STATE_EXPLOSION_THRESHOLDS;
768
- const stateSize = stateSizeFor(run, thresholds, context);
769
- const compactGraph = buildCompactGraphWithContext(run, "compact", { thresholds }, context);
770
- const criticalPathGraph = buildCompactGraphWithContext(run, "critical-path", { thresholds }, context);
771
- const blackboardDigest = blackboardDigestFor(run, context);
772
- const operatorDigest = buildOperatorDigestWithContext(run, thresholds, context);
773
- const currentFingerprint = (0, helpers_1.fingerprintStrings)([
774
- compactGraph.sourceFingerprint,
775
- blackboardDigest.sourceFingerprint,
776
- operatorDigest.sourceFingerprint,
777
- String(stateSize.total)
778
- ]);
779
- const persisted = options.index;
780
- const staleScopes = [];
781
- let status = persisted ? "valid" : "absent";
782
- if (persisted) {
783
- if (persisted.sourceFingerprint !== currentFingerprint)
784
- status = "stale";
785
- for (const entry of persisted.entries) {
786
- const current = currentEntryFingerprint(run, entry, { compactGraph, blackboardDigest, operatorDigest });
787
- if (current && current !== entry.sourceFingerprint)
788
- staleScopes.push(`${entry.scope}:${entry.id}`);
789
- }
790
- if (staleScopes.length)
791
- status = "stale";
792
- }
793
- const nextAction = status === "stale" || status === "absent"
794
- ? `node scripts/cw.js summary refresh ${run.id}`
795
- : operatorDigest.nextAction;
796
- return {
797
- schemaVersion: size_1.STATE_EXPLOSION_SCHEMA_VERSION,
798
- runId: run.id,
799
- generatedAt: new Date().toISOString(),
800
- stateSize,
801
- freshness: {
802
- status,
803
- persistedFingerprint: persisted?.sourceFingerprint,
804
- currentFingerprint,
805
- staleScopes: staleScopes.sort()
806
- },
807
- index: persisted,
808
- compactGraph,
809
- criticalPathGraph,
810
- blackboardDigest,
811
- operatorDigest,
812
- hiddenSourceRecords: operatorDigest.hiddenSourceRecords,
813
- expansionCommands: operatorDigest.expansionCommands,
814
- nextAction
815
- };
816
- }
817
- function currentEntryFingerprint(run, entry, records) {
818
- if (entry.scope === "blackboard")
819
- return records.blackboardDigest.sourceFingerprint;
820
- if (entry.id.startsWith("graph-")) {
821
- if (entry.id === records.compactGraph.id)
822
- return records.compactGraph.sourceFingerprint;
823
- return undefined;
824
- }
825
- if (entry.id === "operator-digest")
826
- return records.operatorDigest.sourceFingerprint;
827
- return undefined;
828
- }
829
- // ---------------------------------------------------------------------------
830
- // Persistence + refresh
831
- // ---------------------------------------------------------------------------
832
- /** Check state size and auto-compact if thresholds exceeded. Best-effort —
833
- * errors are silently caught; never fail a state mutation for compaction.
834
- * BSD: mechanism (check + refresh); policy (when to call) is at the call site. */
835
- function maybeCompactRun(run) {
836
- try {
837
- const size = (0, size_1.computeStateSize)(run);
838
- if (size.compactionRecommended) {
839
- refreshStateExplosionSummaries(run);
840
- }
841
- }
842
- catch {
843
- // Best-effort optimization only.
844
- }
845
- }
846
- function summariesDir(run) {
847
- return node_path_1.default.join(run.paths.runDir, "summaries");
848
- }
849
- function refreshStateExplosionSummaries(run, options = {}) {
850
- const thresholds = options.thresholds || size_1.DEFAULT_STATE_EXPLOSION_THRESHOLDS;
851
- const context = createStateExplosionBuildContext();
852
- const dir = summariesDir(run);
853
- node_fs_1.default.mkdirSync(dir, { recursive: true });
854
- const views = options.views || ["full", "compact", "critical-path", "failures", "evidence", "trust", "topology", "blackboard", "candidate", "commit-gate"];
855
- const blackboardDigest = blackboardDigestFor(run, context);
856
- const operatorDigest = buildOperatorDigestWithContext(run, thresholds, context);
857
- const graphRecords = views.map((view) => buildCompactGraphWithContext(run, view, { thresholds }, context));
858
- const entries = [];
859
- const writeRecord = (id, record, scope, fingerprint, included, omitted) => {
860
- const file = node_path_1.default.join(dir, `${(0, state_1.safeFileName)(id)}.json`);
861
- (0, state_1.writeJson)(file, record);
862
- entries.push({ scope, id, path: file, sourceFingerprint: fingerprint, includedCount: included, omittedCount: omitted, status: "valid" });
863
- };
864
- writeRecord(blackboardDigest.id, blackboardDigest, "blackboard", blackboardDigest.sourceFingerprint, blackboardDigest.includedCount, blackboardDigest.omittedCount);
865
- writeRecord(operatorDigest.id, operatorDigest, "run", operatorDigest.sourceFingerprint, operatorDigest.includedCount, operatorDigest.omittedCount);
866
- for (const record of graphRecords) {
867
- writeRecord(record.id, record, "run", record.sourceFingerprint, record.compactNodeCount, record.collapsedNodeCount);
868
- }
869
- const stateSize = stateSizeFor(run, thresholds, context);
870
- const compactGraph = buildCompactGraphWithContext(run, "compact", { thresholds }, context);
871
- const reportPath = node_path_1.default.join(dir, "state-explosion-report.json");
872
- const index = {
873
- schemaVersion: size_1.STATE_EXPLOSION_SCHEMA_VERSION,
874
- runId: run.id,
875
- id: "multi-agent-summary-index",
876
- scope: "run",
877
- sourceRecordIds: (0, helpers_1.unique)([...blackboardDigest.sourceRecordIds, ...operatorDigest.sourceRecordIds]),
878
- sourceFingerprint: (0, helpers_1.fingerprintStrings)([
879
- compactGraph.sourceFingerprint,
880
- blackboardDigest.sourceFingerprint,
881
- operatorDigest.sourceFingerprint,
882
- String(stateSize.total)
883
- ]),
884
- includedCount: entries.reduce((acc, e) => acc + e.includedCount, 0),
885
- omittedCount: entries.reduce((acc, e) => acc + e.omittedCount, 0),
886
- importantRefs: operatorDigest.criticalPath,
887
- evidenceRefs: operatorDigest.evidenceRefs,
888
- trustAuditEventRefs: blackboardDigest.trustAuditEventRefs,
889
- generatedAt: new Date().toISOString(),
890
- status: "valid",
891
- deterministic: true,
892
- nextAction: `node scripts/cw.js summary show ${run.id}`,
893
- entries: entries.sort((a, b) => a.id.localeCompare(b.id)),
894
- views,
895
- paths: {
896
- summariesDir: dir,
897
- indexPath: node_path_1.default.join(dir, "index.json"),
898
- reportPath
899
- }
900
- };
901
- (0, state_1.writeJson)(index.paths.indexPath, index);
902
- const report = buildStateExplosionReportWithContext(run, { thresholds, index }, context);
903
- (0, state_1.writeJson)(reportPath, report);
904
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
905
- kind: "summary.refresh",
906
- decision: "recorded",
907
- source: "runtime-derived",
908
- actor: "cw",
909
- metadata: {
910
- deterministic: true,
911
- scopes: entries.map((e) => `${e.scope}:${e.id}`),
912
- includedRecords: index.includedCount,
913
- omittedRecords: index.omittedCount,
914
- compactionRecommended: stateSize.compactionRecommended,
915
- sourceFingerprint: index.sourceFingerprint,
916
- stale: false
917
- }
918
- });
919
- return index;
920
- }
921
- function loadStateExplosionSummaryIndex(run) {
922
- const indexPath = node_path_1.default.join(summariesDir(run), "index.json");
923
- if (!node_fs_1.default.existsSync(indexPath))
924
- return undefined;
925
- try {
926
- const parsed = JSON.parse(node_fs_1.default.readFileSync(indexPath, "utf8"));
927
- if (!parsed || parsed.id !== "multi-agent-summary-index")
928
- return undefined;
929
- return parsed;
930
- }
931
- catch {
932
- return undefined;
933
- }
934
- }
935
- function showStateExplosionSummary(run, options = {}) {
936
- const index = loadStateExplosionSummaryIndex(run);
937
- const report = buildStateExplosionReport(run, { thresholds: options.thresholds, index });
938
- if (index && report.freshness.status === "stale") {
939
- (0, trust_audit_1.recordTrustAuditEvent)(run, {
940
- kind: "summary.stale",
941
- decision: "failed",
942
- source: "runtime-derived",
943
- actor: "cw",
944
- metadata: {
945
- persistedFingerprint: report.freshness.persistedFingerprint,
946
- currentFingerprint: report.freshness.currentFingerprint,
947
- staleScopes: report.freshness.staleScopes
948
- }
949
- });
950
- }
951
- return report;
952
- }
953
- function normalizeStateExplosionForEval(run) {
954
- const report = buildStateExplosionReport(run);
955
- const graph = report.compactGraph;
956
- return {
957
- summaryFreshness: [
958
- (0, helpers_1.stableLine)({
959
- compactionRecommended: report.stateSize.compactionRecommended,
960
- total: report.stateSize.total,
961
- deterministic: graph.deterministic
962
- })
963
- ],
964
- compactGraphShape: [
965
- (0, helpers_1.stableLine)({
966
- view: graph.view,
967
- fullNodeCount: graph.fullNodeCount,
968
- fullEdgeCount: graph.fullEdgeCount,
969
- compactNodeCount: graph.compactNodeCount,
970
- compactEdgeCount: graph.compactEdgeCount,
971
- collapsedNodeCount: graph.collapsedNodeCount,
972
- syntheticNodes: graph.syntheticNodes.map((s) => ({
973
- kind: s.id.split(":summary:")[1] || s.kind,
974
- collapsedNodeCount: s.collapsedNodeCount,
975
- collapsedEdgeCount: s.collapsedEdgeCount,
976
- dominantStatus: s.dominantStatus
977
- }))
978
- })
979
- ],
980
- blackboardDigest: [
981
- (0, helpers_1.stableLine)({
982
- topics: report.blackboardDigest.topicRollups.length,
983
- threads: report.blackboardDigest.threadSummaries.length,
984
- unresolved: report.blackboardDigest.unresolvedQuestions.map((q) => q.id),
985
- conflicts: report.blackboardDigest.conflicts.map((c) => c.id),
986
- decisions: report.blackboardDigest.decisions.length,
987
- artifacts: report.blackboardDigest.artifacts.length,
988
- policyViolations: report.blackboardDigest.policyViolations.map((p) => p.id),
989
- judgeRationale: report.blackboardDigest.judgeRationale.map((j) => j.id),
990
- missingEvidence: report.blackboardDigest.missingEvidence.map((m) => m.label)
991
- })
992
- ],
993
- criticalPath: graph.criticalPath.map((id) => (0, helpers_1.stripRunId)(run, id)).sort(),
994
- evidenceDigest: [
995
- (0, helpers_1.stableLine)({
996
- adopted: report.operatorDigest.evidenceDigest.adopted,
997
- missing: report.operatorDigest.evidenceDigest.missing,
998
- rejected: report.operatorDigest.evidenceDigest.rejected
999
- })
1000
- ],
1001
- expansionRefs: report.hiddenSourceRecords.map((h) => `${h.kind}=${h.count}`).sort()
1002
- };
1003
- }
1004
- // ---------------------------------------------------------------------------
1005
- // Helpers + human formatting now live in sibling modules (FreeBSD-audit carve).
1006
- // Re-exported below so every importer of this module stays byte-unchanged.
1007
- // ---------------------------------------------------------------------------
1008
- var helpers_2 = require("./state-explosion/helpers");
1009
- Object.defineProperty(exports, "fingerprintStrings", { enumerable: true, get: function () { return helpers_2.fingerprintStrings; } });
1010
- var format_1 = require("./state-explosion/format");
1011
- Object.defineProperty(exports, "formatStateExplosionReport", { enumerable: true, get: function () { return format_1.formatStateExplosionReport; } });
1012
- Object.defineProperty(exports, "formatCompactGraph", { enumerable: true, get: function () { return format_1.formatCompactGraph; } });
1013
- Object.defineProperty(exports, "formatBlackboardDigest", { enumerable: true, get: function () { return format_1.formatBlackboardDigest; } });
1014
- Object.defineProperty(exports, "stateExplosionReportLines", { enumerable: true, get: function () { return format_1.stateExplosionReportLines; } });