cool-workflow 0.1.98 → 0.2.1

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 (315) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +18 -7
  4. package/apps/architecture-review/app.json +2 -2
  5. package/apps/architecture-review/workflow.js +12 -12
  6. package/apps/architecture-review-fast/app.json +1 -1
  7. package/apps/end-to-end-golden-path/app.json +1 -1
  8. package/apps/pr-review-fix-ci/app.json +1 -1
  9. package/apps/release-cut/app.json +1 -1
  10. package/apps/research-synthesis/app.json +1 -1
  11. package/dist/cli/dispatch.js +236 -0
  12. package/dist/cli/entry.js +120 -0
  13. package/dist/cli/io.js +21 -4
  14. package/dist/cli/parseargv.js +157 -0
  15. package/dist/cli.js +6 -33
  16. package/dist/core/capability-table.js +3518 -0
  17. package/dist/core/format/help.js +314 -0
  18. package/dist/{state-explosion/format.js → core/format/state-explosion-text.js} +10 -1
  19. package/dist/core/hash.js +137 -0
  20. package/dist/core/multi-agent/candidate-scoring.js +219 -0
  21. package/dist/core/multi-agent/collaboration.js +481 -0
  22. package/dist/core/multi-agent/coordinator.js +515 -0
  23. package/dist/core/multi-agent/eval-replay.js +306 -0
  24. package/dist/core/multi-agent/runtime.js +929 -0
  25. package/dist/core/multi-agent/topology.js +298 -0
  26. package/dist/core/multi-agent/trust-policy.js +197 -0
  27. package/dist/core/pipeline/commit-gate.js +320 -0
  28. package/dist/{pipeline-contract.js → core/pipeline/contract.js} +24 -37
  29. package/dist/core/pipeline/dispatch.js +103 -0
  30. package/dist/core/pipeline/drive-decide.js +227 -0
  31. package/dist/core/pipeline/error-feedback.js +161 -0
  32. package/dist/core/pipeline/loop-expansion.js +124 -0
  33. package/dist/{result-normalize.js → core/pipeline/result-normalize.js} +14 -37
  34. package/dist/core/pipeline/runner.js +230 -0
  35. package/dist/{contract-migration.js → core/state/contract-migration.js} +68 -92
  36. package/dist/{state-migrations.js → core/state/migrations.js} +103 -96
  37. package/dist/core/state/node-projection.js +95 -0
  38. package/dist/core/state/node-snapshot.js +230 -0
  39. package/dist/core/state/run-paths.js +93 -0
  40. package/dist/{schema-validate.js → core/state/schema-validate.js} +35 -28
  41. package/dist/core/state/schema.js +50 -0
  42. package/dist/core/state/state-explosion/digest.js +243 -0
  43. package/dist/core/state/state-explosion/graph.js +527 -0
  44. package/dist/{state-explosion → core/state/state-explosion}/helpers.js +34 -3
  45. package/dist/core/state/state-explosion/report.js +187 -0
  46. package/dist/{state-explosion → core/state/state-explosion}/size.js +25 -7
  47. package/dist/{state-node.js → core/state/state-node.js} +90 -113
  48. package/dist/core/state/types.js +19 -0
  49. package/dist/{validation.js → core/state/validation.js} +64 -131
  50. package/dist/core/trust/evidence-grounding.js +134 -0
  51. package/dist/core/trust/ledger.js +199 -0
  52. package/dist/{telemetry-attestation.js → core/trust/telemetry-attestation.js} +94 -68
  53. package/dist/core/trust/telemetry-ledger.js +127 -0
  54. package/dist/core/types.js +20 -0
  55. package/dist/core/version.js +16 -0
  56. package/dist/{workflow-app-framework.js → core/workflow-apps/app-schema.js} +337 -426
  57. package/dist/mcp/dispatch.js +104 -0
  58. package/dist/mcp/server.js +144 -0
  59. package/dist/mcp-server.js +6 -84
  60. package/dist/{agent-config.js → shell/agent-config.js} +118 -71
  61. package/dist/shell/app-run-cli.js +88 -0
  62. package/dist/shell/audit-cli.js +259 -0
  63. package/dist/shell/audit-provenance.js +83 -0
  64. package/dist/shell/candidate-scoring-io.js +459 -0
  65. package/dist/shell/collaboration-io.js +264 -0
  66. package/dist/shell/commit-summary.js +104 -0
  67. package/dist/shell/commit.js +290 -0
  68. package/dist/shell/coordinator-io.js +476 -0
  69. package/dist/shell/demo-cli.js +19 -0
  70. package/dist/shell/dispatch.js +162 -0
  71. package/dist/shell/doctor.js +292 -0
  72. package/dist/shell/drive.js +885 -0
  73. package/dist/shell/error-feedback-io.js +305 -0
  74. package/dist/shell/eval-io.js +473 -0
  75. package/dist/{multi-agent-eval/format.js → shell/eval-text.js} +78 -49
  76. package/dist/{evidence-reasoning.js → shell/evidence-reasoning.js} +124 -255
  77. package/dist/shell/exec-backend-cli.js +88 -0
  78. package/dist/shell/execution-backend/agent.js +507 -0
  79. package/dist/shell/execution-backend/ci.js +15 -0
  80. package/dist/shell/execution-backend/container.js +69 -0
  81. package/dist/shell/execution-backend/envelopes.js +55 -0
  82. package/dist/shell/execution-backend/local.js +113 -0
  83. package/dist/shell/execution-backend/probes.js +175 -0
  84. package/dist/shell/execution-backend/registry.js +402 -0
  85. package/dist/shell/execution-backend/remote.js +128 -0
  86. package/dist/shell/execution-backend/types.js +11 -0
  87. package/dist/shell/feedback-cli.js +81 -0
  88. package/dist/shell/feedback-operations.js +48 -0
  89. package/dist/shell/fs-atomic.js +276 -0
  90. package/dist/shell/harness.js +98 -0
  91. package/dist/shell/ledger-cli.js +212 -0
  92. package/dist/shell/ledger-io.js +169 -0
  93. package/dist/shell/man-cli.js +89 -0
  94. package/dist/shell/metrics-cli.js +100 -0
  95. package/dist/shell/multi-agent-cli.js +1002 -0
  96. package/dist/shell/multi-agent-host.js +563 -0
  97. package/dist/shell/multi-agent-io.js +387 -0
  98. package/dist/{multi-agent-operator-ux.js → shell/multi-agent-operator-ux.js} +234 -191
  99. package/dist/shell/node-store.js +124 -0
  100. package/dist/{observability/format.js → shell/observability-format.js} +7 -1
  101. package/dist/{observability/intake.js → shell/observability-intake.js} +79 -56
  102. package/dist/{observability.js → shell/observability.js} +159 -332
  103. package/dist/{onramp.js → shell/onramp.js} +11 -0
  104. package/dist/{operator-ux/format.js → shell/operator-ux-text.js} +250 -239
  105. package/dist/shell/operator-ux.js +431 -0
  106. package/dist/shell/orchestrator.js +231 -0
  107. package/dist/shell/pipeline-cli.js +667 -0
  108. package/dist/shell/pipeline.js +217 -0
  109. package/dist/shell/reclamation-io.js +1366 -0
  110. package/dist/shell/registry-cli.js +344 -0
  111. package/dist/{remote-source.js → shell/remote-source.js} +2 -2
  112. package/dist/shell/report-cli.js +101 -0
  113. package/dist/shell/report-view-cli.js +117 -0
  114. package/dist/{orchestrator → shell}/report.js +289 -282
  115. package/dist/shell/reporter.js +62 -0
  116. package/dist/shell/run-export-cli.js +106 -0
  117. package/dist/shell/run-export.js +680 -0
  118. package/dist/shell/run-registry-io.js +1014 -0
  119. package/dist/shell/run-store.js +164 -0
  120. package/dist/{sandbox-profile.js → shell/sandbox-profile.js} +134 -95
  121. package/dist/{scheduler.js → shell/scheduler-io.js} +257 -48
  122. package/dist/shell/scheduling-io.js +321 -0
  123. package/dist/shell/state-cli.js +181 -0
  124. package/dist/shell/state-explosion-cli.js +197 -0
  125. package/dist/shell/telemetry-cli.js +85 -0
  126. package/dist/{telemetry-demo.js → shell/telemetry-demo.js} +149 -119
  127. package/dist/shell/telemetry-ledger-io.js +132 -0
  128. package/dist/{term.js → shell/term.js} +36 -46
  129. package/dist/shell/topology-io.js +361 -0
  130. package/dist/shell/trust-audit.js +472 -0
  131. package/dist/{multi-agent-trust.js → shell/trust-policy-io.js} +67 -205
  132. package/dist/shell/verifier.js +48 -0
  133. package/dist/shell/workbench-host.js +258 -0
  134. package/dist/shell/workbench-text.js +18 -0
  135. package/dist/shell/workbench.js +170 -0
  136. package/dist/shell/worker-cli.js +124 -0
  137. package/dist/shell/worker-isolation.js +852 -0
  138. package/dist/shell/workflow-app-loader.js +650 -0
  139. package/docs/agent-delegation-drive.7.md +4 -0
  140. package/docs/cli-mcp-parity.7.md +282 -219
  141. package/docs/contract-migration-tooling.7.md +4 -0
  142. package/docs/control-plane-scheduling.7.md +4 -0
  143. package/docs/durable-state-and-locking.7.md +4 -0
  144. package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
  145. package/docs/execution-backends.7.md +4 -0
  146. package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
  147. package/docs/multi-agent-eval-replay-harness.7.md +4 -0
  148. package/docs/multi-agent-operator-ux.7.md +4 -0
  149. package/docs/node-snapshot-diff-replay.7.md +4 -0
  150. package/docs/observability-cost-accounting.7.md +6 -1
  151. package/docs/project-index.md +137 -71
  152. package/docs/real-execution-backends.7.md +4 -0
  153. package/docs/release-and-migration.7.md +4 -0
  154. package/docs/release-tooling.7.md +4 -0
  155. package/docs/remote-source-review.7.md +4 -4
  156. package/docs/report-verifiable-bundle.7.md +1 -1
  157. package/docs/run-registry-control-plane.7.md +4 -0
  158. package/docs/run-retention-reclamation.7.md +25 -0
  159. package/docs/security-trust-hardening.7.md +3 -1
  160. package/docs/state-explosion-management.7.md +4 -0
  161. package/docs/team-collaboration.7.md +4 -0
  162. package/docs/web-desktop-workbench.7.md +15 -1
  163. package/manifest/plugin.manifest.json +1 -1
  164. package/manifest/source-context-profiles.json +9 -13
  165. package/package.json +1 -1
  166. package/scripts/agents/agent-adapter-core.js +22 -2
  167. package/scripts/agents/claude-p-agent.js +8 -3
  168. package/scripts/agents/cw-attest-wrap.js +2 -2
  169. package/scripts/agents/gemini-agent.js +5 -1
  170. package/scripts/agents/opencode-agent.js +5 -1
  171. package/scripts/bump-version.js +4 -3
  172. package/scripts/canonical-apps.js +4 -4
  173. package/scripts/dogfood-architecture-review.js +2 -3
  174. package/scripts/dogfood-release.js +3 -3
  175. package/scripts/gen-parity-doc.js +15 -2
  176. package/scripts/golden-path.js +4 -4
  177. package/scripts/onramp-check.js +1 -1
  178. package/scripts/parity-check.js +38 -21
  179. package/scripts/release-flow.js +2 -2
  180. package/scripts/sync-project-index.js +51 -27
  181. package/scripts/validate-run-state-schema.js +2 -2
  182. package/scripts/version-sync-check.js +30 -30
  183. package/dist/candidate-scoring.js +0 -729
  184. package/dist/capability-core.js +0 -1189
  185. package/dist/capability-registry.js +0 -885
  186. package/dist/cli/command-surface.js +0 -494
  187. package/dist/cli/format.js +0 -56
  188. package/dist/cli/handlers/audit.js +0 -82
  189. package/dist/cli/handlers/blackboard.js +0 -81
  190. package/dist/cli/handlers/candidate.js +0 -40
  191. package/dist/cli/handlers/clones.js +0 -34
  192. package/dist/cli/handlers/collaboration.js +0 -61
  193. package/dist/cli/handlers/eval.js +0 -40
  194. package/dist/cli/handlers/ledger.js +0 -169
  195. package/dist/cli/handlers/maintenance.js +0 -107
  196. package/dist/cli/handlers/multi-agent.js +0 -165
  197. package/dist/cli/handlers/node.js +0 -41
  198. package/dist/cli/handlers/operational.js +0 -155
  199. package/dist/cli/handlers/operator.js +0 -146
  200. package/dist/cli/handlers/registry.js +0 -68
  201. package/dist/cli/handlers/run.js +0 -153
  202. package/dist/cli/handlers/scheduling.js +0 -132
  203. package/dist/cli/handlers/workbench.js +0 -41
  204. package/dist/cli/handlers/worker.js +0 -45
  205. package/dist/cli/run-summary.js +0 -45
  206. package/dist/clones.js +0 -162
  207. package/dist/collaboration.js +0 -726
  208. package/dist/commit.js +0 -592
  209. package/dist/compare.js +0 -18
  210. package/dist/coordinator/classify.js +0 -45
  211. package/dist/coordinator/paths.js +0 -42
  212. package/dist/coordinator/util.js +0 -126
  213. package/dist/coordinator.js +0 -990
  214. package/dist/daemon.js +0 -44
  215. package/dist/dispatch.js +0 -250
  216. package/dist/doctor.js +0 -212
  217. package/dist/drive.js +0 -864
  218. package/dist/error-feedback.js +0 -419
  219. package/dist/evidence-grounding.js +0 -184
  220. package/dist/execution-backend/agent.js +0 -354
  221. package/dist/execution-backend/probes.js +0 -112
  222. package/dist/execution-backend/util.js +0 -47
  223. package/dist/execution-backend.js +0 -961
  224. package/dist/gates.js +0 -48
  225. package/dist/harness.js +0 -61
  226. package/dist/ledger.js +0 -313
  227. package/dist/loop-expansion.js +0 -60
  228. package/dist/mcp/tool-call.js +0 -470
  229. package/dist/mcp/tool-definitions.js +0 -1066
  230. package/dist/mcp-surface.js +0 -30
  231. package/dist/multi-agent/graph.js +0 -84
  232. package/dist/multi-agent/helpers.js +0 -141
  233. package/dist/multi-agent/ids.js +0 -20
  234. package/dist/multi-agent/paths.js +0 -22
  235. package/dist/multi-agent-eval/normalize.js +0 -51
  236. package/dist/multi-agent-eval.js +0 -678
  237. package/dist/multi-agent-host.js +0 -777
  238. package/dist/multi-agent.js +0 -984
  239. package/dist/node-projection.js +0 -59
  240. package/dist/node-snapshot.js +0 -260
  241. package/dist/operator-ux.js +0 -631
  242. package/dist/orchestrator/app-operations.js +0 -211
  243. package/dist/orchestrator/audit-operations.js +0 -182
  244. package/dist/orchestrator/candidate-operations.js +0 -117
  245. package/dist/orchestrator/cli-options.js +0 -294
  246. package/dist/orchestrator/collaboration-operations.js +0 -86
  247. package/dist/orchestrator/feedback-operations.js +0 -81
  248. package/dist/orchestrator/host-operations.js +0 -78
  249. package/dist/orchestrator/lifecycle-operations.js +0 -650
  250. package/dist/orchestrator/migration-operations.js +0 -44
  251. package/dist/orchestrator/multi-agent-operations.js +0 -362
  252. package/dist/orchestrator/topology-operations.js +0 -84
  253. package/dist/orchestrator.js +0 -925
  254. package/dist/pipeline-runner.js +0 -285
  255. package/dist/reclamation/hash.js +0 -72
  256. package/dist/reclamation.js +0 -812
  257. package/dist/reporter.js +0 -67
  258. package/dist/run-export.js +0 -815
  259. package/dist/run-registry/derive.js +0 -175
  260. package/dist/run-registry/format.js +0 -124
  261. package/dist/run-registry/gc.js +0 -251
  262. package/dist/run-registry/policy.js +0 -16
  263. package/dist/run-registry/queue.js +0 -115
  264. package/dist/run-registry.js +0 -850
  265. package/dist/run-state-schema.js +0 -68
  266. package/dist/scheduling.js +0 -184
  267. package/dist/state-explosion.js +0 -1014
  268. package/dist/state.js +0 -367
  269. package/dist/telemetry-ledger.js +0 -196
  270. package/dist/topology.js +0 -565
  271. package/dist/triggers.js +0 -184
  272. package/dist/trust-audit.js +0 -644
  273. package/dist/types/blackboard.js +0 -2
  274. package/dist/types/candidate.js +0 -2
  275. package/dist/types/collaboration.js +0 -2
  276. package/dist/types/core.js +0 -2
  277. package/dist/types/drive.js +0 -10
  278. package/dist/types/error-feedback.js +0 -2
  279. package/dist/types/evidence-reasoning.js +0 -2
  280. package/dist/types/execution-backend.js +0 -2
  281. package/dist/types/multi-agent.js +0 -2
  282. package/dist/types/observability.js +0 -2
  283. package/dist/types/pipeline.js +0 -2
  284. package/dist/types/reclamation.js +0 -8
  285. package/dist/types/report-bundle.js +0 -6
  286. package/dist/types/result.js +0 -2
  287. package/dist/types/run-registry.js +0 -2
  288. package/dist/types/run.js +0 -2
  289. package/dist/types/sandbox.js +0 -2
  290. package/dist/types/schedule.js +0 -2
  291. package/dist/types/state-node.js +0 -2
  292. package/dist/types/topology.js +0 -2
  293. package/dist/types/trust.js +0 -2
  294. package/dist/types/workbench.js +0 -2
  295. package/dist/types/worker.js +0 -2
  296. package/dist/types/workflow-app.js +0 -2
  297. package/dist/types.js +0 -44
  298. package/dist/util/fingerprint.js +0 -19
  299. package/dist/util/fingerprint.test.js +0 -27
  300. package/dist/verifier.js +0 -78
  301. package/dist/version.js +0 -8
  302. package/dist/workbench-host.js +0 -192
  303. package/dist/workbench.js +0 -192
  304. package/dist/worker-accept/acceptance.js +0 -114
  305. package/dist/worker-accept/blackboard-fanout.js +0 -80
  306. package/dist/worker-accept/blackboard-linkage.js +0 -19
  307. package/dist/worker-accept/context.js +0 -2
  308. package/dist/worker-accept/telemetry-ledger.js +0 -126
  309. package/dist/worker-accept/validation.js +0 -77
  310. package/dist/worker-accept/verifier-completion.js +0 -73
  311. package/dist/worker-isolation/helpers.js +0 -51
  312. package/dist/worker-isolation/paths.js +0 -46
  313. package/dist/worker-isolation.js +0 -656
  314. package/dist/workflow-api.js +0 -131
  315. /package/dist/{types → core/types}/boundary.js +0 -0
@@ -1,990 +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.BLACKBOARD_SCHEMA_VERSION = void 0;
7
- exports.ensureBlackboardState = ensureBlackboardState;
8
- exports.resolveBlackboard = resolveBlackboard;
9
- exports.createBlackboardTopic = createBlackboardTopic;
10
- exports.postBlackboardMessage = postBlackboardMessage;
11
- exports.putBlackboardContext = putBlackboardContext;
12
- exports.addBlackboardArtifact = addBlackboardArtifact;
13
- exports.createBlackboardSnapshot = createBlackboardSnapshot;
14
- exports.recordCoordinatorDecision = recordCoordinatorDecision;
15
- exports.summarizeBlackboard = summarizeBlackboard;
16
- exports.listBlackboardMessages = listBlackboardMessages;
17
- exports.listBlackboardArtifacts = listBlackboardArtifacts;
18
- exports.buildBlackboardGraph = buildBlackboardGraph;
19
- exports.persistBlackboardState = persistBlackboardState;
20
- const node_fs_1 = __importDefault(require("node:fs"));
21
- const node_path_1 = __importDefault(require("node:path"));
22
- const pipeline_contract_1 = require("./pipeline-contract");
23
- const state_1 = require("./state");
24
- const state_node_1 = require("./state-node");
25
- const multi_agent_1 = require("./multi-agent");
26
- const trust_audit_1 = require("./trust-audit");
27
- const multi_agent_trust_1 = require("./multi-agent-trust");
28
- const util_1 = require("./coordinator/util");
29
- const classify_1 = require("./coordinator/classify");
30
- const paths_1 = require("./coordinator/paths");
31
- // NOTE: the symbols imported above from ./coordinator/{util,classify,paths} were
32
- // PRIVATE helpers inside this module before the carve (no importer reaches them,
33
- // including the `import * as cb` consumer in orchestrator/multi-agent-operations).
34
- // They are relocated as pure code movement — zero signature/behavior change — and
35
- // imported back for internal use only, so this module's PUBLIC surface stays
36
- // byte-identical (no new exports). The public exported functions below are
37
- // unchanged.
38
- exports.BLACKBOARD_SCHEMA_VERSION = 1;
39
- function ensureBlackboardState(run) {
40
- run.paths.blackboardDir = (0, paths_1.blackboardRoot)(run);
41
- node_fs_1.default.mkdirSync(run.paths.blackboardDir, { recursive: true });
42
- for (const dir of ["topics", "contexts", "artifacts", "snapshots", "decisions"]) {
43
- node_fs_1.default.mkdirSync(node_path_1.default.join(run.paths.blackboardDir, dir), { recursive: true });
44
- }
45
- if (!run.blackboard) {
46
- run.blackboard = emptyState();
47
- }
48
- run.blackboard.schemaVersion = exports.BLACKBOARD_SCHEMA_VERSION;
49
- run.blackboard.boards = run.blackboard.boards || [];
50
- run.blackboard.topics = run.blackboard.topics || [];
51
- run.blackboard.messages = run.blackboard.messages || [];
52
- run.blackboard.contexts = run.blackboard.contexts || [];
53
- run.blackboard.artifacts = run.blackboard.artifacts || [];
54
- run.blackboard.snapshots = run.blackboard.snapshots || [];
55
- run.blackboard.decisions = run.blackboard.decisions || [];
56
- return run.blackboard;
57
- }
58
- function resolveBlackboard(run, input = {}) {
59
- const state = ensureBlackboardState(run);
60
- const existing = input.id
61
- ? state.boards.find((board) => board.id === input.id)
62
- : input.multiAgentRunId
63
- ? state.boards.find((board) => board.links.multiAgentRunId === input.multiAgentRunId)
64
- : state.boards[0];
65
- if (existing) {
66
- linkMultiAgent(run, existing.id, existing.topicIds, input);
67
- (0, util_1.touch)(existing);
68
- persistBlackboardState(run);
69
- return existing;
70
- }
71
- const id = input.id || (0, util_1.createId)("bb", state.boards.length + 1);
72
- (0, util_1.assertUnique)(state.boards, id, "Blackboard");
73
- const now = (0, util_1.timestamp)();
74
- const author = normalizeAuthor(input.author, "runtime");
75
- const scope = normalizeScope(input.scope, input.multiAgentRunId ? { kind: "multi-agent-run", id: input.multiAgentRunId } : { kind: "run", id: run.id });
76
- const board = {
77
- schemaVersion: exports.BLACKBOARD_SCHEMA_VERSION,
78
- id,
79
- runId: run.id,
80
- createdAt: now,
81
- updatedAt: now,
82
- author,
83
- scope,
84
- status: "active",
85
- parentIds: [],
86
- tags: (0, util_1.sortTags)(input.tags),
87
- title: input.title || id,
88
- topicIds: [],
89
- messageCount: 0,
90
- contextIds: [],
91
- artifactRefIds: [],
92
- snapshotIds: [],
93
- decisionIds: [],
94
- links: compactLinks(run, {
95
- multiAgentRunId: input.multiAgentRunId,
96
- agentGroupId: input.groupId,
97
- agentRoleId: input.roleId,
98
- agentMembershipId: input.membershipId
99
- }),
100
- paths: (0, paths_1.boardPaths)(run),
101
- metadata: (0, util_1.scrub)(input.metadata)
102
- };
103
- linkMultiAgent(run, board.id, [], input);
104
- state.boards.push(board);
105
- appendBlackboardNode(run, "blackboard", board.id, "running", board.title, board.paths.index);
106
- const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
107
- kind: "blackboard.create",
108
- decision: "recorded",
109
- source: "runtime-derived",
110
- actor: author.id,
111
- multiAgentRunId: input.multiAgentRunId,
112
- agentGroupId: input.groupId,
113
- agentRoleId: input.roleId,
114
- agentMembershipId: input.membershipId,
115
- blackboardId: board.id,
116
- metadata: { scope, tags: board.tags }
117
- });
118
- board.links.auditEventIds = [audit.id];
119
- persistBlackboardState(run);
120
- return board;
121
- }
122
- function createBlackboardTopic(run, input) {
123
- const board = resolveBlackboard(run, { id: input.blackboardId });
124
- const state = ensureBlackboardState(run);
125
- const id = input.id || (0, util_1.createId)("topic", state.topics.length + 1);
126
- (0, util_1.assertUnique)(state.topics, id, "BlackboardTopic");
127
- const topicLinks = compactLinks(run, { ...board.links, ...roleLinkFromAuthor(input.author), ...input.scope });
128
- const now = (0, util_1.timestamp)();
129
- const topic = {
130
- ...base(run, board.id, id, input.author, input.scope, "open", input.tags, input.metadata),
131
- createdAt: now,
132
- updatedAt: now,
133
- title: input.title,
134
- description: input.description,
135
- messageIds: [],
136
- contextIds: [],
137
- artifactRefIds: [],
138
- links: topicLinks
139
- };
140
- state.topics.push(topic);
141
- board.topicIds = (0, util_1.unique)([...board.topicIds, topic.id]);
142
- (0, util_1.touch)(board);
143
- linkMultiAgent(run, board.id, [topic.id], board.links);
144
- appendBlackboardNode(run, "blackboard-topic", topic.id, "running", topic.title, (0, paths_1.recordPath)(run, "topics", topic.id), [`${run.id}:blackboard:${board.id}`]);
145
- const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
146
- kind: "blackboard.topic",
147
- decision: "recorded",
148
- source: "operator-recorded",
149
- actor: topic.author.id,
150
- blackboardId: board.id,
151
- blackboardTopicId: topic.id,
152
- multiAgentRunId: topic.links.multiAgentRunId,
153
- agentGroupId: topic.links.agentGroupId,
154
- agentRoleId: topic.links.agentRoleId,
155
- agentMembershipId: topic.links.agentMembershipId,
156
- metadata: { title: topic.title, tags: topic.tags }
157
- });
158
- topic.links.auditEventIds = (0, util_1.unique)([...(topic.links.auditEventIds || []), audit.id]);
159
- (0, multi_agent_trust_1.recordBlackboardWriteAudit)(run, {
160
- operation: "topic",
161
- status: topic.status,
162
- actor: topic.author,
163
- blackboardId: board.id,
164
- blackboardTopicId: topic.id,
165
- multiAgentRunId: topic.links.multiAgentRunId,
166
- agentGroupId: topic.links.agentGroupId,
167
- agentRoleId: topic.links.agentRoleId,
168
- agentMembershipId: topic.links.agentMembershipId,
169
- parentEventIds: [audit.id],
170
- metadata: { title: topic.title }
171
- });
172
- persistBlackboardState(run);
173
- return topic;
174
- }
175
- function postBlackboardMessage(run, input) {
176
- const state = ensureBlackboardState(run);
177
- const topic = requireTopic(run, input.topicId);
178
- const board = requireBoard(run, input.blackboardId || topic.blackboardId);
179
- if (input.replyToId && !state.messages.some((message) => message.id === input.replyToId)) {
180
- throw new Error(`Unknown parent BlackboardMessage id: ${input.replyToId}`);
181
- }
182
- if (!input.body.trim())
183
- throw new Error("Blackboard message body is required");
184
- const id = input.id || (0, util_1.createId)("msg", state.messages.length + 1);
185
- (0, util_1.assertUnique)(state.messages, id, "BlackboardMessage");
186
- const author = normalizeAuthor(input.author, "operator");
187
- const links = compactLinks(run, { ...topic.links, ...roleLinkFromAuthor(author), ...(input.links || {}), evidenceRefs: input.evidenceRefs, auditEventIds: input.auditEventIds });
188
- const enforcePolicy = shouldEnforcePolicy(author, links);
189
- const permission = enforcePolicy
190
- ? (0, multi_agent_trust_1.assertMultiAgentActionAllowed)(run, {
191
- operation: "message",
192
- actor: author,
193
- multiAgentRunId: links.multiAgentRunId,
194
- agentRoleId: links.agentRoleId,
195
- agentGroupId: links.agentGroupId,
196
- agentMembershipId: links.agentMembershipId,
197
- agentFanoutId: links.agentFanoutId,
198
- agentFaninId: links.agentFaninId,
199
- blackboardId: board.id,
200
- blackboardTopicId: topic.id,
201
- blackboardMessageId: id,
202
- evidenceRefs: input.evidenceRefs || []
203
- })
204
- : undefined;
205
- const message = {
206
- ...base(run, board.id, id, author, input.scope, "active", input.tags, input.metadata),
207
- topicId: topic.id,
208
- body: input.body,
209
- visibility: input.visibility || "public",
210
- replyToId: input.replyToId,
211
- parentIds: (0, util_1.unique)([...(input.parentIds || []), ...(input.replyToId ? [input.replyToId] : [])]),
212
- linkedEvidenceRefs: (0, util_1.unique)(input.evidenceRefs || []),
213
- linkedArtifactRefIds: requireArtifactRefs(run, input.artifactRefIds || []),
214
- linkedAuditEventIds: (0, util_1.unique)(input.auditEventIds || []),
215
- links,
216
- provenance: {
217
- schemaVersion: 1,
218
- authorKind: author.kind,
219
- authorId: author.id,
220
- multiAgentRunId: links.multiAgentRunId,
221
- agentRoleId: links.agentRoleId,
222
- agentGroupId: links.agentGroupId,
223
- agentMembershipId: links.agentMembershipId,
224
- agentFanoutId: links.agentFanoutId,
225
- agentFaninId: links.agentFaninId,
226
- workerId: links.workerId || (author.kind === "worker" ? author.id : undefined),
227
- source: (0, multi_agent_trust_1.sourceForActor)(author),
228
- linkedEvidenceRefs: (0, util_1.unique)(input.evidenceRefs || []),
229
- linkedAuditEventIds: (0, util_1.unique)(input.auditEventIds || []),
230
- parentMessageIds: (0, util_1.unique)([...(input.parentIds || []), ...(input.replyToId ? [input.replyToId] : [])]),
231
- topicScope: topic.id,
232
- bodyHash: (0, multi_agent_trust_1.hashText)(input.body),
233
- locator: `${board.id}/messages/${id}`
234
- }
235
- };
236
- state.messages.push(message);
237
- topic.messageIds = (0, util_1.unique)([...topic.messageIds, message.id]);
238
- board.messageCount = state.messages.filter((entry) => entry.blackboardId === board.id).length;
239
- (0, util_1.touch)(topic);
240
- (0, util_1.touch)(board);
241
- appendBlackboardNode(run, "blackboard-message", message.id, "completed", (0, util_1.truncate)(message.body), (0, paths_1.messagesPath)(run), [`${run.id}:blackboard:topic:${topic.id}`]);
242
- const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
243
- kind: "blackboard.message",
244
- decision: "recorded",
245
- source: (0, classify_1.sourceForAuthor)(message.author),
246
- actor: message.author.id,
247
- blackboardId: board.id,
248
- blackboardTopicId: topic.id,
249
- blackboardMessageId: message.id,
250
- workerId: message.links.workerId || (message.author.kind === "worker" ? message.author.id : undefined),
251
- taskId: message.links.taskId,
252
- multiAgentRunId: message.links.multiAgentRunId,
253
- agentGroupId: message.links.agentGroupId,
254
- agentRoleId: message.links.agentRoleId,
255
- agentMembershipId: message.links.agentMembershipId,
256
- evidenceRefs: message.linkedEvidenceRefs,
257
- parentEventIds: message.linkedAuditEventIds,
258
- metadata: { visibility: message.visibility }
259
- });
260
- const writeAudit = (0, multi_agent_trust_1.recordBlackboardWriteAudit)(run, {
261
- operation: "message",
262
- status: message.status,
263
- actor: message.author,
264
- multiAgentRunId: message.links.multiAgentRunId,
265
- agentGroupId: message.links.agentGroupId,
266
- agentRoleId: message.links.agentRoleId,
267
- agentMembershipId: message.links.agentMembershipId,
268
- agentFanoutId: message.links.agentFanoutId,
269
- agentFaninId: message.links.agentFaninId,
270
- blackboardId: board.id,
271
- blackboardTopicId: topic.id,
272
- blackboardMessageId: message.id,
273
- evidenceRefs: message.linkedEvidenceRefs,
274
- parentEventIds: (0, util_1.unique)([...(permission ? [permission.event.id] : []), audit.id]),
275
- policyRef: permission?.policyRef,
276
- metadata: { visibility: message.visibility }
277
- });
278
- const provenanceAudit = (0, multi_agent_trust_1.recordMessageProvenanceAudit)(run, {
279
- messageId: message.id,
280
- topicId: topic.id,
281
- blackboardId: board.id,
282
- actor: message.author,
283
- body: message.body,
284
- multiAgentRunId: message.links.multiAgentRunId,
285
- agentRoleId: message.links.agentRoleId,
286
- agentGroupId: message.links.agentGroupId,
287
- agentMembershipId: message.links.agentMembershipId,
288
- workerId: message.links.workerId,
289
- evidenceRefs: message.linkedEvidenceRefs,
290
- parentMessageIds: message.parentIds,
291
- parentEventIds: [audit.id, writeAudit.id],
292
- policyRef: permission?.policyRef
293
- });
294
- if (message.metadata?.judgeRationale || message.tags.includes("judge-rationale")) {
295
- const rationaleAudit = (0, multi_agent_trust_1.recordJudgeRationaleAudit)(run, {
296
- kind: "judge.rationale",
297
- actor: message.author,
298
- multiAgentRunId: message.links.multiAgentRunId,
299
- agentRoleId: message.links.agentRoleId,
300
- agentGroupId: message.links.agentGroupId,
301
- agentMembershipId: message.links.agentMembershipId,
302
- blackboardId: board.id,
303
- blackboardTopicId: topic.id,
304
- blackboardMessageId: message.id,
305
- evidenceRefs: message.linkedEvidenceRefs,
306
- rationale: message.body,
307
- policyRef: permission?.policyRef,
308
- parentEventIds: [audit.id, writeAudit.id, provenanceAudit.id]
309
- });
310
- message.linkedAuditEventIds = (0, util_1.unique)([...message.linkedAuditEventIds, rationaleAudit.id]);
311
- }
312
- message.linkedAuditEventIds = (0, util_1.unique)([...message.linkedAuditEventIds, audit.id, writeAudit.id, provenanceAudit.id]);
313
- message.links.auditEventIds = (0, util_1.unique)([...(message.links.auditEventIds || []), audit.id, writeAudit.id, provenanceAudit.id]);
314
- if (message.provenance) {
315
- message.provenance.linkedAuditEventIds = (0, util_1.unique)([...message.provenance.linkedAuditEventIds, audit.id, writeAudit.id, provenanceAudit.id]);
316
- }
317
- persistBlackboardState(run);
318
- return message;
319
- }
320
- function putBlackboardContext(run, input) {
321
- const state = ensureBlackboardState(run);
322
- const topic = requireTopic(run, input.topicId);
323
- const board = requireBoard(run, input.blackboardId || topic.blackboardId);
324
- const key = input.key || input.kind;
325
- const id = input.id || (0, util_1.createId)("ctx", state.contexts.length + 1);
326
- (0, util_1.assertUnique)(state.contexts, id, "BlackboardContext");
327
- const author = normalizeAuthor(input.author, "operator");
328
- const links = compactLinks(run, { ...topic.links, ...roleLinkFromAuthor(author), ...(input.links || {}), evidenceRefs: input.evidenceRefs });
329
- const permission = shouldEnforcePolicy(author, links)
330
- ? (0, multi_agent_trust_1.assertMultiAgentActionAllowed)(run, {
331
- operation: "context",
332
- actor: author,
333
- multiAgentRunId: links.multiAgentRunId,
334
- agentRoleId: links.agentRoleId,
335
- agentGroupId: links.agentGroupId,
336
- agentMembershipId: links.agentMembershipId,
337
- blackboardId: board.id,
338
- blackboardTopicId: topic.id,
339
- blackboardContextId: id,
340
- evidenceRefs: input.evidenceRefs || []
341
- })
342
- : undefined;
343
- const conflicts = state.contexts.filter((context) => context.blackboardId === board.id &&
344
- context.topicId === topic.id &&
345
- context.kind === input.kind &&
346
- context.key === key &&
347
- context.status !== "superseded" &&
348
- !input.supersedesContextIds?.includes(context.id) &&
349
- context.value !== input.value);
350
- for (const supersededId of input.supersedesContextIds || []) {
351
- const superseded = requireContext(run, supersededId);
352
- superseded.status = "superseded";
353
- superseded.supersededByContextId = id;
354
- (0, util_1.touch)(superseded);
355
- }
356
- const status = conflicts.length ? "conflicting" : input.kind === "question" ? "open" : "active";
357
- const context = {
358
- ...base(run, board.id, id, author, input.scope, status, input.tags, input.metadata),
359
- topicId: topic.id,
360
- kind: input.kind,
361
- key,
362
- value: input.value,
363
- supersedesContextIds: (0, util_1.unique)(input.supersedesContextIds || []),
364
- conflictingContextIds: conflicts.map((entry) => entry.id),
365
- evidenceRefs: (0, util_1.unique)(input.evidenceRefs || []),
366
- artifactRefIds: requireArtifactRefs(run, input.artifactRefIds || []),
367
- links
368
- };
369
- for (const conflict of conflicts) {
370
- conflict.status = "conflicting";
371
- conflict.conflictingContextIds = (0, util_1.unique)([...conflict.conflictingContextIds, context.id]);
372
- (0, util_1.touch)(conflict);
373
- }
374
- state.contexts.push(context);
375
- topic.contextIds = (0, util_1.unique)([...topic.contextIds, context.id]);
376
- board.contextIds = (0, util_1.unique)([...board.contextIds, context.id]);
377
- (0, util_1.touch)(topic);
378
- (0, util_1.touch)(board);
379
- const decision = recordCoordinatorDecision(run, {
380
- blackboardId: board.id,
381
- topicId: topic.id,
382
- kind: conflicts.length ? "conflict-resolution" : "context-update",
383
- outcome: conflicts.length ? "conflicting" : "accepted",
384
- reason: conflicts.length
385
- ? `Context ${context.id} conflicts with ${conflicts.map((entry) => entry.id).join(", ")}`
386
- : `Accepted ${input.kind} context ${context.id}`,
387
- subjectIds: [context.id, ...conflicts.map((entry) => entry.id)],
388
- evidenceRefs: context.evidenceRefs,
389
- artifactRefIds: context.artifactRefIds,
390
- author: { kind: "coordinator", id: "cw" },
391
- scope: context.scope,
392
- parentIds: context.parentIds,
393
- tags: ["context", input.kind]
394
- });
395
- context.decisionId = decision.id;
396
- appendBlackboardNode(run, "blackboard-context", context.id, (0, classify_1.statusToNodeStatus)(context.status), `${context.kind}:${context.key}`, (0, paths_1.recordPath)(run, "contexts", context.id), [`${run.id}:blackboard:topic:${topic.id}`]);
397
- const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
398
- kind: "blackboard.context",
399
- decision: conflicts.length ? "failed" : "accepted",
400
- source: (0, classify_1.sourceForAuthor)(context.author),
401
- actor: context.author.id,
402
- blackboardId: board.id,
403
- blackboardTopicId: topic.id,
404
- blackboardContextId: context.id,
405
- coordinatorDecisionId: decision.id,
406
- evidenceRefs: context.evidenceRefs,
407
- multiAgentRunId: context.links.multiAgentRunId,
408
- agentGroupId: context.links.agentGroupId,
409
- agentRoleId: context.links.agentRoleId,
410
- agentMembershipId: context.links.agentMembershipId,
411
- metadata: { kind: context.kind, key: context.key, conflicts: context.conflictingContextIds }
412
- });
413
- const writeAudit = (0, multi_agent_trust_1.recordBlackboardWriteAudit)(run, {
414
- operation: "context",
415
- status: context.status,
416
- actor: context.author,
417
- multiAgentRunId: context.links.multiAgentRunId,
418
- agentGroupId: context.links.agentGroupId,
419
- agentRoleId: context.links.agentRoleId,
420
- agentMembershipId: context.links.agentMembershipId,
421
- blackboardId: board.id,
422
- blackboardTopicId: topic.id,
423
- blackboardContextId: context.id,
424
- coordinatorDecisionId: decision.id,
425
- evidenceRefs: context.evidenceRefs,
426
- parentEventIds: (0, util_1.unique)([...(permission ? [permission.event.id] : []), audit.id]),
427
- policyRef: permission?.policyRef,
428
- metadata: { kind: context.kind, key: context.key, conflicts: context.conflictingContextIds }
429
- });
430
- context.links.auditEventIds = (0, util_1.unique)([...(context.links.auditEventIds || []), audit.id]);
431
- context.links.auditEventIds = (0, util_1.unique)([...(context.links.auditEventIds || []), writeAudit.id]);
432
- persistBlackboardState(run);
433
- return context;
434
- }
435
- function addBlackboardArtifact(run, input) {
436
- if (!input.path && !input.locator)
437
- throw new Error("Blackboard artifact requires --path or --locator");
438
- const state = ensureBlackboardState(run);
439
- const board = resolveBlackboard(run, { id: input.blackboardId });
440
- const topic = input.topicId ? requireTopic(run, input.topicId) : undefined;
441
- if (topic && topic.blackboardId !== board.id)
442
- throw new Error(`Topic ${topic.id} does not belong to blackboard ${board.id}`);
443
- const id = input.id || (0, util_1.createId)("artifact", state.artifacts.length + 1);
444
- (0, util_1.assertUnique)(state.artifacts, id, "BlackboardArtifactRef");
445
- const author = normalizeAuthor(input.author, "operator");
446
- const links = compactLinks(run, { ...board.links, ...(topic?.links || {}), ...roleLinkFromAuthor(author), ...(input.links || {}), evidenceRefs: input.evidenceRefs, auditEventIds: input.auditEventIds });
447
- const permission = shouldEnforcePolicy(author, links)
448
- ? (0, multi_agent_trust_1.assertMultiAgentActionAllowed)(run, {
449
- operation: "artifact",
450
- actor: author,
451
- multiAgentRunId: links.multiAgentRunId,
452
- agentRoleId: links.agentRoleId,
453
- agentGroupId: links.agentGroupId,
454
- agentMembershipId: links.agentMembershipId,
455
- blackboardId: board.id,
456
- blackboardTopicId: topic?.id,
457
- blackboardArtifactRefId: id,
458
- evidenceRefs: input.evidenceRefs || []
459
- })
460
- : undefined;
461
- const absolutePath = input.path ? node_path_1.default.resolve(input.path) : undefined;
462
- const artifact = {
463
- ...base(run, board.id, id, author, input.scope, "active", input.tags, input.metadata),
464
- topicId: topic?.id,
465
- kind: input.kind,
466
- path: absolutePath,
467
- locator: input.locator,
468
- owner: normalizeAuthor(input.owner || input.author, "operator"),
469
- source: input.source || "operator-recorded",
470
- provenance: compactLinks(run, { ...(input.provenance || {}), ...links }),
471
- evidenceRefs: (0, util_1.unique)(input.evidenceRefs || []),
472
- checksum: absolutePath && node_fs_1.default.existsSync(absolutePath) && node_fs_1.default.statSync(absolutePath).isFile() ? (0, util_1.checksumFile)(absolutePath) : undefined,
473
- trustAuditEventIds: (0, util_1.unique)(input.auditEventIds || [])
474
- };
475
- state.artifacts.push(artifact);
476
- board.artifactRefIds = (0, util_1.unique)([...board.artifactRefIds, artifact.id]);
477
- if (topic)
478
- topic.artifactRefIds = (0, util_1.unique)([...topic.artifactRefIds, artifact.id]);
479
- (0, util_1.touch)(board);
480
- if (topic)
481
- (0, util_1.touch)(topic);
482
- const decision = recordCoordinatorDecision(run, {
483
- blackboardId: board.id,
484
- topicId: topic?.id,
485
- kind: "artifact-index",
486
- outcome: "accepted",
487
- reason: `Indexed ${artifact.kind} artifact ${artifact.id}`,
488
- subjectIds: [artifact.id],
489
- evidenceRefs: artifact.evidenceRefs,
490
- artifactRefIds: [artifact.id],
491
- author: { kind: "coordinator", id: "cw" },
492
- scope: artifact.scope,
493
- tags: ["artifact", artifact.kind]
494
- });
495
- appendBlackboardNode(run, "blackboard-artifact", artifact.id, "completed", artifact.kind, (0, paths_1.recordPath)(run, "artifacts", artifact.id), [
496
- topic ? `${run.id}:blackboard:topic:${topic.id}` : `${run.id}:blackboard:${board.id}`
497
- ]);
498
- const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
499
- kind: "blackboard.artifact",
500
- decision: "accepted",
501
- source: (0, classify_1.sourceForAuthor)(artifact.author),
502
- actor: artifact.author.id,
503
- blackboardId: board.id,
504
- blackboardTopicId: topic?.id,
505
- blackboardArtifactRefId: artifact.id,
506
- coordinatorDecisionId: decision.id,
507
- workerId: artifact.provenance.workerId,
508
- taskId: artifact.provenance.taskId,
509
- candidateId: artifact.provenance.candidateId,
510
- commitId: artifact.provenance.commitId,
511
- normalizedPath: absolutePath,
512
- evidenceRefs: artifact.evidenceRefs,
513
- parentEventIds: artifact.trustAuditEventIds,
514
- metadata: { kind: artifact.kind, locator: artifact.locator, checksum: artifact.checksum }
515
- });
516
- const writeAudit = (0, multi_agent_trust_1.recordBlackboardWriteAudit)(run, {
517
- operation: "artifact",
518
- status: artifact.status,
519
- actor: artifact.author,
520
- multiAgentRunId: artifact.provenance.multiAgentRunId,
521
- agentGroupId: artifact.provenance.agentGroupId,
522
- agentRoleId: artifact.provenance.agentRoleId,
523
- agentMembershipId: artifact.provenance.agentMembershipId,
524
- blackboardId: board.id,
525
- blackboardTopicId: topic?.id,
526
- blackboardArtifactRefId: artifact.id,
527
- coordinatorDecisionId: decision.id,
528
- evidenceRefs: artifact.evidenceRefs,
529
- parentEventIds: (0, util_1.unique)([...(permission ? [permission.event.id] : []), audit.id]),
530
- policyRef: permission?.policyRef,
531
- metadata: { kind: artifact.kind, locator: artifact.locator, checksum: artifact.checksum }
532
- });
533
- artifact.trustAuditEventIds = (0, util_1.unique)([...artifact.trustAuditEventIds, audit.id, writeAudit.id]);
534
- persistBlackboardState(run);
535
- return artifact;
536
- }
537
- function createBlackboardSnapshot(run, blackboardId) {
538
- const state = ensureBlackboardState(run);
539
- const board = resolveBlackboard(run, { id: blackboardId });
540
- const id = (0, util_1.createId)("snapshot", state.snapshots.length + 1);
541
- const snapshotPath = (0, paths_1.recordPath)(run, "snapshots", id);
542
- const summary = summarizeBlackboard(run, board.id);
543
- const snapshot = {
544
- ...base(run, board.id, id, { kind: "runtime", id: "cw" }, { kind: "run", id: run.id }, "active", ["snapshot"], undefined),
545
- topicIds: [...board.topicIds].sort(),
546
- messageIds: state.messages.filter((entry) => entry.blackboardId === board.id).map((entry) => entry.id).sort(),
547
- contextIds: [...board.contextIds].sort(),
548
- artifactRefIds: [...board.artifactRefIds].sort(),
549
- decisionIds: [...board.decisionIds].sort(),
550
- snapshotPath,
551
- indexPath: board.paths.index,
552
- summary,
553
- links: compactLinks(run, board.links)
554
- };
555
- state.snapshots.push(snapshot);
556
- board.snapshotIds = (0, util_1.unique)([...board.snapshotIds, snapshot.id]);
557
- (0, util_1.touch)(board);
558
- appendBlackboardNode(run, "blackboard-snapshot", snapshot.id, "completed", snapshot.id, snapshotPath, [`${run.id}:blackboard:${board.id}`]);
559
- const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
560
- kind: "blackboard.snapshot",
561
- decision: "recorded",
562
- source: "runtime-derived",
563
- actor: "cw",
564
- blackboardId: board.id,
565
- blackboardSnapshotId: snapshot.id,
566
- metadata: { snapshotPath, counts: summary }
567
- });
568
- const writeAudit = (0, multi_agent_trust_1.recordBlackboardWriteAudit)(run, {
569
- operation: "snapshot",
570
- status: snapshot.status,
571
- actor: snapshot.author,
572
- multiAgentRunId: snapshot.links.multiAgentRunId,
573
- agentGroupId: snapshot.links.agentGroupId,
574
- agentRoleId: snapshot.links.agentRoleId,
575
- agentMembershipId: snapshot.links.agentMembershipId,
576
- blackboardId: board.id,
577
- blackboardSnapshotId: snapshot.id,
578
- parentEventIds: [audit.id],
579
- metadata: { snapshotPath }
580
- });
581
- snapshot.links.auditEventIds = [audit.id];
582
- snapshot.links.auditEventIds = (0, util_1.unique)([...snapshot.links.auditEventIds, writeAudit.id]);
583
- persistBlackboardState(run);
584
- return snapshot;
585
- }
586
- function recordCoordinatorDecision(run, input) {
587
- const state = ensureBlackboardState(run);
588
- const board = resolveBlackboard(run, { id: input.blackboardId });
589
- const id = input.id || (0, util_1.createId)("decision", state.decisions.length + 1);
590
- (0, util_1.assertUnique)(state.decisions, id, "CoordinatorDecision");
591
- const decision = {
592
- ...base(run, board.id, id, input.author || { kind: "coordinator", id: "cw" }, input.scope, (0, classify_1.decisionStatus)(input.outcome), input.tags, input.metadata),
593
- kind: input.kind,
594
- outcome: input.outcome,
595
- subjectIds: (0, util_1.unique)(input.subjectIds || []),
596
- reason: input.reason,
597
- evidenceRefs: (0, util_1.unique)(input.evidenceRefs || []),
598
- artifactRefIds: requireArtifactRefs(run, input.artifactRefIds || []),
599
- messageIds: requireMessages(run, input.messageIds || []),
600
- links: compactLinks(run, { ...board.links, ...roleLinkFromAuthor(input.author), ...(input.links || {}), evidenceRefs: input.evidenceRefs })
601
- };
602
- state.decisions.push(decision);
603
- board.decisionIds = (0, util_1.unique)([...board.decisionIds, decision.id]);
604
- (0, util_1.touch)(board);
605
- appendBlackboardNode(run, "coordinator-decision", decision.id, (0, classify_1.statusToNodeStatus)(decision.status), `${decision.kind}:${decision.outcome}`, (0, paths_1.recordPath)(run, "decisions", decision.id), [
606
- `${run.id}:blackboard:${board.id}`,
607
- ...(input.topicId ? [`${run.id}:blackboard:topic:${input.topicId}`] : [])
608
- ]);
609
- const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
610
- kind: "coordinator.decision",
611
- decision: (0, classify_1.auditDecision)(input.outcome),
612
- source: "cw-validated",
613
- actor: decision.author.id,
614
- blackboardId: board.id,
615
- blackboardTopicId: input.topicId,
616
- coordinatorDecisionId: decision.id,
617
- multiAgentRunId: decision.links.multiAgentRunId,
618
- agentGroupId: decision.links.agentGroupId,
619
- agentRoleId: decision.links.agentRoleId,
620
- agentMembershipId: decision.links.agentMembershipId,
621
- evidenceRefs: decision.evidenceRefs,
622
- metadata: {
623
- kind: decision.kind,
624
- outcome: decision.outcome,
625
- subjectIds: decision.subjectIds,
626
- reason: decision.reason
627
- }
628
- });
629
- const writeAudit = (0, multi_agent_trust_1.recordBlackboardWriteAudit)(run, {
630
- operation: "coordinator-decision",
631
- status: decision.status,
632
- actor: decision.author,
633
- multiAgentRunId: decision.links.multiAgentRunId,
634
- agentGroupId: decision.links.agentGroupId,
635
- agentRoleId: decision.links.agentRoleId,
636
- agentMembershipId: decision.links.agentMembershipId,
637
- blackboardId: board.id,
638
- blackboardTopicId: input.topicId,
639
- coordinatorDecisionId: decision.id,
640
- evidenceRefs: decision.evidenceRefs,
641
- parentEventIds: [audit.id],
642
- metadata: { kind: decision.kind, outcome: decision.outcome }
643
- });
644
- if (decision.kind === "candidate-synthesis" || decision.tags.includes("panel-decision")) {
645
- const panelAudit = (0, multi_agent_trust_1.recordJudgeRationaleAudit)(run, {
646
- kind: "judge.panel-decision",
647
- actor: decision.author,
648
- multiAgentRunId: decision.links.multiAgentRunId,
649
- agentGroupId: decision.links.agentGroupId,
650
- agentRoleId: decision.links.agentRoleId,
651
- agentMembershipId: decision.links.agentMembershipId,
652
- blackboardId: board.id,
653
- blackboardTopicId: input.topicId,
654
- coordinatorDecisionId: decision.id,
655
- evidenceRefs: decision.evidenceRefs,
656
- rationale: decision.reason,
657
- parentEventIds: [audit.id, writeAudit.id]
658
- });
659
- decision.links.auditEventIds = (0, util_1.unique)([...(decision.links.auditEventIds || []), panelAudit.id]);
660
- }
661
- decision.links.auditEventIds = (0, util_1.unique)([...(decision.links.auditEventIds || []), audit.id, writeAudit.id]);
662
- persistBlackboardState(run);
663
- return decision;
664
- }
665
- function summarizeBlackboard(run, blackboardId) {
666
- const state = ensureBlackboardState(run);
667
- const board = blackboardId ? state.boards.find((entry) => entry.id === blackboardId) : state.boards[0];
668
- const scoped = (items) => board ? items.filter((item) => item.blackboardId === board.id) : [];
669
- const contexts = scoped(state.contexts);
670
- const artifacts = scoped(state.artifacts);
671
- const openQuestions = contexts.filter((context) => context.kind === "question" && context.status === "open");
672
- const conflicts = contexts.filter((context) => context.status === "conflicting" || context.conflictingContextIds.length);
673
- const missingEvidence = [
674
- ...openQuestions.filter((context) => !context.evidenceRefs.length && !context.artifactRefIds.length).map((context) => `question ${context.id} has no indexed evidence`),
675
- ...contexts.filter((context) => context.kind !== "question" && context.status !== "superseded" && !context.evidenceRefs.length && !context.artifactRefIds.length).map((context) => `context ${context.id} has no indexed evidence`)
676
- ].sort();
677
- const readyForFanin = Boolean(board && !openQuestions.length && !conflicts.length && artifacts.length > 0 && missingEvidence.length === 0);
678
- const latestSnapshot = scoped(state.snapshots).sort((left, right) => left.createdAt.localeCompare(right.createdAt)).at(-1);
679
- return {
680
- runId: run.id,
681
- blackboardId: board?.id,
682
- topics: scoped(state.topics).length,
683
- messages: scoped(state.messages).length,
684
- contexts: contexts.length,
685
- artifacts: artifacts.length,
686
- snapshots: scoped(state.snapshots).length,
687
- decisions: scoped(state.decisions).length,
688
- openQuestions,
689
- conflicts,
690
- missingEvidence,
691
- readyForFanin,
692
- latestSnapshotPath: latestSnapshot?.snapshotPath,
693
- indexPath: board?.paths.index || node_path_1.default.join((0, paths_1.blackboardRoot)(run), "index.json"),
694
- nextAction: nextAction(run, board, openQuestions, conflicts, artifacts)
695
- };
696
- }
697
- function listBlackboardMessages(run, options = {}) {
698
- const state = ensureBlackboardState(run);
699
- return state.messages
700
- .filter((message) => (!options.blackboardId || message.blackboardId === options.blackboardId) && (!options.topicId || message.topicId === options.topicId))
701
- .sort((left, right) => left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id));
702
- }
703
- function listBlackboardArtifacts(run, options = {}) {
704
- const state = ensureBlackboardState(run);
705
- return state.artifacts
706
- .filter((artifact) => (!options.blackboardId || artifact.blackboardId === options.blackboardId) && (!options.topicId || artifact.topicId === options.topicId))
707
- .sort((left, right) => left.id.localeCompare(right.id));
708
- }
709
- function buildBlackboardGraph(run) {
710
- const state = ensureBlackboardState(run);
711
- const nodes = [];
712
- const edges = [];
713
- for (const board of state.boards) {
714
- nodes.push({ id: `${run.id}:blackboard:${board.id}`, kind: "blackboard", status: board.status, label: board.title, path: board.paths.index });
715
- edges.push({ from: `${run.id}:run`, to: `${run.id}:blackboard:${board.id}` });
716
- if (board.links.multiAgentRunId)
717
- edges.push({ from: `${run.id}:multi-agent:${board.links.multiAgentRunId}`, to: `${run.id}:blackboard:${board.id}`, label: "coordinates" });
718
- }
719
- for (const topic of state.topics) {
720
- nodes.push({ id: `${run.id}:blackboard:topic:${topic.id}`, kind: "blackboard-topic", status: topic.status, label: topic.title, path: (0, paths_1.recordPath)(run, "topics", topic.id) });
721
- edges.push({ from: `${run.id}:blackboard:${topic.blackboardId}`, to: `${run.id}:blackboard:topic:${topic.id}` });
722
- }
723
- for (const context of state.contexts) {
724
- nodes.push({ id: `${run.id}:blackboard:context:${context.id}`, kind: "blackboard-context", status: context.status, label: `${context.kind}:${context.key}`, path: (0, paths_1.recordPath)(run, "contexts", context.id) });
725
- edges.push({ from: `${run.id}:blackboard:topic:${context.topicId}`, to: `${run.id}:blackboard:context:${context.id}` });
726
- for (const conflicting of context.conflictingContextIds)
727
- edges.push({ from: `${run.id}:blackboard:context:${context.id}`, to: `${run.id}:blackboard:context:${conflicting}`, label: "conflicts" });
728
- }
729
- for (const artifact of state.artifacts) {
730
- nodes.push({ id: `${run.id}:blackboard:artifact:${artifact.id}`, kind: "blackboard-artifact", status: artifact.status, label: artifact.kind, path: (0, paths_1.recordPath)(run, "artifacts", artifact.id) });
731
- edges.push({ from: artifact.topicId ? `${run.id}:blackboard:topic:${artifact.topicId}` : `${run.id}:blackboard:${artifact.blackboardId}`, to: `${run.id}:blackboard:artifact:${artifact.id}` });
732
- }
733
- for (const message of state.messages) {
734
- nodes.push({ id: `${run.id}:blackboard:message:${message.id}`, kind: "blackboard-message", status: message.status, label: (0, util_1.truncate)(message.body), path: (0, paths_1.messagesPath)(run) });
735
- edges.push({ from: `${run.id}:blackboard:topic:${message.topicId}`, to: `${run.id}:blackboard:message:${message.id}` });
736
- if (message.replyToId)
737
- edges.push({ from: `${run.id}:blackboard:message:${message.replyToId}`, to: `${run.id}:blackboard:message:${message.id}`, label: "reply" });
738
- for (const artifactId of message.linkedArtifactRefIds)
739
- edges.push({ from: `${run.id}:blackboard:message:${message.id}`, to: `${run.id}:blackboard:artifact:${artifactId}`, label: "cites" });
740
- }
741
- for (const decision of state.decisions) {
742
- nodes.push({ id: `${run.id}:coordinator:decision:${decision.id}`, kind: "coordinator-decision", status: decision.status, label: `${decision.kind}:${decision.outcome}`, path: (0, paths_1.recordPath)(run, "decisions", decision.id) });
743
- edges.push({ from: `${run.id}:blackboard:${decision.blackboardId}`, to: `${run.id}:coordinator:decision:${decision.id}` });
744
- for (const subjectId of decision.subjectIds)
745
- edges.push({ from: `${run.id}:coordinator:decision:${decision.id}`, to: graphSubject(run, subjectId), label: "subject" });
746
- }
747
- for (const snapshot of state.snapshots) {
748
- nodes.push({ id: `${run.id}:blackboard:snapshot:${snapshot.id}`, kind: "blackboard-snapshot", status: snapshot.status, label: snapshot.id, path: snapshot.snapshotPath });
749
- edges.push({ from: `${run.id}:blackboard:${snapshot.blackboardId}`, to: `${run.id}:blackboard:snapshot:${snapshot.id}` });
750
- }
751
- return { nodes, edges: (0, util_1.uniqueEdges)(edges) };
752
- }
753
- function persistBlackboardState(run) {
754
- const state = ensureBlackboardState(run);
755
- const root = (0, paths_1.blackboardRoot)(run);
756
- (0, util_1.assertNoRecordPathCollisions)("BlackboardTopic", state.topics);
757
- (0, util_1.assertNoRecordPathCollisions)("BlackboardContext", state.contexts);
758
- (0, util_1.assertNoRecordPathCollisions)("BlackboardArtifactRef", state.artifacts);
759
- (0, util_1.assertNoRecordPathCollisions)("BlackboardSnapshot", state.snapshots);
760
- (0, util_1.assertNoRecordPathCollisions)("CoordinatorDecision", state.decisions);
761
- const index = {
762
- schemaVersion: exports.BLACKBOARD_SCHEMA_VERSION,
763
- runId: run.id,
764
- generatedAt: (0, util_1.timestamp)(),
765
- counts: {
766
- boards: state.boards.length,
767
- topics: state.topics.length,
768
- messages: state.messages.length,
769
- contexts: state.contexts.length,
770
- artifacts: state.artifacts.length,
771
- snapshots: state.snapshots.length,
772
- decisions: state.decisions.length
773
- },
774
- boards: state.boards.map(util_1.indexRow),
775
- topics: state.topics.map(util_1.indexRow),
776
- contexts: state.contexts.map(util_1.indexRow),
777
- artifacts: state.artifacts.map(util_1.indexRow),
778
- snapshots: state.snapshots.map(util_1.indexRow),
779
- decisions: state.decisions.map(util_1.indexRow),
780
- messages: state.messages.map((message) => ({
781
- id: message.id,
782
- blackboardId: message.blackboardId,
783
- topicId: message.topicId,
784
- createdAt: message.createdAt,
785
- status: message.status,
786
- author: message.author,
787
- evidenceRefs: message.linkedEvidenceRefs,
788
- artifactRefIds: message.linkedArtifactRefIds
789
- }))
790
- };
791
- (0, state_1.writeJson)(node_path_1.default.join(root, "index.json"), index);
792
- node_fs_1.default.writeFileSync((0, paths_1.messagesPath)(run), state.messages.sort(util_1.compareRecords).map((message) => JSON.stringify(message)).join("\n") + (state.messages.length ? "\n" : ""), "utf8");
793
- for (const topic of state.topics)
794
- (0, state_1.writeJson)((0, paths_1.recordPath)(run, "topics", topic.id), topic);
795
- for (const context of state.contexts)
796
- (0, state_1.writeJson)((0, paths_1.recordPath)(run, "contexts", context.id), context);
797
- for (const artifact of state.artifacts)
798
- (0, state_1.writeJson)((0, paths_1.recordPath)(run, "artifacts", artifact.id), artifact);
799
- for (const snapshot of state.snapshots)
800
- (0, state_1.writeJson)((0, paths_1.recordPath)(run, "snapshots", snapshot.id), snapshot);
801
- for (const decision of state.decisions)
802
- (0, state_1.writeJson)((0, paths_1.recordPath)(run, "decisions", decision.id), decision);
803
- }
804
- function emptyState() {
805
- return {
806
- schemaVersion: exports.BLACKBOARD_SCHEMA_VERSION,
807
- boards: [],
808
- topics: [],
809
- messages: [],
810
- contexts: [],
811
- artifacts: [],
812
- snapshots: [],
813
- decisions: []
814
- };
815
- }
816
- function roleLinkFromAuthor(author) {
817
- if (!author?.id)
818
- return {};
819
- if (author.kind === "role")
820
- return { agentRoleId: author.id };
821
- if (author.kind === "group")
822
- return { agentGroupId: author.id };
823
- if (author.kind === "membership")
824
- return { agentMembershipId: author.id };
825
- if (author.kind === "worker")
826
- return { workerId: author.id };
827
- return {};
828
- }
829
- function shouldEnforcePolicy(author, links) {
830
- if (author.kind === "role" || author.kind === "group" || author.kind === "membership" || author.kind === "worker")
831
- return true;
832
- return Boolean(links.agentRoleId || links.agentGroupId || links.agentMembershipId);
833
- }
834
- function base(run, blackboardId, id, author, scope, status = "active", tags, metadata) {
835
- const now = (0, util_1.timestamp)();
836
- return {
837
- schemaVersion: exports.BLACKBOARD_SCHEMA_VERSION,
838
- id,
839
- runId: run.id,
840
- blackboardId,
841
- createdAt: now,
842
- updatedAt: now,
843
- author: normalizeAuthor(author, "operator"),
844
- scope: normalizeScope(scope, { kind: "run", id: run.id }),
845
- status,
846
- parentIds: [],
847
- tags: (0, util_1.sortTags)(tags),
848
- metadata: (0, util_1.scrub)(metadata)
849
- };
850
- }
851
- function normalizeAuthor(input, fallbackKind) {
852
- const kind = input?.kind || fallbackKind;
853
- const id = input?.id || (kind === "runtime" || kind === "coordinator" ? "cw" : kind === "operator" ? "operator" : undefined);
854
- if (!id)
855
- throw new Error("Blackboard author requires an explicit id");
856
- return { kind, id, displayName: input?.displayName };
857
- }
858
- function normalizeScope(input, fallback) {
859
- const kind = input?.kind || fallback.kind;
860
- const id = input?.id || fallback.id;
861
- if (!kind || !id)
862
- throw new Error("Blackboard scope requires kind and id");
863
- return { kind, id };
864
- }
865
- function compactLinks(run, input) {
866
- return (0, util_1.compact)({
867
- workflowRunId: run.id,
868
- multiAgentRunId: input.multiAgentRunId,
869
- agentGroupId: input.agentGroupId,
870
- agentRoleId: input.agentRoleId,
871
- agentMembershipId: input.agentMembershipId,
872
- agentFanoutId: input.agentFanoutId,
873
- agentFaninId: input.agentFaninId,
874
- taskId: input.taskId,
875
- workerId: input.workerId,
876
- candidateId: input.candidateId,
877
- verifierNodeId: input.verifierNodeId,
878
- commitId: input.commitId,
879
- auditEventIds: (0, util_1.unique)(input.auditEventIds || []),
880
- evidenceRefs: (0, util_1.unique)(input.evidenceRefs || [])
881
- });
882
- }
883
- function linkMultiAgent(run, blackboardId, topicIds, input) {
884
- const groupId = "agentGroupId" in input ? input.agentGroupId : ("groupId" in input ? input.groupId : undefined);
885
- const roleId = "agentRoleId" in input ? input.agentRoleId : ("roleId" in input ? input.roleId : undefined);
886
- const membershipId = "agentMembershipId" in input ? input.agentMembershipId : ("membershipId" in input ? input.membershipId : undefined);
887
- if (input.multiAgentRunId) {
888
- const record = (0, multi_agent_1.getMultiAgentRun)(run, input.multiAgentRunId);
889
- if (record) {
890
- record.blackboardId = blackboardId;
891
- record.topicIds = (0, util_1.unique)([...(record.topicIds || []), ...topicIds]);
892
- record.links.blackboardId = blackboardId;
893
- record.links.blackboardTopicIds = (0, util_1.unique)([...(record.links.blackboardTopicIds || []), ...topicIds]);
894
- }
895
- }
896
- if (groupId) {
897
- const record = (0, multi_agent_1.getAgentGroup)(run, groupId);
898
- if (record) {
899
- record.blackboardId = blackboardId;
900
- record.topicIds = (0, util_1.unique)([...(record.topicIds || []), ...topicIds]);
901
- }
902
- }
903
- if (roleId) {
904
- const record = (0, multi_agent_1.getAgentRole)(run, roleId);
905
- if (record) {
906
- record.blackboardId = blackboardId;
907
- record.topicIds = (0, util_1.unique)([...(record.topicIds || []), ...topicIds]);
908
- }
909
- }
910
- if (membershipId) {
911
- const record = (0, multi_agent_1.getAgentMembership)(run, membershipId);
912
- if (record) {
913
- record.blackboardId = blackboardId;
914
- record.topicIds = (0, util_1.unique)([...(record.topicIds || []), ...topicIds]);
915
- }
916
- }
917
- }
918
- function requireBoard(run, id) {
919
- const board = ensureBlackboardState(run).boards.find((entry) => entry.id === id);
920
- if (!board)
921
- throw new Error(`Unknown Blackboard id: ${id}`);
922
- return board;
923
- }
924
- function requireTopic(run, id) {
925
- const topic = ensureBlackboardState(run).topics.find((entry) => entry.id === id);
926
- if (!topic)
927
- throw new Error(`Unknown BlackboardTopic id: ${id}`);
928
- return topic;
929
- }
930
- function requireContext(run, id) {
931
- const context = ensureBlackboardState(run).contexts.find((entry) => entry.id === id);
932
- if (!context)
933
- throw new Error(`Unknown BlackboardContext id: ${id}`);
934
- return context;
935
- }
936
- function requireArtifactRefs(run, ids) {
937
- const state = ensureBlackboardState(run);
938
- for (const id of ids) {
939
- if (!state.artifacts.some((artifact) => artifact.id === id))
940
- throw new Error(`Unknown BlackboardArtifactRef id: ${id}`);
941
- }
942
- return (0, util_1.unique)(ids);
943
- }
944
- function requireMessages(run, ids) {
945
- const state = ensureBlackboardState(run);
946
- for (const id of ids) {
947
- if (!state.messages.some((message) => message.id === id))
948
- throw new Error(`Unknown BlackboardMessage id: ${id}`);
949
- }
950
- return (0, util_1.unique)(ids);
951
- }
952
- function appendBlackboardNode(run, kind, id, status, label, artifactPath, parents = []) {
953
- const nodeId = kind === "blackboard"
954
- ? `${run.id}:blackboard:${id}`
955
- : kind === "coordinator-decision"
956
- ? `${run.id}:coordinator:decision:${id}`
957
- : `${run.id}:blackboard:${kind.replace("blackboard-", "")}:${id}`;
958
- (0, state_node_1.appendRunNode)(run, (0, state_node_1.createStateNode)({
959
- id: nodeId,
960
- kind,
961
- status,
962
- loopStage: run.loopStage,
963
- outputs: { id, label },
964
- artifacts: [{ id: kind, kind: "json", path: artifactPath }],
965
- parents,
966
- contractId: pipeline_contract_1.DEFAULT_PIPELINE_CONTRACT_ID,
967
- metadata: { id, label }
968
- }));
969
- }
970
- function graphSubject(run, id) {
971
- const state = ensureBlackboardState(run);
972
- if (state.contexts.some((entry) => entry.id === id))
973
- return `${run.id}:blackboard:context:${id}`;
974
- if (state.artifacts.some((entry) => entry.id === id))
975
- return `${run.id}:blackboard:artifact:${id}`;
976
- if (state.messages.some((entry) => entry.id === id))
977
- return `${run.id}:blackboard:message:${id}`;
978
- return id;
979
- }
980
- function nextAction(run, board, openQuestions, conflicts, artifacts) {
981
- if (!board)
982
- return `node scripts/cw.js blackboard topic create ${run.id} --id <topic-id> --title "<title>"`;
983
- if (conflicts.length)
984
- return `node scripts/cw.js coordinator decision ${run.id} --kind conflict-resolution --outcome accepted --subject ${conflicts[0].id} --reason "<reason>"`;
985
- if (openQuestions.length)
986
- return `node scripts/cw.js blackboard message post ${run.id} --topic ${openQuestions[0].topicId} --body "<answer with evidence>"`;
987
- if (!artifacts.length)
988
- return `node scripts/cw.js blackboard artifact add ${run.id} --path <path> --kind <kind>`;
989
- return `node scripts/cw.js blackboard snapshot ${run.id}`;
990
- }