cool-workflow 0.1.80 → 0.1.81
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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +42 -2
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- package/apps/end-to-end-golden-path/app.json +1 -1
- package/apps/pr-review-fix-ci/app.json +1 -1
- package/apps/release-cut/app.json +1 -1
- package/apps/research-synthesis/app.json +1 -1
- package/dist/agent-config.js +21 -7
- package/dist/candidate-scoring.js +42 -22
- package/dist/capability-core.js +94 -17
- package/dist/capability-registry.js +138 -171
- package/dist/cli.js +90 -100
- package/dist/collaboration.js +5 -6
- package/dist/commit.js +20 -6
- package/dist/compare.js +18 -0
- package/dist/coordinator/classify.js +45 -0
- package/dist/coordinator/paths.js +42 -0
- package/dist/coordinator/util.js +129 -0
- package/dist/coordinator.js +127 -300
- package/dist/dispatch.js +35 -0
- package/dist/drive.js +7 -7
- package/dist/error-feedback.js +8 -4
- package/dist/evidence-reasoning.js +1 -1
- package/dist/execution-backend/agent.js +331 -0
- package/dist/execution-backend/probes.js +96 -0
- package/dist/execution-backend/util.js +47 -0
- package/dist/execution-backend.js +67 -420
- package/dist/mcp-server.js +34 -173
- package/dist/multi-agent/graph.js +84 -0
- package/dist/multi-agent/helpers.js +145 -0
- package/dist/multi-agent/paths.js +22 -0
- package/dist/multi-agent-eval/format.js +194 -0
- package/dist/multi-agent-eval/normalize.js +51 -0
- package/dist/multi-agent-eval.js +39 -244
- package/dist/multi-agent-host.js +0 -19
- package/dist/multi-agent.js +125 -314
- package/dist/node-snapshot.js +3 -3
- package/dist/observability/format.js +61 -0
- package/dist/observability/intake.js +98 -0
- package/dist/observability.js +14 -160
- package/dist/operator-ux/format.js +364 -0
- package/dist/operator-ux.js +22 -363
- package/dist/orchestrator/report.js +8 -0
- package/dist/orchestrator.js +25 -8
- package/dist/reclamation.js +26 -21
- package/dist/run-export.js +138 -14
- package/dist/run-registry/derive.js +172 -0
- package/dist/run-registry/format.js +124 -0
- package/dist/run-registry/gc.js +251 -0
- package/dist/run-registry/policy.js +16 -0
- package/dist/run-registry/queue.js +116 -0
- package/dist/run-registry.js +78 -593
- package/dist/run-state-schema.js +1 -0
- package/dist/sandbox-profile.js +43 -2
- package/dist/state-explosion/format.js +159 -0
- package/dist/state-explosion/helpers.js +82 -0
- package/dist/state-explosion.js +65 -283
- package/dist/state-node.js +19 -4
- package/dist/telemetry-attestation.js +55 -0
- package/dist/telemetry-demo.js +15 -3
- package/dist/telemetry-ledger.js +60 -15
- package/dist/topology.js +25 -8
- package/dist/triggers.js +33 -14
- package/dist/trust-audit.js +145 -33
- package/dist/version.js +1 -1
- package/dist/worker-isolation/helpers.js +51 -0
- package/dist/worker-isolation/paths.js +46 -0
- package/dist/worker-isolation.js +39 -115
- package/docs/agent-delegation-drive.7.md +13 -0
- package/docs/cli-mcp-parity.7.md +4 -0
- package/docs/contract-migration-tooling.7.md +2 -0
- package/docs/control-plane-scheduling.7.md +2 -0
- package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +40 -0
- package/docs/durable-state-and-locking.7.md +4 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
- package/docs/execution-backends.7.md +2 -0
- package/docs/index.md +1 -0
- package/docs/launch/launch-kit.md +46 -23
- package/docs/launch/pre-launch-checklist.md +14 -14
- package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
- package/docs/multi-agent-eval-replay-harness.7.md +2 -0
- package/docs/multi-agent-operator-ux.7.md +2 -0
- package/docs/multi-agent-trust-policy-audit.7.md +27 -0
- package/docs/node-snapshot-diff-replay.7.md +2 -0
- package/docs/observability-cost-accounting.7.md +2 -0
- package/docs/project-index.md +18 -5
- package/docs/real-execution-backends.7.md +2 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +2 -0
- package/docs/run-registry-control-plane.7.md +54 -8
- package/docs/run-retention-reclamation.7.md +4 -0
- package/docs/state-explosion-management.7.md +2 -0
- package/docs/team-collaboration.7.md +2 -0
- package/docs/trust-model.md +267 -0
- package/docs/vendor-manifest-loadability.7.md +43 -0
- package/docs/web-desktop-workbench.7.md +2 -0
- package/manifest/plugin.manifest.json +1 -1
- package/package.json +4 -2
- package/scripts/agents/builtin-templates.json +7 -0
- package/scripts/bump-version.js +5 -11
- package/scripts/canonical-apps-list.js +64 -0
- package/scripts/canonical-apps.js +19 -4
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/parity-check.js +5 -0
- package/scripts/release-check.js +5 -1
- package/scripts/version-sync-check.js +5 -8
- package/dist/capability-dispatcher.js +0 -86
package/dist/coordinator.js
CHANGED
|
@@ -17,9 +17,6 @@ exports.listBlackboardMessages = listBlackboardMessages;
|
|
|
17
17
|
exports.listBlackboardArtifacts = listBlackboardArtifacts;
|
|
18
18
|
exports.buildBlackboardGraph = buildBlackboardGraph;
|
|
19
19
|
exports.persistBlackboardState = persistBlackboardState;
|
|
20
|
-
exports.bridgeStateArtifactToBlackboard = bridgeStateArtifactToBlackboard;
|
|
21
|
-
exports.evidenceFromArtifactRef = evidenceFromArtifactRef;
|
|
22
|
-
const node_crypto_1 = __importDefault(require("node:crypto"));
|
|
23
20
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
24
21
|
const node_path_1 = __importDefault(require("node:path"));
|
|
25
22
|
const pipeline_contract_1 = require("./pipeline-contract");
|
|
@@ -28,9 +25,19 @@ const state_node_1 = require("./state-node");
|
|
|
28
25
|
const multi_agent_1 = require("./multi-agent");
|
|
29
26
|
const trust_audit_1 = require("./trust-audit");
|
|
30
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.
|
|
31
38
|
exports.BLACKBOARD_SCHEMA_VERSION = 1;
|
|
32
39
|
function ensureBlackboardState(run) {
|
|
33
|
-
run.paths.blackboardDir = blackboardRoot(run);
|
|
40
|
+
run.paths.blackboardDir = (0, paths_1.blackboardRoot)(run);
|
|
34
41
|
node_fs_1.default.mkdirSync(run.paths.blackboardDir, { recursive: true });
|
|
35
42
|
for (const dir of ["topics", "contexts", "artifacts", "snapshots", "decisions"]) {
|
|
36
43
|
node_fs_1.default.mkdirSync(node_path_1.default.join(run.paths.blackboardDir, dir), { recursive: true });
|
|
@@ -57,13 +64,13 @@ function resolveBlackboard(run, input = {}) {
|
|
|
57
64
|
: state.boards[0];
|
|
58
65
|
if (existing) {
|
|
59
66
|
linkMultiAgent(run, existing.id, existing.topicIds, input);
|
|
60
|
-
touch(existing);
|
|
67
|
+
(0, util_1.touch)(existing);
|
|
61
68
|
persistBlackboardState(run);
|
|
62
69
|
return existing;
|
|
63
70
|
}
|
|
64
|
-
const id = input.id || createId("bb");
|
|
65
|
-
assertUnique(state.boards, id, "Blackboard");
|
|
66
|
-
const now = timestamp();
|
|
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)();
|
|
67
74
|
const author = normalizeAuthor(input.author, "runtime");
|
|
68
75
|
const scope = normalizeScope(input.scope, input.multiAgentRunId ? { kind: "multi-agent-run", id: input.multiAgentRunId } : { kind: "run", id: run.id });
|
|
69
76
|
const board = {
|
|
@@ -76,7 +83,7 @@ function resolveBlackboard(run, input = {}) {
|
|
|
76
83
|
scope,
|
|
77
84
|
status: "active",
|
|
78
85
|
parentIds: [],
|
|
79
|
-
tags: sortTags(input.tags),
|
|
86
|
+
tags: (0, util_1.sortTags)(input.tags),
|
|
80
87
|
title: input.title || id,
|
|
81
88
|
topicIds: [],
|
|
82
89
|
messageCount: 0,
|
|
@@ -90,8 +97,8 @@ function resolveBlackboard(run, input = {}) {
|
|
|
90
97
|
agentRoleId: input.roleId,
|
|
91
98
|
agentMembershipId: input.membershipId
|
|
92
99
|
}),
|
|
93
|
-
paths: boardPaths(run),
|
|
94
|
-
metadata: scrub(input.metadata)
|
|
100
|
+
paths: (0, paths_1.boardPaths)(run),
|
|
101
|
+
metadata: (0, util_1.scrub)(input.metadata)
|
|
95
102
|
};
|
|
96
103
|
linkMultiAgent(run, board.id, [], input);
|
|
97
104
|
state.boards.push(board);
|
|
@@ -115,10 +122,10 @@ function resolveBlackboard(run, input = {}) {
|
|
|
115
122
|
function createBlackboardTopic(run, input) {
|
|
116
123
|
const board = resolveBlackboard(run, { id: input.blackboardId });
|
|
117
124
|
const state = ensureBlackboardState(run);
|
|
118
|
-
const id = input.id || createId("topic");
|
|
119
|
-
assertUnique(state.topics, id, "BlackboardTopic");
|
|
125
|
+
const id = input.id || (0, util_1.createId)("topic", state.topics.length + 1);
|
|
126
|
+
(0, util_1.assertUnique)(state.topics, id, "BlackboardTopic");
|
|
120
127
|
const topicLinks = compactLinks(run, { ...board.links, ...roleLinkFromAuthor(input.author), ...input.scope });
|
|
121
|
-
const now = timestamp();
|
|
128
|
+
const now = (0, util_1.timestamp)();
|
|
122
129
|
const topic = {
|
|
123
130
|
...base(run, board.id, id, input.author, input.scope, "open", input.tags, input.metadata),
|
|
124
131
|
createdAt: now,
|
|
@@ -131,10 +138,10 @@ function createBlackboardTopic(run, input) {
|
|
|
131
138
|
links: topicLinks
|
|
132
139
|
};
|
|
133
140
|
state.topics.push(topic);
|
|
134
|
-
board.topicIds = unique([...board.topicIds, topic.id]);
|
|
135
|
-
touch(board);
|
|
141
|
+
board.topicIds = (0, util_1.unique)([...board.topicIds, topic.id]);
|
|
142
|
+
(0, util_1.touch)(board);
|
|
136
143
|
linkMultiAgent(run, board.id, [topic.id], board.links);
|
|
137
|
-
appendBlackboardNode(run, "blackboard-topic", topic.id, "running", topic.title, recordPath(run, "topics", topic.id), [`${run.id}:blackboard:${board.id}`]);
|
|
144
|
+
appendBlackboardNode(run, "blackboard-topic", topic.id, "running", topic.title, (0, paths_1.recordPath)(run, "topics", topic.id), [`${run.id}:blackboard:${board.id}`]);
|
|
138
145
|
const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
139
146
|
kind: "blackboard.topic",
|
|
140
147
|
decision: "recorded",
|
|
@@ -148,7 +155,7 @@ function createBlackboardTopic(run, input) {
|
|
|
148
155
|
agentMembershipId: topic.links.agentMembershipId,
|
|
149
156
|
metadata: { title: topic.title, tags: topic.tags }
|
|
150
157
|
});
|
|
151
|
-
topic.links.auditEventIds = unique([...(topic.links.auditEventIds || []), audit.id]);
|
|
158
|
+
topic.links.auditEventIds = (0, util_1.unique)([...(topic.links.auditEventIds || []), audit.id]);
|
|
152
159
|
(0, multi_agent_trust_1.recordBlackboardWriteAudit)(run, {
|
|
153
160
|
operation: "topic",
|
|
154
161
|
status: topic.status,
|
|
@@ -174,8 +181,8 @@ function postBlackboardMessage(run, input) {
|
|
|
174
181
|
}
|
|
175
182
|
if (!input.body.trim())
|
|
176
183
|
throw new Error("Blackboard message body is required");
|
|
177
|
-
const id = input.id || createId("msg");
|
|
178
|
-
assertUnique(state.messages, id, "BlackboardMessage");
|
|
184
|
+
const id = input.id || (0, util_1.createId)("msg", state.messages.length + 1);
|
|
185
|
+
(0, util_1.assertUnique)(state.messages, id, "BlackboardMessage");
|
|
179
186
|
const author = normalizeAuthor(input.author, "operator");
|
|
180
187
|
const links = compactLinks(run, { ...topic.links, ...roleLinkFromAuthor(author), ...(input.links || {}), evidenceRefs: input.evidenceRefs, auditEventIds: input.auditEventIds });
|
|
181
188
|
const enforcePolicy = shouldEnforcePolicy(author, links);
|
|
@@ -201,10 +208,10 @@ function postBlackboardMessage(run, input) {
|
|
|
201
208
|
body: input.body,
|
|
202
209
|
visibility: input.visibility || "public",
|
|
203
210
|
replyToId: input.replyToId,
|
|
204
|
-
parentIds: unique([...(input.parentIds || []), ...(input.replyToId ? [input.replyToId] : [])]),
|
|
205
|
-
linkedEvidenceRefs: unique(input.evidenceRefs || []),
|
|
211
|
+
parentIds: (0, util_1.unique)([...(input.parentIds || []), ...(input.replyToId ? [input.replyToId] : [])]),
|
|
212
|
+
linkedEvidenceRefs: (0, util_1.unique)(input.evidenceRefs || []),
|
|
206
213
|
linkedArtifactRefIds: requireArtifactRefs(run, input.artifactRefIds || []),
|
|
207
|
-
linkedAuditEventIds: unique(input.auditEventIds || []),
|
|
214
|
+
linkedAuditEventIds: (0, util_1.unique)(input.auditEventIds || []),
|
|
208
215
|
links,
|
|
209
216
|
provenance: {
|
|
210
217
|
schemaVersion: 1,
|
|
@@ -218,24 +225,24 @@ function postBlackboardMessage(run, input) {
|
|
|
218
225
|
agentFaninId: links.agentFaninId,
|
|
219
226
|
workerId: links.workerId || (author.kind === "worker" ? author.id : undefined),
|
|
220
227
|
source: (0, multi_agent_trust_1.sourceForActor)(author),
|
|
221
|
-
linkedEvidenceRefs: unique(input.evidenceRefs || []),
|
|
222
|
-
linkedAuditEventIds: unique(input.auditEventIds || []),
|
|
223
|
-
parentMessageIds: unique([...(input.parentIds || []), ...(input.replyToId ? [input.replyToId] : [])]),
|
|
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] : [])]),
|
|
224
231
|
topicScope: topic.id,
|
|
225
232
|
bodyHash: (0, multi_agent_trust_1.hashText)(input.body),
|
|
226
233
|
locator: `${board.id}/messages/${id}`
|
|
227
234
|
}
|
|
228
235
|
};
|
|
229
236
|
state.messages.push(message);
|
|
230
|
-
topic.messageIds = unique([...topic.messageIds, message.id]);
|
|
237
|
+
topic.messageIds = (0, util_1.unique)([...topic.messageIds, message.id]);
|
|
231
238
|
board.messageCount = state.messages.filter((entry) => entry.blackboardId === board.id).length;
|
|
232
|
-
touch(topic);
|
|
233
|
-
touch(board);
|
|
234
|
-
appendBlackboardNode(run, "blackboard-message", message.id, "completed", truncate(message.body), messagesPath(run), [`${run.id}:blackboard:topic:${topic.id}`]);
|
|
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}`]);
|
|
235
242
|
const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
236
243
|
kind: "blackboard.message",
|
|
237
244
|
decision: "recorded",
|
|
238
|
-
source: sourceForAuthor(message.author),
|
|
245
|
+
source: (0, classify_1.sourceForAuthor)(message.author),
|
|
239
246
|
actor: message.author.id,
|
|
240
247
|
blackboardId: board.id,
|
|
241
248
|
blackboardTopicId: topic.id,
|
|
@@ -264,7 +271,7 @@ function postBlackboardMessage(run, input) {
|
|
|
264
271
|
blackboardTopicId: topic.id,
|
|
265
272
|
blackboardMessageId: message.id,
|
|
266
273
|
evidenceRefs: message.linkedEvidenceRefs,
|
|
267
|
-
parentEventIds: unique([...(permission ? [permission.event.id] : []), audit.id]),
|
|
274
|
+
parentEventIds: (0, util_1.unique)([...(permission ? [permission.event.id] : []), audit.id]),
|
|
268
275
|
policyRef: permission?.policyRef,
|
|
269
276
|
metadata: { visibility: message.visibility }
|
|
270
277
|
});
|
|
@@ -300,12 +307,12 @@ function postBlackboardMessage(run, input) {
|
|
|
300
307
|
policyRef: permission?.policyRef,
|
|
301
308
|
parentEventIds: [audit.id, writeAudit.id, provenanceAudit.id]
|
|
302
309
|
});
|
|
303
|
-
message.linkedAuditEventIds = unique([...message.linkedAuditEventIds, rationaleAudit.id]);
|
|
310
|
+
message.linkedAuditEventIds = (0, util_1.unique)([...message.linkedAuditEventIds, rationaleAudit.id]);
|
|
304
311
|
}
|
|
305
|
-
message.linkedAuditEventIds = unique([...message.linkedAuditEventIds, audit.id, writeAudit.id, provenanceAudit.id]);
|
|
306
|
-
message.links.auditEventIds = unique([...(message.links.auditEventIds || []), audit.id, writeAudit.id, provenanceAudit.id]);
|
|
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]);
|
|
307
314
|
if (message.provenance) {
|
|
308
|
-
message.provenance.linkedAuditEventIds = unique([...message.provenance.linkedAuditEventIds, audit.id, writeAudit.id, provenanceAudit.id]);
|
|
315
|
+
message.provenance.linkedAuditEventIds = (0, util_1.unique)([...message.provenance.linkedAuditEventIds, audit.id, writeAudit.id, provenanceAudit.id]);
|
|
309
316
|
}
|
|
310
317
|
persistBlackboardState(run);
|
|
311
318
|
return message;
|
|
@@ -315,8 +322,8 @@ function putBlackboardContext(run, input) {
|
|
|
315
322
|
const topic = requireTopic(run, input.topicId);
|
|
316
323
|
const board = requireBoard(run, input.blackboardId || topic.blackboardId);
|
|
317
324
|
const key = input.key || input.kind;
|
|
318
|
-
const id = input.id || createId("ctx");
|
|
319
|
-
assertUnique(state.contexts, id, "BlackboardContext");
|
|
325
|
+
const id = input.id || (0, util_1.createId)("ctx", state.contexts.length + 1);
|
|
326
|
+
(0, util_1.assertUnique)(state.contexts, id, "BlackboardContext");
|
|
320
327
|
const author = normalizeAuthor(input.author, "operator");
|
|
321
328
|
const links = compactLinks(run, { ...topic.links, ...roleLinkFromAuthor(author), ...(input.links || {}), evidenceRefs: input.evidenceRefs });
|
|
322
329
|
const permission = shouldEnforcePolicy(author, links)
|
|
@@ -344,7 +351,7 @@ function putBlackboardContext(run, input) {
|
|
|
344
351
|
const superseded = requireContext(run, supersededId);
|
|
345
352
|
superseded.status = "superseded";
|
|
346
353
|
superseded.supersededByContextId = id;
|
|
347
|
-
touch(superseded);
|
|
354
|
+
(0, util_1.touch)(superseded);
|
|
348
355
|
}
|
|
349
356
|
const status = conflicts.length ? "conflicting" : input.kind === "question" ? "open" : "active";
|
|
350
357
|
const context = {
|
|
@@ -353,22 +360,22 @@ function putBlackboardContext(run, input) {
|
|
|
353
360
|
kind: input.kind,
|
|
354
361
|
key,
|
|
355
362
|
value: input.value,
|
|
356
|
-
supersedesContextIds: unique(input.supersedesContextIds || []),
|
|
363
|
+
supersedesContextIds: (0, util_1.unique)(input.supersedesContextIds || []),
|
|
357
364
|
conflictingContextIds: conflicts.map((entry) => entry.id),
|
|
358
|
-
evidenceRefs: unique(input.evidenceRefs || []),
|
|
365
|
+
evidenceRefs: (0, util_1.unique)(input.evidenceRefs || []),
|
|
359
366
|
artifactRefIds: requireArtifactRefs(run, input.artifactRefIds || []),
|
|
360
367
|
links
|
|
361
368
|
};
|
|
362
369
|
for (const conflict of conflicts) {
|
|
363
370
|
conflict.status = "conflicting";
|
|
364
|
-
conflict.conflictingContextIds = unique([...conflict.conflictingContextIds, context.id]);
|
|
365
|
-
touch(conflict);
|
|
371
|
+
conflict.conflictingContextIds = (0, util_1.unique)([...conflict.conflictingContextIds, context.id]);
|
|
372
|
+
(0, util_1.touch)(conflict);
|
|
366
373
|
}
|
|
367
374
|
state.contexts.push(context);
|
|
368
|
-
topic.contextIds = unique([...topic.contextIds, context.id]);
|
|
369
|
-
board.contextIds = unique([...board.contextIds, context.id]);
|
|
370
|
-
touch(topic);
|
|
371
|
-
touch(board);
|
|
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);
|
|
372
379
|
const decision = recordCoordinatorDecision(run, {
|
|
373
380
|
blackboardId: board.id,
|
|
374
381
|
topicId: topic.id,
|
|
@@ -386,11 +393,11 @@ function putBlackboardContext(run, input) {
|
|
|
386
393
|
tags: ["context", input.kind]
|
|
387
394
|
});
|
|
388
395
|
context.decisionId = decision.id;
|
|
389
|
-
appendBlackboardNode(run, "blackboard-context", context.id, statusToNodeStatus(context.status), `${context.kind}:${context.key}`, recordPath(run, "contexts", context.id), [`${run.id}:blackboard:topic:${topic.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}`]);
|
|
390
397
|
const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
391
398
|
kind: "blackboard.context",
|
|
392
399
|
decision: conflicts.length ? "failed" : "accepted",
|
|
393
|
-
source: sourceForAuthor(context.author),
|
|
400
|
+
source: (0, classify_1.sourceForAuthor)(context.author),
|
|
394
401
|
actor: context.author.id,
|
|
395
402
|
blackboardId: board.id,
|
|
396
403
|
blackboardTopicId: topic.id,
|
|
@@ -416,12 +423,12 @@ function putBlackboardContext(run, input) {
|
|
|
416
423
|
blackboardContextId: context.id,
|
|
417
424
|
coordinatorDecisionId: decision.id,
|
|
418
425
|
evidenceRefs: context.evidenceRefs,
|
|
419
|
-
parentEventIds: unique([...(permission ? [permission.event.id] : []), audit.id]),
|
|
426
|
+
parentEventIds: (0, util_1.unique)([...(permission ? [permission.event.id] : []), audit.id]),
|
|
420
427
|
policyRef: permission?.policyRef,
|
|
421
428
|
metadata: { kind: context.kind, key: context.key, conflicts: context.conflictingContextIds }
|
|
422
429
|
});
|
|
423
|
-
context.links.auditEventIds = unique([...(context.links.auditEventIds || []), audit.id]);
|
|
424
|
-
context.links.auditEventIds = unique([...(context.links.auditEventIds || []), writeAudit.id]);
|
|
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]);
|
|
425
432
|
persistBlackboardState(run);
|
|
426
433
|
return context;
|
|
427
434
|
}
|
|
@@ -433,8 +440,8 @@ function addBlackboardArtifact(run, input) {
|
|
|
433
440
|
const topic = input.topicId ? requireTopic(run, input.topicId) : undefined;
|
|
434
441
|
if (topic && topic.blackboardId !== board.id)
|
|
435
442
|
throw new Error(`Topic ${topic.id} does not belong to blackboard ${board.id}`);
|
|
436
|
-
const id = input.id || createId("artifact");
|
|
437
|
-
assertUnique(state.artifacts, id, "BlackboardArtifactRef");
|
|
443
|
+
const id = input.id || (0, util_1.createId)("artifact", state.artifacts.length + 1);
|
|
444
|
+
(0, util_1.assertUnique)(state.artifacts, id, "BlackboardArtifactRef");
|
|
438
445
|
const author = normalizeAuthor(input.author, "operator");
|
|
439
446
|
const links = compactLinks(run, { ...board.links, ...(topic?.links || {}), ...roleLinkFromAuthor(author), ...(input.links || {}), evidenceRefs: input.evidenceRefs, auditEventIds: input.auditEventIds });
|
|
440
447
|
const permission = shouldEnforcePolicy(author, links)
|
|
@@ -461,17 +468,17 @@ function addBlackboardArtifact(run, input) {
|
|
|
461
468
|
owner: normalizeAuthor(input.owner || input.author, "operator"),
|
|
462
469
|
source: input.source || "operator-recorded",
|
|
463
470
|
provenance: compactLinks(run, { ...(input.provenance || {}), ...links }),
|
|
464
|
-
evidenceRefs: unique(input.evidenceRefs || []),
|
|
465
|
-
checksum: absolutePath && node_fs_1.default.existsSync(absolutePath) && node_fs_1.default.statSync(absolutePath).isFile() ? checksumFile(absolutePath) : undefined,
|
|
466
|
-
trustAuditEventIds: unique(input.auditEventIds || [])
|
|
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 || [])
|
|
467
474
|
};
|
|
468
475
|
state.artifacts.push(artifact);
|
|
469
|
-
board.artifactRefIds = unique([...board.artifactRefIds, artifact.id]);
|
|
476
|
+
board.artifactRefIds = (0, util_1.unique)([...board.artifactRefIds, artifact.id]);
|
|
470
477
|
if (topic)
|
|
471
|
-
topic.artifactRefIds = unique([...topic.artifactRefIds, artifact.id]);
|
|
472
|
-
touch(board);
|
|
478
|
+
topic.artifactRefIds = (0, util_1.unique)([...topic.artifactRefIds, artifact.id]);
|
|
479
|
+
(0, util_1.touch)(board);
|
|
473
480
|
if (topic)
|
|
474
|
-
touch(topic);
|
|
481
|
+
(0, util_1.touch)(topic);
|
|
475
482
|
const decision = recordCoordinatorDecision(run, {
|
|
476
483
|
blackboardId: board.id,
|
|
477
484
|
topicId: topic?.id,
|
|
@@ -485,13 +492,13 @@ function addBlackboardArtifact(run, input) {
|
|
|
485
492
|
scope: artifact.scope,
|
|
486
493
|
tags: ["artifact", artifact.kind]
|
|
487
494
|
});
|
|
488
|
-
appendBlackboardNode(run, "blackboard-artifact", artifact.id, "completed", artifact.kind, recordPath(run, "artifacts", artifact.id), [
|
|
495
|
+
appendBlackboardNode(run, "blackboard-artifact", artifact.id, "completed", artifact.kind, (0, paths_1.recordPath)(run, "artifacts", artifact.id), [
|
|
489
496
|
topic ? `${run.id}:blackboard:topic:${topic.id}` : `${run.id}:blackboard:${board.id}`
|
|
490
497
|
]);
|
|
491
498
|
const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
492
499
|
kind: "blackboard.artifact",
|
|
493
500
|
decision: "accepted",
|
|
494
|
-
source: sourceForAuthor(artifact.author),
|
|
501
|
+
source: (0, classify_1.sourceForAuthor)(artifact.author),
|
|
495
502
|
actor: artifact.author.id,
|
|
496
503
|
blackboardId: board.id,
|
|
497
504
|
blackboardTopicId: topic?.id,
|
|
@@ -519,19 +526,19 @@ function addBlackboardArtifact(run, input) {
|
|
|
519
526
|
blackboardArtifactRefId: artifact.id,
|
|
520
527
|
coordinatorDecisionId: decision.id,
|
|
521
528
|
evidenceRefs: artifact.evidenceRefs,
|
|
522
|
-
parentEventIds: unique([...(permission ? [permission.event.id] : []), audit.id]),
|
|
529
|
+
parentEventIds: (0, util_1.unique)([...(permission ? [permission.event.id] : []), audit.id]),
|
|
523
530
|
policyRef: permission?.policyRef,
|
|
524
531
|
metadata: { kind: artifact.kind, locator: artifact.locator, checksum: artifact.checksum }
|
|
525
532
|
});
|
|
526
|
-
artifact.trustAuditEventIds = unique([...artifact.trustAuditEventIds, audit.id, writeAudit.id]);
|
|
533
|
+
artifact.trustAuditEventIds = (0, util_1.unique)([...artifact.trustAuditEventIds, audit.id, writeAudit.id]);
|
|
527
534
|
persistBlackboardState(run);
|
|
528
535
|
return artifact;
|
|
529
536
|
}
|
|
530
537
|
function createBlackboardSnapshot(run, blackboardId) {
|
|
531
538
|
const state = ensureBlackboardState(run);
|
|
532
539
|
const board = resolveBlackboard(run, { id: blackboardId });
|
|
533
|
-
const id = createId("snapshot");
|
|
534
|
-
const snapshotPath = recordPath(run, "snapshots", id);
|
|
540
|
+
const id = (0, util_1.createId)("snapshot", state.snapshots.length + 1);
|
|
541
|
+
const snapshotPath = (0, paths_1.recordPath)(run, "snapshots", id);
|
|
535
542
|
const summary = summarizeBlackboard(run, board.id);
|
|
536
543
|
const snapshot = {
|
|
537
544
|
...base(run, board.id, id, { kind: "runtime", id: "cw" }, { kind: "run", id: run.id }, "active", ["snapshot"], undefined),
|
|
@@ -546,8 +553,8 @@ function createBlackboardSnapshot(run, blackboardId) {
|
|
|
546
553
|
links: compactLinks(run, board.links)
|
|
547
554
|
};
|
|
548
555
|
state.snapshots.push(snapshot);
|
|
549
|
-
board.snapshotIds = unique([...board.snapshotIds, snapshot.id]);
|
|
550
|
-
touch(board);
|
|
556
|
+
board.snapshotIds = (0, util_1.unique)([...board.snapshotIds, snapshot.id]);
|
|
557
|
+
(0, util_1.touch)(board);
|
|
551
558
|
appendBlackboardNode(run, "blackboard-snapshot", snapshot.id, "completed", snapshot.id, snapshotPath, [`${run.id}:blackboard:${board.id}`]);
|
|
552
559
|
const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
553
560
|
kind: "blackboard.snapshot",
|
|
@@ -572,36 +579,36 @@ function createBlackboardSnapshot(run, blackboardId) {
|
|
|
572
579
|
metadata: { snapshotPath }
|
|
573
580
|
});
|
|
574
581
|
snapshot.links.auditEventIds = [audit.id];
|
|
575
|
-
snapshot.links.auditEventIds = unique([...snapshot.links.auditEventIds, writeAudit.id]);
|
|
582
|
+
snapshot.links.auditEventIds = (0, util_1.unique)([...snapshot.links.auditEventIds, writeAudit.id]);
|
|
576
583
|
persistBlackboardState(run);
|
|
577
584
|
return snapshot;
|
|
578
585
|
}
|
|
579
586
|
function recordCoordinatorDecision(run, input) {
|
|
580
587
|
const state = ensureBlackboardState(run);
|
|
581
588
|
const board = resolveBlackboard(run, { id: input.blackboardId });
|
|
582
|
-
const id = input.id || createId("decision");
|
|
583
|
-
assertUnique(state.decisions, id, "CoordinatorDecision");
|
|
589
|
+
const id = input.id || (0, util_1.createId)("decision", state.decisions.length + 1);
|
|
590
|
+
(0, util_1.assertUnique)(state.decisions, id, "CoordinatorDecision");
|
|
584
591
|
const decision = {
|
|
585
|
-
...base(run, board.id, id, input.author || { kind: "coordinator", id: "cw" }, input.scope, decisionStatus(input.outcome), input.tags, input.metadata),
|
|
592
|
+
...base(run, board.id, id, input.author || { kind: "coordinator", id: "cw" }, input.scope, (0, classify_1.decisionStatus)(input.outcome), input.tags, input.metadata),
|
|
586
593
|
kind: input.kind,
|
|
587
594
|
outcome: input.outcome,
|
|
588
|
-
subjectIds: unique(input.subjectIds || []),
|
|
595
|
+
subjectIds: (0, util_1.unique)(input.subjectIds || []),
|
|
589
596
|
reason: input.reason,
|
|
590
|
-
evidenceRefs: unique(input.evidenceRefs || []),
|
|
597
|
+
evidenceRefs: (0, util_1.unique)(input.evidenceRefs || []),
|
|
591
598
|
artifactRefIds: requireArtifactRefs(run, input.artifactRefIds || []),
|
|
592
599
|
messageIds: requireMessages(run, input.messageIds || []),
|
|
593
600
|
links: compactLinks(run, { ...board.links, ...roleLinkFromAuthor(input.author), ...(input.links || {}), evidenceRefs: input.evidenceRefs })
|
|
594
601
|
};
|
|
595
602
|
state.decisions.push(decision);
|
|
596
|
-
board.decisionIds = unique([...board.decisionIds, decision.id]);
|
|
597
|
-
touch(board);
|
|
598
|
-
appendBlackboardNode(run, "coordinator-decision", decision.id, statusToNodeStatus(decision.status), `${decision.kind}:${decision.outcome}`, recordPath(run, "decisions", decision.id), [
|
|
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), [
|
|
599
606
|
`${run.id}:blackboard:${board.id}`,
|
|
600
607
|
...(input.topicId ? [`${run.id}:blackboard:topic:${input.topicId}`] : [])
|
|
601
608
|
]);
|
|
602
609
|
const audit = (0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
603
610
|
kind: "coordinator.decision",
|
|
604
|
-
decision: auditDecision(input.outcome),
|
|
611
|
+
decision: (0, classify_1.auditDecision)(input.outcome),
|
|
605
612
|
source: "cw-validated",
|
|
606
613
|
actor: decision.author.id,
|
|
607
614
|
blackboardId: board.id,
|
|
@@ -649,9 +656,9 @@ function recordCoordinatorDecision(run, input) {
|
|
|
649
656
|
rationale: decision.reason,
|
|
650
657
|
parentEventIds: [audit.id, writeAudit.id]
|
|
651
658
|
});
|
|
652
|
-
decision.links.auditEventIds = unique([...(decision.links.auditEventIds || []), panelAudit.id]);
|
|
659
|
+
decision.links.auditEventIds = (0, util_1.unique)([...(decision.links.auditEventIds || []), panelAudit.id]);
|
|
653
660
|
}
|
|
654
|
-
decision.links.auditEventIds = unique([...(decision.links.auditEventIds || []), audit.id, writeAudit.id]);
|
|
661
|
+
decision.links.auditEventIds = (0, util_1.unique)([...(decision.links.auditEventIds || []), audit.id, writeAudit.id]);
|
|
655
662
|
persistBlackboardState(run);
|
|
656
663
|
return decision;
|
|
657
664
|
}
|
|
@@ -683,7 +690,7 @@ function summarizeBlackboard(run, blackboardId) {
|
|
|
683
690
|
missingEvidence,
|
|
684
691
|
readyForFanin,
|
|
685
692
|
latestSnapshotPath: latestSnapshot?.snapshotPath,
|
|
686
|
-
indexPath: board?.paths.index || node_path_1.default.join(blackboardRoot(run), "index.json"),
|
|
693
|
+
indexPath: board?.paths.index || node_path_1.default.join((0, paths_1.blackboardRoot)(run), "index.json"),
|
|
687
694
|
nextAction: nextAction(run, board, openQuestions, conflicts, artifacts)
|
|
688
695
|
};
|
|
689
696
|
}
|
|
@@ -710,21 +717,21 @@ function buildBlackboardGraph(run) {
|
|
|
710
717
|
edges.push({ from: `${run.id}:multi-agent:${board.links.multiAgentRunId}`, to: `${run.id}:blackboard:${board.id}`, label: "coordinates" });
|
|
711
718
|
}
|
|
712
719
|
for (const topic of state.topics) {
|
|
713
|
-
nodes.push({ id: `${run.id}:blackboard:topic:${topic.id}`, kind: "blackboard-topic", status: topic.status, label: topic.title, path: recordPath(run, "topics", topic.id) });
|
|
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) });
|
|
714
721
|
edges.push({ from: `${run.id}:blackboard:${topic.blackboardId}`, to: `${run.id}:blackboard:topic:${topic.id}` });
|
|
715
722
|
}
|
|
716
723
|
for (const context of state.contexts) {
|
|
717
|
-
nodes.push({ id: `${run.id}:blackboard:context:${context.id}`, kind: "blackboard-context", status: context.status, label: `${context.kind}:${context.key}`, path: recordPath(run, "contexts", context.id) });
|
|
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) });
|
|
718
725
|
edges.push({ from: `${run.id}:blackboard:topic:${context.topicId}`, to: `${run.id}:blackboard:context:${context.id}` });
|
|
719
726
|
for (const conflicting of context.conflictingContextIds)
|
|
720
727
|
edges.push({ from: `${run.id}:blackboard:context:${context.id}`, to: `${run.id}:blackboard:context:${conflicting}`, label: "conflicts" });
|
|
721
728
|
}
|
|
722
729
|
for (const artifact of state.artifacts) {
|
|
723
|
-
nodes.push({ id: `${run.id}:blackboard:artifact:${artifact.id}`, kind: "blackboard-artifact", status: artifact.status, label: artifact.kind, path: recordPath(run, "artifacts", artifact.id) });
|
|
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) });
|
|
724
731
|
edges.push({ from: artifact.topicId ? `${run.id}:blackboard:topic:${artifact.topicId}` : `${run.id}:blackboard:${artifact.blackboardId}`, to: `${run.id}:blackboard:artifact:${artifact.id}` });
|
|
725
732
|
}
|
|
726
733
|
for (const message of state.messages) {
|
|
727
|
-
nodes.push({ id: `${run.id}:blackboard:message:${message.id}`, kind: "blackboard-message", status: message.status, label: truncate(message.body), path: messagesPath(run) });
|
|
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) });
|
|
728
735
|
edges.push({ from: `${run.id}:blackboard:topic:${message.topicId}`, to: `${run.id}:blackboard:message:${message.id}` });
|
|
729
736
|
if (message.replyToId)
|
|
730
737
|
edges.push({ from: `${run.id}:blackboard:message:${message.replyToId}`, to: `${run.id}:blackboard:message:${message.id}`, label: "reply" });
|
|
@@ -732,7 +739,7 @@ function buildBlackboardGraph(run) {
|
|
|
732
739
|
edges.push({ from: `${run.id}:blackboard:message:${message.id}`, to: `${run.id}:blackboard:artifact:${artifactId}`, label: "cites" });
|
|
733
740
|
}
|
|
734
741
|
for (const decision of state.decisions) {
|
|
735
|
-
nodes.push({ id: `${run.id}:coordinator:decision:${decision.id}`, kind: "coordinator-decision", status: decision.status, label: `${decision.kind}:${decision.outcome}`, path: recordPath(run, "decisions", decision.id) });
|
|
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) });
|
|
736
743
|
edges.push({ from: `${run.id}:blackboard:${decision.blackboardId}`, to: `${run.id}:coordinator:decision:${decision.id}` });
|
|
737
744
|
for (const subjectId of decision.subjectIds)
|
|
738
745
|
edges.push({ from: `${run.id}:coordinator:decision:${decision.id}`, to: graphSubject(run, subjectId), label: "subject" });
|
|
@@ -741,20 +748,20 @@ function buildBlackboardGraph(run) {
|
|
|
741
748
|
nodes.push({ id: `${run.id}:blackboard:snapshot:${snapshot.id}`, kind: "blackboard-snapshot", status: snapshot.status, label: snapshot.id, path: snapshot.snapshotPath });
|
|
742
749
|
edges.push({ from: `${run.id}:blackboard:${snapshot.blackboardId}`, to: `${run.id}:blackboard:snapshot:${snapshot.id}` });
|
|
743
750
|
}
|
|
744
|
-
return { nodes, edges: uniqueEdges(edges) };
|
|
751
|
+
return { nodes, edges: (0, util_1.uniqueEdges)(edges) };
|
|
745
752
|
}
|
|
746
753
|
function persistBlackboardState(run) {
|
|
747
754
|
const state = ensureBlackboardState(run);
|
|
748
|
-
const root = blackboardRoot(run);
|
|
749
|
-
assertNoRecordPathCollisions("BlackboardTopic", state.topics);
|
|
750
|
-
assertNoRecordPathCollisions("BlackboardContext", state.contexts);
|
|
751
|
-
assertNoRecordPathCollisions("BlackboardArtifactRef", state.artifacts);
|
|
752
|
-
assertNoRecordPathCollisions("BlackboardSnapshot", state.snapshots);
|
|
753
|
-
assertNoRecordPathCollisions("CoordinatorDecision", state.decisions);
|
|
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);
|
|
754
761
|
const index = {
|
|
755
762
|
schemaVersion: exports.BLACKBOARD_SCHEMA_VERSION,
|
|
756
763
|
runId: run.id,
|
|
757
|
-
generatedAt: timestamp(),
|
|
764
|
+
generatedAt: (0, util_1.timestamp)(),
|
|
758
765
|
counts: {
|
|
759
766
|
boards: state.boards.length,
|
|
760
767
|
topics: state.topics.length,
|
|
@@ -764,12 +771,12 @@ function persistBlackboardState(run) {
|
|
|
764
771
|
snapshots: state.snapshots.length,
|
|
765
772
|
decisions: state.decisions.length
|
|
766
773
|
},
|
|
767
|
-
boards: state.boards.map(indexRow),
|
|
768
|
-
topics: state.topics.map(indexRow),
|
|
769
|
-
contexts: state.contexts.map(indexRow),
|
|
770
|
-
artifacts: state.artifacts.map(indexRow),
|
|
771
|
-
snapshots: state.snapshots.map(indexRow),
|
|
772
|
-
decisions: state.decisions.map(indexRow),
|
|
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),
|
|
773
780
|
messages: state.messages.map((message) => ({
|
|
774
781
|
id: message.id,
|
|
775
782
|
blackboardId: message.blackboardId,
|
|
@@ -782,45 +789,17 @@ function persistBlackboardState(run) {
|
|
|
782
789
|
}))
|
|
783
790
|
};
|
|
784
791
|
(0, state_1.writeJson)(node_path_1.default.join(root, "index.json"), index);
|
|
785
|
-
node_fs_1.default.writeFileSync(messagesPath(run), state.messages.sort(compareRecords).map((message) => JSON.stringify(message)).join("\n") + (state.messages.length ? "\n" : ""), "utf8");
|
|
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");
|
|
786
793
|
for (const topic of state.topics)
|
|
787
|
-
(0, state_1.writeJson)(recordPath(run, "topics", topic.id), topic);
|
|
794
|
+
(0, state_1.writeJson)((0, paths_1.recordPath)(run, "topics", topic.id), topic);
|
|
788
795
|
for (const context of state.contexts)
|
|
789
|
-
(0, state_1.writeJson)(recordPath(run, "contexts", context.id), context);
|
|
796
|
+
(0, state_1.writeJson)((0, paths_1.recordPath)(run, "contexts", context.id), context);
|
|
790
797
|
for (const artifact of state.artifacts)
|
|
791
|
-
(0, state_1.writeJson)(recordPath(run, "artifacts", artifact.id), artifact);
|
|
798
|
+
(0, state_1.writeJson)((0, paths_1.recordPath)(run, "artifacts", artifact.id), artifact);
|
|
792
799
|
for (const snapshot of state.snapshots)
|
|
793
|
-
(0, state_1.writeJson)(recordPath(run, "snapshots", snapshot.id), snapshot);
|
|
800
|
+
(0, state_1.writeJson)((0, paths_1.recordPath)(run, "snapshots", snapshot.id), snapshot);
|
|
794
801
|
for (const decision of state.decisions)
|
|
795
|
-
(0, state_1.writeJson)(recordPath(run, "decisions", decision.id), decision);
|
|
796
|
-
}
|
|
797
|
-
function bridgeStateArtifactToBlackboard(run, artifact, input = {}) {
|
|
798
|
-
return addBlackboardArtifact(run, {
|
|
799
|
-
kind: artifact.kind,
|
|
800
|
-
path: artifact.path,
|
|
801
|
-
locator: artifact.path,
|
|
802
|
-
metadata: { description: artifact.description, stateArtifactId: artifact.id },
|
|
803
|
-
...input
|
|
804
|
-
});
|
|
805
|
-
}
|
|
806
|
-
function evidenceFromArtifactRef(artifact) {
|
|
807
|
-
return {
|
|
808
|
-
id: artifact.id,
|
|
809
|
-
source: "blackboard-artifact",
|
|
810
|
-
path: artifact.path,
|
|
811
|
-
locator: artifact.locator || artifact.path,
|
|
812
|
-
summary: `${artifact.kind} ${artifact.path || artifact.locator || artifact.id}`,
|
|
813
|
-
provenance: {
|
|
814
|
-
schemaVersion: 1,
|
|
815
|
-
runId: artifact.runId,
|
|
816
|
-
source: "cw-validated",
|
|
817
|
-
workerId: artifact.provenance.workerId,
|
|
818
|
-
taskId: artifact.provenance.taskId,
|
|
819
|
-
candidateId: artifact.provenance.candidateId,
|
|
820
|
-
commitId: artifact.provenance.commitId,
|
|
821
|
-
auditEventIds: artifact.trustAuditEventIds
|
|
822
|
-
}
|
|
823
|
-
};
|
|
802
|
+
(0, state_1.writeJson)((0, paths_1.recordPath)(run, "decisions", decision.id), decision);
|
|
824
803
|
}
|
|
825
804
|
function emptyState() {
|
|
826
805
|
return {
|
|
@@ -853,7 +832,7 @@ function shouldEnforcePolicy(author, links) {
|
|
|
853
832
|
return Boolean(links.agentRoleId || links.agentGroupId || links.agentMembershipId);
|
|
854
833
|
}
|
|
855
834
|
function base(run, blackboardId, id, author, scope, status = "active", tags, metadata) {
|
|
856
|
-
const now = timestamp();
|
|
835
|
+
const now = (0, util_1.timestamp)();
|
|
857
836
|
return {
|
|
858
837
|
schemaVersion: exports.BLACKBOARD_SCHEMA_VERSION,
|
|
859
838
|
id,
|
|
@@ -865,8 +844,8 @@ function base(run, blackboardId, id, author, scope, status = "active", tags, met
|
|
|
865
844
|
scope: normalizeScope(scope, { kind: "run", id: run.id }),
|
|
866
845
|
status,
|
|
867
846
|
parentIds: [],
|
|
868
|
-
tags: sortTags(tags),
|
|
869
|
-
metadata: scrub(metadata)
|
|
847
|
+
tags: (0, util_1.sortTags)(tags),
|
|
848
|
+
metadata: (0, util_1.scrub)(metadata)
|
|
870
849
|
};
|
|
871
850
|
}
|
|
872
851
|
function normalizeAuthor(input, fallbackKind) {
|
|
@@ -884,7 +863,7 @@ function normalizeScope(input, fallback) {
|
|
|
884
863
|
return { kind, id };
|
|
885
864
|
}
|
|
886
865
|
function compactLinks(run, input) {
|
|
887
|
-
return compact({
|
|
866
|
+
return (0, util_1.compact)({
|
|
888
867
|
workflowRunId: run.id,
|
|
889
868
|
multiAgentRunId: input.multiAgentRunId,
|
|
890
869
|
agentGroupId: input.agentGroupId,
|
|
@@ -897,8 +876,8 @@ function compactLinks(run, input) {
|
|
|
897
876
|
candidateId: input.candidateId,
|
|
898
877
|
verifierNodeId: input.verifierNodeId,
|
|
899
878
|
commitId: input.commitId,
|
|
900
|
-
auditEventIds: unique(input.auditEventIds || []),
|
|
901
|
-
evidenceRefs: unique(input.evidenceRefs || [])
|
|
879
|
+
auditEventIds: (0, util_1.unique)(input.auditEventIds || []),
|
|
880
|
+
evidenceRefs: (0, util_1.unique)(input.evidenceRefs || [])
|
|
902
881
|
});
|
|
903
882
|
}
|
|
904
883
|
function linkMultiAgent(run, blackboardId, topicIds, input) {
|
|
@@ -909,30 +888,30 @@ function linkMultiAgent(run, blackboardId, topicIds, input) {
|
|
|
909
888
|
const record = (0, multi_agent_1.getMultiAgentRun)(run, input.multiAgentRunId);
|
|
910
889
|
if (record) {
|
|
911
890
|
record.blackboardId = blackboardId;
|
|
912
|
-
record.topicIds = unique([...(record.topicIds || []), ...topicIds]);
|
|
891
|
+
record.topicIds = (0, util_1.unique)([...(record.topicIds || []), ...topicIds]);
|
|
913
892
|
record.links.blackboardId = blackboardId;
|
|
914
|
-
record.links.blackboardTopicIds = unique([...(record.links.blackboardTopicIds || []), ...topicIds]);
|
|
893
|
+
record.links.blackboardTopicIds = (0, util_1.unique)([...(record.links.blackboardTopicIds || []), ...topicIds]);
|
|
915
894
|
}
|
|
916
895
|
}
|
|
917
896
|
if (groupId) {
|
|
918
897
|
const record = (0, multi_agent_1.getAgentGroup)(run, groupId);
|
|
919
898
|
if (record) {
|
|
920
899
|
record.blackboardId = blackboardId;
|
|
921
|
-
record.topicIds = unique([...(record.topicIds || []), ...topicIds]);
|
|
900
|
+
record.topicIds = (0, util_1.unique)([...(record.topicIds || []), ...topicIds]);
|
|
922
901
|
}
|
|
923
902
|
}
|
|
924
903
|
if (roleId) {
|
|
925
904
|
const record = (0, multi_agent_1.getAgentRole)(run, roleId);
|
|
926
905
|
if (record) {
|
|
927
906
|
record.blackboardId = blackboardId;
|
|
928
|
-
record.topicIds = unique([...(record.topicIds || []), ...topicIds]);
|
|
907
|
+
record.topicIds = (0, util_1.unique)([...(record.topicIds || []), ...topicIds]);
|
|
929
908
|
}
|
|
930
909
|
}
|
|
931
910
|
if (membershipId) {
|
|
932
911
|
const record = (0, multi_agent_1.getAgentMembership)(run, membershipId);
|
|
933
912
|
if (record) {
|
|
934
913
|
record.blackboardId = blackboardId;
|
|
935
|
-
record.topicIds = unique([...(record.topicIds || []), ...topicIds]);
|
|
914
|
+
record.topicIds = (0, util_1.unique)([...(record.topicIds || []), ...topicIds]);
|
|
936
915
|
}
|
|
937
916
|
}
|
|
938
917
|
}
|
|
@@ -960,7 +939,7 @@ function requireArtifactRefs(run, ids) {
|
|
|
960
939
|
if (!state.artifacts.some((artifact) => artifact.id === id))
|
|
961
940
|
throw new Error(`Unknown BlackboardArtifactRef id: ${id}`);
|
|
962
941
|
}
|
|
963
|
-
return unique(ids);
|
|
942
|
+
return (0, util_1.unique)(ids);
|
|
964
943
|
}
|
|
965
944
|
function requireMessages(run, ids) {
|
|
966
945
|
const state = ensureBlackboardState(run);
|
|
@@ -968,7 +947,7 @@ function requireMessages(run, ids) {
|
|
|
968
947
|
if (!state.messages.some((message) => message.id === id))
|
|
969
948
|
throw new Error(`Unknown BlackboardMessage id: ${id}`);
|
|
970
949
|
}
|
|
971
|
-
return unique(ids);
|
|
950
|
+
return (0, util_1.unique)(ids);
|
|
972
951
|
}
|
|
973
952
|
function appendBlackboardNode(run, kind, id, status, label, artifactPath, parents = []) {
|
|
974
953
|
const nodeId = kind === "blackboard"
|
|
@@ -988,67 +967,6 @@ function appendBlackboardNode(run, kind, id, status, label, artifactPath, parent
|
|
|
988
967
|
metadata: { id, label }
|
|
989
968
|
}));
|
|
990
969
|
}
|
|
991
|
-
function statusToNodeStatus(status) {
|
|
992
|
-
switch (status) {
|
|
993
|
-
case "active":
|
|
994
|
-
case "open":
|
|
995
|
-
return "running";
|
|
996
|
-
case "resolved":
|
|
997
|
-
case "superseded":
|
|
998
|
-
return "completed";
|
|
999
|
-
case "conflicting":
|
|
1000
|
-
return "blocked";
|
|
1001
|
-
case "rejected":
|
|
1002
|
-
return "rejected";
|
|
1003
|
-
default:
|
|
1004
|
-
return "completed";
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
function decisionStatus(outcome) {
|
|
1008
|
-
if (outcome === "conflicting" || outcome === "blocked")
|
|
1009
|
-
return "conflicting";
|
|
1010
|
-
if (outcome === "rejected")
|
|
1011
|
-
return "rejected";
|
|
1012
|
-
if (outcome === "superseded")
|
|
1013
|
-
return "superseded";
|
|
1014
|
-
return "active";
|
|
1015
|
-
}
|
|
1016
|
-
function auditDecision(outcome) {
|
|
1017
|
-
if (outcome === "rejected")
|
|
1018
|
-
return "rejected";
|
|
1019
|
-
if (outcome === "blocked" || outcome === "conflicting")
|
|
1020
|
-
return "failed";
|
|
1021
|
-
return "accepted";
|
|
1022
|
-
}
|
|
1023
|
-
function sourceForAuthor(author) {
|
|
1024
|
-
if (author.kind === "runtime" || author.kind === "coordinator")
|
|
1025
|
-
return "runtime-derived";
|
|
1026
|
-
if (author.kind === "worker" || author.kind === "verifier")
|
|
1027
|
-
return "cw-validated";
|
|
1028
|
-
return "operator-recorded";
|
|
1029
|
-
}
|
|
1030
|
-
function boardPaths(run) {
|
|
1031
|
-
const root = blackboardRoot(run);
|
|
1032
|
-
return {
|
|
1033
|
-
root,
|
|
1034
|
-
index: node_path_1.default.join(root, "index.json"),
|
|
1035
|
-
messages: messagesPath(run),
|
|
1036
|
-
topicsDir: node_path_1.default.join(root, "topics"),
|
|
1037
|
-
contextsDir: node_path_1.default.join(root, "contexts"),
|
|
1038
|
-
artifactsDir: node_path_1.default.join(root, "artifacts"),
|
|
1039
|
-
snapshotsDir: node_path_1.default.join(root, "snapshots"),
|
|
1040
|
-
decisionsDir: node_path_1.default.join(root, "decisions")
|
|
1041
|
-
};
|
|
1042
|
-
}
|
|
1043
|
-
function blackboardRoot(run) {
|
|
1044
|
-
return run.paths.blackboardDir || node_path_1.default.join(run.paths.runDir, "blackboard");
|
|
1045
|
-
}
|
|
1046
|
-
function messagesPath(run) {
|
|
1047
|
-
return node_path_1.default.join(blackboardRoot(run), "messages.jsonl");
|
|
1048
|
-
}
|
|
1049
|
-
function recordPath(run, kind, id) {
|
|
1050
|
-
return node_path_1.default.join(blackboardRoot(run), kind, `${(0, state_1.safeFileName)(id)}.json`);
|
|
1051
|
-
}
|
|
1052
970
|
function graphSubject(run, id) {
|
|
1053
971
|
const state = ensureBlackboardState(run);
|
|
1054
972
|
if (state.contexts.some((entry) => entry.id === id))
|
|
@@ -1070,94 +988,3 @@ function nextAction(run, board, openQuestions, conflicts, artifacts) {
|
|
|
1070
988
|
return `node scripts/cw.js blackboard artifact add ${run.id} --path <path> --kind <kind>`;
|
|
1071
989
|
return `node scripts/cw.js blackboard snapshot ${run.id}`;
|
|
1072
990
|
}
|
|
1073
|
-
function checksumFile(file) {
|
|
1074
|
-
return `sha256:${node_crypto_1.default.createHash("sha256").update(node_fs_1.default.readFileSync(file)).digest("hex")}`;
|
|
1075
|
-
}
|
|
1076
|
-
function assertUnique(items, id, label) {
|
|
1077
|
-
if (items.some((item) => item.id === id))
|
|
1078
|
-
throw new Error(`Duplicate ${label} id: ${id}`);
|
|
1079
|
-
}
|
|
1080
|
-
function assertNoRecordPathCollisions(label, records) {
|
|
1081
|
-
const seen = new Map();
|
|
1082
|
-
for (const record of records) {
|
|
1083
|
-
const safe = (0, state_1.safeFileName)(record.id);
|
|
1084
|
-
const existing = seen.get(safe);
|
|
1085
|
-
if (existing && existing !== record.id) {
|
|
1086
|
-
throw new Error(`${label} ids ${existing} and ${record.id} collide on safe file name ${safe}`);
|
|
1087
|
-
}
|
|
1088
|
-
seen.set(safe, record.id);
|
|
1089
|
-
}
|
|
1090
|
-
}
|
|
1091
|
-
function indexRow(record) {
|
|
1092
|
-
return { id: record.id, blackboardId: record.blackboardId, topicId: record.topicId, status: record.status, updatedAt: record.updatedAt };
|
|
1093
|
-
}
|
|
1094
|
-
function compareRecords(left, right) {
|
|
1095
|
-
return left.createdAt.localeCompare(right.createdAt) || left.id.localeCompare(right.id);
|
|
1096
|
-
}
|
|
1097
|
-
function uniqueEdges(edges) {
|
|
1098
|
-
const seen = new Set();
|
|
1099
|
-
const result = [];
|
|
1100
|
-
for (const edge of edges) {
|
|
1101
|
-
const key = `${edge.from}\0${edge.to}\0${edge.label || ""}`;
|
|
1102
|
-
if (seen.has(key))
|
|
1103
|
-
continue;
|
|
1104
|
-
seen.add(key);
|
|
1105
|
-
result.push(edge);
|
|
1106
|
-
}
|
|
1107
|
-
return result;
|
|
1108
|
-
}
|
|
1109
|
-
function createId(prefix) {
|
|
1110
|
-
const stamp = new Date().toISOString().replace(/[-:]/g, "").replace(/\..+/, "Z");
|
|
1111
|
-
return `${prefix}-${stamp}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1112
|
-
}
|
|
1113
|
-
function touch(record) {
|
|
1114
|
-
record.updatedAt = timestamp();
|
|
1115
|
-
return record;
|
|
1116
|
-
}
|
|
1117
|
-
function timestamp() {
|
|
1118
|
-
return new Date().toISOString();
|
|
1119
|
-
}
|
|
1120
|
-
function unique(values) {
|
|
1121
|
-
return Array.from(new Set(values.filter(Boolean))).sort();
|
|
1122
|
-
}
|
|
1123
|
-
function sortTags(values) {
|
|
1124
|
-
return unique(values || []);
|
|
1125
|
-
}
|
|
1126
|
-
function truncate(value) {
|
|
1127
|
-
return value.length > 64 ? `${value.slice(0, 61)}...` : value;
|
|
1128
|
-
}
|
|
1129
|
-
function compact(value) {
|
|
1130
|
-
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0)));
|
|
1131
|
-
}
|
|
1132
|
-
// Recursive secret redaction (v0.1.40 self-audit P3): the previous scrub only
|
|
1133
|
-
// inspected TOP-LEVEL keys, so a secret nested under an allowed key
|
|
1134
|
-
// (e.g. `metadata.config.token`) leaked into the recorded coordinator decision.
|
|
1135
|
-
// Now we recurse into nested objects and arrays so a secret-named key at any depth
|
|
1136
|
-
// is dropped and an obvious credential value is redacted.
|
|
1137
|
-
const SECRET_KEY_RE = /secret|token|password|credential|authorization|api[_-]?key|env/i;
|
|
1138
|
-
const SECRET_VALUE_RE = /secret|token|password|credential/i;
|
|
1139
|
-
function scrubValue(value) {
|
|
1140
|
-
if (Array.isArray(value))
|
|
1141
|
-
return value.map(scrubValue);
|
|
1142
|
-
if (value && typeof value === "object")
|
|
1143
|
-
return scrub(value);
|
|
1144
|
-
if (typeof value === "string" && SECRET_VALUE_RE.test(value))
|
|
1145
|
-
return "[redacted]";
|
|
1146
|
-
return value;
|
|
1147
|
-
}
|
|
1148
|
-
function scrub(value) {
|
|
1149
|
-
if (!value)
|
|
1150
|
-
return undefined;
|
|
1151
|
-
const result = {};
|
|
1152
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
1153
|
-
if (entry === undefined)
|
|
1154
|
-
continue;
|
|
1155
|
-
if (SECRET_KEY_RE.test(key)) {
|
|
1156
|
-
result[key] = "[redacted]";
|
|
1157
|
-
}
|
|
1158
|
-
else {
|
|
1159
|
-
result[key] = scrubValue(entry);
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
return Object.keys(result).length ? result : undefined;
|
|
1163
|
-
}
|