cool-workflow 0.1.80 → 0.1.82

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 (122) 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 +62 -48
  12. package/dist/capability-core.js +152 -96
  13. package/dist/capability-registry.js +160 -174
  14. package/dist/cli.js +90 -100
  15. package/dist/collaboration.js +5 -6
  16. package/dist/commit.js +232 -209
  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 +126 -0
  21. package/dist/coordinator.js +127 -300
  22. package/dist/dispatch.js +46 -3
  23. package/dist/drive.js +7 -7
  24. package/dist/error-feedback.js +8 -4
  25. package/dist/evidence-reasoning.js +5 -2
  26. package/dist/execution-backend/agent.js +294 -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 +77 -450
  30. package/dist/gates.js +48 -0
  31. package/dist/mcp-server.js +34 -173
  32. package/dist/multi-agent/graph.js +84 -0
  33. package/dist/multi-agent/helpers.js +141 -0
  34. package/dist/multi-agent/ids.js +20 -0
  35. package/dist/multi-agent/paths.js +22 -0
  36. package/dist/multi-agent-eval/format.js +194 -0
  37. package/dist/multi-agent-eval/normalize.js +51 -0
  38. package/dist/multi-agent-eval.js +63 -242
  39. package/dist/multi-agent-host.js +53 -40
  40. package/dist/multi-agent-operator-ux.js +2 -1
  41. package/dist/multi-agent-trust.js +5 -5
  42. package/dist/multi-agent.js +125 -314
  43. package/dist/node-projection.js +59 -0
  44. package/dist/node-snapshot.js +11 -21
  45. package/dist/observability/format.js +61 -0
  46. package/dist/observability/intake.js +98 -0
  47. package/dist/observability.js +14 -160
  48. package/dist/operator-ux/format.js +364 -0
  49. package/dist/operator-ux.js +22 -363
  50. package/dist/orchestrator/lifecycle-operations.js +22 -1
  51. package/dist/orchestrator/report.js +8 -0
  52. package/dist/orchestrator.js +41 -10
  53. package/dist/reclamation.js +32 -55
  54. package/dist/run-export.js +138 -14
  55. package/dist/run-registry/derive.js +172 -0
  56. package/dist/run-registry/format.js +124 -0
  57. package/dist/run-registry/gc.js +251 -0
  58. package/dist/run-registry/policy.js +16 -0
  59. package/dist/run-registry/queue.js +116 -0
  60. package/dist/run-registry.js +78 -593
  61. package/dist/run-state-schema.js +1 -0
  62. package/dist/sandbox-profile.js +43 -2
  63. package/dist/scheduler.js +34 -4
  64. package/dist/state-explosion/format.js +159 -0
  65. package/dist/state-explosion/helpers.js +82 -0
  66. package/dist/state-explosion.js +65 -283
  67. package/dist/state-node.js +19 -4
  68. package/dist/telemetry-attestation.js +55 -0
  69. package/dist/telemetry-demo.js +15 -3
  70. package/dist/telemetry-ledger.js +60 -15
  71. package/dist/topology.js +50 -12
  72. package/dist/triggers.js +33 -14
  73. package/dist/trust-audit.js +215 -71
  74. package/dist/validation.js +328 -0
  75. package/dist/version.js +1 -1
  76. package/dist/worker-isolation/helpers.js +51 -0
  77. package/dist/worker-isolation/paths.js +46 -0
  78. package/dist/worker-isolation.js +182 -173
  79. package/docs/agent-delegation-drive.7.md +14 -0
  80. package/docs/cli-mcp-parity.7.md +5 -0
  81. package/docs/contract-migration-tooling.7.md +3 -0
  82. package/docs/control-plane-scheduling.7.md +3 -0
  83. package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +40 -0
  84. package/docs/durable-state-and-locking.7.md +5 -0
  85. package/docs/evidence-adoption-reasoning-chain.7.md +3 -0
  86. package/docs/execution-backends.7.md +3 -0
  87. package/docs/index.md +1 -0
  88. package/docs/launch/launch-kit.md +46 -23
  89. package/docs/launch/pre-launch-checklist.md +14 -14
  90. package/docs/multi-agent-cli-mcp-surface.7.md +5 -0
  91. package/docs/multi-agent-eval-replay-harness.7.md +3 -0
  92. package/docs/multi-agent-operator-ux.7.md +3 -0
  93. package/docs/multi-agent-trust-policy-audit.7.md +27 -0
  94. package/docs/node-snapshot-diff-replay.7.md +3 -0
  95. package/docs/observability-cost-accounting.7.md +3 -0
  96. package/docs/project-index.md +23 -6
  97. package/docs/real-execution-backends.7.md +3 -0
  98. package/docs/release-and-migration.7.md +5 -0
  99. package/docs/release-tooling.7.md +35 -2
  100. package/docs/run-registry-control-plane.7.md +55 -8
  101. package/docs/run-retention-reclamation.7.md +5 -0
  102. package/docs/state-explosion-management.7.md +3 -0
  103. package/docs/team-collaboration.7.md +3 -0
  104. package/docs/trust-model.md +267 -0
  105. package/docs/vendor-manifest-loadability.7.md +43 -0
  106. package/docs/web-desktop-workbench.7.md +3 -0
  107. package/manifest/plugin.manifest.json +1 -1
  108. package/manifest/source-context-profiles.json +1 -1
  109. package/package.json +4 -2
  110. package/scripts/agents/builtin-templates.json +7 -0
  111. package/scripts/bump-version.js +5 -11
  112. package/scripts/canonical-apps-list.js +64 -0
  113. package/scripts/canonical-apps.js +19 -4
  114. package/scripts/children/batch-delegate-child.js +58 -0
  115. package/scripts/children/http-delegate-child.js +39 -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/release-flow.js +181 -5
  121. package/scripts/version-sync-check.js +5 -8
  122. package/dist/capability-dispatcher.js +0 -86
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.formatMultiAgentTrustAudit = exports.formatTopologySummary = exports.formatMultiAgentSummary = exports.formatCommitSummary = exports.formatFeedbackSummary = exports.formatCandidateSummary = exports.formatWorkerSummary = exports.formatOperatorGraph = exports.formatOperatorReport = exports.formatOperatorStatus = void 0;
6
7
  exports.summarizeOperatorRun = summarizeOperatorRun;
7
8
  exports.adviseNoRun = adviseNoRun;
8
9
  exports.summarizeOperatorWorkers = summarizeOperatorWorkers;
@@ -10,17 +11,6 @@ exports.summarizeOperatorCandidates = summarizeOperatorCandidates;
10
11
  exports.summarizeOperatorFeedback = summarizeOperatorFeedback;
11
12
  exports.summarizeOperatorCommits = summarizeOperatorCommits;
12
13
  exports.buildOperatorGraph = buildOperatorGraph;
13
- exports.formatOperatorStatus = formatOperatorStatus;
14
- exports.formatOperatorReport = formatOperatorReport;
15
- exports.formatOperatorGraph = formatOperatorGraph;
16
- exports.formatWorkerSummary = formatWorkerSummary;
17
- exports.formatCandidateSummary = formatCandidateSummary;
18
- exports.formatFeedbackSummary = formatFeedbackSummary;
19
- exports.formatCommitSummary = formatCommitSummary;
20
- exports.formatMultiAgentSummary = formatMultiAgentSummary;
21
- exports.formatTopologySummary = formatTopologySummary;
22
- exports.formatMultiAgentTrustAudit = formatMultiAgentTrustAudit;
23
- const node_fs_1 = __importDefault(require("node:fs"));
24
14
  const node_path_1 = __importDefault(require("node:path"));
25
15
  const trust_audit_1 = require("./trust-audit");
26
16
  const multi_agent_trust_1 = require("./multi-agent-trust");
@@ -132,7 +122,7 @@ function summarizeOperatorCandidates(run) {
132
122
  total: candidates.length,
133
123
  byStatus: countBy(candidates, (candidate) => candidate.status),
134
124
  byKind: countBy(candidates, (candidate) => candidate.kind),
135
- latestRankingPath: latestRankingPath && node_fs_1.default.existsSync(latestRankingPath) ? latestRankingPath : latestRankingPath,
125
+ latestRankingPath,
136
126
  selected: selections.map((selection) => ({
137
127
  selectionId: selection.id,
138
128
  candidateId: selection.candidateId,
@@ -281,267 +271,11 @@ function buildOperatorGraph(run) {
281
271
  edges: uniqueEdges(edges).sort(compareEdges)
282
272
  };
283
273
  }
284
- function formatOperatorStatus(summary) {
285
- const operator = summary.multiAgentOperator;
286
- return [
287
- `Run: ${summary.runId}`,
288
- `Workflow: ${summary.workflowId}${summary.appId ? ` (${summary.appId}@${summary.appVersion || "unknown"})` : ""}`,
289
- `Loop Stage: ${summary.loopStage}`,
290
- `Active Phase: ${summary.activePhase || "none"}`,
291
- `Blocked: ${summary.blocked ? summary.blockedReasons.join("; ") : "no"}`,
292
- `Tasks: ${formatCounts(summary.tasks.byStatus)}; total=${summary.tasks.total}`,
293
- "",
294
- "Phases",
295
- ...summary.phases.map((phase) => ` ${phase.name}: ${phase.status} (${phase.tasks.completed}/${phase.tasks.total} completed)`),
296
- "",
297
- formatWorkerPanel(summary.workers),
298
- "",
299
- formatCandidatePanel(summary.candidates),
300
- "",
301
- formatFeedbackPanel(summary.feedback),
302
- "",
303
- formatCommitPanel(summary.commits),
304
- "",
305
- formatTopologyPanel(summary.topologies),
306
- "",
307
- formatMultiAgentPanel(summary.multiAgent),
308
- "",
309
- "Multi-Agent Operator UX",
310
- ` active=${operator.activeMultiAgentRunIds.join(", ") || "none"}; topologies=${operator.topologyRunIds.join(", ") || "none"}; blocked=${operator.blocked ? "yes" : "no"}`,
311
- ` dependencies=${operator.dependencies.length}; failures=${operator.failures.length}; adoptedEvidence=${operator.adoptedEvidence.length}; missingEvidence=${operator.missingEvidence.length}${operator.inspectableEvidence.length ? ` (inspectable=${operator.inspectableEvidence.length})` : ""}`,
312
- ` next=${operator.nextAction}`,
313
- "",
314
- formatBlackboardPanel(summary.blackboard),
315
- "",
316
- formatTrustPanel(summary.trust),
317
- "",
318
- formatMultiAgentTrustAudit(summary.multiAgentTrust),
319
- "",
320
- `Report: ${summary.reportPath}`,
321
- "",
322
- "Next Action",
323
- ...formatRecommendations(summary.nextActions)
324
- ].join("\n");
325
- }
326
- function formatOperatorReport(summary) {
327
- return [
328
- formatOperatorStatus(summary),
329
- "",
330
- "Active and Pending Tasks",
331
- ...formatTaskList(summary.tasks),
332
- "",
333
- "Evidence",
334
- ...(summary.evidencePaths.length ? summary.evidencePaths.map((entry) => ` ${entry}`) : [" none recorded"]),
335
- "",
336
- (0, multi_agent_operator_ux_1.formatMultiAgentDependencies)(summary.multiAgentOperator.dependencies),
337
- "",
338
- (0, multi_agent_operator_ux_1.formatMultiAgentFailures)(summary.multiAgentOperator.failures),
339
- "",
340
- (0, multi_agent_operator_ux_1.formatMultiAgentEvidence)(summary.multiAgentOperator.evidence),
341
- "",
342
- "Resource Commands",
343
- ` node scripts/cw.js graph ${summary.runId}`,
344
- ` node scripts/cw.js worker summary ${summary.runId}`,
345
- ` node scripts/cw.js topology summary ${summary.runId}`,
346
- ` node scripts/cw.js topology graph ${summary.runId}`,
347
- ` node scripts/cw.js multi-agent summary ${summary.runId}`,
348
- ` node scripts/cw.js multi-agent graph ${summary.runId}`,
349
- ` node scripts/cw.js multi-agent dependencies ${summary.runId}`,
350
- ` node scripts/cw.js multi-agent failures ${summary.runId}`,
351
- ` node scripts/cw.js multi-agent evidence ${summary.runId}`,
352
- ` node scripts/cw.js blackboard summary ${summary.runId}`,
353
- ` node scripts/cw.js blackboard graph ${summary.runId}`,
354
- ` node scripts/cw.js coordinator summary ${summary.runId}`,
355
- ` node scripts/cw.js candidate summary ${summary.runId}`,
356
- ` node scripts/cw.js feedback summary ${summary.runId}`,
357
- ` node scripts/cw.js commit summary ${summary.runId}`,
358
- ` node scripts/cw.js audit summary ${summary.runId}`,
359
- ` node scripts/cw.js audit provenance ${summary.runId}`,
360
- ` node scripts/cw.js audit multi-agent ${summary.runId}`,
361
- ` node scripts/cw.js audit policy ${summary.runId}`,
362
- ` node scripts/cw.js audit blackboard ${summary.runId}`,
363
- ` node scripts/cw.js audit judge ${summary.runId}`
364
- ].join("\n");
365
- }
366
- function formatOperatorGraph(graph) {
367
- const lines = [`Run Graph: ${graph.runId}`, "", "Nodes"];
368
- const groups = groupBy(graph.nodes, (node) => node.kind);
369
- for (const kind of Object.keys(groups).sort()) {
370
- lines.push(` ${kind}`);
371
- for (const node of groups[kind]) {
372
- const suffix = node.path ? ` -> ${node.path}` : "";
373
- lines.push(` [${node.status}] ${node.id} (${node.label})${suffix}`);
374
- }
375
- }
376
- lines.push("", "Edges");
377
- if (!graph.edges.length)
378
- lines.push(" none");
379
- for (const edge of graph.edges) {
380
- lines.push(` ${edge.from} -> ${edge.to}${edge.label ? ` (${edge.label})` : ""}`);
381
- }
382
- return lines.join("\n");
383
- }
384
- function formatWorkerSummary(summary) {
385
- return formatWorkerPanel(summary);
386
- }
387
- function formatCandidateSummary(summary) {
388
- return formatCandidatePanel(summary);
389
- }
390
- function formatFeedbackSummary(summary) {
391
- return formatFeedbackPanel(summary);
392
- }
393
- function formatCommitSummary(summary) {
394
- return formatCommitPanel(summary);
395
- }
396
- function formatTrustPanel(summary) {
397
- const lines = [
398
- "Trust Audit",
399
- ` total=${summary.eventCount}; decision=${formatCounts(summary.byDecision)}; source=${formatCounts(summary.bySource)}`,
400
- ` sandbox=${formatCounts(summary.bySandboxProfile)}`,
401
- ` multi-agent trust=${summary.multiAgentTrust ? formatCounts(summary.multiAgentTrust) : "none"}`,
402
- ` events=${summary.eventLogPath}`,
403
- ` summary=${summary.summaryPath}`
404
- ];
405
- for (const worker of summary.workers.slice(0, 6)) {
406
- lines.push(` worker ${worker.workerId}: sandbox=${worker.sandboxProfileId || "none"}, decisions=${formatCounts(worker.decisions)}, denied=${worker.denied}`);
407
- }
408
- return lines.join("\n");
409
- }
410
- function formatMultiAgentSummary(summary) {
411
- return formatMultiAgentPanel(summary);
412
- }
413
- function formatTopologySummary(summary) {
414
- return formatTopologyPanel(summary);
415
- }
416
- function formatMultiAgentTrustAudit(view) {
417
- const rolePolicies = arrayView(view.rolePolicies);
418
- const permissionDecisions = arrayView(view.permissionDecisions);
419
- const blackboardWrites = arrayView(view.blackboardWrites);
420
- const messageProvenance = arrayView(view.messageProvenance);
421
- const judgeRationales = arrayView(view.judgeRationales);
422
- const panelDecisions = arrayView(view.panelDecisions);
423
- const policyViolations = arrayView(view.policyViolations);
424
- return [
425
- `Multi-Agent Trust: ${String(view.runId || "unknown")}`,
426
- "",
427
- "Role Policies",
428
- ...formatRolePolicyRows(rolePolicies),
429
- "",
430
- "Permission Decisions",
431
- ...formatAuditRows(permissionDecisions),
432
- "",
433
- "Blackboard Write Audit",
434
- ...formatAuditRows(blackboardWrites),
435
- "",
436
- "Message Provenance",
437
- ...formatAuditRows(messageProvenance),
438
- "",
439
- "Judge Rationales",
440
- ...formatAuditRows([...judgeRationales, ...panelDecisions]),
441
- "",
442
- "Policy Violations",
443
- ...formatAuditRows(policyViolations),
444
- "",
445
- "Next Action",
446
- ` ${String(view.nextAction || `node scripts/cw.js audit multi-agent ${String(view.runId || "<run-id>")} --json`)}`
447
- ].join("\n");
448
- }
449
- function formatTopologyPanel(summary) {
450
- const lines = [
451
- "Topologies",
452
- ` runs=${summary.totalRuns}; status=${formatCounts(summary.runsByStatus)}; official=${summary.officialTopologies.join(", ")}`
453
- ];
454
- for (const record of summary.active.slice(0, 6)) {
455
- lines.push(` ${record.id}: ${record.topologyId}, status=${record.status}, readiness=${record.readiness}`);
456
- lines.push(` run=${record.multiAgentRunId} board=${record.blackboardId}`);
457
- lines.push(` roles=${record.roles.join(", ") || "none"} topics=${record.topics.join(", ") || "none"}`);
458
- lines.push(` fanout=${record.fanouts.join(", ") || "none"} fanin=${record.fanins.join(", ") || "none"}`);
459
- for (const missing of record.missingEvidence.slice(0, 4))
460
- lines.push(` missing=${missing}`);
461
- for (const conflict of record.conflicts.slice(0, 4))
462
- lines.push(` conflict=${conflict}`);
463
- if (record.nextActions[0])
464
- lines.push(` next=${record.nextActions[0]}`);
465
- }
466
- if (summary.nextAction)
467
- lines.push(` next=${summary.nextAction}`);
468
- return lines.join("\n");
469
- }
470
- function formatMultiAgentPanel(summary) {
471
- const lines = [
472
- "Multi-Agent",
473
- ` runs=${summary.totalRuns}; status=${formatCounts(summary.runsByStatus)}`,
474
- ` roles=${summary.roles}; groups=${summary.groups} (${formatCounts(summary.groupsByStatus)})`,
475
- ` memberships=${summary.memberships} (${formatCounts(summary.membershipsByStatus)})`,
476
- ` fanouts=${summary.fanouts}; fanins=${summary.fanins} (${formatCounts(summary.faninsByStatus)})`
477
- ];
478
- for (const group of summary.groupsDetail.slice(0, 6)) {
479
- lines.push(` group ${group.id}: ${group.status}, phase=${group.phase || "none"}, run=${group.multiAgentRunId}`);
480
- for (const role of group.roles.slice(0, 6)) {
481
- lines.push(` role ${role.roleId}: memberships=${role.memberships}, reported=${role.reported}, missing=${role.missing}`);
482
- }
483
- lines.push(` fanout=${group.fanouts.join(", ") || "none"} fanin=${group.fanins.join(", ") || "none"}`);
484
- }
485
- for (const reason of summary.blockedReasons.slice(0, 6))
486
- lines.push(` blocked: ${reason}`);
487
- if (summary.nextAction)
488
- lines.push(` next=${summary.nextAction}`);
489
- return lines.join("\n");
490
- }
491
- function formatBlackboardPanel(summary) {
492
- const lines = [
493
- "Blackboard / Coordinator",
494
- ` board=${summary.blackboardId || "none"}; topics=${summary.topics}; messages=${summary.messages}; contexts=${summary.contexts}; artifacts=${summary.artifacts}`,
495
- ` open questions=${summary.openQuestions.length}; conflicts=${summary.conflicts.length}; missing evidence=${summary.missingEvidence.length}`,
496
- ` ready for fanin=${summary.readyForFanin ? "yes" : "no"}`,
497
- ` index=${summary.indexPath || "none"}`,
498
- ` latest snapshot=${summary.latestSnapshotPath || "none"}`
499
- ];
500
- for (const question of summary.openQuestions.slice(0, 5))
501
- lines.push(` question ${question.id}: ${question.value}`);
502
- for (const conflict of summary.conflicts.slice(0, 5))
503
- lines.push(` conflict ${conflict.id}: ${conflict.key} -> ${conflict.conflictingContextIds.join(", ") || "unindexed"}`);
504
- for (const missing of summary.missingEvidence.slice(0, 5))
505
- lines.push(` missing: ${missing}`);
506
- if (summary.nextAction)
507
- lines.push(` next=${summary.nextAction}`);
508
- return lines.join("\n");
509
- }
510
- function arrayView(value) {
511
- return Array.isArray(value) ? value : [];
512
- }
513
- function formatRolePolicyRows(rows) {
514
- if (!rows.length)
515
- return [" none"];
516
- return rows.slice(0, 40).map((row) => {
517
- const writes = Array.isArray(row.allowedWriteOperations) ? row.allowedWriteOperations.join(",") : "none";
518
- const candidates = Array.isArray(row.allowedCandidateOperations) ? row.allowedCandidateOperations.join(",") : "none";
519
- const judges = Array.isArray(row.allowedJudgeOperations) ? row.allowedJudgeOperations.join(",") : "none";
520
- const topics = Array.isArray(row.allowedBlackboardTopicIds) ? row.allowedBlackboardTopicIds.join(",") : "none";
521
- return ` ${String(row.policyRef || row.id || row.subjectId)} subject=${String(row.subjectKind || "unknown")}:${String(row.subjectId || "unknown")} topics=${topics} writes=${writes} candidates=${candidates} judges=${judges}`;
522
- });
523
- }
524
- function formatAuditRows(rows) {
525
- if (!rows.length)
526
- return [" none"];
527
- return rows.slice(0, 60).map((row) => {
528
- const metadata = row.metadata && typeof row.metadata === "object" ? row.metadata : {};
529
- const ids = [
530
- row.agentRoleId ? `role=${row.agentRoleId}` : "",
531
- row.agentMembershipId ? `membership=${row.agentMembershipId}` : "",
532
- row.blackboardMessageId ? `message=${row.blackboardMessageId}` : "",
533
- row.blackboardContextId ? `context=${row.blackboardContextId}` : "",
534
- row.blackboardArtifactRefId ? `artifact=${row.blackboardArtifactRefId}` : "",
535
- row.coordinatorDecisionId ? `decision=${row.coordinatorDecisionId}` : "",
536
- row.candidateId ? `candidate=${row.candidateId}` : "",
537
- row.scoreId ? `score=${row.scoreId}` : "",
538
- row.selectionId ? `selection=${row.selectionId}` : ""
539
- ].filter(Boolean).join(" ");
540
- const reason = metadata.reason ? ` reason=${String(metadata.reason)}` : "";
541
- const operation = metadata.operation ? ` operation=${String(metadata.operation)}` : "";
542
- return ` [${String(row.decision || "recorded")}] ${String(row.kind || "event")} ${String(row.id || "")}${operation}${ids ? ` ${ids}` : ""}${row.policyRef ? ` policy=${String(row.policyRef)}` : ""}${reason}`;
543
- });
544
- }
274
+ // Human formatting (CLI-only) for the operator status / report / graph surfaces
275
+ // plus the worker/candidate/feedback/commit/trust/topology/multi-agent panels now
276
+ // lives in ./operator-ux/format.ts (FreeBSD-audit R-series, run-registry/format.ts
277
+ // template). Re-exported below so importers of "./operator-ux" see an unchanged
278
+ // surface. The pure data summarizers and the run-graph builder stay here.
545
279
  function adviseNextSteps(run, summary) {
546
280
  const actions = [];
547
281
  if (summary.feedback.open.length) {
@@ -797,81 +531,6 @@ function evidencePathsFor(run) {
797
531
  values.add(run.paths.report);
798
532
  return [...values].sort();
799
533
  }
800
- function formatWorkerPanel(summary) {
801
- const lines = [
802
- "Workers",
803
- ` total=${summary.total}; status=${formatCounts(summary.byStatus)}; sandbox=${formatCounts(summary.bySandboxProfile)}; backend=${formatCounts(summary.byBackend)}`
804
- ];
805
- for (const worker of summary.workers.slice(0, 8)) {
806
- const attestation = worker.backendAttestationStatus ? `/${worker.backendAttestationStatus}` : "";
807
- lines.push(` ${worker.id}: ${worker.status}, task=${worker.taskId}, sandbox=${worker.sandboxProfileId || "none"}, backend=${worker.backendId || "none"}${attestation}`);
808
- lines.push(` manifest=${worker.manifestPath}`);
809
- lines.push(` result=${worker.resultPath}`);
810
- if (worker.feedbackIds.length)
811
- lines.push(` feedback=${worker.feedbackIds.join(", ")}`);
812
- }
813
- if (summary.workers.length > 8)
814
- lines.push(` ... ${summary.workers.length - 8} more worker(s)`);
815
- return lines.join("\n");
816
- }
817
- function formatCandidatePanel(summary) {
818
- const lines = [
819
- "Candidates",
820
- ` total=${summary.total}; status=${formatCounts(summary.byStatus)}; kind=${formatCounts(summary.byKind)}`,
821
- ` latest ranking=${summary.latestRankingPath || "none"}`,
822
- ` selected=${summary.selected.map((selection) => `${selection.candidateId}/${selection.selectionId}`).join(", ") || "none"}`,
823
- ` ready for commit=${summary.readyForCommit.map((item) => `${item.candidateId}/${item.selectionId}`).join(", ") || "none"}`
824
- ];
825
- for (const problem of summary.problems.slice(0, 5))
826
- lines.push(` problem: ${problem}`);
827
- for (const candidate of summary.candidates.slice(0, 8)) {
828
- lines.push(` ${candidate.id}: ${candidate.status}, scores=${candidate.scoreCount}, selected=${candidate.selected ? "yes" : "no"}`);
829
- }
830
- if (summary.candidates.length > 8)
831
- lines.push(` ... ${summary.candidates.length - 8} more candidate(s)`);
832
- return lines.join("\n");
833
- }
834
- function formatFeedbackPanel(summary) {
835
- const lines = [
836
- "Feedback",
837
- ` total=${summary.total}; status=${formatCounts(summary.byStatus)}`,
838
- ` severity=${formatCounts(summary.bySeverity)}`,
839
- ` classification=${formatCounts(summary.byClassification)}`,
840
- ` retryable=${summary.retryable}; nonRetryable=${summary.nonRetryable}`
841
- ];
842
- for (const record of summary.open.slice(0, 6)) {
843
- lines.push(` ${record.id}: ${record.severity}/${record.classification}, retryable=${record.retryable ? "yes" : "no"}`);
844
- lines.push(` ${record.message}`);
845
- }
846
- return lines.join("\n");
847
- }
848
- function formatCommitPanel(summary) {
849
- const lines = [
850
- "Commits",
851
- ` total=${summary.total}; verifier-gated=${summary.verifierGated}; checkpoints=${summary.checkpoints}`,
852
- ` latest=${summary.latest ? `${summary.latest.id} (${summary.latest.kind}) ${summary.latest.snapshotPath}` : "none"}`
853
- ];
854
- for (const commit of summary.commits.slice(-8)) {
855
- lines.push(` ${commit.id}: ${commit.kind}, reason=${commit.reason}`);
856
- lines.push(` verifier=${commit.verifierNodeId || "none"} candidate=${commit.candidateId || "none"} selection=${commit.selectionId || "none"} evidence=${commit.evidenceCount}`);
857
- lines.push(` snapshot=${commit.snapshotPath}`);
858
- }
859
- return lines.join("\n");
860
- }
861
- function formatTaskList(summary) {
862
- const lines = [];
863
- for (const [label, values] of [
864
- ["pending", summary.pending],
865
- ["running", summary.running],
866
- ["failed", summary.failed]
867
- ]) {
868
- lines.push(` ${label}: ${values.length ? values.join(", ") : "none"}`);
869
- }
870
- return lines;
871
- }
872
- function formatRecommendations(actions) {
873
- return actions.length ? actions.map((action) => ` ${action.command}\n reason: ${action.reason}`) : [" none"];
874
- }
875
534
  function formatCommitRow(commit) {
876
535
  return {
877
536
  id: commit.id,
@@ -948,24 +607,24 @@ function countByKnown(items, getKey, keys) {
948
607
  counts[getKey(item)] += 1;
949
608
  return counts;
950
609
  }
951
- function formatCounts(counts) {
952
- const entries = Object.entries(counts).filter(([, value]) => value > 0).sort(([left], [right]) => left.localeCompare(right));
953
- if (!entries.length)
954
- return "none";
955
- return entries.map(([key, value]) => `${key}=${value}`).join(", ");
956
- }
957
- function groupBy(items, getKey) {
958
- const groups = {};
959
- for (const item of items) {
960
- const key = getKey(item);
961
- groups[key] = groups[key] || [];
962
- groups[key].push(item);
963
- }
964
- return groups;
965
- }
966
610
  function sortRecord(record) {
967
611
  return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
968
612
  }
969
613
  function safeId(value) {
970
614
  return String(value).replace(/[^a-zA-Z0-9_.:-]+/g, "_");
971
615
  }
616
+ // Human formatting (CLI-only) now lives in ./operator-ux/format.ts (FreeBSD-audit
617
+ // R-series: rendering carved out of the operator module, run-registry/format.ts
618
+ // template). Re-exported so that importers of "./operator-ux" see an unchanged
619
+ // surface.
620
+ var format_1 = require("./operator-ux/format");
621
+ Object.defineProperty(exports, "formatOperatorStatus", { enumerable: true, get: function () { return format_1.formatOperatorStatus; } });
622
+ Object.defineProperty(exports, "formatOperatorReport", { enumerable: true, get: function () { return format_1.formatOperatorReport; } });
623
+ Object.defineProperty(exports, "formatOperatorGraph", { enumerable: true, get: function () { return format_1.formatOperatorGraph; } });
624
+ Object.defineProperty(exports, "formatWorkerSummary", { enumerable: true, get: function () { return format_1.formatWorkerSummary; } });
625
+ Object.defineProperty(exports, "formatCandidateSummary", { enumerable: true, get: function () { return format_1.formatCandidateSummary; } });
626
+ Object.defineProperty(exports, "formatFeedbackSummary", { enumerable: true, get: function () { return format_1.formatFeedbackSummary; } });
627
+ Object.defineProperty(exports, "formatCommitSummary", { enumerable: true, get: function () { return format_1.formatCommitSummary; } });
628
+ Object.defineProperty(exports, "formatMultiAgentSummary", { enumerable: true, get: function () { return format_1.formatMultiAgentSummary; } });
629
+ Object.defineProperty(exports, "formatTopologySummary", { enumerable: true, get: function () { return format_1.formatTopologySummary; } });
630
+ Object.defineProperty(exports, "formatMultiAgentTrustAudit", { enumerable: true, get: function () { return format_1.formatMultiAgentTrustAudit; } });
@@ -17,6 +17,7 @@ exports.commit = commit;
17
17
  // plan() receives an already-resolved workflow app record (the runner still owns
18
18
  // app loading, which is instance-stateful). Behavior is identical to the inline
19
19
  // implementations; only the location changed.
20
+ const node_crypto_1 = __importDefault(require("node:crypto"));
20
21
  const node_fs_1 = __importDefault(require("node:fs"));
21
22
  const node_path_1 = __importDefault(require("node:path"));
22
23
  const state_1 = require("../state");
@@ -456,8 +457,28 @@ function renderPrompt(prompt, inputs) {
456
457
  }
457
458
  return rendered;
458
459
  }
460
+ // Deterministic run id (replay-determinism self-audit): the wall-clock stamp is an
461
+ // edge timestamp (recorded once and stripped on replay), but the former
462
+ // Math.random() suffix made the run id itself non-reproducible — re-deriving the id
463
+ // for the SAME recorded run would never match. The suffix is now a content hash of
464
+ // the run's deterministic identity (workflowId + the recorded stamp), so the id is a
465
+ // pure function of inputs that already live in state. Distinct plan() invocations
466
+ // still get distinct ids because the per-millisecond stamp differs; replaying a
467
+ // recorded run reproduces the byte-identical id. Mirrors the de-clock done for
468
+ // worker ids in src/worker-isolation/paths.ts.
469
+ let runIdSequence = 0;
459
470
  function createRunId(workflowId) {
460
471
  const stamp = new Date().toISOString().replace(/[-:]/g, "").replace(/\..+/, "Z");
461
- const suffix = Math.random().toString(36).slice(2, 8);
472
+ // The stamp is second-resolution, so several runs of the same workflowId minted
473
+ // within one second would otherwise hash to the SAME id. process.pid + a monotonic
474
+ // counter break the tie across BOTH same-process (counter) and concurrent-process
475
+ // (pid) minting — deterministic-by-environment, not a PRNG, so it keeps the
476
+ // replay-determinism intent; the id is an edge stamp stripped on replay anyway.
477
+ runIdSequence += 1;
478
+ const suffix = node_crypto_1.default
479
+ .createHash("sha256")
480
+ .update(`${workflowId}:${stamp}:${process.pid}:${runIdSequence}`)
481
+ .digest("hex")
482
+ .slice(0, 6);
462
483
  return `${workflowId}-${stamp}-${suffix}`;
463
484
  }
@@ -289,8 +289,16 @@ function renderCandidates(summary) {
289
289
  }
290
290
  function renderTrustAudit(run) {
291
291
  const summary = (0, trust_audit_1.summarizeTrustAudit)(run);
292
+ const integrity = summary.integrity;
292
293
  return [
293
294
  `- Events: ${summary.eventCount}`,
295
+ `- Chain integrity: ${integrity ? (integrity.verified ? "verified" : "FAILED") : "n/a"}` +
296
+ `${integrity ? ` (${integrity.chained} chained, ${integrity.unchained} legacy${integrity.corruptLines ? `, ${integrity.corruptLines} corrupt` : ""})` : ""}`,
297
+ // An auditable control-plane never lets a broken decision-log chain pass
298
+ // silently — name the failing checks loudly, same as the telemetry chain.
299
+ ...(integrity && !integrity.verified
300
+ ? [` !! TRUST-AUDIT CHAIN TAMPER DETECTED: ${integrity.checks.filter((c) => !c.pass).map((c) => c.code).join(", ")}`]
301
+ : []),
294
302
  `- Decisions: ${formatCounts(summary.byDecision)}`,
295
303
  `- Sources: ${formatCounts(summary.bySource)}`,
296
304
  `- Sandbox profiles: ${formatCounts(summary.bySandboxProfile)}`,
@@ -48,7 +48,6 @@ const state_1 = require("./state");
48
48
  const observability_1 = require("./observability");
49
49
  const pipeline_runner_1 = require("./pipeline-runner");
50
50
  const worker_isolation_1 = require("./worker-isolation");
51
- const candidate_scoring_1 = require("./candidate-scoring");
52
51
  const sandbox_profile_1 = require("./sandbox-profile");
53
52
  const execution_backend_1 = require("./execution-backend");
54
53
  const operator_ux_1 = require("./operator-ux");
@@ -69,14 +68,46 @@ const feedbackOps = __importStar(require("./orchestrator/feedback-operations"));
69
68
  const topologyOps = __importStar(require("./orchestrator/topology-operations"));
70
69
  const lifecycleOps = __importStar(require("./orchestrator/lifecycle-operations"));
71
70
  const migrationOps = __importStar(require("./orchestrator/migration-operations"));
71
+ // CoolWorkflowRunner — the single FACADE both surfaces (cli.ts and the MCP server)
72
+ // call through. It is deliberately WIDE but THIN: each method either
73
+ // (a) loads the run's durable state and delegates to a domain function in
74
+ // ./orchestrator/*-operations.ts — the v0.1.40 self-audit "router pattern":
75
+ // one thin delegator per capability, NOT a god-object to dismantle; or
76
+ // (b) holds a small amount of surface-shared logic (app/worker loaders, report
77
+ // composition, read-snapshot-then-op).
78
+ // The high method count is INTENTIONAL — it is the union of every both-surface
79
+ // capability — and the fail-closed CLI<->MCP parity gate keeps each one honest (a
80
+ // method present on one surface but not the other is exactly the drift it forbids).
81
+ //
82
+ // FreeBSD-audit R3 ("142-method god-facade with no-op passthroughs") was assessed
83
+ // and CLOSED as won't-fix: of 141 public methods exactly ONE is a true
84
+ // runner->runner forward (collaborationReject -> collaborationApprove(...,"reject")),
85
+ // and it is kept on purpose — it is a registered capability `entry` bound to the
86
+ // parity gate AND an intent-revealing veto verb, so collapsing it would be a
87
+ // behavior-neutral readability LOSS touching both surfaces. Dismantling the facade
88
+ // is an explicit anti-goal (small kernel, explicit delegation — see DIRECTION.md).
72
89
  class CoolWorkflowRunner {
73
90
  pluginRoot;
74
91
  workflowsDir;
75
92
  appsDir;
76
- constructor({ pluginRoot }) {
93
+ // F7: the directory a run is resolved against (replaces the former process.chdir
94
+ // bracket in capability-core). undefined => fall back to process.cwd(). The runner
95
+ // reads runs from disk per call (no in-memory run state), so withBaseDir hands back
96
+ // a cheap scoped clone instead of mutating the global process cwd.
97
+ baseDir;
98
+ constructor({ pluginRoot, baseDir }) {
77
99
  this.pluginRoot = resolvePluginRoot(pluginRoot);
78
100
  this.workflowsDir = node_path_1.default.join(this.pluginRoot, "workflows");
79
101
  this.appsDir = node_path_1.default.join(this.pluginRoot, "apps");
102
+ this.baseDir = baseDir ? node_path_1.default.resolve(baseDir) : undefined;
103
+ }
104
+ /** Return a runner that resolves runs against `dir` instead of process.cwd(),
105
+ * WITHOUT chdir-ing the process (F7). Same instance when the dir is unchanged. */
106
+ withBaseDir(dir) {
107
+ const resolved = dir ? node_path_1.default.resolve(dir) : undefined;
108
+ if (resolved === this.baseDir)
109
+ return this;
110
+ return new CoolWorkflowRunner({ pluginRoot: this.pluginRoot, baseDir: resolved });
80
111
  }
81
112
  listWorkflows() {
82
113
  return this.loadWorkflowApps().map((record) => {
@@ -355,9 +386,6 @@ class CoolWorkflowRunner {
355
386
  formatCommentList(comments) {
356
387
  return collaborationOps.formatCommentList(comments);
357
388
  }
358
- summarizeCandidateRecords(runId) {
359
- return (0, candidate_scoring_1.summarizeCandidates)(this.loadRun(runId));
360
- }
361
389
  summarizeWorkerRecords(runId) {
362
390
  return (0, operator_ux_1.summarizeOperatorWorkers)(this.loadRun(runId));
363
391
  }
@@ -686,10 +714,7 @@ class CoolWorkflowRunner {
686
714
  return feedbackOps.resolveFeedback(this.loadRun(runId), feedbackId, options);
687
715
  }
688
716
  loadRun(runId) {
689
- return (0, state_1.loadRunFromCwd)(runId);
690
- }
691
- loadWorkflowById(workflowId) {
692
- return this.loadWorkflowAppById(workflowId).app.workflow;
717
+ return (0, state_1.loadRunFromCwd)(runId, this.baseDir);
693
718
  }
694
719
  loadWorkflowAppById(appId) {
695
720
  const record = this.loadWorkflowApps().find((candidate) => candidate.app.id === appId);
@@ -759,6 +784,13 @@ function parseArgv(argv) {
759
784
  const positionals = [];
760
785
  for (let index = 0; index < rest.length; index += 1) {
761
786
  const token = rest[index];
787
+ if (token === "--") {
788
+ // POSIX end-of-options: everything after `--` is a positional, even if it
789
+ // begins with `--`. Lets a legitimate value that starts with `--` through.
790
+ for (let restIndex = index + 1; restIndex < rest.length; restIndex += 1)
791
+ positionals.push(rest[restIndex]);
792
+ break;
793
+ }
762
794
  if (!token.startsWith("--")) {
763
795
  positionals.push(token);
764
796
  continue;
@@ -845,7 +877,6 @@ function formatHelp() {
845
877
  " workbench serve [--port N] [--scope repo|home] [--once|--json]",
846
878
  ""
847
879
  ].join("\n");
848
- return `Cool Workflow\n\nCommands:\n list\n init <workflow-id> [--title TEXT] [--output PATH]\n plan <workflow-id> [--repo PATH] [--question TEXT] [--invariant TEXT]\n status <run-id> [--json|--format json]\n next <run-id> [--limit N]\n graph <run-id> [--json]\n dispatch <run-id> [--limit N] [--sandbox PROFILE]\n result <run-id> <task-id> <result-file>\n state check <run-id> [--state PATH] [--write]\n commit <run-id> --verifier <node-id> [--reason TEXT]\n commit <run-id> --candidate <candidate-id> [--reason TEXT]\n commit <run-id> --selection <selection-id> [--reason TEXT]\n commit <run-id> --allow-unverified-checkpoint [--reason TEXT]\n commit summary <run-id> [--json]\n report <run-id> [--show|--summary]\n app list\n app show <app-id>\n app validate <path-or-app-id>\n app init <app-id> --title TEXT\n app package <app-id> [--output PATH]\n sandbox list\n sandbox show <profile-id>\n sandbox validate <profile-file>\n contract show <run-id> [contract-id]\n node list <run-id>\n node show <run-id> <node-id>\n node graph <run-id> [--json]\n feedback list <run-id> [--status open]\n feedback summary <run-id> [--json]\n feedback show <run-id> <feedback-id>\n feedback collect <run-id>\n feedback task <run-id> <feedback-id> [--verify CMD]\n feedback resolve <run-id> <feedback-id> --node <node-id>\n worker list <run-id> [--status running]\n worker summary <run-id> [--json]\n worker show <run-id> <worker-id>\n worker manifest <run-id> <worker-id>\n worker output <run-id> <worker-id> <result-file>\n worker fail <run-id> <worker-id> --message TEXT\n worker validate <run-id> <worker-id> [path]\n audit summary <run-id>\n audit worker <run-id> <worker-id>\n audit provenance <run-id> [--worker ID|--candidate ID|--commit ID]\n audit attest <run-id> [--worker ID] [--hostEnforced true] [--env NAME]\n audit decision <run-id> <worker-id> [--path PATH|--command CMD|--network TARGET|--env NAME]\n candidate list <run-id> [--status scored]\n candidate summary <run-id> [--json]\n candidate register <run-id> --worker <worker-id>\n candidate score <run-id> <candidate-id> --criterion name=value --evidence PATH\n candidate rank <run-id>\n candidate select <run-id> <candidate-id> [--reason TEXT]\n candidate reject <run-id> <candidate-id> --reason TEXT\n blackboard summary <run-id>\n blackboard graph <run-id>\n blackboard topic create <run-id> --id <topic-id> --title TEXT\n blackboard message post <run-id> --topic <topic-id> --body TEXT\n blackboard message list <run-id> [--topic <topic-id>]\n blackboard context put <run-id> --topic <topic-id> --kind fact|constraint|assumption|question|decision --value TEXT\n blackboard artifact add <run-id> --path PATH --kind KIND\n blackboard artifact list <run-id>\n blackboard snapshot <run-id>\n coordinator summary <run-id>\n coordinator decision <run-id> --kind KIND --outcome OUTCOME --reason TEXT\n loop --intervalMinutes 30 --prompt TEXT\n schedule create --kind loop --intervalMinutes 30 --prompt TEXT\n schedule list [--status active]\n schedule due\n schedule complete <schedule-id>\n schedule pause <schedule-id>\n schedule resume <schedule-id>\n schedule run-now <schedule-id>\n schedule history [schedule-id]\n schedule daemon [--once] [--intervalSeconds 60]\n schedule delete <schedule-id>\n routine create --kind api|github --prompt TEXT [--match JSON]\n routine fire api|github [payload.json]\n routine list\n routine events [trigger-id]\n routine delete <trigger-id>\n\n`;
849
880
  }
850
881
  function appendOption(options, key, value) {
851
882
  if (Object.prototype.hasOwnProperty.call(options, key)) {