cool-workflow 0.1.79 → 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 (131) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +51 -3
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +64 -0
  6. package/apps/architecture-review-fast/workflow.js +153 -0
  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/agent-config.js +21 -7
  12. package/dist/candidate-scoring.js +42 -22
  13. package/dist/capability-core.js +132 -17
  14. package/dist/capability-registry.js +138 -168
  15. package/dist/cli.js +97 -98
  16. package/dist/collaboration.js +5 -6
  17. package/dist/commit.js +20 -6
  18. package/dist/compare.js +18 -0
  19. package/dist/coordinator/classify.js +45 -0
  20. package/dist/coordinator/paths.js +42 -0
  21. package/dist/coordinator/util.js +129 -0
  22. package/dist/coordinator.js +127 -300
  23. package/dist/dispatch.js +35 -0
  24. package/dist/drive.js +79 -6
  25. package/dist/error-feedback.js +8 -4
  26. package/dist/evidence-reasoning.js +3 -3
  27. package/dist/execution-backend/agent.js +331 -0
  28. package/dist/execution-backend/probes.js +96 -0
  29. package/dist/execution-backend/util.js +47 -0
  30. package/dist/execution-backend.js +73 -421
  31. package/dist/mcp-server.js +79 -183
  32. package/dist/multi-agent/graph.js +84 -0
  33. package/dist/multi-agent/helpers.js +145 -0
  34. package/dist/multi-agent/paths.js +22 -0
  35. package/dist/multi-agent-eval/format.js +194 -0
  36. package/dist/multi-agent-eval/normalize.js +51 -0
  37. package/dist/multi-agent-eval.js +39 -244
  38. package/dist/multi-agent-host.js +0 -19
  39. package/dist/multi-agent.js +125 -314
  40. package/dist/node-snapshot.js +3 -3
  41. package/dist/observability/format.js +61 -0
  42. package/dist/observability/intake.js +98 -0
  43. package/dist/observability.js +14 -160
  44. package/dist/operator-ux/format.js +364 -0
  45. package/dist/operator-ux.js +22 -363
  46. package/dist/orchestrator/lifecycle-operations.js +2 -1
  47. package/dist/orchestrator/report.js +8 -0
  48. package/dist/orchestrator.js +26 -9
  49. package/dist/reclamation.js +26 -21
  50. package/dist/run-export.js +494 -25
  51. package/dist/run-registry/derive.js +172 -0
  52. package/dist/run-registry/format.js +124 -0
  53. package/dist/run-registry/gc.js +251 -0
  54. package/dist/run-registry/policy.js +16 -0
  55. package/dist/run-registry/queue.js +116 -0
  56. package/dist/run-registry.js +89 -597
  57. package/dist/run-state-schema.js +1 -0
  58. package/dist/sandbox-profile.js +43 -2
  59. package/dist/state-explosion/format.js +159 -0
  60. package/dist/state-explosion/helpers.js +82 -0
  61. package/dist/state-explosion.js +165 -304
  62. package/dist/state-node.js +19 -4
  63. package/dist/telemetry-attestation.js +55 -0
  64. package/dist/telemetry-demo.js +15 -3
  65. package/dist/telemetry-ledger.js +60 -15
  66. package/dist/topology.js +25 -8
  67. package/dist/triggers.js +33 -14
  68. package/dist/trust-audit.js +145 -33
  69. package/dist/version.js +1 -1
  70. package/dist/worker-isolation/helpers.js +51 -0
  71. package/dist/worker-isolation/paths.js +46 -0
  72. package/dist/worker-isolation.js +39 -115
  73. package/docs/agent-delegation-drive.7.md +71 -0
  74. package/docs/canonical-workflow-apps.7.md +37 -0
  75. package/docs/cli-mcp-parity.7.md +16 -0
  76. package/docs/contract-migration-tooling.7.md +6 -0
  77. package/docs/control-plane-scheduling.7.md +6 -0
  78. package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +40 -0
  79. package/docs/durable-state-and-locking.7.md +8 -0
  80. package/docs/evidence-adoption-reasoning-chain.7.md +6 -0
  81. package/docs/execution-backends.7.md +6 -0
  82. package/docs/index.md +2 -0
  83. package/docs/launch/demo.tape +28 -0
  84. package/docs/launch/launch-kit.md +96 -17
  85. package/docs/launch/pre-launch-checklist.md +53 -0
  86. package/docs/multi-agent-cli-mcp-surface.7.md +8 -0
  87. package/docs/multi-agent-eval-replay-harness.7.md +6 -0
  88. package/docs/multi-agent-operator-ux.7.md +6 -0
  89. package/docs/multi-agent-trust-policy-audit.7.md +27 -0
  90. package/docs/node-snapshot-diff-replay.7.md +6 -0
  91. package/docs/observability-cost-accounting.7.md +6 -0
  92. package/docs/project-index.md +27 -6
  93. package/docs/real-execution-backends.7.md +6 -0
  94. package/docs/release-and-migration.7.md +8 -0
  95. package/docs/release-tooling.7.md +6 -0
  96. package/docs/routines.md +23 -0
  97. package/docs/run-registry-control-plane.7.md +89 -2
  98. package/docs/run-retention-reclamation.7.md +8 -0
  99. package/docs/source-context-profiles.7.md +119 -0
  100. package/docs/state-explosion-management.7.md +13 -0
  101. package/docs/team-collaboration.7.md +6 -0
  102. package/docs/trust-model.md +267 -0
  103. package/docs/unix-principles.md +49 -1
  104. package/docs/vendor-manifest-loadability.7.md +43 -0
  105. package/docs/web-desktop-workbench.7.md +6 -0
  106. package/manifest/plugin.manifest.json +1 -1
  107. package/manifest/source-context-profiles.json +142 -0
  108. package/package.json +4 -1
  109. package/scripts/agents/builtin-templates.json +7 -0
  110. package/scripts/agents/claude-p-agent.js +129 -43
  111. package/scripts/architecture-review-fast.js +362 -0
  112. package/scripts/bump-version.js +5 -10
  113. package/scripts/canonical-apps-list.js +64 -0
  114. package/scripts/canonical-apps.js +36 -4
  115. package/scripts/coverage-gate.js +211 -0
  116. package/scripts/dogfood-release.js +1 -1
  117. package/scripts/golden-path.js +4 -4
  118. package/scripts/parity-check.js +5 -0
  119. package/scripts/release-check.js +5 -1
  120. package/scripts/source-context.js +291 -0
  121. package/scripts/version-sync-check.js +5 -7
  122. package/skills/ci-triage/SKILL.md +50 -0
  123. package/skills/ci-triage/agents/openai.yaml +4 -0
  124. package/skills/cool-workflow/SKILL.md +4 -1
  125. package/skills/deploy-check/SKILL.md +55 -0
  126. package/skills/deploy-check/agents/openai.yaml +4 -0
  127. package/skills/design-qa/SKILL.md +49 -0
  128. package/skills/design-qa/agents/openai.yaml +4 -0
  129. package/skills/pr-review/SKILL.md +45 -0
  130. package/skills/pr-review/agents/openai.yaml +4 -0
  131. 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,11 +401,19 @@ 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":
393
408
  return (0, capability_core_1.runRerun)((0, capability_core_1.runRegistryFor)(args, runner), String(args.runId || ""), args);
409
+ case "cw_run_export":
410
+ return (0, capability_core_1.runExportArchive)(runner, String(args.runId || ""), args);
411
+ case "cw_run_import":
412
+ return (0, capability_core_1.runImportArchive)(runner, args);
413
+ case "cw_run_verify_import":
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);
394
417
  case "cw_run_drive":
395
418
  return (0, capability_core_1.runDrivePreview)(runner, args);
396
419
  case "cw_run_drive_step":
@@ -436,22 +459,8 @@ function callTool(name, args) {
436
459
  // (identical to `cw workbench serve --json`). The CLI default additionally
437
460
  // starts the localhost host — declared divergence (see capability-registry).
438
461
  return (0, workbench_1.buildWorkbenchServeDescriptor)(runner, { ...args, once: true });
439
- default: {
440
- // ---- Dynamic capability dispatch fallback (v0.1.53) ---------------
441
- // Mechanism: try the capability registry before failing. Policy: which
442
- // tools exist is declared via registerCapabilityHandler at load time.
443
- const capabilityId = (0, capability_registry_1.resolveMcpTool)(name);
444
- if (capabilityId) {
445
- const handler = (0, capability_registry_1.getCapabilityHandler)(capabilityId);
446
- if (handler) {
447
- return (0, capability_registry_1.dispatchCapability)(capabilityId, args, {
448
- runner,
449
- cwd: process.cwd()
450
- });
451
- }
452
- }
462
+ default:
453
463
  throw new Error(`Unknown tool: ${name}`);
454
- }
455
464
  }
456
465
  }
457
466
  finally {
@@ -478,159 +487,11 @@ function requiredToolArguments(name, value) {
478
487
  return args;
479
488
  }
480
489
  function requiredArgsForTool(name) {
481
- if (name === "cw_plan" || name === "cw_init")
482
- return ["workflowId"];
483
- if (name === "cw_app_run")
484
- return ["appId"];
485
- if (name === "cw_node_show")
486
- return ["runId", "nodeId"];
487
- if (name === "cw_eval_replay")
488
- return ["snapshot|snapshotId|path"];
489
- if (name === "cw_eval_compare")
490
- return ["baseline|baselinePath", "replay|replayPath"];
491
- if (name === "cw_eval_score" || name === "cw_eval_report")
492
- return ["replay|replayPath|path"];
493
- if (name === "cw_eval_gate")
494
- return ["suite|suiteId|path"];
495
- if (name === "cw_topology_show" || name === "cw_topology_validate")
496
- return ["topologyId|id"];
497
- if (name === "cw_topology_apply")
498
- return ["runId", "topologyId|id"];
499
- if (name === "cw_sandbox_show")
500
- return ["profileId"];
501
- if (name === "cw_sandbox_validate")
502
- return ["profileFile"];
503
- if (name === "cw_schedule_delete" || name === "cw_schedule_complete" || name === "cw_schedule_pause" || name === "cw_schedule_resume" || name === "cw_schedule_run_now")
504
- return ["id"];
505
- if (name === "cw_routine_delete")
506
- return ["id"];
507
- if (name === "cw_routine_fire")
508
- return ["kind"];
509
- if (name === "cw_approve" || name === "cw_reject")
510
- return ["runId", "targetKind|kind", "targetId|target"];
511
- if (name === "cw_comment_add")
512
- return ["runId", "targetKind|kind", "targetId|target", "body|message|text"];
513
- if (name === "cw_handoff")
514
- return ["runId", "targetKind|kind", "targetId|target", "to|toActor"];
515
- if (name === "cw_run_show" || name === "cw_run_resume" || name === "cw_run_rerun")
516
- return ["runId"];
517
- if (name === "cw_run_archive")
518
- return ["runId|olderThanDays"];
519
- if (name === "cw_gc_verify")
520
- return ["runId"];
521
- if (name === "cw_telemetry_verify")
522
- return ["runId"];
523
- if (name === "cw_queue_show")
524
- return ["id"];
525
- if (name.endsWith("_show")) {
526
- if (name.includes("_role_"))
527
- return ["runId", "roleId"];
528
- if (name.includes("_group_"))
529
- return ["runId", "groupId"];
530
- if (name.includes("_membership_"))
531
- return ["runId", "membershipId"];
532
- if (name.includes("_fanout_"))
533
- return ["runId", "fanoutId"];
534
- if (name.includes("_fanin_"))
535
- return ["runId", "faninId"];
536
- if (name.includes("_candidate_"))
537
- return ["runId", "candidateId"];
538
- if (name.includes("_feedback_"))
539
- return ["runId", "feedbackId"];
540
- if (name.includes("_worker_"))
541
- return ["runId", "workerId"];
542
- }
543
- if (name.startsWith("cw_") && [
544
- "cw_status",
545
- "cw_next",
546
- "cw_state_check",
547
- "cw_contract_show",
548
- "cw_node_list",
549
- "cw_node_graph",
550
- "cw_operator_status",
551
- "cw_operator_graph",
552
- "cw_operator_report",
553
- "cw_worker_summary",
554
- "cw_workbench_view",
555
- "cw_candidate_summary",
556
- "cw_feedback_summary",
557
- "cw_commit_summary",
558
- "cw_multi_agent_summary",
559
- "cw_multi_agent_graph",
560
- "cw_multi_agent_dependencies",
561
- "cw_multi_agent_failures",
562
- "cw_multi_agent_evidence",
563
- "cw_evidence_reasoning",
564
- "cw_evidence_reasoning_refresh",
565
- "cw_summary_refresh",
566
- "cw_summary_show",
567
- "cw_metrics_show",
568
- "cw_blackboard_summarize",
569
- "cw_multi_agent_summarize",
570
- "cw_multi_agent_graph_compact",
571
- "cw_multi_agent_status",
572
- "cw_multi_agent_step",
573
- "cw_multi_agent_blackboard",
574
- "cw_multi_agent_score",
575
- "cw_multi_agent_select",
576
- "cw_eval_snapshot",
577
- "cw_multi_agent_run_create",
578
- "cw_multi_agent_run_transition",
579
- "cw_multi_agent_run_show",
580
- "cw_multi_agent_role_create",
581
- "cw_multi_agent_group_create",
582
- "cw_multi_agent_membership_create",
583
- "cw_multi_agent_fanout_create",
584
- "cw_multi_agent_fanin_collect",
585
- "cw_topology_summary",
586
- "cw_topology_graph",
587
- "cw_blackboard_summary",
588
- "cw_blackboard_graph",
589
- "cw_blackboard_resolve",
590
- "cw_blackboard_topic_create",
591
- "cw_blackboard_message_post",
592
- "cw_blackboard_message_list",
593
- "cw_blackboard_context_put",
594
- "cw_blackboard_artifact_add",
595
- "cw_blackboard_artifact_list",
596
- "cw_blackboard_snapshot",
597
- "cw_coordinator_summary",
598
- "cw_coordinator_decision",
599
- "cw_audit_summary",
600
- "cw_audit_worker",
601
- "cw_audit_provenance",
602
- "cw_audit_multi_agent",
603
- "cw_audit_policy",
604
- "cw_audit_role",
605
- "cw_audit_blackboard",
606
- "cw_audit_judge",
607
- "cw_audit_attest",
608
- "cw_audit_decision",
609
- "cw_dispatch",
610
- "cw_result",
611
- "cw_commit",
612
- "cw_report",
613
- "cw_worker_list",
614
- "cw_worker_manifest",
615
- "cw_worker_output",
616
- "cw_worker_fail",
617
- "cw_worker_validate",
618
- "cw_candidate_list",
619
- "cw_candidate_register",
620
- "cw_candidate_score",
621
- "cw_candidate_rank",
622
- "cw_candidate_select",
623
- "cw_candidate_reject",
624
- "cw_review_status",
625
- "cw_review_policy",
626
- "cw_comment_list",
627
- "cw_feedback_list",
628
- "cw_feedback_collect",
629
- "cw_feedback_task",
630
- "cw_feedback_resolve"
631
- ].includes(name))
632
- return ["runId"];
633
- 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 ?? [];
634
495
  }
635
496
  function toolDefinitions() {
636
497
  return [
@@ -704,24 +565,23 @@ function toolDefinitions() {
704
565
  contract: stringSchema("run-state | workflow-app (default run-state)"),
705
566
  cwd: stringSchema("Run workspace")
706
567
  }),
707
- tool("cw_operator_status", "Read the structured Operator UX run status.", runIdSchema()),
708
- tool("cw_operator_graph", "Read the structured Operator UX run graph.", runIdSchema()),
709
- tool("cw_operator_report", "Refresh and read the structured Operator UX report summary.", runIdSchema()),
710
- tool("cw_worker_summary", "Read the structured worker summary for a run.", runIdSchema()),
568
+ ...runIdCapabilityTools(["operator.status", "graph", "operator.report", "worker.summary"]),
711
569
  tool("cw_workbench_view", "Read the read-only five-panel Workbench view (graph, blackboard, worker, candidate, audit) for one run. Each panel embeds the verbatim `cw <cmd> --json` payload of one existing capability; absent panels are surfaced honestly. Peer of `cw workbench view`.", runIdSchema()),
712
570
  tool("cw_workbench_serve", "Describe the optional localhost-only, read-only Workbench host (bind, scope, routes). Returns the serve descriptor identical to `cw workbench serve --json`; MCP never starts the blocking server.", {
713
571
  cwd: stringSchema("Run workspace"),
714
572
  port: numberSchema("Optional loopback port, defaults to 7717"),
715
573
  scope: stringSchema("Registry scope: repo|home")
716
574
  }),
717
- tool("cw_candidate_summary", "Read the structured candidate summary for a run.", runIdSchema()),
718
- tool("cw_feedback_summary", "Read the structured feedback summary for a run.", runIdSchema()),
719
- tool("cw_commit_summary", "Read the structured commit summary for a run.", runIdSchema()),
720
- tool("cw_multi_agent_summary", "Read the structured multi-agent runtime summary for a run.", runIdSchema()),
721
- tool("cw_multi_agent_graph", "Read the structured multi-agent operator graph for a run.", runIdSchema()),
722
- tool("cw_multi_agent_dependencies", "Read derived multi-agent dependency edges for operator inspection.", runIdSchema()),
723
- tool("cw_multi_agent_failures", "Read failed, blocked, rejected, and ambiguous multi-agent records.", runIdSchema()),
724
- tool("cw_multi_agent_evidence", "Read evidence adoption status from worker output through selection and commit. Each row carries a derived rationaleStatus (explained|unexplained|not-applicable).", runIdSchema()),
575
+ ...runIdCapabilityTools([
576
+ "candidate.summary",
577
+ "feedback.summary",
578
+ "commit.summary",
579
+ "multi-agent.summary",
580
+ "multi-agent.graph",
581
+ "multi-agent.dependencies",
582
+ "multi-agent.failures",
583
+ "multi-agent.evidence"
584
+ ]),
725
585
  tool("cw_evidence_reasoning", "Explain WHY each evidence item was adopted/rejected/superseded/conflicting: a derived, fingerprinted reasoning chain with decision, basis, authority, rationale, and counterfactual per gate (fanin, candidate-score, selection, verifier, commit). Fails closed to `unexplained` when a rationale cannot be traced. Reads valid|stale|absent freshness against current source state.", {
726
586
  ...runIdSchema(),
727
587
  evidence: stringSchema("Optional evidence id/ref to explain a single adoption"),
@@ -1029,6 +889,7 @@ function toolDefinitions() {
1029
889
  message: arraySchema("Blackboard message ids")
1030
890
  }),
1031
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()),
1032
893
  tool("cw_audit_worker", "Read trust/audit events for one worker.", workerIdSchema()),
1033
894
  tool("cw_audit_provenance", "Inspect evidence provenance for a run, worker, candidate, or commit.", {
1034
895
  ...runIdSchema(),
@@ -1440,6 +1301,31 @@ function toolDefinitions() {
1440
1301
  scope: stringSchema("home (default, cross-repo) or repo"),
1441
1302
  reason: stringSchema("Rerun reason")
1442
1303
  }),
1304
+ tool("cw_run_export", "Export a run to a portable, digest-checked archive containing run-local artifacts, audit overlays, telemetry, reports, workers, and commit snapshots.", {
1305
+ runId: stringSchema("Run id to export"),
1306
+ cwd: stringSchema("Repo workspace containing .cw/runs/<run-id>"),
1307
+ output: stringSchema("Archive output path"),
1308
+ path: stringSchema("Alias for output"),
1309
+ archive: stringSchema("Alias for output")
1310
+ }),
1311
+ tool("cw_run_import", "Restore a portable run archive into a target repo and immediately verify restored file digests.", {
1312
+ archive: stringSchema("Archive path"),
1313
+ path: stringSchema("Alias for archive"),
1314
+ file: stringSchema("Alias for archive"),
1315
+ target: stringSchema("Restore target repo directory"),
1316
+ repo: stringSchema("Alias for target"),
1317
+ cwd: stringSchema("Invocation workspace")
1318
+ }),
1319
+ tool("cw_run_verify_import", "Verify an imported run against its restore manifest and telemetry chain; detects missing or tampered restored files.", {
1320
+ runId: stringSchema("Imported run id to verify"),
1321
+ cwd: stringSchema("Restored repo workspace")
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
+ }),
1443
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.", {
1444
1330
  runId: stringSchema("Run id to preview"),
1445
1331
  cwd: stringSchema("Run workspace")
@@ -1535,9 +1421,10 @@ function toolDefinitions() {
1535
1421
  scope: stringSchema("home (default, cross-repo) or repo"),
1536
1422
  runId: stringSchema("Run id to verify")
1537
1423
  }),
1538
- 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`.", {
1539
1425
  cwd: stringSchema("Repo workspace"),
1540
- 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")
1541
1428
  }),
1542
1429
  tool("cw_history", "Read a cross-repo unified run timeline (newest first), deterministic and paginated, with provenance links.", {
1543
1430
  cwd: stringSchema("Repo workspace"),
@@ -1560,6 +1447,15 @@ function tool(name, description, properties) {
1560
1447
  }
1561
1448
  };
1562
1449
  }
1450
+ function runIdCapabilityTools(capabilityIds) {
1451
+ return capabilityIds.map((capabilityId) => capabilityTool(capabilityId, runIdSchema()));
1452
+ }
1453
+ function capabilityTool(capabilityId, properties) {
1454
+ const descriptor = capability_registry_1.CAPABILITY_REGISTRY.find((capability) => capability.capability === capabilityId);
1455
+ if (!descriptor?.mcp)
1456
+ throw new Error(`MCP capability not declared: ${capabilityId}`);
1457
+ return tool(descriptor.mcp.tool, descriptor.summary, properties);
1458
+ }
1563
1459
  function stringSchema(description) {
1564
1460
  return { type: "string", description };
1565
1461
  }
@@ -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
+ }