cool-workflow 0.2.3 → 0.2.5
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/.gemini-plugin/mcp.json +10 -0
- package/.gemini-plugin/plugin.json +40 -0
- package/.opencode-plugin/mcp.json +10 -0
- package/.opencode-plugin/plugin.json +40 -0
- package/README.md +202 -48
- package/apps/architecture-review/app.json +1 -1
- package/apps/architecture-review-fast/app.json +1 -1
- 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/cli/dispatch.js +33 -4
- package/dist/cli/entry.js +11 -19
- package/dist/cli/global-flags.js +113 -0
- package/dist/cli/io.js +6 -20
- package/dist/cli/parseargv.js +7 -1
- package/dist/core/capability-data.js +339 -10
- package/dist/core/format/help.js +80 -4
- package/dist/core/format/recovery-hint.js +32 -0
- package/dist/core/multi-agent/collaboration.js +35 -6
- package/dist/core/multi-agent/runtime.js +7 -0
- package/dist/core/multi-agent/trust-policy.js +7 -1
- package/dist/core/pipeline/contract.js +7 -0
- package/dist/core/pipeline/error-feedback.js +2 -2
- package/dist/core/trust/evidence-grounding.js +13 -1
- package/dist/core/util/cli-args.js +55 -0
- package/dist/core/version.js +1 -1
- package/dist/mcp/dispatch.js +22 -2
- package/dist/mcp/server.js +124 -13
- package/dist/mcp-server.js +20 -0
- package/dist/shell/commit.js +8 -2
- package/dist/shell/coordinator-io.js +73 -1
- package/dist/shell/drive.js +129 -64
- package/dist/shell/error-feedback-io.js +6 -0
- package/dist/shell/execution-backend/agent.js +205 -24
- package/dist/shell/execution-backend/container.js +44 -10
- package/dist/shell/execution-backend/local.js +47 -10
- package/dist/shell/fs-atomic.js +93 -12
- package/dist/shell/ledger-cli.js +9 -2
- package/dist/shell/multi-agent-cli.js +5 -1
- package/dist/shell/onramp.js +48 -5
- package/dist/shell/pipeline-cli.js +20 -2
- package/dist/shell/pipeline.js +2 -1
- package/dist/shell/reclamation-io.js +76 -7
- package/dist/shell/registry-cli.js +4 -0
- package/dist/shell/run-export.js +52 -4
- package/dist/shell/run-registry-io.js +1 -0
- package/dist/shell/run-store.js +156 -0
- package/dist/shell/scheduler-io.js +101 -10
- package/dist/shell/telemetry-ledger-io.js +36 -24
- package/dist/shell/trust-audit.js +104 -10
- package/dist/shell/workbench-host.js +121 -10
- package/dist/shell/workbench.js +79 -5
- package/dist/shell/worker-isolation.js +1 -1
- package/dist/shell/workflow-app-loader.js +67 -1
- package/dist/wiring/capability-table/basics.js +7 -2
- package/dist/wiring/capability-table/exec-backend.js +42 -24
- package/dist/wiring/capability-table/multi-agent.js +69 -69
- package/dist/wiring/capability-table/pipeline.js +60 -28
- package/dist/wiring/capability-table/registry-core.js +29 -6
- package/dist/wiring/capability-table/reporting.js +45 -39
- package/dist/wiring/capability-table/scheduling-registry.js +66 -60
- package/dist/wiring/capability-table/state.js +34 -34
- package/dist/wiring/capability-table/trust-ledger.js +66 -24
- package/dist/wiring/capability-table/workflow-apps.js +15 -15
- package/docs/agent-delegation-drive.7.md +17 -0
- package/docs/cli-mcp-parity.7.md +43 -13
- package/docs/contract-migration-tooling.7.md +4 -0
- package/docs/control-plane-scheduling.7.md +38 -0
- package/docs/cross-agent-ledger.7.md +20 -8
- package/docs/durable-state-and-locking.7.md +4 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +4 -0
- package/docs/execution-backends.7.md +4 -0
- package/docs/fix.7.md +4 -4
- package/docs/getting-started.md +40 -32
- package/docs/index.md +17 -0
- package/docs/launch/demo.tape +4 -3
- package/docs/mcp-app-surface.7.md +6 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +4 -0
- package/docs/multi-agent-eval-replay-harness.7.md +4 -0
- package/docs/multi-agent-operator-ux.7.md +4 -0
- package/docs/node-snapshot-diff-replay.7.md +4 -0
- package/docs/observability-cost-accounting.7.md +4 -0
- package/docs/project-index.md +43 -9
- package/docs/real-execution-backends.7.md +4 -0
- package/docs/release-and-migration.7.md +4 -0
- package/docs/release-tooling.7.md +22 -0
- package/docs/routine.7.md +22 -0
- package/docs/run-registry-control-plane.7.md +4 -0
- package/docs/run-retention-reclamation.7.md +28 -3
- package/docs/state-explosion-management.7.md +4 -0
- package/docs/team-collaboration.7.md +4 -0
- package/docs/trust-audit-anchor.7.md +4 -0
- package/docs/web-desktop-workbench.7.md +26 -2
- package/docs/workflow-app-framework.7.md +31 -0
- package/manifest/plugin.manifest.json +1 -1
- package/manifest/source-context-profiles.json +4 -3
- package/package.json +5 -2
- package/scripts/agents/agent-adapter-core.js +26 -0
- package/scripts/agents/claude-p-agent.js +4 -1
- package/scripts/agents/codex-agent.js +4 -0
- package/scripts/agents/cw-attest-wrap.js +1 -1
- package/scripts/agents/gemini-agent.js +4 -0
- package/scripts/agents/opencode-agent.js +5 -0
- package/scripts/block-unapproved-tag.js +160 -0
- package/scripts/bump-version.js +27 -10
- package/scripts/canonical-apps.js +4 -4
- package/scripts/children/batch-delegate-child.js +72 -4
- package/scripts/children/http-batch-delegate-child.js +132 -0
- package/scripts/children/http-delegate-child.js +8 -0
- package/scripts/dogfood-release.js +2 -2
- package/scripts/fake-date-for-reproduction.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/lang-policy-check.js +82 -0
- package/scripts/purity-baseline.json +0 -30
- package/scripts/purity-gate.js +16 -3
- package/scripts/release-check.js +2 -1
- package/scripts/release-flow.js +264 -41
- package/scripts/release-gate.js +184 -0
- package/scripts/release-oneclick.js +438 -0
- package/scripts/release-tags.js +47 -0
- package/scripts/verdict-keygen.js +2 -2
- package/scripts/verify-bump-reproduction.js +193 -0
- package/scripts/verify-verdict-signature.js +1 -1
- package/scripts/version-sync-check.js +39 -22
- package/ui/workbench/app.css +41 -9
- package/ui/workbench/app.js +160 -27
- package/ui/workbench/index.html +2 -2
- package/docs/agent-framework.md +0 -177
- package/docs/designs/handoff-ledger.md +0 -145
- package/docs/dogfood/resume-drive-real-agent-2026-06-14.md +0 -40
- package/docs/launch/launch-kit.md +0 -195
- package/docs/launch/pre-launch-checklist.md +0 -53
- package/docs/readme-v0.1.87-full.md +0 -301
- package/docs/routines.md +0 -101
- package/docs/scheduled-tasks.md +0 -80
- package/scripts/agents/claude-p-agent.sh +0 -9
- package/scripts/block-unapproved-tag.sh +0 -60
- package/scripts/release-gate.sh +0 -94
- package/scripts/verify-bump-reproduction.sh +0 -148
- package/scripts/verify-container-selfref.js +0 -64
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// retyped).
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
const registry_core_1 = require("./registry-core");
|
|
9
|
-
const
|
|
9
|
+
const cli_args_1 = require("../../core/util/cli-args");
|
|
10
10
|
// MILESTONE 8 (ledger, telemetry, trust-audit, tamper/bundle demos) CLI
|
|
11
11
|
// bindings: ledger propose|review|verify|apply|list, telemetry verify,
|
|
12
12
|
// audit verify, demo tamper|bundle, report bundle|verify-bundle. Handler
|
|
@@ -18,10 +18,13 @@ const io_1 = require("../../cli/io");
|
|
|
18
18
|
// cli/parseargv.ts) even though dispatchTable now handles it as a real
|
|
19
19
|
// row — a known, preserved wart.
|
|
20
20
|
// ---------------------------------------------------------------------
|
|
21
|
-
const ledger_cli_1 = require("../../shell/ledger-cli");
|
|
22
21
|
// This file is required at startup for every command. Loading these shell
|
|
23
22
|
// modules only when their handler runs, not at import time, keeps that
|
|
24
|
-
// load cost out of commands that never touch telemetry/audit/demo/
|
|
23
|
+
// load cost out of commands that never touch ledger/telemetry/audit/demo/
|
|
24
|
+
// report.
|
|
25
|
+
function loadLedgerCli() {
|
|
26
|
+
return require("../../shell/ledger-cli");
|
|
27
|
+
}
|
|
25
28
|
function loadTelemetryCli() {
|
|
26
29
|
return require("../../shell/telemetry-cli");
|
|
27
30
|
}
|
|
@@ -40,81 +43,120 @@ function loadReportCli() {
|
|
|
40
43
|
(0, registry_core_1.attachCliBinding)("ledger.propose", {
|
|
41
44
|
path: ["ledger", "propose"],
|
|
42
45
|
jsonMode: "default",
|
|
43
|
-
handler: (args) => ({ json: (
|
|
46
|
+
handler: (args) => ({ json: loadLedgerCli().ledgerProposeCli(args.options) }),
|
|
47
|
+
// UI/UX fix: `cw help ledger` used to list only the one-line summary for
|
|
48
|
+
// each row, so a first-run user had no way to learn these flags without
|
|
49
|
+
// reading source. Real flag names verified against ledgerProposeCli's
|
|
50
|
+
// required()/stringOption() calls above.
|
|
51
|
+
flags: [
|
|
52
|
+
{ name: "--from AGENT/REPO", summary: "Who is making the change." },
|
|
53
|
+
{ name: "--to AGENT/REPO", summary: "Who should get the change." },
|
|
54
|
+
{ name: "--title TEXT", summary: "A short name for the change." },
|
|
55
|
+
{ name: "--rationale TEXT", summary: "Why the change should happen." },
|
|
56
|
+
{ name: "--files LIST", summary: "The files the change touches, as a comma list." },
|
|
57
|
+
{ name: "--diff PATCH", summary: "The change as one diff file." },
|
|
58
|
+
],
|
|
59
|
+
// ledgerProposeCli reads exactly from/to/title/rationale/files/diff
|
|
60
|
+
// (shell/ledger-cli.ts) — the list above is complete, so the dispatcher
|
|
61
|
+
// may warn about an unknown flag (TTY-only; see cli/global-flags.ts).
|
|
62
|
+
flagsComplete: true,
|
|
44
63
|
});
|
|
45
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.propose").mcp.handler = (args) => (
|
|
64
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.propose").mcp.handler = (args) => loadLedgerCli().ledgerProposeMcp(args);
|
|
46
65
|
(0, registry_core_1.attachCliBinding)("ledger.review", {
|
|
47
66
|
path: ["ledger", "review"],
|
|
48
67
|
jsonMode: "default",
|
|
49
|
-
handler: (args) => ({ json: (
|
|
68
|
+
handler: (args) => ({ json: loadLedgerCli().ledgerReviewCli(args.options) }),
|
|
69
|
+
// Real flag names verified against ledgerReviewCli's required()/
|
|
70
|
+
// stringOption() calls above — NOT the same flag set as ledger propose
|
|
71
|
+
// (this row needs --target/--verdict/--findings, not --title/
|
|
72
|
+
// --rationale/--diff).
|
|
73
|
+
flags: [
|
|
74
|
+
{ name: "--from AGENT/REPO", summary: "Who is doing the review." },
|
|
75
|
+
{ name: "--to AGENT/REPO", summary: "Who made the change being reviewed." },
|
|
76
|
+
{ name: "--target ID", summary: "The id of the proposal or PR to review." },
|
|
77
|
+
{ name: "--verdict approved|rejected", summary: "The result of the review." },
|
|
78
|
+
{ name: "--findings TEXT", summary: "Notes on what the review found." },
|
|
79
|
+
],
|
|
80
|
+
// ledgerReviewCli reads exactly from/to/target/verdict/findings
|
|
81
|
+
// (shell/ledger-cli.ts) — the list above is complete, so the dispatcher
|
|
82
|
+
// may warn about an unknown flag (TTY-only; see cli/global-flags.ts).
|
|
83
|
+
flagsComplete: true,
|
|
50
84
|
});
|
|
51
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.review").mcp.handler = (args) => (
|
|
85
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.review").mcp.handler = (args) => loadLedgerCli().ledgerReviewMcp(args);
|
|
52
86
|
(0, registry_core_1.attachCliBinding)("ledger.verify", {
|
|
53
87
|
path: ["ledger", "verify"],
|
|
54
88
|
jsonMode: "default",
|
|
55
89
|
handler: (args) => {
|
|
56
|
-
const result = (
|
|
90
|
+
const result = loadLedgerCli().ledgerVerifyCli(args.options);
|
|
57
91
|
return { json: result, exitCode: result.ok ? undefined : 1 };
|
|
58
92
|
},
|
|
59
93
|
});
|
|
60
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.verify").mcp.handler = (args) => (
|
|
94
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.verify").mcp.handler = (args) => loadLedgerCli().ledgerVerifyEntry(args.entry);
|
|
61
95
|
(0, registry_core_1.attachCliBinding)("ledger.apply", {
|
|
62
96
|
path: ["ledger", "apply"],
|
|
63
97
|
jsonMode: "default",
|
|
64
98
|
handler: (args) => {
|
|
65
|
-
const result = (
|
|
99
|
+
const result = loadLedgerCli().ledgerApplyCli(args.options);
|
|
66
100
|
return { json: result, exitCode: result.ok ? undefined : 1 };
|
|
67
101
|
},
|
|
68
102
|
});
|
|
69
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.apply").mcp.handler = (args) => (
|
|
103
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.apply").mcp.handler = (args) => loadLedgerCli().ledgerApplyEntry(args.entry);
|
|
70
104
|
(0, registry_core_1.attachCliBinding)("ledger.list", {
|
|
71
105
|
path: ["ledger", "list"],
|
|
72
106
|
jsonMode: "default",
|
|
73
107
|
handler: (args) => {
|
|
74
|
-
const result = (
|
|
108
|
+
const result = loadLedgerCli().ledgerListCli(args.options);
|
|
75
109
|
return { json: result, exitCode: result.allOk ? undefined : 1 };
|
|
76
110
|
},
|
|
111
|
+
// UI/UX fix: `--dir` here named the ledger directory, while the global
|
|
112
|
+
// front door (cli/entry.ts) treats `--dir` as an alias of `--repo` for
|
|
113
|
+
// every command — one flag, two meanings. `--ledger-dir` is the
|
|
114
|
+
// unambiguous spelling; `--dir` stays as the legacy alias, byte-compat.
|
|
115
|
+
flags: [
|
|
116
|
+
{ name: "--ledger-dir DIR", summary: "The ledger directory to read. Give it more than once to union-verify mirrors." },
|
|
117
|
+
{ name: "--dir DIR", summary: "Old name for --ledger-dir (also the global --repo alias; kept working)." },
|
|
118
|
+
],
|
|
77
119
|
});
|
|
78
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.list").mcp.handler = (args) => (
|
|
120
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("ledger.list").mcp.handler = (args) => loadLedgerCli().ledgerListMcp(args);
|
|
79
121
|
(0, registry_core_1.attachCliBinding)("telemetry.verify", {
|
|
80
122
|
path: ["telemetry", "verify"],
|
|
81
123
|
jsonMode: "flag",
|
|
82
124
|
handler: (args) => {
|
|
83
|
-
const runId = (0,
|
|
125
|
+
const runId = (0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.positionals[0]) || (0, cli_args_1.optionalArg)(args.options.runId) || (0, cli_args_1.optionalArg)(args.options.run), "run id");
|
|
84
126
|
const result = loadTelemetryCli().telemetryVerifyCli(runId, args.options);
|
|
85
127
|
return { json: result, text: loadTelemetryDemo().formatTelemetryVerify(result), exitCode: result.verified ? undefined : 1 };
|
|
86
128
|
},
|
|
87
129
|
});
|
|
88
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("telemetry.verify").mcp.handler = (args) => loadTelemetryCli().telemetryVerifyCli((0,
|
|
130
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("telemetry.verify").mcp.handler = (args) => loadTelemetryCli().telemetryVerifyCli((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.runId), "run id"), args);
|
|
89
131
|
(0, registry_core_1.attachCliBinding)("audit.verify", {
|
|
90
132
|
path: ["audit", "verify"],
|
|
91
133
|
jsonMode: "default",
|
|
92
134
|
handler: (args) => {
|
|
93
|
-
const runId = (0,
|
|
135
|
+
const runId = (0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.positionals[0]), "run id");
|
|
94
136
|
const result = loadAuditCli().auditVerifyCli(runId, args.options);
|
|
95
137
|
return { json: result, exitCode: result.verified ? undefined : 1 };
|
|
96
138
|
},
|
|
97
139
|
});
|
|
98
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("audit.verify").mcp.handler = (args) => loadAuditCli().auditVerifyCli((0,
|
|
140
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("audit.verify").mcp.handler = (args) => loadAuditCli().auditVerifyCli((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.runId), "run id"), args);
|
|
99
141
|
(0, registry_core_1.attachCliBinding)("audit.head", {
|
|
100
142
|
path: ["audit", "head"],
|
|
101
143
|
jsonMode: "default",
|
|
102
144
|
handler: (args) => {
|
|
103
|
-
const runId = (0,
|
|
145
|
+
const runId = (0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.positionals[0]), "run id");
|
|
104
146
|
return { json: loadAuditCli().auditHeadCli(runId, args.options) };
|
|
105
147
|
},
|
|
106
148
|
});
|
|
107
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("audit.head").mcp.handler = (args) => loadAuditCli().auditHeadCli((0,
|
|
149
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("audit.head").mcp.handler = (args) => loadAuditCli().auditHeadCli((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.runId), "run id"), args);
|
|
108
150
|
(0, registry_core_1.attachCliBinding)("audit.repair", {
|
|
109
151
|
path: ["audit", "repair"],
|
|
110
152
|
jsonMode: "default",
|
|
111
153
|
handler: (args) => {
|
|
112
|
-
const runId = (0,
|
|
154
|
+
const runId = (0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.positionals[0]), "run id");
|
|
113
155
|
const result = loadAuditCli().auditRepairCli(runId, args.options);
|
|
114
156
|
return { json: result, exitCode: result.outcome === "refused" ? 1 : undefined };
|
|
115
157
|
},
|
|
116
158
|
});
|
|
117
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("audit.repair").mcp.handler = (args) => loadAuditCli().auditRepairCli((0,
|
|
159
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("audit.repair").mcp.handler = (args) => loadAuditCli().auditRepairCli((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.runId), "run id"), args);
|
|
118
160
|
(0, registry_core_1.addCliOnlyCapability)("demo.tamper", "Prove tamper-evidence: build a signed telemetry ledger, forge it, watch verification fail offline.", {
|
|
119
161
|
path: ["demo", "tamper"],
|
|
120
162
|
jsonMode: "flag",
|
|
@@ -135,17 +177,17 @@ registry_core_1.REGISTRY_BY_CAPABILITY.get("audit.repair").mcp.handler = (args)
|
|
|
135
177
|
path: ["report", "bundle"],
|
|
136
178
|
jsonMode: "default",
|
|
137
179
|
handler: (args) => {
|
|
138
|
-
const runId = (0,
|
|
180
|
+
const runId = (0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.positionals[0]), "run id");
|
|
139
181
|
const result = loadReportCli().reportBundleCli(runId, args.options);
|
|
140
182
|
return { json: result, exitCode: result.ok ? undefined : 1 };
|
|
141
183
|
},
|
|
142
184
|
});
|
|
143
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("report.bundle").mcp.handler = (args) => loadReportCli().reportBundleCli((0,
|
|
185
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("report.bundle").mcp.handler = (args) => loadReportCli().reportBundleCli((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.runId), "run id"), args);
|
|
144
186
|
(0, registry_core_1.attachCliBinding)("report.verify-bundle", {
|
|
145
187
|
path: ["report", "verify-bundle"],
|
|
146
188
|
jsonMode: "flag",
|
|
147
189
|
handler: (args) => {
|
|
148
|
-
const archivePath = (0,
|
|
190
|
+
const archivePath = (0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.positionals[0]), "bundle path");
|
|
149
191
|
const reportCli = loadReportCli();
|
|
150
192
|
const result = reportCli.reportVerifyBundleCli({ ...args.options, archive: archivePath });
|
|
151
193
|
return { json: result, text: reportCli.formatReportVerifyBundle(result), exitCode: result.ok ? undefined : 1 };
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// sed, not retyped).
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
const registry_core_1 = require("./registry-core");
|
|
9
|
-
const
|
|
9
|
+
const cli_args_1 = require("../../core/util/cli-args");
|
|
10
10
|
// This whole module is required unconditionally at startup for EVERY
|
|
11
11
|
// command (see wiring/capability-table/index.ts) — loading `next`'s and
|
|
12
12
|
// `app.run`'s shell modules lazily, inside the handler that actually
|
|
@@ -44,24 +44,24 @@ registry_core_1.REGISTRY_BY_CAPABILITY.get("app.list").mcp.handler = () => loadW
|
|
|
44
44
|
(0, registry_core_1.attachCliBinding)("app.show", {
|
|
45
45
|
path: ["app", "show"],
|
|
46
46
|
jsonMode: "default",
|
|
47
|
-
handler: (args) => ({ json: loadWorkflowAppLoader().showWorkflowApp((0,
|
|
47
|
+
handler: (args) => ({ json: loadWorkflowAppLoader().showWorkflowApp((0, cli_args_1.required)(args.positionals[0], "workflow app id")) }),
|
|
48
48
|
});
|
|
49
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.show").mcp.handler = (args) => loadWorkflowAppLoader().showWorkflowApp((0,
|
|
49
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.show").mcp.handler = (args) => loadWorkflowAppLoader().showWorkflowApp((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.appId), "workflow app id"));
|
|
50
50
|
(0, registry_core_1.attachCliBinding)("app.validate", {
|
|
51
51
|
path: ["app", "validate"],
|
|
52
52
|
jsonMode: "default",
|
|
53
53
|
handler: (args) => {
|
|
54
|
-
const result = loadWorkflowAppLoader().validateWorkflowAppTarget((0,
|
|
54
|
+
const result = loadWorkflowAppLoader().validateWorkflowAppTarget((0, cli_args_1.required)(args.positionals[0], "workflow app path or id"));
|
|
55
55
|
return { json: result, exitCode: result.valid ? undefined : 1 };
|
|
56
56
|
},
|
|
57
57
|
});
|
|
58
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.validate").mcp.handler = (args) => loadWorkflowAppLoader().validateWorkflowAppTarget((0,
|
|
58
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.validate").mcp.handler = (args) => loadWorkflowAppLoader().validateWorkflowAppTarget((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.target ?? args.appId), "workflow app path or id"));
|
|
59
59
|
(0, registry_core_1.attachCliBinding)("app.init", {
|
|
60
60
|
path: ["app", "init"],
|
|
61
61
|
jsonMode: "default",
|
|
62
|
-
handler: (args) => ({ json: loadWorkflowAppLoader().initWorkflowApp((0,
|
|
62
|
+
handler: (args) => ({ json: loadWorkflowAppLoader().initWorkflowApp((0, cli_args_1.required)(args.positionals[0], "app id"), args.options) }),
|
|
63
63
|
});
|
|
64
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.init").mcp.handler = (args) => loadWorkflowAppLoader().initWorkflowApp((0,
|
|
64
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.init").mcp.handler = (args) => loadWorkflowAppLoader().initWorkflowApp((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.appId), "app id"), args);
|
|
65
65
|
// `cw init <id>` — the standalone scaffold verb. v2 folds `init` into
|
|
66
66
|
// `app.init` (the old build's legacy `.workflow.js` scaffold is gone), so
|
|
67
67
|
// both surfaces route through initWorkflowApp, same as `cw app init`. The
|
|
@@ -71,15 +71,15 @@ registry_core_1.REGISTRY_BY_CAPABILITY.get("app.init").mcp.handler = (args) => l
|
|
|
71
71
|
(0, registry_core_1.attachCliBinding)("init", {
|
|
72
72
|
path: ["init"],
|
|
73
73
|
jsonMode: "default",
|
|
74
|
-
handler: (args) => ({ json: loadWorkflowAppLoader().initWorkflowApp((0,
|
|
74
|
+
handler: (args) => ({ json: loadWorkflowAppLoader().initWorkflowApp((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.positionals[0]), "workflow id"), args.options) }),
|
|
75
75
|
});
|
|
76
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("init").mcp.handler = (args) => loadWorkflowAppLoader().initWorkflowApp((0,
|
|
76
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("init").mcp.handler = (args) => loadWorkflowAppLoader().initWorkflowApp((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.workflowId ?? args.appId), "workflow id"), args);
|
|
77
77
|
(0, registry_core_1.attachCliBinding)("app.package", {
|
|
78
78
|
path: ["app", "package"],
|
|
79
79
|
jsonMode: "default",
|
|
80
|
-
handler: (args) => ({ json: loadWorkflowAppLoader().packageWorkflowApp((0,
|
|
80
|
+
handler: (args) => ({ json: loadWorkflowAppLoader().packageWorkflowApp((0, cli_args_1.required)(args.positionals[0], "app id"), args.options) }),
|
|
81
81
|
});
|
|
82
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.package").mcp.handler = (args) => loadWorkflowAppLoader().packageWorkflowApp((0,
|
|
82
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.package").mcp.handler = (args) => loadWorkflowAppLoader().packageWorkflowApp((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.appId), "app id"), args);
|
|
83
83
|
// `cw app run <app-id>` — plan+drive+report an app in one call. 2-token
|
|
84
84
|
// cli.path found before the ["app"] usage catch-all; `appRunCli` reads the
|
|
85
85
|
// app id from `appId`, so the first positional after "run" is forwarded as
|
|
@@ -87,7 +87,7 @@ registry_core_1.REGISTRY_BY_CAPABILITY.get("app.package").mcp.handler = (args) =
|
|
|
87
87
|
(0, registry_core_1.attachCliBinding)("app.run", {
|
|
88
88
|
path: ["app", "run"],
|
|
89
89
|
jsonMode: "default",
|
|
90
|
-
handler: (args) => ({ json: loadAppRunCli().appRunCli({ ...args.options, appId: (0,
|
|
90
|
+
handler: (args) => ({ json: loadAppRunCli().appRunCli({ ...args.options, appId: (0, cli_args_1.required)(args.positionals[0], "app id") }) }),
|
|
91
91
|
});
|
|
92
92
|
// A 1-token `["app"]` row that exists ONLY to own the fixed usage string
|
|
93
93
|
// for an unrecognized `app` subcommand (`app run` is not yet CLI-wired at
|
|
@@ -329,7 +329,7 @@ registry_core_1.REGISTRY_BY_CAPABILITY.get("app.package").mcp.handler = (args) =
|
|
|
329
329
|
path: ["info"],
|
|
330
330
|
jsonMode: "flag",
|
|
331
331
|
handler: (args) => {
|
|
332
|
-
const appId = (0,
|
|
332
|
+
const appId = (0, cli_args_1.required)(args.positionals[0], "workflow app id");
|
|
333
333
|
const data = loadWorkflowAppLoader().showWorkflowApp(appId);
|
|
334
334
|
return { json: data, text: `${(0, help_1.formatInfo)(appId, data)}\n` };
|
|
335
335
|
},
|
|
@@ -351,9 +351,9 @@ registry_core_1.REGISTRY_BY_CAPABILITY.get("app.package").mcp.handler = (args) =
|
|
|
351
351
|
(0, registry_core_1.attachCliBinding)("next", {
|
|
352
352
|
path: ["next"],
|
|
353
353
|
jsonMode: "default",
|
|
354
|
-
handler: (args) => ({ json: loadStateCli().nextCli((0,
|
|
354
|
+
handler: (args) => ({ json: loadStateCli().nextCli((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.positionals[0]), "run id"), args.options) }),
|
|
355
355
|
});
|
|
356
|
-
registry_core_1.REGISTRY_BY_CAPABILITY.get("next").mcp.handler = (args) => loadStateCli().nextCli((0,
|
|
356
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("next").mcp.handler = (args) => loadStateCli().nextCli((0, cli_args_1.required)((0, cli_args_1.optionalArg)(args.runId), "run id"), args);
|
|
357
357
|
// `ledger.propose`/`.review`/`.verify`/`.apply`/`.list` are documented
|
|
358
358
|
// payload-probe opt-outs in the old build (each mints a fresh timestamped/
|
|
359
359
|
// digested entry, or reads args that arrive by --file/stdin on the CLI vs
|
|
@@ -125,6 +125,19 @@ exactly one fixed step (injected `now`); bare `--drive` runs to the end or to a
|
|
|
125
125
|
parked/blocked stop. `run drive <run-id>` (no `--step`) is the read-only, fixed
|
|
126
126
|
preview of the next step.
|
|
127
127
|
|
|
128
|
+
## Concurrent rounds (`--concurrency N`)
|
|
129
|
+
|
|
130
|
+
`--drive --concurrency N` (or an auto-width parallel phase) runs a whole round's
|
|
131
|
+
tasks in ONE window instead of one at a time. CW dispatches the round's tasks,
|
|
132
|
+
collects every agent outcome concurrently, then settles + accepts them in
|
|
133
|
+
DETERMINISTIC batch (task-id) order — so the wall-clock drops but the recorded
|
|
134
|
+
state, reports, and exit codes are byte-identical to a serial run. Both agent
|
|
135
|
+
shapes get real concurrency: a **CLI-binary** agent (`CW_AGENT_COMMAND`) runs
|
|
136
|
+
all children at once through the batch delegate child, and an **HTTP-endpoint**
|
|
137
|
+
agent (`CW_AGENT_ENDPOINT`) POSTs all N delegations at once through the HTTP
|
|
138
|
+
batch delegate child. A cache-hit task still settles on the serial path inside
|
|
139
|
+
the same round. An unconfigured agent still refuses (it is never a fake pass).
|
|
140
|
+
|
|
128
141
|
## Fail closed — probe vs refusal vs park
|
|
129
142
|
|
|
130
143
|
- **Probe.** `backend probe agent` reports `readiness: "ready"` iff a
|
|
@@ -421,3 +434,7 @@ The one-command `cw -q` headline now routes the question and defaults the repo t
|
|
|
421
434
|
0.2.2
|
|
422
435
|
|
|
423
436
|
0.2.3
|
|
437
|
+
|
|
438
|
+
0.2.4
|
|
439
|
+
|
|
440
|
+
0.2.5
|
package/docs/cli-mcp-parity.7.md
CHANGED
|
@@ -74,6 +74,29 @@ show/validate/apply/summary/graph, sandbox show/validate/choose/resolve, state
|
|
|
74
74
|
summary refresh/show, `plan`, `approve`, `reject`, `comment.add`, `handoff`, and
|
|
75
75
|
`review.policy`.
|
|
76
76
|
|
|
77
|
+
## MCP Tool Hints and Version Negotiation
|
|
78
|
+
|
|
79
|
+
A `tools/list` entry may carry the standard MCP `annotations` field with
|
|
80
|
+
two behavior hints:
|
|
81
|
+
|
|
82
|
+
- `readOnlyHint: true` — the tool only reads; it makes no change on disk.
|
|
83
|
+
- `destructiveHint: true` (with `readOnlyHint: false`) — the tool deletes
|
|
84
|
+
stored data (the gc / delete sweeps: `cw_gc_run`, `cw_orphans_gc`,
|
|
85
|
+
`cw_clones_gc`, `cw_schedule_delete`, `cw_routine_delete`).
|
|
86
|
+
|
|
87
|
+
The hints come from one side table (`MCP_TOOL_ANNOTATIONS` in
|
|
88
|
+
`src/core/capability-data.ts`), and a tool goes in only after its handler
|
|
89
|
+
was read and checked by hand — a wrong "read-only" mark on a writing tool
|
|
90
|
+
would be a safety bug, so a tool we are not certain about carries no
|
|
91
|
+
`annotations` field at all. Absent beats wrong. The field is additive: a
|
|
92
|
+
client that does not know it simply does not read it.
|
|
93
|
+
|
|
94
|
+
The MCP `initialize` reply also negotiates the protocol version now: a
|
|
95
|
+
client that asks for a supported version gets that version echoed back,
|
|
96
|
+
and any other request falls back to the newest supported entry (see
|
|
97
|
+
`SUPPORTED_PROTOCOL_VERSIONS` in `src/mcp/server.ts`). With today's
|
|
98
|
+
one-entry list the reply bytes are unchanged.
|
|
99
|
+
|
|
77
100
|
## The Parity Matrix
|
|
78
101
|
|
|
79
102
|
The matrix below is made from the live registry — one row per capability,
|
|
@@ -429,19 +452,22 @@ Parity is checked by `scripts/parity-check.js --check`, run by
|
|
|
429
452
|
the registry, lists the live CLI commands and MCP tools, and fails closed on any
|
|
430
453
|
of the rules above.
|
|
431
454
|
|
|
432
|
-
The CLI
|
|
433
|
-
|
|
434
|
-
(
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
`
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
455
|
+
The CLI dispatch surface is table-driven, not a hand-kept `switch`. The source
|
|
456
|
+
tree is small: `src/cli/entry.ts` (process entry), `src/cli/parseargv.ts`
|
|
457
|
+
(argv reading), `src/cli/dispatch.ts` (the one dispatcher), and `src/cli/io.ts`
|
|
458
|
+
(output helpers: `printJson`, `styledHelp`). `dispatch(args)` looks the parsed
|
|
459
|
+
command up in the capability table (`src/core/capability-table.ts`, put
|
|
460
|
+
together from the slices under `src/wiring/capability-table/`) and runs that
|
|
461
|
+
row's `cli.handler` — a new capability is a new table row, never a new `case`.
|
|
462
|
+
The shared arg helpers (`required`, `optionalArg`, `wantsJson`) live in
|
|
463
|
+
`src/core/util/cli-args.ts`, a pure module used by the CLI and MCP sides of
|
|
464
|
+
every wiring slice; they were moved out of `cli/io.ts` because the purity
|
|
465
|
+
gate's layer rule says `wiring/` may not take imports from `cli/`. The parity
|
|
466
|
+
scanner works the same way: `cliDispatchTokens()` gets the live token list
|
|
467
|
+
straight from the registry's CLI capabilities (`cli.caseTokens` when a row
|
|
468
|
+
names more than one first token, else `cli.path`), then makes sure each
|
|
469
|
+
declared path resolves through the live dispatcher — there is no grep over
|
|
470
|
+
built dispatch source.
|
|
445
471
|
|
|
446
472
|
`test/cli-mcp-parity-smoke.js` proves the contract from end to end. It checks
|
|
447
473
|
registry ⇄ CLI ⇄ MCP coverage (every declared capability is found on its declared
|
|
@@ -638,3 +664,7 @@ CLI golden-path fixes: `cw -q "…"` routes the question (was read as an app id
|
|
|
638
664
|
0.2.2
|
|
639
665
|
|
|
640
666
|
0.2.3
|
|
667
|
+
|
|
668
|
+
0.2.4
|
|
669
|
+
|
|
670
|
+
0.2.5
|
|
@@ -66,6 +66,40 @@ Additive: `RunQueueEntry` gets the optional `attempts`/`leaseId`/`leaseExpiresAt
|
|
|
66
66
|
`queue add|list|drain|show` verbs that are already there do not change. No new database, no
|
|
67
67
|
daemon-owned state.
|
|
68
68
|
|
|
69
|
+
## Scheduled Tasks In Practice
|
|
70
|
+
|
|
71
|
+
CW scheduled tasks give looping prompts, cron-like schedules, one-shot
|
|
72
|
+
reminders, expiration, jitter, and clear completion. Schedules live in
|
|
73
|
+
`.cw/schedules/tasks.json`.
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# a /loop-ready schedule (cw loop is the short form of schedule create --kind loop)
|
|
77
|
+
cw loop --intervalMinutes 30 --prompt "Check this workflow and continue if work is due."
|
|
78
|
+
|
|
79
|
+
# a cron schedule
|
|
80
|
+
cw schedule create --kind cron --cron "*/15 * * * *" --prompt "Run the due workflow scan."
|
|
81
|
+
|
|
82
|
+
# a one-shot reminder
|
|
83
|
+
cw schedule create --kind reminder --delayMinutes 60 --prompt "Remind me to inspect the report."
|
|
84
|
+
|
|
85
|
+
# list, inspect, and manage
|
|
86
|
+
cw schedule list
|
|
87
|
+
cw schedule due
|
|
88
|
+
cw schedule complete <schedule-id>
|
|
89
|
+
cw schedule pause <schedule-id> / resume <schedule-id> / run-now <schedule-id>
|
|
90
|
+
cw schedule history <schedule-id>
|
|
91
|
+
cw schedule delete <schedule-id>
|
|
92
|
+
|
|
93
|
+
# the local daemon: one sweep, or a loop
|
|
94
|
+
cw schedule daemon --once
|
|
95
|
+
cw schedule daemon --intervalSeconds 60
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Notes: time is measured to the minute; expiration defaults to 7 days;
|
|
99
|
+
`jitterSeconds` can put space between runs. CW does not start the daemon by
|
|
100
|
+
default — use `schedule daemon`, cron, or another overseer to call
|
|
101
|
+
`schedule due` and run due prompts.
|
|
102
|
+
|
|
69
103
|
## See Also
|
|
70
104
|
|
|
71
105
|
run-registry-control-plane(7), cli-mcp-parity(7), release-and-migration(7)
|
|
@@ -165,3 +199,7 @@ _No behavioral change in v0.1.89 (CLI-surface golden-path + help-output fixes on
|
|
|
165
199
|
0.2.2
|
|
166
200
|
|
|
167
201
|
0.2.3
|
|
202
|
+
|
|
203
|
+
0.2.4
|
|
204
|
+
|
|
205
|
+
0.2.5
|
|
@@ -3,8 +3,15 @@
|
|
|
3
3
|
CW adds `cw ledger` — a way for two agents scoped to two separate repos to hand
|
|
4
4
|
each other a CHANGE PROPOSAL or a REVIEW VERDICT as verifiable data, not chat.
|
|
5
5
|
One side proposes or reviews; the other side verifies the entry fail-closed and
|
|
6
|
-
turns a proposal into a real pull request.
|
|
7
|
-
|
|
6
|
+
turns a proposal into a real pull request.
|
|
7
|
+
|
|
8
|
+
Design note (why not a shared folder): the obvious first design — a shared
|
|
9
|
+
local directory both agents read and append to — only works when both agents
|
|
10
|
+
run on ONE machine with ONE filesystem. Two agents scoped to two repos (or two
|
|
11
|
+
machines) need a transport both can already reach, with saved, inspectable,
|
|
12
|
+
fail-closed state — never a fabricated hand-off. That is why an entry is a
|
|
13
|
+
self-verifying file in a git repo both sides can push and pull, and why the
|
|
14
|
+
kernel holds no git logic at all.
|
|
8
15
|
|
|
9
16
|
Each entry is a self-contained JSON object that carries its own sha256 content
|
|
10
17
|
digest. The producing side prints one; it reaches the other session by human
|
|
@@ -51,13 +58,18 @@ cw ledger review --from <a> --to <b> --target <proposal-id|pr-ref> \
|
|
|
51
58
|
--verdict <approved|rejected> [--findings "a,b"]
|
|
52
59
|
cw ledger verify [--file <path>] # else reads the entry from stdin
|
|
53
60
|
cw ledger apply [--file <path>] # verify a proposal, then print its diff
|
|
54
|
-
cw ledger list --dir <ledger-dir> [--dir <mirror-2> ...] # verify a dir (or union of mirrors)
|
|
61
|
+
cw ledger list --ledger-dir <ledger-dir> [--ledger-dir <mirror-2> ...] # verify a dir (or union of mirrors)
|
|
55
62
|
```
|
|
56
63
|
|
|
57
64
|
All write JSON to stdout (stdout is data). `propose` and `review` print a sealed
|
|
58
65
|
entry; `verify` prints a check report; `apply` prints a verify-plus-diff report;
|
|
59
66
|
`list` prints a per-entry report over a directory.
|
|
60
67
|
|
|
68
|
+
`--ledger-dir` is the preferred spelling for `list`: the CLI front door
|
|
69
|
+
treats `--dir` as a global alias of `--repo` on every command, so the old
|
|
70
|
+
`--dir` made one flag mean two things here. `--dir` keeps working
|
|
71
|
+
unchanged as the legacy alias; when both are given, `--ledger-dir` wins.
|
|
72
|
+
|
|
61
73
|
## Applying a proposal — fail-closed
|
|
62
74
|
|
|
63
75
|
A proposal carries a `suggestedDiff`, but a proposal never mutates the target
|
|
@@ -131,12 +143,12 @@ on the mirror-union output and on the `cw_ledger_list` MCP tool.
|
|
|
131
143
|
|
|
132
144
|
### Mirrors — union-verifying several directories
|
|
133
145
|
|
|
134
|
-
`--dir` is repeatable. With two or more, `cw ledger list` **union-verifies** the
|
|
146
|
+
`--ledger-dir` (and the legacy `--dir`) is repeatable. With two or more, `cw ledger list` **union-verifies** the
|
|
135
147
|
directories as mirrors of one ledger (e.g. the same handoff repo cloned from a
|
|
136
148
|
GitHub remote and one or more self-hosted Gitea remotes in different places):
|
|
137
149
|
|
|
138
150
|
```
|
|
139
|
-
cw ledger list --dir gh/ledger --dir gitea-eu/ledger --dir gitea-asia/ledger
|
|
151
|
+
cw ledger list --ledger-dir gh/ledger --ledger-dir gitea-eu/ledger --ledger-dir gitea-asia/ledger
|
|
140
152
|
```
|
|
141
153
|
|
|
142
154
|
The union is **conflict-free by construction**: entries are immutable and
|
|
@@ -146,10 +158,10 @@ across mirrors** — a tampered entry in ANY mirror sets `allOk:false` and exits
|
|
|
146
158
|
`1`. This is for redundancy and reachability, not load: the ledger's traffic is
|
|
147
159
|
tiny; multiple hosts guard against one being down or unreachable.
|
|
148
160
|
|
|
149
|
-
A single
|
|
161
|
+
A single directory flag keeps the original single-directory output (a `dir` field, no
|
|
150
162
|
`dirs`); two or more switch to the union shape (`dirs` plus a per-entry `dirs`).
|
|
151
163
|
The transport stays git-host-agnostic — adding a mirror is one more clone + one
|
|
152
|
-
more `--dir`, no code change.
|
|
164
|
+
more `--ledger-dir`, no code change.
|
|
153
165
|
|
|
154
166
|
## Entry shape
|
|
155
167
|
|
|
@@ -214,4 +226,4 @@ cw ledger verify --file verdict.json
|
|
|
214
226
|
Stage 1 shipped the CLI verbs (human relay). Stage 2 adds the MCP surface and
|
|
215
227
|
the git-as-ledger transport (`cw ledger list` over a shared repo). Still open:
|
|
216
228
|
the operator creates the shared handoff repo and scopes both agent environments
|
|
217
|
-
into it.
|
|
229
|
+
into it. Setup runbook: [handoff-setup](handoff-setup.md).
|
package/docs/fix.7.md
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
```text
|
|
10
10
|
node dist/cli.js fix
|
|
11
|
-
node dist/cli.js fix --json
|
|
12
11
|
```
|
|
13
12
|
|
|
14
13
|
## DESCRIPTION
|
|
@@ -28,9 +27,10 @@ If any check has status `fail`, the command exits with code 1.
|
|
|
28
27
|
|
|
29
28
|
## OPTIONS
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
`cw fix` takes no options of its own; its output is always the plain fix-command
|
|
31
|
+
text (a `--json` flag is silently ignored — this byte behavior is pinned by
|
|
32
|
+
`v2/conformance/cases/report-fix.case.js`). For a machine-readable report of the
|
|
33
|
+
same checks, use `cw doctor --json`: its `checks` array carries every fix string.
|
|
34
34
|
|
|
35
35
|
## EXIT CODES
|
|
36
36
|
|