cool-workflow 0.1.85 → 0.1.87

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 (69) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +53 -332
  4. package/apps/architecture-review/app.json +1 -1
  5. package/apps/architecture-review-fast/app.json +1 -1
  6. package/apps/architecture-review-fast/workflow.js +2 -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/capability-core.js +131 -3
  12. package/dist/capability-registry.js +108 -50
  13. package/dist/cli/command-surface.js +83 -10
  14. package/dist/cli.js +2 -1
  15. package/dist/doctor.js +50 -5
  16. package/dist/execution-backend.js +8 -0
  17. package/dist/mcp/tool-call.js +428 -0
  18. package/dist/mcp/tool-definitions.js +1027 -0
  19. package/dist/mcp-surface.js +5 -1442
  20. package/dist/onramp.js +421 -0
  21. package/dist/operator-ux/format.js +21 -15
  22. package/dist/operator-ux.js +2 -1
  23. package/dist/orchestrator.js +190 -87
  24. package/dist/term.js +93 -0
  25. package/dist/version.js +1 -1
  26. package/dist/workbench-host.js +1 -8
  27. package/docs/agent-delegation-drive.7.md +45 -8
  28. package/docs/cli-mcp-parity.7.md +41 -6
  29. package/docs/contract-migration-tooling.7.md +6 -0
  30. package/docs/control-plane-scheduling.7.md +6 -0
  31. package/docs/dogfood-one-real-repo.7.md +9 -1
  32. package/docs/durable-state-and-locking.7.md +6 -0
  33. package/docs/evidence-adoption-reasoning-chain.7.md +6 -0
  34. package/docs/execution-backends.7.md +6 -0
  35. package/docs/getting-started.md +40 -2
  36. package/docs/index.md +51 -38
  37. package/docs/multi-agent-cli-mcp-surface.7.md +6 -0
  38. package/docs/multi-agent-eval-replay-harness.7.md +6 -0
  39. package/docs/multi-agent-operator-ux.7.md +6 -0
  40. package/docs/node-snapshot-diff-replay.7.md +6 -0
  41. package/docs/observability-cost-accounting.7.md +6 -0
  42. package/docs/project-index.md +24 -7
  43. package/docs/real-execution-backends.7.md +6 -0
  44. package/docs/release-and-migration.7.md +7 -1
  45. package/docs/release-history.md +352 -0
  46. package/docs/release-tooling.7.md +28 -0
  47. package/docs/run-registry-control-plane.7.md +6 -0
  48. package/docs/run-retention-reclamation.7.md +6 -0
  49. package/docs/state-explosion-management.7.md +6 -0
  50. package/docs/team-collaboration.7.md +6 -0
  51. package/docs/web-desktop-workbench.7.md +6 -0
  52. package/manifest/plugin.manifest.json +1 -1
  53. package/manifest/source-context-profiles.json +1 -1
  54. package/package.json +2 -1
  55. package/scripts/agents/agent-adapter-core.js +180 -0
  56. package/scripts/agents/builtin-templates.json +4 -1
  57. package/scripts/agents/codex-agent.js +134 -0
  58. package/scripts/agents/gemini-agent.js +115 -0
  59. package/scripts/agents/opencode-agent.js +119 -0
  60. package/scripts/architecture-review-fast.js +44 -2
  61. package/scripts/canonical-apps.js +4 -4
  62. package/scripts/dogfood-release.js +55 -133
  63. package/scripts/golden-path.js +4 -4
  64. package/scripts/onramp-check.js +47 -0
  65. package/scripts/parity-check.js +741 -2
  66. package/scripts/release-check.js +5 -3
  67. package/scripts/release-gate.sh +1 -1
  68. package/scripts/source-context.js +31 -5
  69. package/scripts/version-sync-check.js +4 -2
@@ -36,8 +36,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
36
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
37
  };
38
38
  Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.CoolWorkflowRunner = void 0;
39
+ exports.KNOWN_COMMANDS = exports.CoolWorkflowRunner = void 0;
40
40
  exports.parseArgv = parseArgv;
41
+ exports.suggestCommand = suggestCommand;
42
+ exports.formatSearchResults = formatSearchResults;
43
+ exports.formatInfo = formatInfo;
41
44
  exports.formatHelp = formatHelp;
42
45
  const node_fs_1 = __importDefault(require("node:fs"));
43
46
  const node_path_1 = __importDefault(require("node:path"));
@@ -68,6 +71,7 @@ const feedbackOps = __importStar(require("./orchestrator/feedback-operations"));
68
71
  const topologyOps = __importStar(require("./orchestrator/topology-operations"));
69
72
  const lifecycleOps = __importStar(require("./orchestrator/lifecycle-operations"));
70
73
  const migrationOps = __importStar(require("./orchestrator/migration-operations"));
74
+ const term_1 = require("./term");
71
75
  // CoolWorkflowRunner — the single FACADE both surfaces (cli.ts and the MCP server)
72
76
  // call through. It is deliberately WIDE but THIN: each method either
73
77
  // (a) loads the run's durable state and delegates to a domain function in
@@ -178,7 +182,7 @@ class CoolWorkflowRunner {
178
182
  return {
179
183
  valid: false,
180
184
  appId: target,
181
- appPath: node_path_1.default.resolve(target),
185
+ appPath: this.resolveFromBase(target),
182
186
  issues
183
187
  };
184
188
  }
@@ -188,7 +192,7 @@ class CoolWorkflowRunner {
188
192
  if (!id)
189
193
  throw new Error("App id must include at least one letter or digit");
190
194
  const title = String(options.title || titleize(id));
191
- const destinationDir = node_path_1.default.resolve(String(options.directory || options.output || node_path_1.default.join(this.appsDir, id)));
195
+ const destinationDir = this.resolveFromBase(String(options.directory || options.output || node_path_1.default.join(this.appsDir, id)));
192
196
  const manifestPath = node_path_1.default.join(destinationDir, "app.json");
193
197
  const entrypointPath = node_path_1.default.join(destinationDir, "workflow.js");
194
198
  if (!options.force && (node_fs_1.default.existsSync(manifestPath) || node_fs_1.default.existsSync(entrypointPath))) {
@@ -205,8 +209,7 @@ class CoolWorkflowRunner {
205
209
  }
206
210
  packageApp(appId, options = {}) {
207
211
  const record = this.loadWorkflowAppById(appId);
208
- const destination = node_path_1.default.resolve(String(options.output ||
209
- node_path_1.default.join(process.cwd(), ".cw", "packages", `${record.app.id}-${record.app.version}.cwapp.json`)));
212
+ const destination = this.resolveFromBase(String(options.output || node_path_1.default.join(".cw", "packages", `${record.app.id}-${record.app.version}.cwapp.json`)));
210
213
  node_fs_1.default.mkdirSync(node_path_1.default.dirname(destination), { recursive: true });
211
214
  (0, state_1.writeJson)(destination, {
212
215
  schemaVersion: 1,
@@ -221,7 +224,7 @@ class CoolWorkflowRunner {
221
224
  if (!id)
222
225
  throw new Error("Workflow id must include at least one letter or digit");
223
226
  const title = String(options.title || titleize(id));
224
- const destination = node_path_1.default.resolve(String(options.output || node_path_1.default.join(this.workflowsDir, `${id}.workflow.js`)));
227
+ const destination = this.resolveFromBase(String(options.output || node_path_1.default.join(this.workflowsDir, `${id}.workflow.js`)));
225
228
  if (node_fs_1.default.existsSync(destination) && !options.force) {
226
229
  throw new Error(`Refusing to overwrite existing workflow: ${destination}`);
227
230
  }
@@ -248,7 +251,7 @@ class CoolWorkflowRunner {
248
251
  return lifecycleOps.dispatch(this.loadRun(runId), options);
249
252
  }
250
253
  recordResult(runId, taskId, resultPath, options = {}) {
251
- return lifecycleOps.recordResult(this.loadRun(runId), taskId, resultPath, options);
254
+ return lifecycleOps.recordResult(this.loadRun(runId), taskId, this.resolveFromBase(resultPath), options);
252
255
  }
253
256
  listWorkers(runId, options = {}) {
254
257
  return (0, worker_isolation_1.listWorkerScopes)(this.loadRun(runId), {
@@ -272,13 +275,13 @@ class CoolWorkflowRunner {
272
275
  return (0, worker_isolation_1.writeWorkerManifest)(run, worker);
273
276
  }
274
277
  recordWorkerOutput(runId, workerId, resultPath, options = {}) {
275
- return lifecycleOps.recordWorkerOutput(this.loadRun(runId), workerId, resultPath, options);
278
+ return lifecycleOps.recordWorkerOutput(this.loadRun(runId), workerId, this.resolveFromBase(resultPath), options);
276
279
  }
277
280
  recordWorkerFailure(runId, workerId, message, options = {}) {
278
281
  return lifecycleOps.recordWorkerFailure(this.loadRun(runId), workerId, message, options);
279
282
  }
280
283
  validateWorker(runId, workerId, targetPath) {
281
- return (0, worker_isolation_1.validateWorkerBoundary)(this.loadRun(runId), workerId, targetPath ? { path: targetPath } : {});
284
+ return (0, worker_isolation_1.validateWorkerBoundary)(this.loadRun(runId), workerId, targetPath ? { path: this.resolveFromBase(targetPath) } : {});
282
285
  }
283
286
  // Audit domain — delegated to ./orchestrator/audit-operations (v0.1.40 P3
284
287
  // router pattern). The runner stays the routing surface; the logic lives in the
@@ -314,13 +317,13 @@ class CoolWorkflowRunner {
314
317
  return auditOps.recordAuditDecision(this.loadRun(runId), workerId, options);
315
318
  }
316
319
  listSandboxProfiles(options = {}) {
317
- return (0, sandbox_profile_1.listBundledSandboxProfiles)((0, sandbox_profile_1.sandboxContextForValidation)(String(options.cwd || process.cwd())));
320
+ return (0, sandbox_profile_1.listBundledSandboxProfiles)((0, sandbox_profile_1.sandboxContextForValidation)(String(options.cwd || this.invocationCwd())));
318
321
  }
319
322
  showSandboxProfile(profileId, options = {}) {
320
- return (0, sandbox_profile_1.showBundledSandboxProfile)(profileId, (0, sandbox_profile_1.sandboxContextForValidation)(String(options.cwd || process.cwd())));
323
+ return (0, sandbox_profile_1.showBundledSandboxProfile)(profileId, (0, sandbox_profile_1.sandboxContextForValidation)(String(options.cwd || this.invocationCwd())));
321
324
  }
322
325
  validateSandboxProfile(profileFile, options = {}) {
323
- return (0, sandbox_profile_1.validateSandboxProfileFile)(profileFile, (0, sandbox_profile_1.sandboxContextForValidation)(String(options.cwd || process.cwd())));
326
+ return (0, sandbox_profile_1.validateSandboxProfileFile)(this.resolveFromBase(profileFile), (0, sandbox_profile_1.sandboxContextForValidation)(String(options.cwd || this.invocationCwd())));
324
327
  }
325
328
  listBackends(options = {}) {
326
329
  void options;
@@ -331,7 +334,7 @@ class CoolWorkflowRunner {
331
334
  return (0, execution_backend_1.backendShowPayload)(backendId);
332
335
  }
333
336
  probeBackend(backendId, options = {}) {
334
- return (0, execution_backend_1.backendProbePayload)(backendId, { cwd: String(options.cwd || process.cwd()) });
337
+ return (0, execution_backend_1.backendProbePayload)(backendId, { cwd: String(options.cwd || this.invocationCwd()) });
335
338
  }
336
339
  // Candidate domain — delegated to ./orchestrator/candidate-operations.
337
340
  listCandidates(runId, options = {}) {
@@ -716,6 +719,12 @@ class CoolWorkflowRunner {
716
719
  loadRun(runId) {
717
720
  return (0, state_1.loadRunFromCwd)(runId, this.baseDir);
718
721
  }
722
+ invocationCwd() {
723
+ return this.baseDir || process.cwd();
724
+ }
725
+ resolveFromBase(target) {
726
+ return node_path_1.default.resolve(this.invocationCwd(), target);
727
+ }
719
728
  loadWorkflowAppById(appId) {
720
729
  const record = this.loadWorkflowApps().find((candidate) => candidate.app.id === appId);
721
730
  if (!record)
@@ -725,7 +734,7 @@ class CoolWorkflowRunner {
725
734
  loadWorkflowAppTarget(target) {
726
735
  if (!target)
727
736
  throw new Error("Missing workflow app path or id");
728
- const resolved = node_path_1.default.resolve(target);
737
+ const resolved = this.resolveFromBase(target);
729
738
  if (node_fs_1.default.existsSync(resolved)) {
730
739
  const stat = node_fs_1.default.statSync(resolved);
731
740
  if (stat.isDirectory())
@@ -811,83 +820,177 @@ function parseArgv(argv) {
811
820
  }
812
821
  return { command, positionals, options };
813
822
  }
823
+ /** All known top-level CW commands. Used for "did you mean?" suggestions. */
824
+ exports.KNOWN_COMMANDS = new Set([
825
+ "help", "list", "doctor", "info", "search", "man", "init", "quickstart", "plan", "status", "next",
826
+ "dispatch", "result", "state", "commit", "report", "app", "sandbox",
827
+ "backend", "contract", "node", "feedback", "worker", "audit", "candidate",
828
+ "review", "loop", "schedule", "routine", "registry", "run", "queue",
829
+ "history", "audit-run", "multi-agent", "topology", "summary", "blackboard",
830
+ "coordinator", "metrics", "operator", "sched", "gc", "telemetry",
831
+ "migration", "demo", "workbench", "approve", "reject", "comment", "handoff",
832
+ "graph", "eval"
833
+ ]);
834
+ /** Levenshtein distance between two short strings. */
835
+ function levenshtein(a, b) {
836
+ const m = a.length;
837
+ const n = b.length;
838
+ let prev = Array.from({ length: n + 1 }, (_, j) => j);
839
+ let curr = new Array(n + 1);
840
+ for (let i = 1; i <= m; i++) {
841
+ curr[0] = i;
842
+ for (let j = 1; j <= n; j++) {
843
+ curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
844
+ }
845
+ [prev, curr] = [curr, prev];
846
+ }
847
+ return prev[n];
848
+ }
849
+ /** Suggest the closest known command for a typo. Returns undefined if no match
850
+ * within half the length of the input (avoiding wild guesses on short strings). */
851
+ function suggestCommand(input) {
852
+ if (!input || input.length < 2)
853
+ return undefined;
854
+ const lower = input.toLowerCase();
855
+ let best = "";
856
+ let bestDist = Infinity;
857
+ for (const cmd of exports.KNOWN_COMMANDS) {
858
+ const dist = levenshtein(lower, cmd);
859
+ if (dist < bestDist) {
860
+ best = cmd;
861
+ bestDist = dist;
862
+ }
863
+ }
864
+ // Threshold: distance must be <= half the input length AND <= 3
865
+ if (bestDist <= 3 && bestDist <= lower.length / 2)
866
+ return best;
867
+ return undefined;
868
+ }
869
+ function formatSearchResults(keyword, results) {
870
+ if (!results.length)
871
+ return `No workflows matched "${keyword}".\n Tip: cw list for all available workflows.`;
872
+ return [
873
+ (0, term_1.bold)(`${results.length} workflow${results.length !== 1 ? "s" : ""} matching "${keyword}"`),
874
+ ...results.map((r) => ` ${r.id} — ${r.title}\n ${(0, term_1.dim)(r.summary.slice(0, 120))}${r.summary.length > 120 ? "…" : ""}`),
875
+ "",
876
+ (0, term_1.dim)("Use cw info <id> for full details.")
877
+ ].join("\n");
878
+ }
879
+ function formatInfo(appId, data) {
880
+ const app = (data.app || {});
881
+ const inputs = (Array.isArray(data.inputs) ? data.inputs : []);
882
+ const phases = (Array.isArray(data.phases) ? data.phases : []);
883
+ const lines = [(0, term_1.bold)(`cw info ${appId}`)];
884
+ if (data.title)
885
+ lines.push(` Title: ${data.title}`);
886
+ if (data.version)
887
+ lines.push(` Version: ${data.version}`);
888
+ if (data.summary)
889
+ lines.push(` Summary: ${data.summary}`);
890
+ if (data.author)
891
+ lines.push(` Author: ${typeof data.author === "object" ? data.author.name : data.author}`);
892
+ if (data.compatible !== undefined)
893
+ lines.push(` Compatible: ${data.compatible ? "yes" : "no"}`);
894
+ if (inputs.length > 0) {
895
+ lines.push(" Inputs:");
896
+ for (const input of inputs) {
897
+ const name = input.name || "";
898
+ const type = input.type || "string";
899
+ const required = input.required ? ", required" : "";
900
+ const def = input.default ? `, default: ${input.default}` : "";
901
+ const desc = input.description ? ` — ${input.description}` : "";
902
+ lines.push(` - ${name} (${type}${required}${def})${desc}`);
903
+ }
904
+ }
905
+ if (Array.isArray(data.sandboxProfiles) && data.sandboxProfiles.length > 0) {
906
+ lines.push(` Sandbox: ${data.sandboxProfiles.join(", ")}`);
907
+ }
908
+ const taskCount = data.taskCount || 0;
909
+ if (phases.length > 0) {
910
+ lines.push(` Phases: ${phases.length} phase${phases.length !== 1 ? "s" : ""}, ${taskCount} task${taskCount !== 1 ? "s" : ""}`);
911
+ }
912
+ lines.push(` Run: cw quickstart ${appId} --repo . --question "..."`);
913
+ return lines.join("\n");
914
+ }
814
915
  function formatHelp() {
815
916
  return [
816
- "Cool Workflow",
917
+ (0, term_1.bold)("Cool Workflow"),
918
+ "",
919
+ " Quick start (one command — plan → drive → report):",
920
+ " cw quickstart [app] --repo . --question \"...\" --agent-command builtin:claude",
921
+ " (--preview for a dry run without an agent; --bundle for a portable sealed report)",
922
+ "",
923
+ (0, term_1.bold)("Getting Started"),
924
+ " list List available workflow apps",
925
+ " search <keyword> Search workflows by title or description",
926
+ " info <app-id> [--json] Show what a workflow app does and how to run it",
927
+ " doctor [--json] [--onramp] [--fix] Check setup (--fix for consolidated fix commands)",
928
+ " init <id> [--title T] Create a new workflow app",
929
+ " quickstart [app] [...] Plan → drive → report in one command",
930
+ " demo tamper|bundle Prove trust checks work (30s, no agent needed)",
931
+ " man <topic> Show a man page (e.g. cw man release-tooling)",
932
+ "",
933
+ (0, term_1.bold)("Run Management"),
934
+ " plan <id> [--repo P] [--question Q] Create a new run plan",
935
+ " quickstart|audit-run [app] [...] Plan → drive → report in one command",
936
+ " status <run-id> [--json] [--brief] Show run status (--brief for compact summary)",
937
+ " next <run-id> [--limit N] Show pending dispatch tasks",
938
+ " dispatch <run-id> [--limit N] Dispatch tasks to workers",
939
+ " result <run-id> <task-id> <file> Record a task result",
940
+ " state check <run-id> [--write] Validate run state",
941
+ " commit <run-id> <mode> [...] Record a gated commit",
942
+ " report <run-id> [--show|--summary] Show the report (or bundle/verify-bundle)",
943
+ " graph <run-id> [--json] Show operator graph",
944
+ "",
945
+ (0, term_1.bold)("Inspection & Diagnostics"),
946
+ " operator status|report <run-id> [--json] Human-friendly operator panel",
947
+ " metrics show|summary <run-id> [--json] Cost and usage metrics",
948
+ " telemetry verify <run-id> [--pubkey P] Verify tamper-evident telemetry",
949
+ " migration list|check|prove [target] Schema migration tools",
950
+ " gc plan|run|verify [run-id] Garbage collection",
951
+ "",
952
+ (0, term_1.bold)("Audit & Trust"),
953
+ " audit summary|worker|provenance|multi-agent|... <run-id> Trust audit operations",
954
+ " candidate list|register|score|rank|select|reject <run-id> Candidate management",
955
+ " node list|show|graph|snapshot|diff|replay|verify <run-id> State-node inspection",
956
+ " eval snapshot|replay|compare|score|gate|report Eval/replay harness",
957
+ "",
958
+ (0, term_1.bold)("Multi‑Agent & Collaboration"),
959
+ " multi-agent run|status|step|blackboard|score|... <run-id> Multi-agent coordination",
960
+ " topology list|show|validate|apply|summary|graph Topology management",
961
+ " blackboard summary|graph|resolve|topic|message|... <run-id> Blackboard workspace",
962
+ " coordinator summary|decision <run-id> Coordinator interface",
963
+ " summary refresh|show <run-id> State explosion summaries",
964
+ " approve|reject|comment <kind> <run-id> <id> [--reason T] Team approval actions",
965
+ " handoff <kind> <run-id> <id> [--to ROLE] Team handoff",
966
+ " review status|policy <run-id> [--json] Review status",
967
+ "",
968
+ (0, term_1.bold)("Run Registry & Scheduling"),
969
+ " run search|list|show|resume|archive|export|import <id> Cross-repo run management",
970
+ " registry refresh|show [--scope repo|home] [--json] Run registry index",
971
+ " queue add|list|drain|show [queue-id] Work queue operations",
972
+ " history [--scope repo|home] [--json] Run history",
973
+ " schedule create|list|due|complete|... Scheduled tasks",
974
+ " routine create|fire|list|events|delete Event-driven triggers",
975
+ " sched plan|lease|release|complete|... Lease-based scheduling",
976
+ " loop --prompt T [--interval-minutes N] Continuous loop runner",
817
977
  "",
818
- "Quick start (ONE command — plan -> drive -> report):",
819
- " quickstart [architecture-review] --repo PATH --question TEXT --agent-command \"claude -p\"",
820
- " (delegates each worker to YOUR configured agent backend; --preview for a dry run)",
978
+ (0, term_1.bold)("Developer & Workspace"),
979
+ " app list|show|validate|init|package|run [id|path] Workflow app management",
980
+ " sandbox list|show|validate|choose|resolve [id] Sandbox profiles",
981
+ " backend list|show|probe [id] Agent execution backends",
982
+ " contract show <run-id> [id] Run contract view",
983
+ " worker list|summary|show|manifest|output|... <id> Worker operations",
984
+ " feedback list|show|summary|collect|task|resolve <id> Feedback loop",
985
+ " workbench serve [--port N] | view <run-id> Optional localhost workbench",
821
986
  "",
822
- "Commands:",
823
- " list",
824
- " doctor [--json] (check your setup: Node, agent backend, git, writable state)",
825
- " init <workflow-id> [--title TEXT] [--output PATH]",
826
- " quickstart [app-id] [--repo PATH] [--question TEXT] [--agent-command CMD] [--once] [--preview]",
827
- " plan <workflow-id> [--repo PATH] [--question TEXT] [--invariant TEXT]",
828
- " status <run-id> [--json|--format json]",
829
- " next <run-id> [--limit N]",
830
- " graph <run-id> [--json]",
831
- " dispatch <run-id> [--limit N] [--sandbox PROFILE] [--backend node|bun|shell|container|remote|ci]",
832
- " result <run-id> <task-id> <result-file>",
833
- " state check <run-id> [--state PATH] [--write]",
834
- " commit <run-id> --verifier <node-id> [--reason TEXT]",
835
- " commit <run-id> --candidate <candidate-id> [--reason TEXT]",
836
- " commit <run-id> --selection <selection-id> [--reason TEXT]",
837
- " commit <run-id> --allow-unverified-checkpoint [--reason TEXT]",
838
- " commit summary <run-id> [--json]",
839
- " report <run-id> [--show|--summary]",
840
- " app list|show|validate|init|package",
841
- " sandbox list|show|validate",
842
- " backend list|show|probe [backend-id]",
843
- " contract show <run-id> [contract-id]",
844
- " node list|show|graph <run-id>",
845
- " feedback list|summary|show|collect|task|resolve <run-id>",
846
- " worker list|summary|show|manifest|output|fail|validate <run-id>",
847
- " audit summary <run-id>",
848
- " audit worker <run-id> <worker-id>",
849
- " audit provenance <run-id> [--worker ID|--candidate ID|--commit ID]",
850
- " audit multi-agent <run-id> [--json]",
851
- " audit policy <run-id> [--json]",
852
- " audit role <run-id> <role-id> [--json]",
853
- " audit blackboard <run-id> [--json]",
854
- " audit judge <run-id> [--json]",
855
- " audit attest <run-id> [--worker ID] [--hostEnforced true] [--env NAME]",
856
- " audit decision <run-id> <worker-id> [--path PATH|--command CMD|--network TARGET|--env NAME]",
857
- " candidate list|summary|register|score|rank|select|reject <run-id>",
858
- " eval snapshot|replay|compare|score|gate|report",
859
- " summary refresh|show <run-id> [--json]",
860
- " blackboard summary|summarize|graph|resolve <run-id>",
861
- " blackboard topic create <run-id> --id <topic-id> --title TEXT",
862
- " blackboard message post|list <run-id>",
863
- " blackboard context put <run-id>",
864
- " blackboard artifact add|list <run-id>",
865
- " blackboard snapshot <run-id>",
866
- " coordinator summary <run-id>",
867
- " coordinator decision <run-id> --kind KIND --outcome OUTCOME --reason TEXT",
868
- " multi-agent run|status|step|blackboard|score|select|summary|summarize|graph|dependencies|failures|evidence <run-id>",
869
- " multi-agent graph <run-id> --view full|compact|critical-path|failures|evidence|trust|topology|blackboard|candidate|commit-gate [--focus ID] [--depth N]",
870
- " topology list|show|validate|apply|summary|graph",
871
- " schedule create|list|due|complete|pause|resume|run-now|history|daemon|delete",
872
- " routine create|fire|list|events|delete",
873
- " registry refresh|show [--scope repo|home] [--json]",
874
- " run search|list|show|resume|archive|rerun|export|import|verify-import [run-id|archive] [--scope repo|home] [--json]",
875
- " queue add|list|drain|show [queue-id] [--repo PATH] [--priority N]",
876
- " history [--scope repo|home] [--app ID] [--status STATE] [--json]",
877
- " audit-run <app-id> [--repo PATH] [--question TEXT] [--agent-command CMD]",
878
- " metrics show|summary <run-id> [--scope repo|home] [--json]",
879
- " telemetry verify <run-id> [--pubkey PEM|PATH] [--json]",
880
- " gc plan|run|verify [run-id] [--json]",
881
- " sched plan|lease|release|complete|reclaim|reset|policy [--json]",
882
- " migration list|check|prove [target] [--json]",
883
- " operator status|report <run-id> [--json]",
884
- " review status|policy <run-id> [--json]",
885
- " approve|reject|comment <kind> <run-id> <target-id> [--reason TEXT]",
886
- " handoff <kind> <run-id> <target-id> [--to ROLE]",
887
- " loop --prompt TEXT [--interval-minutes N]",
888
- " demo tamper",
889
- " workbench view <run-id> [--json]",
890
- " workbench serve [--port N] [--scope repo|home] [--once|--json]",
987
+ (0, term_1.bold)("Common Flags"),
988
+ " --json, --format json Machine-readable JSON output",
989
+ " --repo PATH Target repository path",
990
+ " --question TEXT The task or question to answer",
991
+ " --agent-command CMD Agent backend (e.g. builtin:claude, builtin:codex)",
992
+ " --scope repo|home Scope for cross-repo operations",
993
+ " --cwd PATH Working directory override",
891
994
  ""
892
995
  ].join("\n");
893
996
  }
package/dist/term.js ADDED
@@ -0,0 +1,93 @@
1
+ "use strict";
2
+ // src/term.ts — zero-dependency terminal styling.
3
+ //
4
+ // Provides TTY-gated ANSI formatting for human-readable output. When output is
5
+ // piped (non-TTY), styled calls return plain text. This keeps data channels
6
+ // (stdout) and diagnostics (stderr) clean — never adds escape codes to pipes.
7
+ //
8
+ // Used by: doctor, help, error messages, status summaries.
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.bold = bold;
11
+ exports.dim = dim;
12
+ exports.green = green;
13
+ exports.yellow = yellow;
14
+ exports.red = red;
15
+ exports.cyan = cyan;
16
+ exports.doctorGlyph = doctorGlyph;
17
+ exports.cwLabel = cwLabel;
18
+ exports.indent = indent;
19
+ exports.printSuccessSummary = printSuccessSummary;
20
+ function isTTY(stream = process.stderr) {
21
+ return Boolean(stream.isTTY);
22
+ }
23
+ // ---- ansi codes ----
24
+ const ansi = {
25
+ reset: "\x1b[0m",
26
+ bold: "\x1b[1m",
27
+ dim: "\x1b[2m",
28
+ green: "\x1b[32m",
29
+ yellow: "\x1b[33m",
30
+ red: "\x1b[31m",
31
+ cyan: "\x1b[36m",
32
+ };
33
+ // ---- styled text ----
34
+ function style(code, text, stream) {
35
+ if (!isTTY(stream))
36
+ return text;
37
+ return `${code}${text}${ansi.reset}`;
38
+ }
39
+ function bold(text, stream) {
40
+ return style(ansi.bold, text, stream);
41
+ }
42
+ function dim(text, stream) {
43
+ return style(ansi.dim, text, stream);
44
+ }
45
+ function green(text, stream) {
46
+ return style(ansi.green, text, stream);
47
+ }
48
+ function yellow(text, stream) {
49
+ return style(ansi.yellow, text, stream);
50
+ }
51
+ function red(text, stream) {
52
+ return style(ansi.red, text, stream);
53
+ }
54
+ function cyan(text, stream) {
55
+ return style(ansi.cyan, text, stream);
56
+ }
57
+ // ---- semantic helpers ----
58
+ /** Returns the styled glyph + label for a doctor check severity. */
59
+ function doctorGlyph(status, stream) {
60
+ const glyph = { ok: "✓", warn: "!", fail: "✗" };
61
+ const color = {
62
+ ok: green,
63
+ warn: yellow,
64
+ fail: red,
65
+ };
66
+ return color[status](`${glyph[status]}`, stream);
67
+ }
68
+ /** "cw:" prefix with bold and optional color. */
69
+ function cwLabel(stream) {
70
+ return bold("cw:", stream);
71
+ }
72
+ /** Render a multi-line block with consistent 2-space indentation. */
73
+ function indent(text, spaces = 2) {
74
+ const prefix = " ".repeat(spaces);
75
+ return text.split("\n").map((line) => `${prefix}${line}`).join("\n");
76
+ }
77
+ /** Print a success summary to stderr (TTY-gated). Shows the report path and a
78
+ * suggested next command. Pipe-friendly: silent when stderr is not a TTY. */
79
+ function printSuccessSummary(fields, stream) {
80
+ if (!isTTY(stream))
81
+ return;
82
+ const s = stream || process.stderr;
83
+ s.write(`\n${green("✓")} Report: ${fields.reportPath}\n`);
84
+ if (fields.status === "complete") {
85
+ s.write(` Next: cw status ${fields.runId} --brief\n`);
86
+ if (fields.bundle !== false) {
87
+ s.write(` Bundle: cw report bundle ${fields.runId}\n`);
88
+ }
89
+ }
90
+ else {
91
+ s.write(` ${yellow("!")} Status: ${fields.status}. Next: cw status ${fields.runId}\n`);
92
+ }
93
+ }
package/dist/version.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MIN_SUPPORTED_RUN_STATE_SCHEMA_VERSION = exports.LEGACY_RUN_STATE_SCHEMA_VERSION = exports.CURRENT_RUN_STATE_SCHEMA_VERSION = exports.WORKFLOW_APP_SCHEMA_VERSION = exports.CURRENT_COOL_WORKFLOW_VERSION = void 0;
4
- exports.CURRENT_COOL_WORKFLOW_VERSION = "0.1.85";
4
+ exports.CURRENT_COOL_WORKFLOW_VERSION = "0.1.87";
5
5
  exports.WORKFLOW_APP_SCHEMA_VERSION = 1;
6
6
  exports.CURRENT_RUN_STATE_SCHEMA_VERSION = 1;
7
7
  exports.LEGACY_RUN_STATE_SCHEMA_VERSION = 0;
@@ -99,14 +99,7 @@ class WorkbenchHost {
99
99
  }
100
100
  const runMatch = /^\/api\/run\/([^/]+)$/.exec(route);
101
101
  if (runMatch) {
102
- const previousCwd = process.cwd();
103
- process.chdir(this.cwd);
104
- try {
105
- return this.send(res, 200, (0, workbench_1.buildWorkbenchRunView)(this.runner, runMatch[1]));
106
- }
107
- finally {
108
- process.chdir(previousCwd);
109
- }
102
+ return this.send(res, 200, (0, workbench_1.buildWorkbenchRunView)(this.runner.withBaseDir(this.cwd), runMatch[1]));
110
103
  }
111
104
  this.send(res, 404, { error: `no such read-only view: ${route}` });
112
105
  }
@@ -128,6 +128,7 @@ node dist/cli.js backend agent config # show the effective config (se
128
128
  node dist/cli.js backend probe agent --json # ready iff configured, else unverified
129
129
 
130
130
  # drive a real repo end-to-end (zero hand-written result.md)
131
+ node dist/cli.js quickstart architecture-review --check --repo /path/to/repo --question "Is the design sound?" --agent-command "node $(pwd)/scripts/agents/claude-p-agent.js {{input}} {{result}}"
131
132
  node dist/cli.js run architecture-review --drive --repo /path/to/repo --question "Is the design sound?"
132
133
  node dist/cli.js run architecture-review --drive --once --repo /path/to/repo --question "..." # one step
133
134
  node dist/cli.js run drive <run-id> --json # read-only preview of the next step
@@ -135,12 +136,22 @@ node dist/cli.js run drive <run-id> --json # read-only preview of the next
135
136
  # quickstart --resume: a guided stop-then-resume a newcomer can WITNESS in <5 min
136
137
  node dist/cli.js quickstart --resume --repo /path/to/repo --question "..." # advances ONE step, prints a continue line
137
138
  node dist/cli.js quickstart --run <run-id> --resume # continues that run to completion
139
+ node dist/cli.js quickstart --run <run-id> --resume --bundle # continues, then seals a completed run
138
140
  ```
139
141
 
142
+ `quickstart --check` is a zero-write preflight. It does not make a run, write
143
+ `.cw/`, call the agent, write a report, or commit. It checks the app id, repo,
144
+ question, agent config, and (with `--bundle`) the trust-key shape, then gives the
145
+ next command to run. A blocked check exits non-zero, so scripts may use it as a
146
+ gate before a real run.
147
+
140
148
  `quickstart --resume` with no `--run` drives a single step and prints a
141
149
  copy-pasteable `cw quickstart --run <id> --resume` continue line; run it again with
142
150
  the `--run <id>` to finish. The continuing invocation echoes `resumedFrom: <id>`.
143
151
  Bare `quickstart` (no `--resume`) is unchanged — it drives straight to the end.
152
+ When `--bundle` is present on the fresh resume step, no bundle is sealed until
153
+ the run is complete; the continue line keeps `--bundle` so the second command
154
+ finishes and seals the report.
144
155
 
145
156
  For faster first results, use the opt-in fast app in place of changing the full
146
157
  review contract:
@@ -171,9 +182,15 @@ an Assess cache hit. A cache hit still goes through `recordWorkerOutput`
171
182
  validation; a corrupt cached result parks/fails closed rather than spawning a
172
183
  quiet fallback.
173
184
 
185
+ Verify and Verdict also get the source-context instruction so they do not have to
186
+ start by scanning the repo again. They are not result-cached; they still have to
187
+ cite evidence and make the final check from the accepted Map and Assess work.
188
+
174
189
  `--metrics` is diagnostic and opt-in. It adds elapsed milliseconds, step counts,
175
- agent-spawn counts, and `result-cache` hit counts to the wrapper JSON payload;
176
- without it, the wrapper's default output shape stays unchanged.
190
+ agent-spawn counts, `result-cache` hit counts, source-context bytes/digest, and
191
+ one row per driven task with phase, task id, elapsed time, and spawn/cache state
192
+ to the wrapper JSON payload; without it, the wrapper's default output shape stays
193
+ unchanged.
177
194
 
178
195
  `{{manifest}}`, `{{input}}`, `{{result}}`, `{{workerDir}}`, `{{model}}`, and
179
196
  `{{prompt}}` are put into DISCRETE argv elements (never a shell-interpreted
@@ -187,13 +204,15 @@ A drive can show the agent's activity live, without touching the evidence
187
204
  contract, when the operator opts in with `CW_AGENT_STREAM=1`:
188
205
 
189
206
  - **Default stays buffered.** Without `CW_AGENT_STREAM=1`, the bundled wrapper
190
- keeps the legacy `--output-format json` path and forwards claude's JSON stdout
191
- word for word after writing `result.md`.
207
+ keeps the buffered path and writes one JSON report to stdout after writing
208
+ `result.md`.
192
209
  - **The opt-in wrapper renders; stderr only.** With `CW_AGENT_STREAM=1`, the
193
- bundled wrapper runs claude in `--output-format stream-json` and renders a short
194
- human trace (tool uses, assistant text, per-turn summaries) to its
195
- **stderr** diagnostics, never data. It builds the single
196
- `{model, usage, result}` object for stdout again only on that opt-in path.
210
+ bundled Claude wrapper runs claude in `--output-format stream-json`, and the
211
+ bundled Codex wrapper runs `codex exec --json --output-last-message`.
212
+ Each wrapper renders a short human trace (tool uses, assistant text, per-turn
213
+ summaries where present) to its **stderr** diagnostics, never data. It builds
214
+ the single `{model, usage, result}` object for stdout after the final answer is
215
+ captured.
197
216
  - **Core forwards, never parses.** `runAgentProcess` passes the agent child's
198
217
  stderr straight through to the operator's terminal (`stdio` inherit) only when
199
218
  `CW_AGENT_STREAM=1`, CW's own stderr is a TTY, and `CW_NO_STREAM` is not set.
@@ -202,6 +221,18 @@ contract, when the operator opts in with `CW_AGENT_STREAM=1`:
202
221
  - **Determinism intact.** The backend evidence triple hashes stdout only, so
203
222
  the live stderr stream never changes recorded evidence or replay.
204
223
 
224
+ The built-in templates are:
225
+
226
+ ```text
227
+ --agent-command builtin:claude
228
+ --agent-command builtin:codex
229
+ ```
230
+
231
+ Gemini, OpenCode, DeepSeek, and GLM stay as external agent commands or HTTP
232
+ endpoints until their stream format is proven by a local, deterministic wrapper
233
+ smoke. DeepSeek and GLM are best reached through OpenCode or an HTTP agent
234
+ adapter first; CW still imports no model SDK.
235
+
205
236
  ## Compatibility
206
237
 
207
238
  Agent Delegation Drive comes in first in CW v0.1.38. Adding the `agent` row leaves
@@ -272,3 +303,9 @@ Loaders fail closed on corrupt state; store writes are made safe under more than
272
303
  No other change to this page in v0.1.84.
273
304
 
274
305
  0.1.85
306
+
307
+ 0.1.86
308
+
309
+ ## 0.1.87 (v0.1.87)
310
+
311
+ npm test parallel, 4-vendor wrappers (Claude/Codex/Gemini/OpenCode), Homebrew-style CLI UX (colors/did-you-mean/categorized help/error tips/cw info/cw search/cw man/doctor --fix), post-success summaries, agent execution timing