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
@@ -9,11 +9,12 @@
9
9
  // expressed here and called identically by both surfaces. A composite that lives
10
10
  // in only one surface is exactly the cross-surface drift v0.1.27 forbids.
11
11
  //
12
- // From v0.1.46: each exported entry function SHOULD self-register its capability
13
- // metadata via registerCapability() from capability-registry.ts. This replaces
14
- // the manual "add an entry to the giant array in capability-registry.ts" workflow
15
- // with automatic discovery. New capabilities just add a registerCapability() call
16
- // next to their implementation no need to touch capability-registry.ts.
12
+ // Capability metadata (which entry is on which surface, tool names, jsonMode) is
13
+ // declared in ONE place — the BUILTIN_CAPABILITIES table in capability-registry.ts,
14
+ // the single source of truth both surfaces and the parity gate read. New
15
+ // capabilities add a row there. (A v0.1.46 "self-register at load time" mechanism
16
+ // was removed: the registry snapshot was taken before those registrations ran, so
17
+ // they were silently dead duplicates of the table — see capability-registry.ts.)
17
18
  //
18
19
  // See docs/cli-mcp-parity.7.md and src/capability-registry.ts.
19
20
  var __importDefault = (this && this.__importDefault) || function (mod) {
@@ -35,6 +36,10 @@ exports.runShow = runShow;
35
36
  exports.runResume = runResume;
36
37
  exports.runArchive = runArchive;
37
38
  exports.runRerun = runRerun;
39
+ exports.runExportArchive = runExportArchive;
40
+ exports.runImportArchive = runImportArchive;
41
+ exports.runInspectArchive = runInspectArchive;
42
+ exports.runVerifyImport = runVerifyImport;
38
43
  exports.queueAdd = queueAdd;
39
44
  exports.queueList = queueList;
40
45
  exports.queueDrain = queueDrain;
@@ -62,15 +67,18 @@ exports.withoutRuntimeKeys = withoutRuntimeKeys;
62
67
  exports.optionalString = optionalString;
63
68
  exports.isRecord = isRecord;
64
69
  exports.telemetryVerify = telemetryVerify;
70
+ exports.auditVerify = auditVerify;
65
71
  exports.demoTamper = demoTamper;
66
- const capability_registry_1 = require("./capability-registry");
67
72
  const drive_1 = require("./drive");
68
73
  const agent_config_1 = require("./agent-config");
69
74
  const run_registry_1 = require("./run-registry");
70
75
  const observability_1 = require("./observability");
71
76
  const telemetry_ledger_1 = require("./telemetry-ledger");
77
+ const telemetry_attestation_1 = require("./telemetry-attestation");
78
+ const trust_audit_1 = require("./trust-audit");
72
79
  const telemetry_demo_1 = require("./telemetry-demo");
73
80
  const state_1 = require("./state");
81
+ const run_export_1 = require("./run-export");
74
82
  const node_fs_1 = __importDefault(require("node:fs"));
75
83
  const node_path_1 = __importDefault(require("node:path"));
76
84
  const scheduling_1 = require("./scheduling");
@@ -86,8 +94,6 @@ function planSummary(runner, workflowId, options) {
86
94
  pendingTasks: run.tasks.filter((task) => task.status === "pending").length
87
95
  };
88
96
  }
89
- // Auto-register with the capability registry (v0.1.46 — no need to edit capability-registry.ts)
90
- (0, capability_registry_1.registerCapability)({ capability: "plan", summary: "Plan a workflow run on a repo + app.", entry: "planSummary", surface: "both", cli: { path: ["plan"], jsonMode: "default" }, mcp: { tool: "cw_plan" } });
91
97
  // ---- canonical app-run payload --------------------------------------------
92
98
  // Both `cw app run` and `cw_app_run` resolve to this exact object. Structured
93
99
  // app inputs + optional sandbox resolution, then a compact operator status.
@@ -113,7 +119,6 @@ function appRun(runner, args) {
113
119
  sandboxProfile: resolvedSandbox
114
120
  };
115
121
  }
116
- (0, capability_registry_1.registerCapability)({ capability: "app.run", summary: "Plan a run on a named app with structured inputs.", entry: "appRun", surface: "both", cli: { path: ["app", "run"], caseTokens: ["app"], jsonMode: "default" }, mcp: { tool: "cw_app_run" } });
117
122
  // ---- canonical sandbox choice payload -------------------------------------
118
123
  // Both `cw sandbox choose|resolve` and `cw_sandbox_choose|cw_sandbox_resolve`
119
124
  // resolve to this exact object.
@@ -150,7 +155,6 @@ function commitEnvelope(runner, runId, args) {
150
155
  commit
151
156
  };
152
157
  }
153
- (0, capability_registry_1.registerCapability)({ capability: "commit", summary: "Create a verifier-gated state commit with evidence.", entry: "commitEnvelope", surface: "both", cli: { path: ["commit"], jsonMode: "default" }, mcp: { tool: "cw_commit" }, payloadIdentical: false, reason: "CLI renders a human summary with path hints; MCP returns the structured commit payload alone." });
154
158
  function compactOperatorStatus(status) {
155
159
  return {
156
160
  runId: status.runId,
@@ -194,6 +198,19 @@ function flag(value) {
194
198
  return false;
195
199
  return Boolean(value);
196
200
  }
201
+ function withInvocationCwd(args, fn) {
202
+ const cwd = optionalString(args.cwd);
203
+ if (!cwd)
204
+ return fn();
205
+ const previous = process.cwd();
206
+ process.chdir(cwd);
207
+ try {
208
+ return fn();
209
+ }
210
+ finally {
211
+ process.chdir(previous);
212
+ }
213
+ }
197
214
  function runRegistryRefresh(reg, args) {
198
215
  return reg.refresh({ scope: scopeOf(args, "repo") });
199
216
  }
@@ -225,11 +242,19 @@ function runList(reg, args) {
225
242
  function runShow(reg, runId, args) {
226
243
  return reg.showRun(runId, { scope: scopeOf(args, "home") });
227
244
  }
228
- function runResume(reg, runId, args) {
229
- return reg.resume(runId, {
245
+ function runResume(reg, runner, runId, args) {
246
+ const base = reg.resume(runId, {
230
247
  scope: scopeOf(args, "home"),
231
248
  limit: args.limit === undefined ? undefined : Number(args.limit)
232
249
  });
250
+ // Default (no --drive/--once): read-only, byte-identical to before.
251
+ if (!isTrue(args.drive) && !isTrue(args.once))
252
+ return base;
253
+ // Opt-in continuation: hand the resolved run to the EXISTING agent-delegation
254
+ // drive loop (re-plans nothing; picks up pending/running tasks from durable
255
+ // state). An unconfigured agent surfaces drive.status="blocked" (fail-closed).
256
+ const drive = runDrive(runner, { ...args, runId: base.runId, repo: base.repo, once: isTrue(args.once) });
257
+ return { ...base, drive };
233
258
  }
234
259
  function runArchive(reg, runId, args) {
235
260
  if (runId) {
@@ -251,6 +276,38 @@ function runArchive(reg, runId, args) {
251
276
  function runRerun(reg, runId, args) {
252
277
  return reg.rerun(runId, { scope: scopeOf(args, "home"), reason: optionalString(args.reason) });
253
278
  }
279
+ function runExportArchive(runner, runId, args) {
280
+ return withInvocationCwd(args, () => {
281
+ const output = optionalString(args.output || args.path || args.archive) || `${runId}.cwrun.json`;
282
+ return (0, run_export_1.exportRun)(runner.loadRun(runId), node_path_1.default.resolve(output));
283
+ });
284
+ }
285
+ function runImportArchive(runner, args) {
286
+ return withInvocationCwd(args, () => {
287
+ const archive = optionalString(args.archive || args.path || args.file);
288
+ if (!archive)
289
+ throw new Error("run import requires an archive path (positional, --archive, --path, or --file)");
290
+ const target = optionalString(args.target || args.repo || args.cwd) || process.cwd();
291
+ const imported = (0, run_export_1.importRun)(node_path_1.default.resolve(archive), node_path_1.default.resolve(target));
292
+ const registry = new run_registry_1.RunRegistry(node_path_1.default.resolve(target), runner);
293
+ const registryReport = registry.refresh({ scope: "repo" });
294
+ return { ...imported, registry: registryReport };
295
+ });
296
+ }
297
+ // Read-only: inspect a portable archive's integrity WITHOUT importing it. Routes
298
+ // both surfaces through one shared core entry. The runner is unused (no registry
299
+ // touch — inspection writes nothing) but kept for dispatch-signature symmetry.
300
+ function runInspectArchive(_runner, args) {
301
+ return withInvocationCwd(args, () => {
302
+ const archive = optionalString(args.archive || args.path || args.file);
303
+ if (!archive)
304
+ throw new Error("run inspect-archive requires an archive path (positional, --archive, --path, or --file)");
305
+ return (0, run_export_1.inspectArchive)(node_path_1.default.resolve(archive));
306
+ });
307
+ }
308
+ function runVerifyImport(runner, runId, args) {
309
+ return withInvocationCwd(args, () => (0, run_export_1.verifyImportedRun)(runner.loadRun(runId)));
310
+ }
254
311
  function queueAdd(reg, args) {
255
312
  return reg.queueAdd({
256
313
  runId: optionalString(args.runId),
@@ -384,7 +441,8 @@ const DRIVE_RUNTIME_KEYS = [
384
441
  "agentModel",
385
442
  "agent-model",
386
443
  "agentTimeoutMs",
387
- "agent-timeout-ms"
444
+ "agent-timeout-ms",
445
+ "resume"
388
446
  ];
389
447
  function planInputsFor(args) {
390
448
  const copy = withoutRuntimeKeys(args);
@@ -436,6 +494,12 @@ exports.QUICKSTART_DEFAULT_APP = "architecture-review";
436
494
  function quickstart(runner, args) {
437
495
  const appId = String(args.appId || args.app || args.workflowId || exports.QUICKSTART_DEFAULT_APP);
438
496
  const agentConfigured = Boolean((0, agent_config_1.resolveAgentConfig)(args).command || (0, agent_config_1.resolveAgentConfig)(args).endpoint);
497
+ // `--resume`: a discoverability flag over the existing continuation. With no
498
+ // `--run`, advance exactly ONE step (reuse the `--once` path) and print a
499
+ // copy-pasteable continue line; with `--run <id>`, continue that run to
500
+ // completion (the default drive). It adds no new execution path.
501
+ const resume = isTrue(args.resume);
502
+ const resumeRunId = resume ? optionalString(args.runId || args.run) : undefined;
439
503
  // `--preview`: read-only, deterministic next-step projection (no spawn, no commit).
440
504
  // Plan a fresh run (the read-only first verb) then project the next drive step.
441
505
  if (isTrue(args.preview)) {
@@ -460,7 +524,10 @@ function quickstart(runner, args) {
460
524
  // Drive end-to-end (or one `--once` step). runDrive plans the run, delegates each
461
525
  // worker to the agent backend, and commits — we add only the report write + a
462
526
  // single assembled payload. No orchestration is duplicated here.
463
- const result = runDrive(runner, { ...args, appId });
527
+ // `--resume` with no run id advances a single step so a newcomer WITNESSES the
528
+ // stop-then-resume; with a run id it continues to completion. Non-resume paths
529
+ // are untouched (byte-identical default).
530
+ const result = runDrive(runner, { ...args, appId, ...(resume && !resumeRunId ? { once: true } : {}) });
464
531
  // Always (re)write the report so the one command yields a report.md on disk, even
465
532
  // when the drive blocked/parked (a partial report is still useful triage).
466
533
  const cwd0 = process.cwd();
@@ -492,7 +559,9 @@ function quickstart(runner, args) {
492
559
  hint = `the drive is blocked — inspect: cw run drive ${result.runId}`;
493
560
  }
494
561
  else if (result.status === "in-progress") {
495
- hint = `one step advanced (--once) — continue: cw quickstart ${appId} --run ${result.runId} --once`;
562
+ hint = resume
563
+ ? `one step advanced — continue: cw quickstart ${appId} --run ${result.runId} --resume`
564
+ : `one step advanced (--once) — continue: cw quickstart ${appId} --run ${result.runId} --once`;
496
565
  }
497
566
  return {
498
567
  schemaVersion: 1,
@@ -508,7 +577,11 @@ function quickstart(runner, args) {
508
577
  statePath: result.statePath,
509
578
  agentConfigured,
510
579
  steps: result.steps,
511
- hint
580
+ hint,
581
+ // Stamp resumedFrom ONLY when we continued an explicit run. Conditional spread
582
+ // keeps the key absent on the default/fresh path (own-property absent + omitted
583
+ // by JSON.stringify), so default output is byte-identical.
584
+ ...(resumeRunId ? { resumedFrom: resumeRunId } : {})
512
585
  };
513
586
  }
514
587
  /** Read-only, deterministic projection of the effective agent config (secret-stripped). */
@@ -642,15 +715,57 @@ function telemetryVerify(runner, args) {
642
715
  throw new Error("telemetry verify requires a run id (cw telemetry verify <run-id>)");
643
716
  const run = runner.loadRun(runId);
644
717
  const v = (0, telemetry_ledger_1.verifyTelemetryLedger)(run);
718
+ // Opt-in independent signature re-verification. verifyTelemetryLedger re-proves
719
+ // the chain (so the stored attestation verdicts were not edited); supplying the
720
+ // trust public key (--pubkey / CW_AGENT_ATTEST_PUBKEY) additionally RE-RUNS the
721
+ // ed25519 check over each `attested` record's stored raw usage rather than
722
+ // trusting that verdict, so a forged signature can no longer ride a green chain.
723
+ const trustPublicKeyInput = optionalString(args.pubkey || args.pubKey || args.publicKey) || process.env.CW_AGENT_ATTEST_PUBKEY;
724
+ const trustPublicKey = (0, telemetry_attestation_1.resolveTrustPublicKey)(trustPublicKeyInput);
725
+ const keyChecks = trustPublicKeyInput && !trustPublicKey
726
+ ? [{ name: "signature-key", pass: false, code: "telemetry-pubkey-unreadable" }]
727
+ : [];
728
+ const sig = (0, telemetry_attestation_1.verifyTelemetrySignatures)(v.records, trustPublicKey);
729
+ const failedChecks = [...v.checks.filter((c) => !c.pass), ...keyChecks, ...sig.checks.filter((c) => !c.pass)];
645
730
  return {
646
731
  schemaVersion: 1,
647
732
  runId: run.id,
648
733
  present: v.present,
649
- verified: v.verified,
734
+ // Chain integrity AND (when a key was supplied) every attested signature must
735
+ // re-verify. With no key, sig.failed is 0 → unchanged chain-only behavior.
736
+ verified: v.verified && keyChecks.length === 0 && sig.failed === 0,
650
737
  records: v.records.length,
651
738
  attested: v.attested,
652
739
  unattested: v.unattested,
653
740
  absent: v.absent,
741
+ signatureKeyProvided: sig.keyProvided,
742
+ signaturesChecked: sig.checked,
743
+ signaturesReverified: sig.reverified,
744
+ signaturesFailed: sig.failed,
745
+ failedChecks: failedChecks.map((c) => ({ name: c.name, code: c.code }))
746
+ };
747
+ }
748
+ // audit.verify — fail-closed re-prove of a run's trust-audit hash chain. The peer
749
+ // of telemetry.verify for the sandbox/policy/commit-gate decision log: recomputes
750
+ // every event hash from genesis, checks chain linkage, and catches the
751
+ // unchained-event forgery. Exposed as a verb (not just embedded in `audit summary`,
752
+ // which always exits 0) so `cw audit verify <run> && deploy` can gate on the exit
753
+ // code. POLA: a run with no audit log is present:false / verified:true / exit 0.
754
+ function auditVerify(runner, args) {
755
+ const runId = optionalString(args.runId || args.run);
756
+ if (!runId)
757
+ throw new Error("audit verify requires a run id (cw audit verify <run-id>)");
758
+ const run = runner.loadRun(runId);
759
+ const v = (0, trust_audit_1.verifyTrustAudit)(run);
760
+ return {
761
+ schemaVersion: 1,
762
+ runId: run.id,
763
+ present: v.present,
764
+ verified: v.verified,
765
+ eventCount: v.eventCount,
766
+ chained: v.chained,
767
+ unchained: v.unchained,
768
+ corruptLines: v.corruptLines,
654
769
  failedChecks: v.checks.filter((c) => !c.pass).map((c) => ({ name: c.name, code: c.code }))
655
770
  };
656
771
  }