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.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +53 -332
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- package/apps/architecture-review-fast/workflow.js +2 -0
- package/apps/end-to-end-golden-path/app.json +1 -1
- package/apps/pr-review-fix-ci/app.json +1 -1
- package/apps/release-cut/app.json +1 -1
- package/apps/research-synthesis/app.json +1 -1
- package/dist/capability-core.js +131 -3
- package/dist/capability-registry.js +108 -50
- package/dist/cli/command-surface.js +83 -10
- package/dist/cli.js +2 -1
- package/dist/doctor.js +50 -5
- package/dist/execution-backend.js +8 -0
- package/dist/mcp/tool-call.js +428 -0
- package/dist/mcp/tool-definitions.js +1027 -0
- package/dist/mcp-surface.js +5 -1442
- package/dist/onramp.js +421 -0
- package/dist/operator-ux/format.js +21 -15
- package/dist/operator-ux.js +2 -1
- package/dist/orchestrator.js +190 -87
- package/dist/term.js +93 -0
- package/dist/version.js +1 -1
- package/dist/workbench-host.js +1 -8
- package/docs/agent-delegation-drive.7.md +45 -8
- package/docs/cli-mcp-parity.7.md +41 -6
- package/docs/contract-migration-tooling.7.md +6 -0
- package/docs/control-plane-scheduling.7.md +6 -0
- package/docs/dogfood-one-real-repo.7.md +9 -1
- package/docs/durable-state-and-locking.7.md +6 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +6 -0
- package/docs/execution-backends.7.md +6 -0
- package/docs/getting-started.md +40 -2
- package/docs/index.md +51 -38
- package/docs/multi-agent-cli-mcp-surface.7.md +6 -0
- package/docs/multi-agent-eval-replay-harness.7.md +6 -0
- package/docs/multi-agent-operator-ux.7.md +6 -0
- package/docs/node-snapshot-diff-replay.7.md +6 -0
- package/docs/observability-cost-accounting.7.md +6 -0
- package/docs/project-index.md +24 -7
- package/docs/real-execution-backends.7.md +6 -0
- package/docs/release-and-migration.7.md +7 -1
- package/docs/release-history.md +352 -0
- package/docs/release-tooling.7.md +28 -0
- package/docs/run-registry-control-plane.7.md +6 -0
- package/docs/run-retention-reclamation.7.md +6 -0
- package/docs/state-explosion-management.7.md +6 -0
- package/docs/team-collaboration.7.md +6 -0
- package/docs/web-desktop-workbench.7.md +6 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +1 -1
- package/package.json +2 -1
- package/scripts/agents/agent-adapter-core.js +180 -0
- package/scripts/agents/builtin-templates.json +4 -1
- package/scripts/agents/codex-agent.js +134 -0
- package/scripts/agents/gemini-agent.js +115 -0
- package/scripts/agents/opencode-agent.js +119 -0
- package/scripts/architecture-review-fast.js +44 -2
- package/scripts/canonical-apps.js +4 -4
- package/scripts/dogfood-release.js +55 -133
- package/scripts/golden-path.js +4 -4
- package/scripts/onramp-check.js +47 -0
- package/scripts/parity-check.js +741 -2
- package/scripts/release-check.js +5 -3
- package/scripts/release-gate.sh +1 -1
- package/scripts/source-context.js +31 -5
- package/scripts/version-sync-check.js +4 -2
package/dist/orchestrator.js
CHANGED
|
@@ -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:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 ||
|
|
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 ||
|
|
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 ||
|
|
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 ||
|
|
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 =
|
|
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
|
-
|
|
819
|
-
"
|
|
820
|
-
"
|
|
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
|
-
"
|
|
823
|
-
"
|
|
824
|
-
"
|
|
825
|
-
"
|
|
826
|
-
"
|
|
827
|
-
"
|
|
828
|
-
"
|
|
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.
|
|
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;
|
package/dist/workbench-host.js
CHANGED
|
@@ -99,14 +99,7 @@ class WorkbenchHost {
|
|
|
99
99
|
}
|
|
100
100
|
const runMatch = /^\/api\/run\/([^/]+)$/.exec(route);
|
|
101
101
|
if (runMatch) {
|
|
102
|
-
|
|
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,
|
|
176
|
-
|
|
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
|
|
191
|
-
|
|
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
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|