@kal-elsam/kairo-runtime 0.14.0 → 0.16.0
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/CHANGELOG.md +110 -0
- package/bin/kairo-runtime.js +0 -0
- package/bin/kairo.js +0 -0
- package/package.json +1 -1
- package/src/cli.js +182 -8
- package/src/global/check-resolutions.js +31 -0
- package/src/global/cli-help.js +21 -2
- package/src/global/component-ecosystem-checks.js +2 -0
- package/src/global/component-integration-cli.js +29 -10
- package/src/global/components-resolve-cli.js +246 -0
- package/src/global/connection-actions.js +147 -0
- package/src/global/connections.js +269 -0
- package/src/global/control-plane/attention.js +141 -0
- package/src/global/control-plane/build-report.js +146 -0
- package/src/global/control-plane/cli.js +36 -0
- package/src/global/control-plane/constants.js +38 -0
- package/src/global/control-plane/gentle-adapters.js +183 -0
- package/src/global/control-plane/provider.js +69 -0
- package/src/global/control-plane/review-status.js +115 -0
- package/src/global/control-plane/sdd-status.js +49 -0
- package/src/global/control-plane/team.js +63 -0
- package/src/global/fleet-configure-plan.js +123 -0
- package/src/global/fleet-configure.js +303 -0
- package/src/global/fleet-models.js +188 -0
- package/src/global/fleet-set.js +219 -0
- package/src/global/fleet-shared.js +38 -0
- package/src/global/ink/cockpit-controller.js +1 -1
- package/src/global/ink/cockpit-models.js +4 -1
- package/src/global/ink/orchestrator-app.js +21 -2
- package/src/global/ink/ux/live-overview.js +5 -11
- package/src/global/ink/ux/overview-needs.js +1 -1
- package/src/global/integrations/engram-evidence.js +7 -2
- package/src/global/integrations/sdd-apply.js +17 -7
- package/src/global/integrations/sdd-evidence.js +22 -3
- package/src/global/integrations/sdd-plan.js +21 -3
- package/src/global/integrations/sdd-resolutions.js +73 -0
- package/src/global/integrations/sdd-state.js +69 -0
- package/src/global/integrations/sdd-verify.js +9 -4
- package/src/global/mcp/kairo-mcp.js +56 -5
- package/src/global/mcp/resolve-mcp-workspace.js +51 -0
- package/src/global/mcp/work-snapshot-rule.js +89 -0
- package/src/global/mcp/work-snapshot-tool.js +49 -0
- package/src/global/mcp-install.js +239 -0
- package/src/global/next/next-cli.js +35 -0
- package/src/global/next/next-report.js +145 -0
- package/src/global/next/project-key.js +36 -0
- package/src/global/next/publish-work-snapshot.js +116 -0
- package/src/global/next/work-enroll.js +91 -0
- package/src/global/next/work-snapshot.js +216 -0
- package/src/global/observability/fleet-activity.js +197 -0
- package/src/global/observability/fleet-models-catalog.js +137 -0
- package/src/global/observability/fleet-platforms.js +166 -0
- package/src/global/observability/fleet-probe.js +229 -0
- package/src/global/observability/gentle-probe.js +30 -2
- package/src/global/observability/index.js +2 -1
- package/src/global/paths.js +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,116 @@ Historical entries below may reference the legacy `@kal-elsam/harness` package n
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.16.0 — 2026-08-13 (Kairo Runtime)
|
|
9
|
+
|
|
10
|
+
Minor release. Public `kairo control-plane` command and
|
|
11
|
+
`kairo.control-plane/v1` Gentle companion report. Publish tag:
|
|
12
|
+
`kairo-runtime-v0.16.0`. Extension VSIX stays out of this unit.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- `kairo control-plane [--json] [--client cursor]`: atomic panel report
|
|
17
|
+
(work + Gentle workflow + team + attention) as `kairo.control-plane/v1`.
|
|
18
|
+
- Negotiate `gentle-ai.review-integration/v2` (protocol 2.0 and 2.1) before
|
|
19
|
+
any workflow fetch. Provider states: `connected`, `upgrade_required`,
|
|
20
|
+
`unavailable`, `incompatible`.
|
|
21
|
+
- Official `review status` from Gentle's announced bootstrap argv; pass
|
|
22
|
+
`next_transition` through unaltered. Receipt/gate only when Gentle publishes
|
|
23
|
+
them.
|
|
24
|
+
- `sdd-status --json` projection copies `changeName` / `nextRecommended` only.
|
|
25
|
+
|
|
26
|
+
### Docs
|
|
27
|
+
|
|
28
|
+
- Gentle companion boundary: Kairo observes `gentle-ai.review-integration/v2`
|
|
29
|
+
and projects official `next_transition` / `sdd-status --json`. Freeze
|
|
30
|
+
`kairo review`, Cockpit receipts, orchestrator, and intelligence routing so
|
|
31
|
+
they do not feed the panel Workflow. Propose upstream `gentle-ai observe --json`
|
|
32
|
+
in Kairo docs only (`docs/gentle-companion.md`).
|
|
33
|
+
|
|
34
|
+
## 0.15.0 — 2026-08-12 (Kairo Runtime)
|
|
35
|
+
|
|
36
|
+
Minor release. Declared Fleet board + model configure, and the Cursor
|
|
37
|
+
observable companion (work snapshots, MCP publish, `kairo next`, managed
|
|
38
|
+
rule, honest panel). Publish tag: `kairo-runtime-v0.15.0`. Extension
|
|
39
|
+
marketplace delivery stays out of this unit.
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- Contract `kairo.work-snapshot/v1` and MCP tool `kairo_publish_work_snapshot`
|
|
44
|
+
to enroll the current Cursor conversation with Goal / Progress / Now /
|
|
45
|
+
Constraints / Next.
|
|
46
|
+
- `kairo next` / `kairo.next/v1`: selected work snapshot plus integration
|
|
47
|
+
state (`active` / `enrolled` / `showRepair`) for the IDE panel.
|
|
48
|
+
- `kairo mcp install [--yes]`: consent-gated registration of Kairo MCP in
|
|
49
|
+
`~/.cursor/mcp.json` (plan first; atomic write + backup) and managed
|
|
50
|
+
Cursor rule `~/.cursor/rules/kairo-work-snapshot.mdc` (`alwaysApply`).
|
|
51
|
+
- Panel **0.7.0**: honest companion surface — Repair only when integration
|
|
52
|
+
is broken; otherwise active/enrolled without false prompts.
|
|
53
|
+
- MCP workspace binding: prefer Cursor env (`VSCODE_CWD` /
|
|
54
|
+
`WORKSPACE_FOLDER_PATHS`) over process cwd; canonicalize macOS `/tmp` vs
|
|
55
|
+
`/private/tmp` before hashing `projectKey`.
|
|
56
|
+
- Panel **0.6.5**: One **Configure all** for multi-agent (Claude + OpenCode +
|
|
57
|
+
Cursor agents). **Codex aparte** (`--codex-model`). `kairo fleet models`
|
|
58
|
+
shows available vs enabled per tool. Cursor desk: open agents/skills/rules.
|
|
59
|
+
Profile at `~/.harness/fleet-models.json` (seeded from disk; preserves
|
|
60
|
+
tuned OpenCode). `--from gentle` remaps OpenCode tiers when you want that.
|
|
61
|
+
- Panel **0.6.4**: Fleet Details puts configure buttons first (Edit per
|
|
62
|
+
minion on Claude/OpenCode; Cursor offers Claude/OpenCode configure +
|
|
63
|
+
optional Pixel Agents). `fleet configure` defaults to Claude only (no
|
|
64
|
+
surprise OpenCode overwrite).
|
|
65
|
+
- `kairo fleet configure`: Gentle-style model assignments across OpenCode +
|
|
66
|
+
Claude (+ Codex when `codex_default` set). Plan / `--yes` + backups. Panel
|
|
67
|
+
**Models** button. Cursor Auto remains IDE-managed.
|
|
68
|
+
- Panel **0.6.2**: Fleet floor (compact platform desks). Working floor only
|
|
69
|
+
shows live agents — no idle OpenCode wall. CLI `kairo fleet` compact by
|
|
70
|
+
default (`--verbose` for full minion list).
|
|
71
|
+
- Panel **0.6.3**: Configure models toolbar + desk actions for sync/set.
|
|
72
|
+
- `kairo fleet [--json]`: declared orchestrator→minion fleet topology from
|
|
73
|
+
OpenCode config (Gentle + SDD models); Cursor Auto marked opaque.
|
|
74
|
+
MCP tool `kairo_fleet`; `kairo connections --json` includes `fleets`.
|
|
75
|
+
- Panel **0.5.0**: Fleet tree under connections (platform · orchestrator ·
|
|
76
|
+
model, indented minions). Details note: declared config, not live tokens.
|
|
77
|
+
- `kairo connections [--json]`: Gentle / Hermes / Engram / Graphify / Agent
|
|
78
|
+
connection chips for the IDE panel (companion probes + MCP registration).
|
|
79
|
+
- VS Code / Cursor panel **0.3.0**: connection chips, Connect Agent button,
|
|
80
|
+
Entries + Details webview. Docs: `docs/mcp.md`.
|
|
81
|
+
- Panel **0.3.1**: soften "not installed / unconfigured" entries to `note`;
|
|
82
|
+
fix false Engram conflict when Claude uses `~/.claude/mcp/engram.json`
|
|
83
|
+
without `mcpServers.engram` in settings.json.
|
|
84
|
+
- Panel **0.3.2**: **Setup** button + per-connection actions (Configure /
|
|
85
|
+
How to install / Update graph). Optional tools labeled; Kairo never
|
|
86
|
+
auto-installs Gentle/Hermes/Graphify.
|
|
87
|
+
- Panel **0.3.3**: every Entry shows resolve buttons in Details (Fix SDD,
|
|
88
|
+
Repair, Update graph, Why optional?). Hermes chip offers **Start Hermes
|
|
89
|
+
gateway**. Conflicts sort first so buttons are visible immediately.
|
|
90
|
+
- Panel **0.3.4**: Hermes tip documents `API_SERVER_ENABLED=true` — gateway
|
|
91
|
+
alone without API Server does not expose :8642.
|
|
92
|
+
- Check **resolutions[]** contract + panel **0.4.0**: status checks can declare
|
|
93
|
+
clickable fix buttons. For `sdd-core:skills` conflicts:
|
|
94
|
+
- `kairo components diff sdd-core` (read-only)
|
|
95
|
+
- `kairo components adopt sdd-core` (keep disk; record adopted hashes)
|
|
96
|
+
- `kairo components configure sdd-core --overwrite-conflicts` (backup + replace)
|
|
97
|
+
Destructive overwrite asks for a modal confirm in the IDE panel.
|
|
98
|
+
- Panel **0.4.1**: adopt/overwrite buttons apply with `--yes` (click = consent).
|
|
99
|
+
Previous `--dry-run` left CONFLICT unchanged after clicking Conservar el mío.
|
|
100
|
+
- Panel **0.4.2**: status/connections/terminal use the open workspace folder as
|
|
101
|
+
`cwd`, so graphify-out/ is detected (was falsely "not found" from IDE cwd).
|
|
102
|
+
|
|
103
|
+
### Fixed
|
|
104
|
+
|
|
105
|
+
- Cockpit Home opened with focus on the tab bar, so the two Home buttons never
|
|
106
|
+
showed a selection mark and the arrow keys moved between tabs instead. Home
|
|
107
|
+
now starts on the buttons.
|
|
108
|
+
|
|
109
|
+
### Changed
|
|
110
|
+
|
|
111
|
+
- Home buttons render as `› [1] Label` with `← Press Enter` on the focused
|
|
112
|
+
option; press `1` / `2` to run a button without arrow navigation.
|
|
113
|
+
- Home footer names each key (`1·2 Select · Enter Run · ? Help · Esc Exit`)
|
|
114
|
+
instead of listing bare keys.
|
|
115
|
+
- Home shows at most two plain-language needs; the rest collapse into the
|
|
116
|
+
`More info (n)` disclosure, which absorbs the duplicated "n more" line.
|
|
117
|
+
|
|
8
118
|
## 0.14.0 — 2026-08-07 (Kairo Runtime)
|
|
9
119
|
|
|
10
120
|
Minor release. Simpler Cockpit, one-command CLI self-update, pnpm for
|
package/bin/kairo-runtime.js
CHANGED
|
File without changes
|
package/bin/kairo.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kal-elsam/kairo-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Kairo Runtime — local agent operating system for Codex, Cursor, Claude, Pi, Engram, and Graphify.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://github.com/Kal-elSam/harness#readme",
|
package/src/cli.js
CHANGED
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
runComponentsRollback,
|
|
7
7
|
runComponentsVerify
|
|
8
8
|
} from "./global/component-integration-cli.js";
|
|
9
|
+
import {
|
|
10
|
+
runComponentsAdopt,
|
|
11
|
+
runComponentsDiff
|
|
12
|
+
} from "./global/components-resolve-cli.js";
|
|
9
13
|
import {
|
|
10
14
|
printGlobalComponents,
|
|
11
15
|
printGlobalDetect,
|
|
@@ -128,17 +132,109 @@ export async function runCli(argv) {
|
|
|
128
132
|
await runGraphifyCli(optionsWithPolicy, packageManifest);
|
|
129
133
|
return;
|
|
130
134
|
case "mcp": {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
const { runMcpCli } = await import("./global/mcp-install.js");
|
|
136
|
+
await runMcpCli({
|
|
137
|
+
mcpAction: optionsWithPolicy.mcpAction ?? "serve",
|
|
138
|
+
mcpClient: optionsWithPolicy.mcpClient ?? "cursor",
|
|
139
|
+
yes: optionsWithPolicy.yes === true,
|
|
140
|
+
json: optionsWithPolicy.json === true,
|
|
135
141
|
cwd: optionsWithPolicy.cwd,
|
|
142
|
+
cwdExplicit: optionsWithPolicy.cwdExplicit,
|
|
136
143
|
packageRoot,
|
|
137
144
|
packageName: packageManifest.name,
|
|
138
145
|
version: packageManifest.version
|
|
139
146
|
});
|
|
140
147
|
return;
|
|
141
148
|
}
|
|
149
|
+
case "connections": {
|
|
150
|
+
const { buildConnectionsReport } = await import("./global/connections.js");
|
|
151
|
+
const { printJson } = await import("./global/json-output.js");
|
|
152
|
+
const { commandHeader } = await import("./global/brand/index.js");
|
|
153
|
+
const report = await buildConnectionsReport({
|
|
154
|
+
workspaceRoot: optionsWithPolicy.cwd,
|
|
155
|
+
packageRoot,
|
|
156
|
+
packageName: packageManifest.name,
|
|
157
|
+
cliVersion: packageManifest.version,
|
|
158
|
+
client: optionsWithPolicy.mcpClient ?? "cursor"
|
|
159
|
+
});
|
|
160
|
+
if (optionsWithPolicy.json) {
|
|
161
|
+
printJson(report);
|
|
162
|
+
} else {
|
|
163
|
+
console.log(commandHeader("Connections"));
|
|
164
|
+
for (const c of report.connections) {
|
|
165
|
+
console.log(`${c.label} · ${c.state}`);
|
|
166
|
+
console.log(` ${c.access}`);
|
|
167
|
+
if (c.detail) console.log(` ${c.detail}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
case "next": {
|
|
173
|
+
const { runNextCli } = await import("./global/next/next-cli.js");
|
|
174
|
+
await runNextCli({
|
|
175
|
+
cwd: optionsWithPolicy.cwd,
|
|
176
|
+
json: optionsWithPolicy.json === true,
|
|
177
|
+
mcpClient: optionsWithPolicy.mcpClient ?? "cursor"
|
|
178
|
+
});
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
case "control-plane": {
|
|
182
|
+
const { runControlPlaneCli } = await import("./global/control-plane/cli.js");
|
|
183
|
+
await runControlPlaneCli({
|
|
184
|
+
cwd: optionsWithPolicy.cwd,
|
|
185
|
+
json: optionsWithPolicy.json === true,
|
|
186
|
+
mcpClient: optionsWithPolicy.mcpClient ?? "cursor"
|
|
187
|
+
});
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
case "fleet": {
|
|
191
|
+
const fleetAction = optionsWithPolicy.fleetAction ?? "show";
|
|
192
|
+
if (fleetAction === "set") {
|
|
193
|
+
const { runFleetSet } = await import("./global/fleet-set.js");
|
|
194
|
+
await runFleetSet({
|
|
195
|
+
platform: optionsWithPolicy.fleetPlatform,
|
|
196
|
+
agent: optionsWithPolicy.fleetAgent ?? optionsWithPolicy.agent,
|
|
197
|
+
model: optionsWithPolicy.model,
|
|
198
|
+
yes: optionsWithPolicy.yes === true,
|
|
199
|
+
dryRun: optionsWithPolicy.dryRun === true,
|
|
200
|
+
json: optionsWithPolicy.json === true
|
|
201
|
+
});
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (fleetAction === "configure") {
|
|
205
|
+
const { runFleetConfigure } = await import("./global/fleet-configure.js");
|
|
206
|
+
await runFleetConfigure({
|
|
207
|
+
yes: optionsWithPolicy.yes === true,
|
|
208
|
+
json: optionsWithPolicy.json === true,
|
|
209
|
+
platforms: optionsWithPolicy.fleetPlatforms ?? null,
|
|
210
|
+
from: optionsWithPolicy.fleetFrom ?? "profile",
|
|
211
|
+
assignmentsRaw: optionsWithPolicy.fleetAssignments ?? null,
|
|
212
|
+
codexModel: optionsWithPolicy.fleetCodexModel ?? null
|
|
213
|
+
});
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (fleetAction === "models") {
|
|
217
|
+
const { runFleetModels } = await import("./global/fleet-configure.js");
|
|
218
|
+
await runFleetModels({
|
|
219
|
+
json: optionsWithPolicy.json === true,
|
|
220
|
+
profile: optionsWithPolicy.fleetProfile === true
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const { buildFleetReport, formatFleetText } = await import("./global/observability/fleet-probe.js");
|
|
225
|
+
const { printJson } = await import("./global/json-output.js");
|
|
226
|
+
const report = await buildFleetReport({
|
|
227
|
+
includeVariants: optionsWithPolicy.includeVariants === true
|
|
228
|
+
});
|
|
229
|
+
if (optionsWithPolicy.json) {
|
|
230
|
+
printJson(report);
|
|
231
|
+
} else {
|
|
232
|
+
console.log(formatFleetText(report, {
|
|
233
|
+
verbose: optionsWithPolicy.verbose === true || optionsWithPolicy.includeVariants === true
|
|
234
|
+
}));
|
|
235
|
+
}
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
142
238
|
case "intelligence":
|
|
143
239
|
await runIntelligenceCli(optionsWithPolicy, packageManifest);
|
|
144
240
|
return;
|
|
@@ -285,6 +381,12 @@ async function dispatchComponentsCommand(options, invoke) {
|
|
|
285
381
|
case "verify":
|
|
286
382
|
await runComponentsVerify({ ...options, packageRoot });
|
|
287
383
|
return;
|
|
384
|
+
case "adopt":
|
|
385
|
+
await runComponentsAdopt({ ...options, packageRoot });
|
|
386
|
+
return;
|
|
387
|
+
case "diff":
|
|
388
|
+
await runComponentsDiff({ ...options, packageRoot });
|
|
389
|
+
return;
|
|
288
390
|
case "rollback":
|
|
289
391
|
await runComponentsRollback(options);
|
|
290
392
|
return;
|
|
@@ -363,6 +465,7 @@ export function parseArgs(argv) {
|
|
|
363
465
|
const command = normalizeCommand(rawCommand);
|
|
364
466
|
const options = {
|
|
365
467
|
cwd: process.cwd(),
|
|
468
|
+
cwdExplicit: false,
|
|
366
469
|
scope: null,
|
|
367
470
|
mode: "standard",
|
|
368
471
|
modeExplicit: false,
|
|
@@ -382,6 +485,7 @@ export function parseArgs(argv) {
|
|
|
382
485
|
dryRun: false,
|
|
383
486
|
yes: false,
|
|
384
487
|
confirm: false,
|
|
488
|
+
overwriteConflicts: false,
|
|
385
489
|
preflight: true,
|
|
386
490
|
preflightExplicit: false,
|
|
387
491
|
yesExplicit: false,
|
|
@@ -419,6 +523,18 @@ export function parseArgs(argv) {
|
|
|
419
523
|
confirmDismiss: false,
|
|
420
524
|
graphifyAction: null, graphifyArgs: [], graphifyBudget: null, graphPath: null,
|
|
421
525
|
updatesAction: "check",
|
|
526
|
+
mcpAction: "serve",
|
|
527
|
+
mcpClient: "cursor",
|
|
528
|
+
fleetAction: "show",
|
|
529
|
+
fleetPlatform: null,
|
|
530
|
+
fleetAgent: null,
|
|
531
|
+
fleetPlatforms: null,
|
|
532
|
+
fleetFrom: "profile",
|
|
533
|
+
fleetAssignments: null,
|
|
534
|
+
fleetCodexModel: null,
|
|
535
|
+
fleetProfile: false,
|
|
536
|
+
includeVariants: false,
|
|
537
|
+
verbose: false,
|
|
422
538
|
base: null,
|
|
423
539
|
commit: null,
|
|
424
540
|
staged: false,
|
|
@@ -473,6 +589,8 @@ export function parseArgs(argv) {
|
|
|
473
589
|
|
|
474
590
|
if (command === "graphify") parseGraphifyAction(args, options);
|
|
475
591
|
if (command === "updates") parseUpdatesAction(args, options);
|
|
592
|
+
if (command === "mcp") parseMcpAction(args, options);
|
|
593
|
+
if (command === "fleet") parseFleetAction(args, options);
|
|
476
594
|
|
|
477
595
|
if (command === "help") {
|
|
478
596
|
while (args[0] === "all" || args[0] === "--all") {
|
|
@@ -484,7 +602,10 @@ export function parseArgs(argv) {
|
|
|
484
602
|
for (let index = 0; index < args.length; index += 1) {
|
|
485
603
|
const arg = args[index];
|
|
486
604
|
|
|
487
|
-
if (arg === "--cwd")
|
|
605
|
+
if (arg === "--cwd") {
|
|
606
|
+
options.cwd = resolve(args[++index]);
|
|
607
|
+
options.cwdExplicit = true;
|
|
608
|
+
}
|
|
488
609
|
else if (arg === "--scope") options.scope = parseScope(args[++index]);
|
|
489
610
|
else if (arg.startsWith("--scope=")) options.scope = parseScope(arg.slice("--scope=".length));
|
|
490
611
|
else if (arg === "--mode") {
|
|
@@ -518,8 +639,26 @@ export function parseArgs(argv) {
|
|
|
518
639
|
options.componentsExplicit = true;
|
|
519
640
|
} else if (arg === "--force") options.force = true;
|
|
520
641
|
else if (arg === "--dry-run") options.dryRun = true;
|
|
642
|
+
else if (arg === "--overwrite-conflicts") options.overwriteConflicts = true;
|
|
521
643
|
else if (arg === "--json") options.json = true;
|
|
522
|
-
else if (arg === "--
|
|
644
|
+
else if (arg === "--include-variants") options.includeVariants = true;
|
|
645
|
+
else if (arg === "--platforms") options.fleetPlatforms = args[++index];
|
|
646
|
+
else if (arg.startsWith("--platforms=")) options.fleetPlatforms = arg.slice("--platforms=".length);
|
|
647
|
+
else if (arg === "--from") options.fleetFrom = args[++index];
|
|
648
|
+
else if (arg.startsWith("--from=")) options.fleetFrom = arg.slice("--from=".length);
|
|
649
|
+
else if (arg === "--assignments") options.fleetAssignments = args[++index];
|
|
650
|
+
else if (arg.startsWith("--assignments=")) options.fleetAssignments = arg.slice("--assignments=".length);
|
|
651
|
+
else if (arg === "--codex-model") options.fleetCodexModel = args[++index];
|
|
652
|
+
else if (arg.startsWith("--codex-model=")) options.fleetCodexModel = arg.slice("--codex-model=".length);
|
|
653
|
+
else if (arg === "--profile") options.fleetProfile = true;
|
|
654
|
+
else if (arg === "--verbose") options.verbose = true;
|
|
655
|
+
else if (arg === "--platform") options.fleetPlatform = args[++index];
|
|
656
|
+
else if (arg.startsWith("--platform=")) options.fleetPlatform = arg.slice("--platform=".length);
|
|
657
|
+
else if (arg === "--client") {
|
|
658
|
+
options.mcpClient = args[++index];
|
|
659
|
+
} else if (arg.startsWith("--client=")) {
|
|
660
|
+
options.mcpClient = arg.slice("--client=".length);
|
|
661
|
+
} else if (arg === "--yes" || arg === "-y") {
|
|
523
662
|
options.yes = true;
|
|
524
663
|
options.yesExplicit = true;
|
|
525
664
|
} else if (arg === "--confirm") {
|
|
@@ -651,7 +790,8 @@ function parseComponentsAction(args, options) {
|
|
|
651
790
|
|
|
652
791
|
if (action === "validate") return;
|
|
653
792
|
|
|
654
|
-
if (action === "configure" || action === "verify" || action === "rollback"
|
|
793
|
+
if (action === "configure" || action === "verify" || action === "rollback"
|
|
794
|
+
|| action === "adopt" || action === "diff") {
|
|
655
795
|
const componentId = args[0];
|
|
656
796
|
if (!componentId || componentId.startsWith("-")) {
|
|
657
797
|
throw new Error(
|
|
@@ -662,7 +802,7 @@ function parseComponentsAction(args, options) {
|
|
|
662
802
|
return;
|
|
663
803
|
}
|
|
664
804
|
|
|
665
|
-
throw new Error(`Unknown components action "${action}". Use validate, init, pack, import, configure, verify, or rollback.`);
|
|
805
|
+
throw new Error(`Unknown components action "${action}". Use validate, init, pack, import, configure, verify, adopt, diff, or rollback.`);
|
|
666
806
|
}
|
|
667
807
|
|
|
668
808
|
function parsePolicyAction(args, options) {
|
|
@@ -842,6 +982,36 @@ function parseUpdatesAction(args, options) {
|
|
|
842
982
|
options.updatesAction = "check";
|
|
843
983
|
}
|
|
844
984
|
|
|
985
|
+
function parseMcpAction(args, options) {
|
|
986
|
+
const action = args[0];
|
|
987
|
+
if (!action || action.startsWith("-")) {
|
|
988
|
+
options.mcpAction = "serve";
|
|
989
|
+
return;
|
|
990
|
+
}
|
|
991
|
+
if (!new Set(["serve", "install"]).has(action)) {
|
|
992
|
+
throw new Error(
|
|
993
|
+
`Unknown mcp action "${action}". Use: ${formatCliCommand("mcp")} or ${formatCliCommand("mcp install [--yes]")}`
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
args.shift();
|
|
997
|
+
options.mcpAction = action;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
function parseFleetAction(args, options) {
|
|
1001
|
+
const action = args[0];
|
|
1002
|
+
if (!action || action.startsWith("-")) {
|
|
1003
|
+
options.fleetAction = "show";
|
|
1004
|
+
return;
|
|
1005
|
+
}
|
|
1006
|
+
if (!new Set(["show", "set", "activity", "configure", "models"]).has(action)) {
|
|
1007
|
+
throw new Error(
|
|
1008
|
+
`Unknown fleet action "${action}". Use: ${formatCliCommand("fleet")}, ${formatCliCommand("fleet models")}, ${formatCliCommand("fleet configure")}, or ${formatCliCommand("fleet set --platform opencode --agent <id> --model <id>")}`
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
args.shift();
|
|
1012
|
+
options.fleetAction = action === "activity" ? "show" : action;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
845
1015
|
function parsePathList(value) {
|
|
846
1016
|
if (!value) return [];
|
|
847
1017
|
return [...new Set(
|
|
@@ -889,6 +1059,10 @@ function normalizeCommand(command) {
|
|
|
889
1059
|
if (command === "alerts") return "alerts";
|
|
890
1060
|
if (command === "graphify") return "graphify";
|
|
891
1061
|
if (command === "mcp") return "mcp";
|
|
1062
|
+
if (command === "connections") return "connections";
|
|
1063
|
+
if (command === "next") return "next";
|
|
1064
|
+
if (command === "control-plane") return "control-plane";
|
|
1065
|
+
if (command === "fleet") return "fleet";
|
|
892
1066
|
if (command === "intelligence" || command === "intel") return "intelligence";
|
|
893
1067
|
if (command === "setup") return "setup";
|
|
894
1068
|
if (command === "status") return "status";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable resolution contract for doctor/status checks.
|
|
3
|
+
* Panels render these as buttons; commands stay consent-gated in the CLI.
|
|
4
|
+
*/
|
|
5
|
+
export function resolution(id, label, command, {
|
|
6
|
+
kind = "run",
|
|
7
|
+
safety = "consent",
|
|
8
|
+
detail = ""
|
|
9
|
+
} = {}) {
|
|
10
|
+
return {
|
|
11
|
+
id: String(id),
|
|
12
|
+
label: String(label),
|
|
13
|
+
command: command == null ? null : String(command),
|
|
14
|
+
kind: String(kind),
|
|
15
|
+
safety: String(safety),
|
|
16
|
+
detail: detail == null ? "" : String(detail)
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const RESOLUTION_SAFETY = Object.freeze({
|
|
21
|
+
READ_ONLY: "read-only",
|
|
22
|
+
CONSENT: "consent",
|
|
23
|
+
DESTRUCTIVE: "destructive"
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export const RESOLUTION_KIND = Object.freeze({
|
|
27
|
+
RUN: "run",
|
|
28
|
+
CONFIGURE: "configure",
|
|
29
|
+
GUIDE: "guide",
|
|
30
|
+
REFRESH: "refresh"
|
|
31
|
+
});
|
package/src/global/cli-help.js
CHANGED
|
@@ -109,10 +109,20 @@ Bootstrap: see README.md and docs/install.md (curl install.sh or npx ${PACKAGE_N
|
|
|
109
109
|
${cli} components
|
|
110
110
|
${cli} components validate|init|pack|import ...
|
|
111
111
|
${cli} components configure engram-memory [--agents <list>] [--dry-run|--yes] [--json]
|
|
112
|
-
${cli} components configure sdd-core [--agents <list>] [--persona off|teaching] [--dry-run|--yes] [--json]
|
|
112
|
+
${cli} components configure sdd-core [--agents <list>] [--persona off|teaching] [--overwrite-conflicts] [--dry-run|--yes] [--json]
|
|
113
113
|
${cli} components verify sdd-core [--agents <list>] [--json]
|
|
114
|
+
${cli} components adopt sdd-core [--agents <list>] [--dry-run|--yes] [--json]
|
|
115
|
+
${cli} components diff sdd-core [--agents <list>] [--json]
|
|
114
116
|
${cli} components rollback engram-memory|sdd-core --receipt <id> [--dry-run|--yes] [--json]
|
|
117
|
+
${cli} connections [--json] [--client cursor]
|
|
118
|
+
${cli} next [--json] [--client cursor]
|
|
119
|
+
${cli} control-plane [--json] [--client cursor]
|
|
120
|
+
${cli} fleet [--json] [--verbose] [--include-variants]
|
|
121
|
+
${cli} fleet models [--profile] [--json]
|
|
122
|
+
${cli} fleet configure [--platforms claude,opencode,cursor|codex] [--from profile|gentle] [--codex-model <id>] [--assignments a=b,...] [--yes] [--json]
|
|
123
|
+
${cli} fleet set --platform opencode|claude|codex --agent <id> --model <id> [--yes] [--json]
|
|
115
124
|
${cli} mcp
|
|
125
|
+
${cli} mcp install [--yes] [--json] [--client cursor]
|
|
116
126
|
${cli} install --scope=workspace [--mode minimal|standard|enterprise] (opt-in/legacy)
|
|
117
127
|
${cli} init [--mode minimal|standard|enterprise] (workspace alias)
|
|
118
128
|
|
|
@@ -157,12 +167,21 @@ Commands:
|
|
|
157
167
|
policy View or edit local operation preferences under ~/.harness/policy.json.
|
|
158
168
|
report Read-only diagnostics bundle: status, policy, adapters, diff, history.
|
|
159
169
|
components List, validate, scaffold, pack, import, or configure integrations (Engram, SDD).
|
|
170
|
+
connections Companion chips + MCP registration (IDE panel).
|
|
171
|
+
next Selected work snapshot + integration state (panel contract).
|
|
172
|
+
control-plane Atomic panel report (work + Gentle workflow + team + attention).
|
|
173
|
+
fleet Declared fleet floor + working activity; configure/set models across CLIs.
|
|
174
|
+
fleet models [--profile] available vs enabled per tool
|
|
175
|
+
fleet configure one plan for Claude+OpenCode+Cursor (profile)
|
|
176
|
+
fleet configure --codex-model <id> Codex only (single-default)
|
|
177
|
+
fleet set --platform opencode|claude|codex --agent <id> --model <id> [--yes]
|
|
178
|
+
mcp Serve or install MCP for agents (mcp install writes entry + snapshot rule).
|
|
160
179
|
uninstall Remove managed sections and global state. Backups are preserved.
|
|
161
180
|
init Alias for install --scope=workspace (legacy).
|
|
162
181
|
|
|
163
182
|
JSON output (--json on supported commands):
|
|
164
183
|
status, sync, doctor, adapters, explain, diff, history, history last,
|
|
165
|
-
policy (show/set/reset), report, monitor
|
|
184
|
+
policy (show/set/reset), report, monitor, connections, fleet
|
|
166
185
|
Human text remains the default. See docs/cli-reference.md for examples and field notes.
|
|
167
186
|
|
|
168
187
|
Version:
|
|
@@ -9,6 +9,7 @@ import { requireIntegrationProvider } from "./integrations/provider-registry.js"
|
|
|
9
9
|
import { buildEngramIntegrationChecks, buildSddIntegrationChecks } from "./component-integration-cli.js";
|
|
10
10
|
import { KAIRO_ENGRAM_AGENT_IDS } from "./integrations/engram-evidence.js";
|
|
11
11
|
import { SDD_MANAGED_AGENT_IDS } from "./integrations/sdd-destinations.js";
|
|
12
|
+
import { adoptedHashesFromState } from "./integrations/sdd-state.js";
|
|
12
13
|
import { harnessHomePaths } from "./paths.js";
|
|
13
14
|
import { readGlobalState } from "./state.js";
|
|
14
15
|
|
|
@@ -78,6 +79,7 @@ async function buildSddChecks({ homeDir }) {
|
|
|
78
79
|
requestedAgentIds: installedAgents.length ? installedAgents : [],
|
|
79
80
|
detectedAgentIds: installedAgents,
|
|
80
81
|
trackedFiles,
|
|
82
|
+
adoptedFiles: adoptedHashesFromState(state?.sdd),
|
|
81
83
|
personaAgentIds: state?.sdd?.personaAgentIds ?? [],
|
|
82
84
|
packageRoot: PACKAGE_ROOT
|
|
83
85
|
});
|
|
@@ -9,11 +9,13 @@ import { formatCliCommand } from "./brand/cli.js";
|
|
|
9
9
|
import { requireIntegrationProvider } from "./integrations/provider-registry.js";
|
|
10
10
|
import { ensureIntegrationProvidersRegistered } from "./integrations/index.js";
|
|
11
11
|
import { ENGRAM_INTEGRATION_STATUS } from "./integrations/engram-evidence.js";
|
|
12
|
-
import { SDD_HEALTH } from "./integrations/sdd-evidence.js";
|
|
12
|
+
import { SDD_HEALTH, SDD_FILE_OUTCOMES } from "./integrations/sdd-evidence.js";
|
|
13
13
|
import {
|
|
14
|
-
hasSuccessfulSddRollbackMutations, recordSddMaterialization, reconcileSddStateAfterRollback
|
|
14
|
+
hasSuccessfulSddRollbackMutations, recordSddMaterialization, reconcileSddStateAfterRollback,
|
|
15
|
+
adoptedHashesFromState, clearSddAdoptionsForPaths
|
|
15
16
|
} from "./integrations/sdd-state.js";
|
|
16
17
|
import { loadSddReceipt } from "./integrations/sdd-receipts.js";
|
|
18
|
+
import { buildSddSkillResolutions } from "./integrations/sdd-resolutions.js";
|
|
17
19
|
|
|
18
20
|
const DEFAULT_PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
19
21
|
|
|
@@ -169,14 +171,24 @@ async function buildProviderContext(options, { homeDir, componentId }) {
|
|
|
169
171
|
packageRoot: options.packageRoot ?? DEFAULT_PACKAGE_ROOT,
|
|
170
172
|
persona: options.persona ?? state?.sdd?.persona ?? "off",
|
|
171
173
|
personaAgentIds: state?.sdd?.personaAgentIds ?? [],
|
|
172
|
-
trackedFiles
|
|
174
|
+
trackedFiles,
|
|
175
|
+
adoptedFiles: adoptedHashesFromState(state?.sdd),
|
|
176
|
+
overwriteConflicts: Boolean(options.overwriteConflicts)
|
|
173
177
|
};
|
|
174
178
|
}
|
|
175
179
|
|
|
176
180
|
async function persistSddReceiptState(homeDir, receipt) {
|
|
177
181
|
const paths = harnessHomePaths(homeDir);
|
|
178
182
|
const state = (await readGlobalState(paths.statePath)) ?? {};
|
|
179
|
-
|
|
183
|
+
let next = recordSddMaterialization(state, { receipt });
|
|
184
|
+
const appliedPaths = (receipt.files ?? [])
|
|
185
|
+
.filter((file) => file.outcome === SDD_FILE_OUTCOMES.APPLIED)
|
|
186
|
+
.map((file) => file.destinationPath)
|
|
187
|
+
.filter(Boolean);
|
|
188
|
+
if (appliedPaths.length) {
|
|
189
|
+
next = clearSddAdoptionsForPaths(next, appliedPaths);
|
|
190
|
+
}
|
|
191
|
+
await writeGlobalState(paths.statePath, next);
|
|
180
192
|
}
|
|
181
193
|
|
|
182
194
|
async function reconcileSddRollbackState(homeDir, result) {
|
|
@@ -230,13 +242,19 @@ export function buildEngramIntegrationChecks(inspection) {
|
|
|
230
242
|
export function buildSddIntegrationChecks(verification) {
|
|
231
243
|
const summary = verification.summary ?? {};
|
|
232
244
|
const persona = verification.persona ?? {};
|
|
245
|
+
const skillsHealthy = verification.status === SDD_HEALTH.CONFIGURED
|
|
246
|
+
|| verification.status === SDD_HEALTH.ADOPTED;
|
|
247
|
+
const skillsCheck = {
|
|
248
|
+
name: "sdd-core:skills",
|
|
249
|
+
status: skillsHealthy ? "ok" : "warning",
|
|
250
|
+
category: "integration",
|
|
251
|
+
componentId: "sdd-core",
|
|
252
|
+
detail: `SDD skills ${verification.status}: configured=${summary.configured ?? 0}, adopted=${summary.adopted ?? 0}, missing=${summary.missing ?? 0}, drifted=${summary.drifted ?? 0}, conflict=${summary.conflict ?? 0} (disk presence ≠ runtime active).`
|
|
253
|
+
};
|
|
254
|
+
const resolutions = buildSddSkillResolutions(verification);
|
|
255
|
+
if (resolutions.length) skillsCheck.resolutions = resolutions;
|
|
233
256
|
return [
|
|
234
|
-
|
|
235
|
-
name: "sdd-core:skills",
|
|
236
|
-
status: verification.status === SDD_HEALTH.CONFIGURED ? "ok" : "warning",
|
|
237
|
-
category: "integration", componentId: "sdd-core",
|
|
238
|
-
detail: `SDD skills ${verification.status}: configured=${summary.configured ?? 0}, missing=${summary.missing ?? 0}, drifted=${summary.drifted ?? 0}, conflict=${summary.conflict ?? 0} (disk presence ≠ runtime active).`
|
|
239
|
-
},
|
|
257
|
+
skillsCheck,
|
|
240
258
|
{
|
|
241
259
|
name: "sdd-core:persona",
|
|
242
260
|
status: persona.status === "configured" || persona.status === "off" ? "ok" : "warning",
|
|
@@ -283,6 +301,7 @@ function printSddConfigureHuman(result) {
|
|
|
283
301
|
if (result.dryRun) return void console.log("Dry-run only — no skills materialized.");
|
|
284
302
|
if (result.cancelled) return void console.log("Cancelled.");
|
|
285
303
|
if (result.blocked) return void console.log(`Blocked: ${result.reason ?? "conflicts present"}`);
|
|
304
|
+
if (result.overwriteConflicts) console.log("Mode: overwrite-conflicts (backups before replace).");
|
|
286
305
|
if (result.receipt) {
|
|
287
306
|
console.log(`Receipt: ${result.receipt.id}${result.receipt.partial ? " (partial)" : ""}`);
|
|
288
307
|
if (result.sessionRefreshRequired) {
|