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.
Files changed (110) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +42 -2
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +1 -1
  6. package/apps/end-to-end-golden-path/app.json +1 -1
  7. package/apps/pr-review-fix-ci/app.json +1 -1
  8. package/apps/release-cut/app.json +1 -1
  9. package/apps/research-synthesis/app.json +1 -1
  10. package/dist/agent-config.js +21 -7
  11. package/dist/candidate-scoring.js +42 -22
  12. package/dist/capability-core.js +94 -17
  13. package/dist/capability-registry.js +138 -171
  14. package/dist/cli.js +90 -100
  15. package/dist/collaboration.js +5 -6
  16. package/dist/commit.js +20 -6
  17. package/dist/compare.js +18 -0
  18. package/dist/coordinator/classify.js +45 -0
  19. package/dist/coordinator/paths.js +42 -0
  20. package/dist/coordinator/util.js +129 -0
  21. package/dist/coordinator.js +127 -300
  22. package/dist/dispatch.js +35 -0
  23. package/dist/drive.js +7 -7
  24. package/dist/error-feedback.js +8 -4
  25. package/dist/evidence-reasoning.js +1 -1
  26. package/dist/execution-backend/agent.js +331 -0
  27. package/dist/execution-backend/probes.js +96 -0
  28. package/dist/execution-backend/util.js +47 -0
  29. package/dist/execution-backend.js +67 -420
  30. package/dist/mcp-server.js +34 -173
  31. package/dist/multi-agent/graph.js +84 -0
  32. package/dist/multi-agent/helpers.js +145 -0
  33. package/dist/multi-agent/paths.js +22 -0
  34. package/dist/multi-agent-eval/format.js +194 -0
  35. package/dist/multi-agent-eval/normalize.js +51 -0
  36. package/dist/multi-agent-eval.js +39 -244
  37. package/dist/multi-agent-host.js +0 -19
  38. package/dist/multi-agent.js +125 -314
  39. package/dist/node-snapshot.js +3 -3
  40. package/dist/observability/format.js +61 -0
  41. package/dist/observability/intake.js +98 -0
  42. package/dist/observability.js +14 -160
  43. package/dist/operator-ux/format.js +364 -0
  44. package/dist/operator-ux.js +22 -363
  45. package/dist/orchestrator/report.js +8 -0
  46. package/dist/orchestrator.js +25 -8
  47. package/dist/reclamation.js +26 -21
  48. package/dist/run-export.js +138 -14
  49. package/dist/run-registry/derive.js +172 -0
  50. package/dist/run-registry/format.js +124 -0
  51. package/dist/run-registry/gc.js +251 -0
  52. package/dist/run-registry/policy.js +16 -0
  53. package/dist/run-registry/queue.js +116 -0
  54. package/dist/run-registry.js +78 -593
  55. package/dist/run-state-schema.js +1 -0
  56. package/dist/sandbox-profile.js +43 -2
  57. package/dist/state-explosion/format.js +159 -0
  58. package/dist/state-explosion/helpers.js +82 -0
  59. package/dist/state-explosion.js +65 -283
  60. package/dist/state-node.js +19 -4
  61. package/dist/telemetry-attestation.js +55 -0
  62. package/dist/telemetry-demo.js +15 -3
  63. package/dist/telemetry-ledger.js +60 -15
  64. package/dist/topology.js +25 -8
  65. package/dist/triggers.js +33 -14
  66. package/dist/trust-audit.js +145 -33
  67. package/dist/version.js +1 -1
  68. package/dist/worker-isolation/helpers.js +51 -0
  69. package/dist/worker-isolation/paths.js +46 -0
  70. package/dist/worker-isolation.js +39 -115
  71. package/docs/agent-delegation-drive.7.md +13 -0
  72. package/docs/cli-mcp-parity.7.md +4 -0
  73. package/docs/contract-migration-tooling.7.md +2 -0
  74. package/docs/control-plane-scheduling.7.md +2 -0
  75. package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +40 -0
  76. package/docs/durable-state-and-locking.7.md +4 -0
  77. package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
  78. package/docs/execution-backends.7.md +2 -0
  79. package/docs/index.md +1 -0
  80. package/docs/launch/launch-kit.md +46 -23
  81. package/docs/launch/pre-launch-checklist.md +14 -14
  82. package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
  83. package/docs/multi-agent-eval-replay-harness.7.md +2 -0
  84. package/docs/multi-agent-operator-ux.7.md +2 -0
  85. package/docs/multi-agent-trust-policy-audit.7.md +27 -0
  86. package/docs/node-snapshot-diff-replay.7.md +2 -0
  87. package/docs/observability-cost-accounting.7.md +2 -0
  88. package/docs/project-index.md +18 -5
  89. package/docs/real-execution-backends.7.md +2 -0
  90. package/docs/release-and-migration.7.md +4 -0
  91. package/docs/release-tooling.7.md +2 -0
  92. package/docs/run-registry-control-plane.7.md +54 -8
  93. package/docs/run-retention-reclamation.7.md +4 -0
  94. package/docs/state-explosion-management.7.md +2 -0
  95. package/docs/team-collaboration.7.md +2 -0
  96. package/docs/trust-model.md +267 -0
  97. package/docs/vendor-manifest-loadability.7.md +43 -0
  98. package/docs/web-desktop-workbench.7.md +2 -0
  99. package/manifest/plugin.manifest.json +1 -1
  100. package/package.json +4 -2
  101. package/scripts/agents/builtin-templates.json +7 -0
  102. package/scripts/bump-version.js +5 -11
  103. package/scripts/canonical-apps-list.js +64 -0
  104. package/scripts/canonical-apps.js +19 -4
  105. package/scripts/dogfood-release.js +1 -1
  106. package/scripts/golden-path.js +4 -4
  107. package/scripts/parity-check.js +5 -0
  108. package/scripts/release-check.js +5 -1
  109. package/scripts/version-sync-check.js +5 -8
  110. package/dist/capability-dispatcher.js +0 -86
@@ -65,6 +65,19 @@ function handleLine(line) {
65
65
  sendError(message.id, -32000, messageOf(error));
66
66
  }
67
67
  }
68
+ // This is an EXPLICIT switch by design, NOT a descriptor-driven generic dispatcher
69
+ // (FreeBSD-audit R1, assessed & closed as won't-do). A data-routing rewrite is
70
+ // ACTIVELY DANGEROUS here, not just risky: (1) `descriptor.entry` does NOT reliably
71
+ // name the function an arm calls (e.g. cw_app_run entry="validateApp" actually calls
72
+ // appRun; cw_commit entry="commit" calls commitEnvelope), so `runner[entry](args)`
73
+ // would silently call the WRONG method; (2) the parity gate is token-set-only +
74
+ // payload-probes ~30 read-only runId caps, so ~150 multi-positional/write arms are
75
+ // UNPROBED — a mis-marshalling generic dispatcher would pass BOTH gates green = the
76
+ // existential public false-green (a CW red line — see DIRECTION.md). The arms
77
+ // work and parity guards the surface; the real defect the audit flagged (a DEAD
78
+ // dispatcher) was already removed (#131). Cheap safe hardening, if ever wanted:
79
+ // broaden parity-check payload probes to cover multi-positional/write arms, and
80
+ // correct the wrong `entry` metadata — NOT a dispatch rewrite.
68
81
  function callTool(name, args) {
69
82
  const previousCwd = process.cwd();
70
83
  if (args.cwd)
@@ -237,6 +250,8 @@ function callTool(name, args) {
237
250
  return runner.recordCoordinatorDecision(String(args.runId || ""), args);
238
251
  case "cw_audit_summary":
239
252
  return runner.auditSummary(String(args.runId || ""));
253
+ case "cw_audit_verify":
254
+ return (0, capability_core_1.auditVerify)(runner, args);
240
255
  case "cw_audit_worker":
241
256
  return runner.workerAudit(String(args.runId || ""), String(args.workerId || ""));
242
257
  case "cw_audit_provenance":
@@ -386,7 +401,7 @@ function callTool(name, args) {
386
401
  case "cw_run_show":
387
402
  return (0, capability_core_1.runShow)((0, capability_core_1.runRegistryFor)(args, runner), String(args.runId || ""), args);
388
403
  case "cw_run_resume":
389
- return (0, capability_core_1.runResume)((0, capability_core_1.runRegistryFor)(args, runner), String(args.runId || ""), args);
404
+ return (0, capability_core_1.runResume)((0, capability_core_1.runRegistryFor)(args, runner), runner, String(args.runId || ""), args);
390
405
  case "cw_run_archive":
391
406
  return (0, capability_core_1.runArchive)((0, capability_core_1.runRegistryFor)(args, runner), (0, capability_core_1.optionalString)(args.runId), args);
392
407
  case "cw_run_rerun":
@@ -397,6 +412,8 @@ function callTool(name, args) {
397
412
  return (0, capability_core_1.runImportArchive)(runner, args);
398
413
  case "cw_run_verify_import":
399
414
  return (0, capability_core_1.runVerifyImport)(runner, String(args.runId || ""), args);
415
+ case "cw_run_inspect_archive":
416
+ return (0, capability_core_1.runInspectArchive)(runner, args);
400
417
  case "cw_run_drive":
401
418
  return (0, capability_core_1.runDrivePreview)(runner, args);
402
419
  case "cw_run_drive_step":
@@ -442,22 +459,8 @@ function callTool(name, args) {
442
459
  // (identical to `cw workbench serve --json`). The CLI default additionally
443
460
  // starts the localhost host — declared divergence (see capability-registry).
444
461
  return (0, workbench_1.buildWorkbenchServeDescriptor)(runner, { ...args, once: true });
445
- default: {
446
- // ---- Dynamic capability dispatch fallback (v0.1.53) ---------------
447
- // Mechanism: try the capability registry before failing. Policy: which
448
- // tools exist is declared via registerCapabilityHandler at load time.
449
- const capabilityId = (0, capability_registry_1.resolveMcpTool)(name);
450
- if (capabilityId) {
451
- const handler = (0, capability_registry_1.getCapabilityHandler)(capabilityId);
452
- if (handler) {
453
- return (0, capability_registry_1.dispatchCapability)(capabilityId, args, {
454
- runner,
455
- cwd: process.cwd()
456
- });
457
- }
458
- }
462
+ default:
459
463
  throw new Error(`Unknown tool: ${name}`);
460
- }
461
464
  }
462
465
  }
463
466
  finally {
@@ -484,161 +487,11 @@ function requiredToolArguments(name, value) {
484
487
  return args;
485
488
  }
486
489
  function requiredArgsForTool(name) {
487
- if (name === "cw_plan" || name === "cw_init")
488
- return ["workflowId"];
489
- if (name === "cw_app_run")
490
- return ["appId"];
491
- if (name === "cw_node_show")
492
- return ["runId", "nodeId"];
493
- if (name === "cw_eval_replay")
494
- return ["snapshot|snapshotId|path"];
495
- if (name === "cw_eval_compare")
496
- return ["baseline|baselinePath", "replay|replayPath"];
497
- if (name === "cw_eval_score" || name === "cw_eval_report")
498
- return ["replay|replayPath|path"];
499
- if (name === "cw_eval_gate")
500
- return ["suite|suiteId|path"];
501
- if (name === "cw_topology_show" || name === "cw_topology_validate")
502
- return ["topologyId|id"];
503
- if (name === "cw_topology_apply")
504
- return ["runId", "topologyId|id"];
505
- if (name === "cw_sandbox_show")
506
- return ["profileId"];
507
- if (name === "cw_sandbox_validate")
508
- return ["profileFile"];
509
- if (name === "cw_schedule_delete" || name === "cw_schedule_complete" || name === "cw_schedule_pause" || name === "cw_schedule_resume" || name === "cw_schedule_run_now")
510
- return ["id"];
511
- if (name === "cw_routine_delete")
512
- return ["id"];
513
- if (name === "cw_routine_fire")
514
- return ["kind"];
515
- if (name === "cw_approve" || name === "cw_reject")
516
- return ["runId", "targetKind|kind", "targetId|target"];
517
- if (name === "cw_comment_add")
518
- return ["runId", "targetKind|kind", "targetId|target", "body|message|text"];
519
- if (name === "cw_handoff")
520
- return ["runId", "targetKind|kind", "targetId|target", "to|toActor"];
521
- if (name === "cw_run_show" || name === "cw_run_resume" || name === "cw_run_rerun" || name === "cw_run_export" || name === "cw_run_verify_import")
522
- return ["runId"];
523
- if (name === "cw_run_import")
524
- return ["archive|path|file"];
525
- if (name === "cw_run_archive")
526
- return ["runId|olderThanDays"];
527
- if (name === "cw_gc_verify")
528
- return ["runId"];
529
- if (name === "cw_telemetry_verify")
530
- return ["runId"];
531
- if (name === "cw_queue_show")
532
- return ["id"];
533
- if (name.endsWith("_show")) {
534
- if (name.includes("_role_"))
535
- return ["runId", "roleId"];
536
- if (name.includes("_group_"))
537
- return ["runId", "groupId"];
538
- if (name.includes("_membership_"))
539
- return ["runId", "membershipId"];
540
- if (name.includes("_fanout_"))
541
- return ["runId", "fanoutId"];
542
- if (name.includes("_fanin_"))
543
- return ["runId", "faninId"];
544
- if (name.includes("_candidate_"))
545
- return ["runId", "candidateId"];
546
- if (name.includes("_feedback_"))
547
- return ["runId", "feedbackId"];
548
- if (name.includes("_worker_"))
549
- return ["runId", "workerId"];
550
- }
551
- if (name.startsWith("cw_") && [
552
- "cw_status",
553
- "cw_next",
554
- "cw_state_check",
555
- "cw_contract_show",
556
- "cw_node_list",
557
- "cw_node_graph",
558
- "cw_operator_status",
559
- "cw_operator_graph",
560
- "cw_operator_report",
561
- "cw_worker_summary",
562
- "cw_workbench_view",
563
- "cw_candidate_summary",
564
- "cw_feedback_summary",
565
- "cw_commit_summary",
566
- "cw_multi_agent_summary",
567
- "cw_multi_agent_graph",
568
- "cw_multi_agent_dependencies",
569
- "cw_multi_agent_failures",
570
- "cw_multi_agent_evidence",
571
- "cw_evidence_reasoning",
572
- "cw_evidence_reasoning_refresh",
573
- "cw_summary_refresh",
574
- "cw_summary_show",
575
- "cw_metrics_show",
576
- "cw_blackboard_summarize",
577
- "cw_multi_agent_summarize",
578
- "cw_multi_agent_graph_compact",
579
- "cw_multi_agent_status",
580
- "cw_multi_agent_step",
581
- "cw_multi_agent_blackboard",
582
- "cw_multi_agent_score",
583
- "cw_multi_agent_select",
584
- "cw_eval_snapshot",
585
- "cw_multi_agent_run_create",
586
- "cw_multi_agent_run_transition",
587
- "cw_multi_agent_run_show",
588
- "cw_multi_agent_role_create",
589
- "cw_multi_agent_group_create",
590
- "cw_multi_agent_membership_create",
591
- "cw_multi_agent_fanout_create",
592
- "cw_multi_agent_fanin_collect",
593
- "cw_topology_summary",
594
- "cw_topology_graph",
595
- "cw_blackboard_summary",
596
- "cw_blackboard_graph",
597
- "cw_blackboard_resolve",
598
- "cw_blackboard_topic_create",
599
- "cw_blackboard_message_post",
600
- "cw_blackboard_message_list",
601
- "cw_blackboard_context_put",
602
- "cw_blackboard_artifact_add",
603
- "cw_blackboard_artifact_list",
604
- "cw_blackboard_snapshot",
605
- "cw_coordinator_summary",
606
- "cw_coordinator_decision",
607
- "cw_audit_summary",
608
- "cw_audit_worker",
609
- "cw_audit_provenance",
610
- "cw_audit_multi_agent",
611
- "cw_audit_policy",
612
- "cw_audit_role",
613
- "cw_audit_blackboard",
614
- "cw_audit_judge",
615
- "cw_audit_attest",
616
- "cw_audit_decision",
617
- "cw_dispatch",
618
- "cw_result",
619
- "cw_commit",
620
- "cw_report",
621
- "cw_worker_list",
622
- "cw_worker_manifest",
623
- "cw_worker_output",
624
- "cw_worker_fail",
625
- "cw_worker_validate",
626
- "cw_candidate_list",
627
- "cw_candidate_register",
628
- "cw_candidate_score",
629
- "cw_candidate_rank",
630
- "cw_candidate_select",
631
- "cw_candidate_reject",
632
- "cw_review_status",
633
- "cw_review_policy",
634
- "cw_comment_list",
635
- "cw_feedback_list",
636
- "cw_feedback_collect",
637
- "cw_feedback_task",
638
- "cw_feedback_resolve"
639
- ].includes(name))
640
- return ["runId"];
641
- return [];
490
+ // Required args are declared once per capability as data on the mcp binding
491
+ // (McpBinding.requiredArgs). This is a pure data read of the parity-gated
492
+ // registry no string-pattern ladder.
493
+ const descriptor = capability_registry_1.CAPABILITY_REGISTRY.find((capability) => capability.mcp?.tool === name);
494
+ return descriptor?.mcp?.requiredArgs ?? [];
642
495
  }
643
496
  function toolDefinitions() {
644
497
  return [
@@ -1036,6 +889,7 @@ function toolDefinitions() {
1036
889
  message: arraySchema("Blackboard message ids")
1037
890
  }),
1038
891
  tool("cw_audit_summary", "Read durable trust/audit summary for a run.", runIdSchema()),
892
+ tool("cw_audit_verify", "Re-prove a run's trust-audit hash chain offline: recompute every event hash from genesis + check chain linkage; a forged, edited, truncated, or unchained-injected event fails it. Peer of `cw audit verify`; fail-closed.", runIdSchema()),
1039
893
  tool("cw_audit_worker", "Read trust/audit events for one worker.", workerIdSchema()),
1040
894
  tool("cw_audit_provenance", "Inspect evidence provenance for a run, worker, candidate, or commit.", {
1041
895
  ...runIdSchema(),
@@ -1466,6 +1320,12 @@ function toolDefinitions() {
1466
1320
  runId: stringSchema("Imported run id to verify"),
1467
1321
  cwd: stringSchema("Restored repo workspace")
1468
1322
  }),
1323
+ tool("cw_run_inspect_archive", "Read-only integrity inspection of a portable run archive without importing it: re-proves every file digest/size, the manifest digest + file count, and the whole-archive sha256, naming any offending file. Writes nothing.", {
1324
+ archive: stringSchema("Archive path"),
1325
+ path: stringSchema("Alias for archive"),
1326
+ file: stringSchema("Alias for archive"),
1327
+ cwd: stringSchema("Invocation workspace")
1328
+ }),
1469
1329
  tool("cw_run_drive", "Preview the next agent-delegation drive step for a run (read-only, deterministic). Counts come from state; no spawn, no mutation.", {
1470
1330
  runId: stringSchema("Run id to preview"),
1471
1331
  cwd: stringSchema("Run workspace")
@@ -1561,9 +1421,10 @@ function toolDefinitions() {
1561
1421
  scope: stringSchema("home (default, cross-repo) or repo"),
1562
1422
  runId: stringSchema("Run id to verify")
1563
1423
  }),
1564
- tool("cw_telemetry_verify", "Re-prove a run's telemetry attestation ledger offline: prevHash chain linkage + independent per-record hash recompute (never trusts the stored hash). A forged or edited record fails it. Peer of `cw telemetry verify`.", {
1424
+ tool("cw_telemetry_verify", "Re-prove a run's telemetry attestation ledger offline: prevHash chain linkage + independent per-record hash recompute (never trusts the stored hash), and optionally re-run ed25519 checks with a public key. A forged or edited record fails it. Peer of `cw telemetry verify`.", {
1565
1425
  cwd: stringSchema("Repo workspace"),
1566
- runId: stringSchema("Run id to verify")
1426
+ runId: stringSchema("Run id to verify"),
1427
+ pubkey: stringSchema("Optional inline PEM or path to a public key for re-checking attested signatures")
1567
1428
  }),
1568
1429
  tool("cw_history", "Read a cross-repo unified run timeline (newest first), deterministic and paginated, with provenance links.", {
1569
1430
  cwd: stringSchema("Repo workspace"),
@@ -0,0 +1,84 @@
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.buildMultiAgentGraphFromState = buildMultiAgentGraphFromState;
7
+ // Multi-agent provenance-graph builder (god-module carve, FreeBSD router pattern
8
+ // — cf. orchestrator/topology-operations.ts and run-registry/derive.ts). This is
9
+ // the largest cohesive renderer in the module: it walks the resolved
10
+ // MultiAgentState and emits the nodes/edges that the operator-UX and orchestrator
11
+ // graph surfaces consume. BEHAVIOR-PRESERVING — pure code movement, zero logic
12
+ // change. multi-agent.ts keeps the public buildMultiAgentGraph(run) entry point
13
+ // as a thin delegator (it resolves the state via ensureMultiAgentState, then
14
+ // calls buildMultiAgentGraphFromState) so the state is still ensured exactly
15
+ // once, in the same order, with the same side effects.
16
+ const node_fs_1 = __importDefault(require("node:fs"));
17
+ const paths_1 = require("./paths");
18
+ const helpers_1 = require("./helpers");
19
+ function buildMultiAgentGraphFromState(run, state) {
20
+ const root = (0, paths_1.multiAgentRoot)(run);
21
+ const nodes = [];
22
+ const edges = [];
23
+ for (const record of state.runs) {
24
+ nodes.push({ id: `${run.id}:multi-agent:${record.id}`, kind: "multi-agent-run", status: record.status, label: record.title || record.id, path: (0, paths_1.recordPath)(run, "runs", record.id) });
25
+ edges.push({ from: `${run.id}:run`, to: `${run.id}:multi-agent:${record.id}` });
26
+ if (record.blackboardId)
27
+ edges.push({ from: `${run.id}:multi-agent:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
28
+ if (record.parentMultiAgentRunId)
29
+ edges.push({ from: `${run.id}:multi-agent:${record.parentMultiAgentRunId}`, to: `${run.id}:multi-agent:${record.id}`, label: "child" });
30
+ }
31
+ for (const record of state.roles) {
32
+ nodes.push({ id: `${run.id}:multi-agent:role:${record.id}`, kind: "agent-role", status: record.status, label: record.title, path: (0, paths_1.recordPath)(run, "roles", record.id) });
33
+ edges.push({ from: `${run.id}:multi-agent:${record.multiAgentRunId}`, to: `${run.id}:multi-agent:role:${record.id}` });
34
+ if (record.blackboardId)
35
+ edges.push({ from: `${run.id}:multi-agent:role:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
36
+ }
37
+ for (const record of state.groups) {
38
+ nodes.push({ id: `${run.id}:multi-agent:group:${record.id}`, kind: "agent-group", status: record.status, label: record.title || record.id, path: (0, paths_1.recordPath)(run, "groups", record.id) });
39
+ edges.push({ from: `${run.id}:multi-agent:${record.multiAgentRunId}`, to: `${run.id}:multi-agent:group:${record.id}` });
40
+ if (record.blackboardId)
41
+ edges.push({ from: `${run.id}:multi-agent:group:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
42
+ for (const taskId of record.taskIds)
43
+ edges.push({ from: `${run.id}:multi-agent:group:${record.id}`, to: `${run.id}:task:${taskId}`, label: "task" });
44
+ }
45
+ for (const record of state.fanouts) {
46
+ nodes.push({ id: `${run.id}:multi-agent:fanout:${record.id}`, kind: "agent-fanout", status: record.status, label: record.reason, path: (0, paths_1.recordPath)(run, "fanouts", record.id) });
47
+ edges.push({ from: `${run.id}:multi-agent:group:${record.groupId}`, to: `${run.id}:multi-agent:fanout:${record.id}` });
48
+ for (const dispatchId of record.dispatchIds)
49
+ edges.push({ from: `${run.id}:multi-agent:fanout:${record.id}`, to: `${run.id}:dispatch:${dispatchId}`, label: "dispatch" });
50
+ }
51
+ for (const record of state.memberships) {
52
+ nodes.push({ id: `${run.id}:multi-agent:membership:${record.id}`, kind: "agent-membership", status: record.status, label: `${record.roleId}/${record.taskId}`, path: (0, paths_1.recordPath)(run, "memberships", record.id) });
53
+ edges.push({ from: `${run.id}:multi-agent:group:${record.groupId}`, to: `${run.id}:multi-agent:membership:${record.id}` });
54
+ edges.push({ from: `${run.id}:multi-agent:role:${record.roleId}`, to: `${run.id}:multi-agent:membership:${record.id}` });
55
+ edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:task:${record.taskId}`, label: "task" });
56
+ if (record.workerId)
57
+ edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:worker:${record.workerId}`, label: "worker" });
58
+ if (record.resultNodeId)
59
+ edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: record.resultNodeId, label: "result" });
60
+ if (record.verifierNodeId)
61
+ edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: record.verifierNodeId, label: "verifier" });
62
+ if (record.blackboardId)
63
+ edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
64
+ for (const artifactId of record.blackboardArtifactRefIds || [])
65
+ edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:blackboard:artifact:${artifactId}`, label: "evidence" });
66
+ for (const messageId of record.blackboardMessageIds || [])
67
+ edges.push({ from: `${run.id}:multi-agent:membership:${record.id}`, to: `${run.id}:blackboard:message:${messageId}`, label: "message" });
68
+ }
69
+ for (const record of state.fanins) {
70
+ nodes.push({ id: `${run.id}:multi-agent:fanin:${record.id}`, kind: "agent-fanin", status: record.status, label: record.strategy, path: (0, paths_1.recordPath)(run, "fanins", record.id) });
71
+ edges.push({ from: `${run.id}:multi-agent:group:${record.groupId}`, to: `${run.id}:multi-agent:fanin:${record.id}` });
72
+ if (record.fanoutId)
73
+ edges.push({ from: `${run.id}:multi-agent:fanout:${record.fanoutId}`, to: `${run.id}:multi-agent:fanin:${record.id}` });
74
+ for (const membershipId of record.reportedMembershipIds)
75
+ edges.push({ from: `${run.id}:multi-agent:membership:${membershipId}`, to: `${run.id}:multi-agent:fanin:${record.id}`, label: "reported" });
76
+ for (const membershipId of record.missingMembershipIds)
77
+ edges.push({ from: `${run.id}:multi-agent:membership:${membershipId}`, to: `${run.id}:multi-agent:fanin:${record.id}`, label: "missing" });
78
+ if (record.blackboardId)
79
+ edges.push({ from: `${run.id}:multi-agent:fanin:${record.id}`, to: `${run.id}:blackboard:${record.blackboardId}`, label: "blackboard" });
80
+ }
81
+ if (!node_fs_1.default.existsSync(root))
82
+ node_fs_1.default.mkdirSync(root, { recursive: true });
83
+ return { nodes, edges: (0, helpers_1.uniqueEdges)(edges) };
84
+ }
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MULTI_AGENT_SCHEMA_VERSION = void 0;
4
+ exports.indexRow = indexRow;
5
+ exports.assertNoRecordPathCollisions = assertNoRecordPathCollisions;
6
+ exports.pluralKind = pluralKind;
7
+ exports.statusToNodeStatus = statusToNodeStatus;
8
+ exports.assertLifecycleTransition = assertLifecycleTransition;
9
+ exports.lifecycleEvent = lifecycleEvent;
10
+ exports.isMembershipReported = isMembershipReported;
11
+ exports.touch = touch;
12
+ exports.createId = createId;
13
+ exports.compact = compact;
14
+ exports.unique = unique;
15
+ exports.countBy = countBy;
16
+ exports.uniqueEdges = uniqueEdges;
17
+ const state_1 = require("../state");
18
+ exports.MULTI_AGENT_SCHEMA_VERSION = 1;
19
+ function indexRow(record) {
20
+ return { id: record.id, status: record.status, updatedAt: record.updatedAt };
21
+ }
22
+ function assertNoRecordPathCollisions(label, records) {
23
+ const seen = new Map();
24
+ for (const record of records) {
25
+ const safe = (0, state_1.safeFileName)(record.id);
26
+ const existing = seen.get(safe);
27
+ if (existing && existing !== record.id) {
28
+ throw new Error(`${label} ids ${existing} and ${record.id} collide on safe file name ${safe}`);
29
+ }
30
+ seen.set(safe, record.id);
31
+ }
32
+ }
33
+ function pluralKind(kind) {
34
+ switch (kind) {
35
+ case "multi-agent-run":
36
+ return "runs";
37
+ case "agent-role":
38
+ return "roles";
39
+ case "agent-group":
40
+ return "groups";
41
+ case "agent-membership":
42
+ return "memberships";
43
+ case "agent-fanout":
44
+ return "fanouts";
45
+ case "agent-fanin":
46
+ return "fanins";
47
+ default:
48
+ return `${kind}s`;
49
+ }
50
+ }
51
+ function statusToNodeStatus(status) {
52
+ switch (status) {
53
+ case "completed":
54
+ case "reported":
55
+ case "ready":
56
+ return "completed";
57
+ case "running":
58
+ case "forming":
59
+ case "collecting":
60
+ case "verifying":
61
+ case "assigned":
62
+ case "active":
63
+ case "dispatched":
64
+ return "running";
65
+ case "blocked":
66
+ return "blocked";
67
+ case "failed":
68
+ return "failed";
69
+ case "cancelled":
70
+ case "rejected":
71
+ return "rejected";
72
+ default:
73
+ return "pending";
74
+ }
75
+ }
76
+ function assertLifecycleTransition(from, to) {
77
+ const allowed = {
78
+ planned: ["forming", "running", "failed", "cancelled"],
79
+ forming: ["running", "failed", "cancelled"],
80
+ running: ["collecting", "completed", "failed", "cancelled"],
81
+ collecting: ["verifying", "completed", "failed", "cancelled"],
82
+ verifying: ["completed", "failed", "cancelled"],
83
+ completed: [],
84
+ failed: [],
85
+ cancelled: []
86
+ };
87
+ if (from === to)
88
+ return;
89
+ if (!allowed[from].includes(to))
90
+ throw new Error(`Invalid MultiAgentRun lifecycle transition: ${from} -> ${to}`);
91
+ }
92
+ function lifecycleEvent(from, to, reason, actor = "cw", metadata) {
93
+ return {
94
+ at: new Date().toISOString(),
95
+ from,
96
+ to,
97
+ actor,
98
+ reason,
99
+ metadata: compact(metadata)
100
+ };
101
+ }
102
+ function isMembershipReported(membership) {
103
+ return (membership.status === "reported" || membership.status === "verified") && membership.evidenceRefs.length > 0;
104
+ }
105
+ function touch(record) {
106
+ record.updatedAt = new Date().toISOString();
107
+ return record;
108
+ }
109
+ // Deterministic record id (FreeBSD-audit L12/L13): the record's POSITION in its
110
+ // per-run collection, threaded from the call site. No wall-clock stamp, no PRNG
111
+ // suffix — re-running the same multi-agent topology mints byte-identical ids, so
112
+ // snapshot/replay digests match. Each call site already asserts the minted id is
113
+ // unique within its collection, and these collections only ever append.
114
+ function createId(prefix, seq) {
115
+ return `${prefix}-${String(seq).padStart(4, "0")}`;
116
+ }
117
+ function compact(value) {
118
+ if (!value)
119
+ return undefined;
120
+ const entries = Object.entries(value).filter(([, entry]) => entry !== undefined);
121
+ return entries.length ? Object.fromEntries(entries) : undefined;
122
+ }
123
+ function unique(values) {
124
+ return Array.from(new Set(values.filter(Boolean))).sort();
125
+ }
126
+ function countBy(items, key) {
127
+ const counts = {};
128
+ for (const item of items) {
129
+ const value = key(item);
130
+ counts[value] = (counts[value] || 0) + 1;
131
+ }
132
+ return counts;
133
+ }
134
+ function uniqueEdges(edges) {
135
+ const seen = new Set();
136
+ const result = [];
137
+ for (const edge of edges) {
138
+ const key = `${edge.from}\0${edge.to}\0${edge.label || ""}`;
139
+ if (seen.has(key))
140
+ continue;
141
+ seen.add(key);
142
+ result.push(edge);
143
+ }
144
+ return result;
145
+ }
@@ -0,0 +1,22 @@
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.multiAgentRoot = multiAgentRoot;
7
+ exports.recordPath = recordPath;
8
+ // Filesystem path resolution for multi-agent records (god-module carve, FreeBSD
9
+ // router pattern). BEHAVIOR-PRESERVING — pure code movement, zero logic change.
10
+ // These two free functions derive paths from run.paths only; they are shared by
11
+ // the persistence, node-append, and graph clusters, so they live in their own
12
+ // leaf module to keep those clusters free of a circular import back to
13
+ // multi-agent.ts. Re-exported there is unnecessary (both are private), but the
14
+ // derivation is byte-identical to the originals.
15
+ const node_path_1 = __importDefault(require("node:path"));
16
+ const state_1 = require("../state");
17
+ function multiAgentRoot(run) {
18
+ return run.paths.multiAgentDir || node_path_1.default.join(run.paths.runDir, "multi-agent");
19
+ }
20
+ function recordPath(run, kind, id) {
21
+ return node_path_1.default.join(multiAgentRoot(run), kind, `${(0, state_1.safeFileName)(id)}.json`);
22
+ }