cool-workflow 0.2.1 → 0.2.2
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/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 +18 -86
- package/dist/cli/parseargv.js +5 -2
- package/dist/core/capability-data.js +270 -0
- package/dist/core/capability-table.js +16 -3504
- package/dist/core/format/help.js +28 -5
- package/dist/core/multi-agent/collaboration.js +3 -2
- package/dist/core/multi-agent/coordinator.js +4 -3
- package/dist/core/pipeline/commit-gate.js +2 -1
- package/dist/core/state/state-explosion/digest.js +3 -2
- package/dist/core/state/state-explosion/graph.js +9 -8
- package/dist/core/state/state-explosion/helpers.js +2 -1
- package/dist/core/trust/ledger.js +2 -1
- package/dist/core/types/execution-backend.js +18 -0
- package/dist/core/types/observability.js +7 -0
- package/dist/core/util/collate.js +23 -0
- package/dist/core/version.js +1 -1
- package/dist/shell/audit-cli.js +46 -2
- package/dist/shell/commit-summary.js +2 -1
- package/dist/shell/drive.js +26 -10
- package/dist/shell/evidence-reasoning.js +4 -3
- package/dist/shell/execution-backend/registry.js +2 -1
- package/dist/shell/execution-backend/types.js +0 -9
- package/dist/shell/fs-atomic.js +14 -1
- package/dist/shell/multi-agent-operator-ux.js +4 -3
- package/dist/shell/observability.js +12 -11
- package/dist/shell/onramp.js +17 -1
- package/dist/shell/operator-ux-text.js +2 -1
- package/dist/shell/operator-ux.js +7 -6
- package/dist/shell/pipeline-cli.js +82 -72
- package/dist/shell/reclamation-io.js +2 -1
- package/dist/shell/report.js +2 -1
- package/dist/shell/run-store.js +17 -0
- package/dist/shell/state-explosion-cli.js +2 -1
- package/dist/shell/topology-io.js +2 -1
- package/dist/shell/trust-audit.js +41 -2
- package/dist/shell/worker-cli.js +9 -1
- package/dist/shell/worker-isolation.js +34 -9
- package/dist/shell/workflow-app-loader.js +3 -2
- package/dist/wiring/capability-table/basics.js +66 -0
- package/dist/wiring/capability-table/exec-backend.js +162 -0
- package/dist/wiring/capability-table/index.js +42 -0
- package/dist/wiring/capability-table/multi-agent.js +623 -0
- package/dist/wiring/capability-table/parity.js +466 -0
- package/dist/wiring/capability-table/pipeline.js +280 -0
- package/dist/wiring/capability-table/registry-core.js +189 -0
- package/dist/wiring/capability-table/reporting.js +394 -0
- package/dist/wiring/capability-table/scheduling-registry.js +558 -0
- package/dist/wiring/capability-table/state.js +173 -0
- package/dist/wiring/capability-table/trust-ledger.js +134 -0
- package/dist/wiring/capability-table/workflow-apps.js +366 -0
- package/docs/agent-delegation-drive.7.md +2 -0
- package/docs/cli-mcp-parity.7.md +7 -2
- package/docs/contract-migration-tooling.7.md +2 -0
- package/docs/control-plane-scheduling.7.md +2 -0
- package/docs/durable-state-and-locking.7.md +22 -0
- package/docs/evidence-adoption-reasoning-chain.7.md +2 -0
- package/docs/execution-backends.7.md +2 -0
- package/docs/index.md +1 -0
- package/docs/multi-agent-cli-mcp-surface.7.md +2 -0
- package/docs/multi-agent-eval-replay-harness.7.md +2 -0
- package/docs/multi-agent-operator-ux.7.md +2 -0
- package/docs/node-snapshot-diff-replay.7.md +2 -0
- package/docs/observability-cost-accounting.7.md +2 -0
- package/docs/project-index.md +25 -5
- package/docs/real-execution-backends.7.md +2 -0
- package/docs/release-and-migration.7.md +2 -0
- package/docs/release-tooling.7.md +2 -0
- package/docs/run-registry-control-plane.7.md +2 -0
- package/docs/run-retention-reclamation.7.md +2 -0
- package/docs/security-trust-hardening.7.md +30 -0
- package/docs/state-explosion-management.7.md +2 -0
- package/docs/team-collaboration.7.md +2 -0
- package/docs/trust-audit-anchor.7.md +69 -0
- package/docs/web-desktop-workbench.7.md +2 -0
- package/manifest/plugin.manifest.json +1 -1
- package/package.json +3 -1
- package/scripts/bump-version.js +24 -2
- package/scripts/canonical-apps.js +4 -4
- package/scripts/dogfood-release.js +1 -1
- package/scripts/golden-path.js +4 -4
- package/scripts/purity-baseline.json +68 -0
- package/scripts/purity-gate.js +239 -0
- package/scripts/release-check.js +8 -1
- package/scripts/version-sync-check.js +33 -12
- package/workflows/README.md +19 -0
|
@@ -106,6 +106,7 @@ function workerBlackboardManifest(run, task) {
|
|
|
106
106
|
const verifier_1 = require("./verifier");
|
|
107
107
|
const runner_1 = require("../core/pipeline/runner");
|
|
108
108
|
const hash_1 = require("../core/hash");
|
|
109
|
+
const collate_1 = require("../core/util/collate");
|
|
109
110
|
const telemetry_attestation_1 = require("../core/trust/telemetry-attestation");
|
|
110
111
|
const telemetry_ledger_io_1 = require("./telemetry-ledger-io");
|
|
111
112
|
exports.WORKER_ISOLATION_SCHEMA_VERSION = 1;
|
|
@@ -531,13 +532,37 @@ function recordWorkerOutput(run, workerId, resultPath, options = {}) {
|
|
|
531
532
|
})
|
|
532
533
|
: undefined;
|
|
533
534
|
// Opt-in fail-closed gate (default off): when the operator requires
|
|
534
|
-
// attested telemetry,
|
|
535
|
-
//
|
|
536
|
-
//
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
535
|
+
// attested telemetry, an accept whose usage cannot be verified is
|
|
536
|
+
// REJECTED here — BEFORE any accept-side state mutation — so the drive
|
|
537
|
+
// parks it instead of recording unverifiable usage. This fires on BOTH
|
|
538
|
+
// shapes: a delegation present but not attested (telemetry.status !==
|
|
539
|
+
// "attested"), and NO delegation metadata at all. The second shape is
|
|
540
|
+
// the gap a manual `cw worker output` / `cw result` accept used to slip
|
|
541
|
+
// through silently: options.agentDelegation was simply absent, so
|
|
542
|
+
// `telemetry` was undefined and the old `telemetry &&` condition
|
|
543
|
+
// short-circuited false — an unattested result could be laundered
|
|
544
|
+
// through the manual accept path even with the require flag on.
|
|
545
|
+
// --allow-unattested is the operator's explicit way past this: it never
|
|
546
|
+
// skips the gate silently, it records a telemetry.gate-override event.
|
|
547
|
+
if (options.requireAttestedTelemetry && (!telemetry || telemetry.status !== "attested")) {
|
|
548
|
+
if (options.allowUnattested) {
|
|
549
|
+
(0, trust_audit_1.recordTrustAuditEvent)(run, {
|
|
550
|
+
kind: "telemetry.gate-override",
|
|
551
|
+
decision: "allowed",
|
|
552
|
+
source: "operator",
|
|
553
|
+
workerId,
|
|
554
|
+
taskId: task.id,
|
|
555
|
+
metadata: { reason: "--allow-unattested", telemetryStatus: telemetry ? telemetry.status : "absent" },
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
else {
|
|
559
|
+
const code = telemetry ? "telemetry-unattested-blocked" : "telemetry-missing-blocked";
|
|
560
|
+
const message = telemetry
|
|
561
|
+
? `Worker ${workerId} telemetry is ${telemetry.status} (${telemetry.reason || "unverified"}) and require-attested-telemetry is enabled — refusing to accept a hop whose usage cannot be cryptographically verified`
|
|
562
|
+
: `Worker ${workerId} carries no agent-delegation telemetry at all and require-attested-telemetry is enabled — refusing to accept an unattested manual result (pass --allow-unattested to record an audited override)`;
|
|
563
|
+
recordWorkerFailure(run, workerId, message, { code, path: absoluteResultPath, retryable: false });
|
|
564
|
+
throw new Error(message);
|
|
565
|
+
}
|
|
541
566
|
}
|
|
542
567
|
const agentDelegationMeta = delegation
|
|
543
568
|
? {
|
|
@@ -797,7 +822,7 @@ function listWorkerScopes(run, options = {}) {
|
|
|
797
822
|
// silently drops workers whenever run.workers was reset.
|
|
798
823
|
const merged = mergeScopes(run.workers || [], loadWorkerScopesFromDisk(run));
|
|
799
824
|
run.workers = merged;
|
|
800
|
-
const workers = merged.slice().sort((a, b) => a.id
|
|
825
|
+
const workers = merged.slice().sort((a, b) => (0, collate_1.stableCompare)(a.id, b.id));
|
|
801
826
|
return options.status ? workers.filter((w) => w.status === options.status) : workers;
|
|
802
827
|
}
|
|
803
828
|
function countByStatus(workers) {
|
|
@@ -824,7 +849,7 @@ function countBucket(values) {
|
|
|
824
849
|
return counts;
|
|
825
850
|
}
|
|
826
851
|
function formatCountBucket(counts) {
|
|
827
|
-
const entries = Object.entries(counts).sort(([a], [b]) =>
|
|
852
|
+
const entries = Object.entries(counts).sort(([a], [b]) => (0, collate_1.stableCompare)(a, b));
|
|
828
853
|
if (!entries.length)
|
|
829
854
|
return "none";
|
|
830
855
|
return entries.map(([k, v]) => `${k}=${v}`).join(", ");
|
|
@@ -75,6 +75,7 @@ const path = __importStar(require("node:path"));
|
|
|
75
75
|
const app_schema_1 = require("../core/workflow-apps/app-schema");
|
|
76
76
|
const sandbox_profile_1 = require("./sandbox-profile");
|
|
77
77
|
const version_1 = require("../core/version");
|
|
78
|
+
const collate_1 = require("../core/util/collate");
|
|
78
79
|
class WorkflowAppNotFoundError extends Error {
|
|
79
80
|
constructor(appId) {
|
|
80
81
|
super(`Workflow app not found: ${appId}`);
|
|
@@ -421,10 +422,10 @@ function listWorkflowAppRecords() {
|
|
|
421
422
|
...loadWorkflowFiles(workflowsDir).map((file) => loadWorkflowAppFromEntrypoint(file)),
|
|
422
423
|
...loadAppManifestFiles(appsDir).map((file) => loadWorkflowAppFromManifest(file)),
|
|
423
424
|
].sort((left, right) => {
|
|
424
|
-
const byId = left.app.id
|
|
425
|
+
const byId = (0, collate_1.stableCompare)(left.app.id, right.app.id);
|
|
425
426
|
if (byId)
|
|
426
427
|
return byId;
|
|
427
|
-
return sourcePathOf(left)
|
|
428
|
+
return (0, collate_1.stableCompare)(sourcePathOf(left), sourcePathOf(right));
|
|
428
429
|
});
|
|
429
430
|
const seen = new Map();
|
|
430
431
|
for (const record of records) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// wiring/capability-table/basics.ts — MILESTONE 2's CLI bindings (version,
|
|
3
|
+
// list, status, sandbox.list). Split out of core/capability-table.ts,
|
|
4
|
+
// byte-for-byte (extracted with sed, not retyped).
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const registry_core_1 = require("./registry-core");
|
|
7
|
+
// ---------------------------------------------------------------------
|
|
8
|
+
// CLI bindings wired at THIS milestone (version, list, status,
|
|
9
|
+
// sandbox.list). `version` is cli-only per SPEC/mcp.md's declared
|
|
10
|
+
// one-surface list (`help` is handled directly by cli/entry.ts's
|
|
11
|
+
// top-level flag redirect, same as milestone 1 — it is not itself a
|
|
12
|
+
// dispatchable command row); `list`/`status`/`sandbox.list` reuse the mcp
|
|
13
|
+
// row's capability id and get a cli binding layered on top. Every handler
|
|
14
|
+
// below returns a `CliHandlerResult`; core/ never touches process.stdout
|
|
15
|
+
// or process.exitCode directly (see docs/rebuild/PLAN.md's core/shell split) —
|
|
16
|
+
// cli/dispatch.ts's generic executor performs the actual write.
|
|
17
|
+
// ---------------------------------------------------------------------
|
|
18
|
+
const version_1 = require("../../core/version");
|
|
19
|
+
const workflow_app_loader_1 = require("../../shell/workflow-app-loader");
|
|
20
|
+
const help_1 = require("../../core/format/help");
|
|
21
|
+
(0, registry_core_1.addCliOnlyCapability)("version", "Print the current cool-workflow version.", {
|
|
22
|
+
path: ["version"],
|
|
23
|
+
jsonMode: "default",
|
|
24
|
+
handler: () => ({ text: `${version_1.CURRENT_COOL_WORKFLOW_VERSION}\n` }),
|
|
25
|
+
}, "version is a local, no-run-state print; the old build never gave it an MCP peer.");
|
|
26
|
+
/** `cw search <keyword>` — filters the SAME real app discovery `cw list`
|
|
27
|
+
* shows, by id/title/summary (byte-behavior port of cli/dispatch.ts's
|
|
28
|
+
* milestone-1 carry-over `search` arm, moved here so the dispatchLegacy
|
|
29
|
+
* switch shrinks per its file header's rule). `hiddenFromHelp` keeps it
|
|
30
|
+
* out of the per-verb help listing exactly as before (it never had one —
|
|
31
|
+
* `search` only ever appeared in formatHelp's hard-coded "More commands"
|
|
32
|
+
* index line, which this row does not touch), so `cw help search` keeps
|
|
33
|
+
* its existing "Unknown command: search" text. */
|
|
34
|
+
(0, registry_core_1.addCliOnlyCapability)("search", "Search bundled workflows by id/title/summary keyword.", {
|
|
35
|
+
path: ["search"],
|
|
36
|
+
jsonMode: "flag",
|
|
37
|
+
hiddenFromHelp: true,
|
|
38
|
+
handler: (args) => {
|
|
39
|
+
const keyword = args.positionals.join(" ");
|
|
40
|
+
if (!keyword.trim()) {
|
|
41
|
+
throw new Error('Missing search keyword.\n Tip: cw search architecture to find workflows about architecture.');
|
|
42
|
+
}
|
|
43
|
+
const lower = keyword.toLowerCase();
|
|
44
|
+
const results = (0, workflow_app_loader_1.listWorkflowApps)()
|
|
45
|
+
.filter((a) => String(a.title).toLowerCase().includes(lower) ||
|
|
46
|
+
String(a.summary).toLowerCase().includes(lower) ||
|
|
47
|
+
String(a.id).toLowerCase().includes(lower))
|
|
48
|
+
.map((a) => ({ id: String(a.id), title: String(a.title), summary: String(a.summary) }));
|
|
49
|
+
return { json: results, text: (0, help_1.formatSearchResults)(keyword, results) };
|
|
50
|
+
},
|
|
51
|
+
}, "CLI-only discovery helper over the same real app data cw list shows; no MCP client needs a free-text search tool alongside cw_list's structured output.");
|
|
52
|
+
(0, registry_core_1.attachCliBinding)("list", {
|
|
53
|
+
path: ["list"],
|
|
54
|
+
jsonMode: "default",
|
|
55
|
+
handler: () => ({ json: (0, registry_core_1.listBundledWorkflows)() }),
|
|
56
|
+
});
|
|
57
|
+
(0, registry_core_1.attachCliBinding)("status", {
|
|
58
|
+
path: ["status"],
|
|
59
|
+
jsonMode: "flag",
|
|
60
|
+
handler: (args) => ({ json: (0, registry_core_1.statusPayload)(args.positionals[0]) }),
|
|
61
|
+
});
|
|
62
|
+
(0, registry_core_1.attachCliBinding)("sandbox.list", {
|
|
63
|
+
path: ["sandbox", "list"],
|
|
64
|
+
jsonMode: "default",
|
|
65
|
+
handler: () => ({ json: (0, registry_core_1.listBundledSandboxProfiles)() }),
|
|
66
|
+
});
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// wiring/capability-table/exec-backend.ts — MILESTONE 5 (execution backend,
|
|
3
|
+
// agent spawn, sandbox) CLI bindings: sandbox.*, backend.*, app.run. Split
|
|
4
|
+
// out of core/capability-table.ts, byte-for-byte (extracted with sed, not
|
|
5
|
+
// retyped).
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const registry_core_1 = require("./registry-core");
|
|
8
|
+
// MILESTONE 5 (execution backend, agent spawn, sandbox) CLI bindings:
|
|
9
|
+
// sandbox.list|show|validate, backend.list|show|probe,
|
|
10
|
+
// backend.agent.config.show|set, doctor, fix. Handler BODIES live in
|
|
11
|
+
// shell/exec-backend-cli.ts / shell/doctor.ts (impure — env/fs reads);
|
|
12
|
+
// this table only wires argv shape -> handler call, per cli/dispatch.ts's
|
|
13
|
+
// generic executor contract. `sandbox.list`/`backend.list` are ALREADY
|
|
14
|
+
// declared MCP-only rows from milestone 2 (MCP_TOOL_DATA above) — this
|
|
15
|
+
// section layers a `cli` binding onto them (attachCliBinding) and replaces
|
|
16
|
+
// their milestone-2 placeholder `mcp.handler` with the real body, exactly
|
|
17
|
+
// as milestones 3/4 did for their own rows.
|
|
18
|
+
// ---------------------------------------------------------------------
|
|
19
|
+
const exec_backend_cli_1 = require("../../shell/exec-backend-cli");
|
|
20
|
+
const doctor_1 = require("../../shell/doctor");
|
|
21
|
+
const io_1 = require("../../cli/io");
|
|
22
|
+
const app_run_cli_1 = require("../../shell/app-run-cli");
|
|
23
|
+
(0, registry_core_1.attachCliBinding)("sandbox.list", {
|
|
24
|
+
path: ["sandbox", "list"],
|
|
25
|
+
jsonMode: "default",
|
|
26
|
+
handler: (args) => ({ json: (0, exec_backend_cli_1.listSandboxProfilesCli)(args.options) }),
|
|
27
|
+
});
|
|
28
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("sandbox.list").mcp.handler = (args) => (0, exec_backend_cli_1.listSandboxProfilesCli)(args);
|
|
29
|
+
// GAP #24: cw_sandbox_choose / cw_sandbox_resolve + cw_app_run were declared
|
|
30
|
+
// MCP-only rows with the notYetImplemented placeholder handler. Wire them to
|
|
31
|
+
// the ported shell bodies (both are MCP-only in the old build — no CLI path).
|
|
32
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("sandbox.choose").mcp.handler = (args) => (0, app_run_cli_1.sandboxChooseCli)(args);
|
|
33
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("sandbox.resolve").mcp.handler = (args) => (0, app_run_cli_1.sandboxChooseCli)(args);
|
|
34
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("app.run").mcp.handler = (args) => (0, app_run_cli_1.appRunCli)(args);
|
|
35
|
+
(0, registry_core_1.attachCliBinding)("sandbox.show", {
|
|
36
|
+
path: ["sandbox", "show"],
|
|
37
|
+
jsonMode: "default",
|
|
38
|
+
handler: (args) => ({ json: (0, exec_backend_cli_1.showSandboxProfileCli)((0, io_1.required)(args.positionals[0], "profile id"), args.options) }),
|
|
39
|
+
});
|
|
40
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("sandbox.show").mcp.handler = (args) => (0, exec_backend_cli_1.showSandboxProfileCli)((0, io_1.required)((0, io_1.optionalArg)(args.profileId), "profile id"), args);
|
|
41
|
+
(0, registry_core_1.attachCliBinding)("sandbox.validate", {
|
|
42
|
+
path: ["sandbox", "validate"],
|
|
43
|
+
jsonMode: "default",
|
|
44
|
+
handler: (args) => {
|
|
45
|
+
const result = (0, exec_backend_cli_1.validateSandboxProfileCli)((0, io_1.required)(args.positionals[0], "profile file"), args.options);
|
|
46
|
+
return { json: result, exitCode: result.valid ? undefined : 1 };
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("sandbox.validate").mcp.handler = (args) => (0, exec_backend_cli_1.validateSandboxProfileCli)((0, io_1.required)((0, io_1.optionalArg)(args.profileFile), "profile file"), args);
|
|
50
|
+
// PARITY: `sandbox.choose`/`sandbox.resolve` are BOTH-surface capabilities
|
|
51
|
+
// per SPEC/mcp.md (old build cli.path ["sandbox","choose"]/["sandbox",
|
|
52
|
+
// "resolve"]) — they were left MCP-only at GAP #24 (see the comment
|
|
53
|
+
// above sandboxChooseCli's mcp.handler wiring). Attach the same, already-
|
|
54
|
+
// working shell body as the cli.handler too, so the CLI front door and
|
|
55
|
+
// the parity payload probe both reach it (no new business logic, same
|
|
56
|
+
// function both surfaces already call over MCP).
|
|
57
|
+
(0, registry_core_1.attachCliBinding)("sandbox.choose", {
|
|
58
|
+
path: ["sandbox", "choose"],
|
|
59
|
+
jsonMode: "default",
|
|
60
|
+
handler: (args) => ({ json: (0, app_run_cli_1.sandboxChooseCli)(args.options) }),
|
|
61
|
+
});
|
|
62
|
+
(0, registry_core_1.attachCliBinding)("sandbox.resolve", {
|
|
63
|
+
path: ["sandbox", "resolve"],
|
|
64
|
+
jsonMode: "default",
|
|
65
|
+
handler: (args) => ({ json: (0, app_run_cli_1.sandboxChooseCli)(args.options) }),
|
|
66
|
+
});
|
|
67
|
+
(0, registry_core_1.attachCliBinding)("backend.list", {
|
|
68
|
+
path: ["backend", "list"],
|
|
69
|
+
jsonMode: "default",
|
|
70
|
+
handler: () => ({ json: (0, exec_backend_cli_1.listBackendsCli)() }),
|
|
71
|
+
});
|
|
72
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("backend.list").mcp.handler = () => (0, exec_backend_cli_1.listBackendsCli)();
|
|
73
|
+
(0, registry_core_1.attachCliBinding)("backend.show", {
|
|
74
|
+
path: ["backend", "show"],
|
|
75
|
+
jsonMode: "default",
|
|
76
|
+
handler: (args) => ({ json: (0, exec_backend_cli_1.showBackendCli)((0, io_1.required)(args.positionals[0], "backend id")) }),
|
|
77
|
+
});
|
|
78
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("backend.show").mcp.handler = (args) => (0, exec_backend_cli_1.showBackendCli)((0, io_1.required)((0, io_1.optionalArg)(args.backendId), "backend id"));
|
|
79
|
+
(0, registry_core_1.attachCliBinding)("backend.probe", {
|
|
80
|
+
path: ["backend", "probe"],
|
|
81
|
+
jsonMode: "default",
|
|
82
|
+
handler: (args) => ({ json: (0, exec_backend_cli_1.probeBackendCli)(args.positionals[0], args.options) }),
|
|
83
|
+
});
|
|
84
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("backend.probe").mcp.handler = (args) => (0, exec_backend_cli_1.probeBackendCli)((0, io_1.optionalArg)(args.backendId), args);
|
|
85
|
+
// `backend agent config [show]` = read-only; `backend agent config set
|
|
86
|
+
// ...` = mutating. CLI path is ["backend", "agent"] (2 tokens, matching
|
|
87
|
+
// dispatchTable's supported path lengths); the remaining positionals
|
|
88
|
+
// ("config", "show"/"set") are read inside the handler, byte-exact to the
|
|
89
|
+
// old build's handleBackend "agent" case (src/cli/handlers/
|
|
90
|
+
// operational.ts:52-62).
|
|
91
|
+
(0, registry_core_1.attachCliBinding)("backend.agent.config.show", {
|
|
92
|
+
path: ["backend", "agent"],
|
|
93
|
+
helpPath: ["backend", "agent", "config"],
|
|
94
|
+
jsonMode: "default",
|
|
95
|
+
handler: (args) => {
|
|
96
|
+
const action = args.positionals[1];
|
|
97
|
+
if (action === "set")
|
|
98
|
+
return { json: (0, exec_backend_cli_1.backendAgentConfigSet)(args.options) };
|
|
99
|
+
return { json: (0, exec_backend_cli_1.backendAgentConfigShow)(args.options) };
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
// `backend.agent.config.set` shares the SAME dispatch path/handler as
|
|
103
|
+
// `.show` above (dispatchTable only supports 2-token paths, and the
|
|
104
|
+
// show-vs-set branch lives inside that one handler on positionals[1] —
|
|
105
|
+
// byte-exact to the old build's handleBackend "agent" case). This second
|
|
106
|
+
// attachCliBinding call exists ONLY so `cw help backend` lists both rows
|
|
107
|
+
// (cliCommandHelpRows iterates cliCapabilities(), one row per capability),
|
|
108
|
+
// matching the old registry's two declared rows sharing one caseTokens
|
|
109
|
+
// group; dispatchTable itself never reaches this row a second time because
|
|
110
|
+
// `backend.agent.config.show`'s row is found first by
|
|
111
|
+
// findCapabilityByCliPath's linear scan and its handler already covers
|
|
112
|
+
// both actions.
|
|
113
|
+
(0, registry_core_1.attachCliBinding)("backend.agent.config.set", {
|
|
114
|
+
path: ["backend", "agent"],
|
|
115
|
+
helpPath: ["backend", "agent", "config"],
|
|
116
|
+
jsonMode: "default",
|
|
117
|
+
handler: (args) => {
|
|
118
|
+
const action = args.positionals[1];
|
|
119
|
+
if (action === "set")
|
|
120
|
+
return { json: (0, exec_backend_cli_1.backendAgentConfigSet)(args.options) };
|
|
121
|
+
return { json: (0, exec_backend_cli_1.backendAgentConfigShow)(args.options) };
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("backend.agent.config.show").mcp.handler = (args) => (0, exec_backend_cli_1.backendAgentConfigShow)(args);
|
|
125
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("backend.agent.config.set").mcp.handler = (args) => (0, exec_backend_cli_1.backendAgentConfigSet)(args);
|
|
126
|
+
// PARITY: `backend.agent.config.set` mutates $CW_HOME/agent-config.json
|
|
127
|
+
// (secret-stripped) before returning the effective config; both surfaces
|
|
128
|
+
// perform the same write, so it is a documented opt-out from the
|
|
129
|
+
// read-payload probe, not an undocumented divergence.
|
|
130
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("backend.agent.config.set").payloadIdentical = false;
|
|
131
|
+
registry_core_1.REGISTRY_BY_CAPABILITY.get("backend.agent.config.set").reason =
|
|
132
|
+
"Mutating: persists $CW_HOME/agent-config.json (secret-stripped) before returning the effective config; both surfaces perform the same write — it is a surface-mutating verb, not a read probe.";
|
|
133
|
+
(0, registry_core_1.addCliOnlyCapability)("doctor", "Diagnose the host for setup problems (Node version, agent backend, agent binary on PATH, git, writable home/repo state) and print an actionable fix per check.", {
|
|
134
|
+
path: ["doctor"],
|
|
135
|
+
jsonMode: "flag",
|
|
136
|
+
handler: (args) => {
|
|
137
|
+
const report = (0, doctor_1.runDoctor)(args.options, process.env, String(args.options.cwd || process.cwd()));
|
|
138
|
+
// Byte-exact port of src/cli/command-surface.ts:170-176: both text
|
|
139
|
+
// branches are written as `${formatX(report)}\n` UNCONDITIONALLY —
|
|
140
|
+
// formatDoctorFixes already ends in its own "\n" (its last joined
|
|
141
|
+
// element is ""), so its case needs one MORE explicit "\n" here to
|
|
142
|
+
// reproduce that unconditional append; cli/dispatch.ts's generic
|
|
143
|
+
// renderer only appends "\n" when the text does NOT already end in
|
|
144
|
+
// one, so a bare `formatDoctorFixes(report)` here would silently
|
|
145
|
+
// drop the old build's trailing blank line.
|
|
146
|
+
const text = (0, io_1.wantsJson)(args.options) ? undefined : args.options.fix ? `${(0, doctor_1.formatDoctorFixes)(report)}\n` : (0, doctor_1.formatDoctorReport)(report);
|
|
147
|
+
return { json: report, text, exitCode: report.ok ? undefined : 1 };
|
|
148
|
+
},
|
|
149
|
+
}, "Environment diagnostics are inherently local to the CLI host — Node version, $PATH, $CW_HOME/cwd writability. An MCP client diagnosing the server process's environment is not meaningful; agents already receive the same readiness facts in their typed results (e.g. status: blocked, agentConfigured). Inspired by `brew doctor`.");
|
|
150
|
+
(0, registry_core_1.addCliOnlyCapability)("fix", "Print consolidated fix commands for CW setup issues.", {
|
|
151
|
+
path: ["fix"],
|
|
152
|
+
jsonMode: "human",
|
|
153
|
+
handler: (args) => {
|
|
154
|
+
const report = (0, doctor_1.runDoctor)(args.options, process.env, String(args.options.cwd || process.cwd()));
|
|
155
|
+
// See the "doctor" handler's comment above: formatDoctorFixes
|
|
156
|
+
// already ends in "\n", so one more explicit "\n" here reproduces
|
|
157
|
+
// src/cli/command-surface.ts:126-130's unconditional
|
|
158
|
+
// `${formatDoctorFixes(report)}\n` write.
|
|
159
|
+
return { text: `${(0, doctor_1.formatDoctorFixes)(report)}\n`, exitCode: report.ok ? undefined : 1 };
|
|
160
|
+
},
|
|
161
|
+
}, "Environment fix commands are local diagnostics, same reasoning as doctor.");
|
|
162
|
+
// ---------------------------------------------------------------------
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// wiring/capability-table/index.ts — composes the capability table from
|
|
3
|
+
// registry-core (the shared machinery) plus every domain slice, in the
|
|
4
|
+
// EXACT original source order (REGISTRY array order is a pinned
|
|
5
|
+
// behavior: tools/list order, gen-parity-doc's byte-diff gate, cw help
|
|
6
|
+
// line order). Each slice is a plain module whose top-level
|
|
7
|
+
// attachCliBinding/addCliOnlyCapability/REGISTRY_BY_CAPABILITY calls run
|
|
8
|
+
// once, at first import — Node's module system guarantees that happens
|
|
9
|
+
// in exactly the order these imports are written below, the same
|
|
10
|
+
// guarantee the single original file relied on for its own top-to-bottom
|
|
11
|
+
// statement order.
|
|
12
|
+
//
|
|
13
|
+
// No slice imports another slice; every slice imports only from
|
|
14
|
+
// registry-core.ts, core/capability-data.ts, and shell/core as needed —
|
|
15
|
+
// so this file is the only place the full domain list is assembled, and
|
|
16
|
+
// there is no cross-slice circular dependency to reason about.
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
29
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
30
|
+
};
|
|
31
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
32
|
+
__exportStar(require("./registry-core"), exports);
|
|
33
|
+
require("./basics");
|
|
34
|
+
require("./state");
|
|
35
|
+
require("./exec-backend");
|
|
36
|
+
require("./pipeline");
|
|
37
|
+
require("./trust-ledger");
|
|
38
|
+
require("./multi-agent");
|
|
39
|
+
require("./scheduling-registry");
|
|
40
|
+
require("./reporting");
|
|
41
|
+
require("./workflow-apps");
|
|
42
|
+
__exportStar(require("./parity"), exports);
|