@kal-elsam/kairo-runtime 0.14.0 → 0.15.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 +84 -0
- package/bin/kairo-runtime.js +0 -0
- package/bin/kairo.js +0 -0
- package/package.json +1 -1
- package/src/cli.js +172 -8
- package/src/global/check-resolutions.js +31 -0
- package/src/global/cli-help.js +19 -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/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/paths.js +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,90 @@ Historical entries below may reference the legacy `@kal-elsam/harness` package n
|
|
|
5
5
|
|
|
6
6
|
## Unreleased
|
|
7
7
|
|
|
8
|
+
## 0.15.0 — 2026-08-12 (Kairo Runtime)
|
|
9
|
+
|
|
10
|
+
Minor release. Declared Fleet board + model configure, and the Cursor
|
|
11
|
+
observable companion (work snapshots, MCP publish, `kairo next`, managed
|
|
12
|
+
rule, honest panel). Publish tag: `kairo-runtime-v0.15.0`. Extension
|
|
13
|
+
marketplace delivery stays out of this unit.
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Contract `kairo.work-snapshot/v1` and MCP tool `kairo_publish_work_snapshot`
|
|
18
|
+
to enroll the current Cursor conversation with Goal / Progress / Now /
|
|
19
|
+
Constraints / Next.
|
|
20
|
+
- `kairo next` / `kairo.next/v1`: selected work snapshot plus integration
|
|
21
|
+
state (`active` / `enrolled` / `showRepair`) for the IDE panel.
|
|
22
|
+
- `kairo mcp install [--yes]`: consent-gated registration of Kairo MCP in
|
|
23
|
+
`~/.cursor/mcp.json` (plan first; atomic write + backup) and managed
|
|
24
|
+
Cursor rule `~/.cursor/rules/kairo-work-snapshot.mdc` (`alwaysApply`).
|
|
25
|
+
- Panel **0.7.0**: honest companion surface — Repair only when integration
|
|
26
|
+
is broken; otherwise active/enrolled without false prompts.
|
|
27
|
+
- MCP workspace binding: prefer Cursor env (`VSCODE_CWD` /
|
|
28
|
+
`WORKSPACE_FOLDER_PATHS`) over process cwd; canonicalize macOS `/tmp` vs
|
|
29
|
+
`/private/tmp` before hashing `projectKey`.
|
|
30
|
+
- Panel **0.6.5**: One **Configure all** for multi-agent (Claude + OpenCode +
|
|
31
|
+
Cursor agents). **Codex aparte** (`--codex-model`). `kairo fleet models`
|
|
32
|
+
shows available vs enabled per tool. Cursor desk: open agents/skills/rules.
|
|
33
|
+
Profile at `~/.harness/fleet-models.json` (seeded from disk; preserves
|
|
34
|
+
tuned OpenCode). `--from gentle` remaps OpenCode tiers when you want that.
|
|
35
|
+
- Panel **0.6.4**: Fleet Details puts configure buttons first (Edit per
|
|
36
|
+
minion on Claude/OpenCode; Cursor offers Claude/OpenCode configure +
|
|
37
|
+
optional Pixel Agents). `fleet configure` defaults to Claude only (no
|
|
38
|
+
surprise OpenCode overwrite).
|
|
39
|
+
- `kairo fleet configure`: Gentle-style model assignments across OpenCode +
|
|
40
|
+
Claude (+ Codex when `codex_default` set). Plan / `--yes` + backups. Panel
|
|
41
|
+
**Models** button. Cursor Auto remains IDE-managed.
|
|
42
|
+
- Panel **0.6.2**: Fleet floor (compact platform desks). Working floor only
|
|
43
|
+
shows live agents — no idle OpenCode wall. CLI `kairo fleet` compact by
|
|
44
|
+
default (`--verbose` for full minion list).
|
|
45
|
+
- Panel **0.6.3**: Configure models toolbar + desk actions for sync/set.
|
|
46
|
+
- `kairo fleet [--json]`: declared orchestrator→minion fleet topology from
|
|
47
|
+
OpenCode config (Gentle + SDD models); Cursor Auto marked opaque.
|
|
48
|
+
MCP tool `kairo_fleet`; `kairo connections --json` includes `fleets`.
|
|
49
|
+
- Panel **0.5.0**: Fleet tree under connections (platform · orchestrator ·
|
|
50
|
+
model, indented minions). Details note: declared config, not live tokens.
|
|
51
|
+
- `kairo connections [--json]`: Gentle / Hermes / Engram / Graphify / Agent
|
|
52
|
+
connection chips for the IDE panel (companion probes + MCP registration).
|
|
53
|
+
- VS Code / Cursor panel **0.3.0**: connection chips, Connect Agent button,
|
|
54
|
+
Entries + Details webview. Docs: `docs/mcp.md`.
|
|
55
|
+
- Panel **0.3.1**: soften "not installed / unconfigured" entries to `note`;
|
|
56
|
+
fix false Engram conflict when Claude uses `~/.claude/mcp/engram.json`
|
|
57
|
+
without `mcpServers.engram` in settings.json.
|
|
58
|
+
- Panel **0.3.2**: **Setup** button + per-connection actions (Configure /
|
|
59
|
+
How to install / Update graph). Optional tools labeled; Kairo never
|
|
60
|
+
auto-installs Gentle/Hermes/Graphify.
|
|
61
|
+
- Panel **0.3.3**: every Entry shows resolve buttons in Details (Fix SDD,
|
|
62
|
+
Repair, Update graph, Why optional?). Hermes chip offers **Start Hermes
|
|
63
|
+
gateway**. Conflicts sort first so buttons are visible immediately.
|
|
64
|
+
- Panel **0.3.4**: Hermes tip documents `API_SERVER_ENABLED=true` — gateway
|
|
65
|
+
alone without API Server does not expose :8642.
|
|
66
|
+
- Check **resolutions[]** contract + panel **0.4.0**: status checks can declare
|
|
67
|
+
clickable fix buttons. For `sdd-core:skills` conflicts:
|
|
68
|
+
- `kairo components diff sdd-core` (read-only)
|
|
69
|
+
- `kairo components adopt sdd-core` (keep disk; record adopted hashes)
|
|
70
|
+
- `kairo components configure sdd-core --overwrite-conflicts` (backup + replace)
|
|
71
|
+
Destructive overwrite asks for a modal confirm in the IDE panel.
|
|
72
|
+
- Panel **0.4.1**: adopt/overwrite buttons apply with `--yes` (click = consent).
|
|
73
|
+
Previous `--dry-run` left CONFLICT unchanged after clicking Conservar el mío.
|
|
74
|
+
- Panel **0.4.2**: status/connections/terminal use the open workspace folder as
|
|
75
|
+
`cwd`, so graphify-out/ is detected (was falsely "not found" from IDE cwd).
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
|
|
79
|
+
- Cockpit Home opened with focus on the tab bar, so the two Home buttons never
|
|
80
|
+
showed a selection mark and the arrow keys moved between tabs instead. Home
|
|
81
|
+
now starts on the buttons.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- Home buttons render as `› [1] Label` with `← Press Enter` on the focused
|
|
86
|
+
option; press `1` / `2` to run a button without arrow navigation.
|
|
87
|
+
- Home footer names each key (`1·2 Select · Enter Run · ? Help · Esc Exit`)
|
|
88
|
+
instead of listing bare keys.
|
|
89
|
+
- Home shows at most two plain-language needs; the rest collapse into the
|
|
90
|
+
`More info (n)` disclosure, which absorbs the duplicated "n more" line.
|
|
91
|
+
|
|
8
92
|
## 0.14.0 — 2026-08-07 (Kairo Runtime)
|
|
9
93
|
|
|
10
94
|
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.15.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,100 @@ 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 "fleet": {
|
|
182
|
+
const fleetAction = optionsWithPolicy.fleetAction ?? "show";
|
|
183
|
+
if (fleetAction === "set") {
|
|
184
|
+
const { runFleetSet } = await import("./global/fleet-set.js");
|
|
185
|
+
await runFleetSet({
|
|
186
|
+
platform: optionsWithPolicy.fleetPlatform,
|
|
187
|
+
agent: optionsWithPolicy.fleetAgent ?? optionsWithPolicy.agent,
|
|
188
|
+
model: optionsWithPolicy.model,
|
|
189
|
+
yes: optionsWithPolicy.yes === true,
|
|
190
|
+
dryRun: optionsWithPolicy.dryRun === true,
|
|
191
|
+
json: optionsWithPolicy.json === true
|
|
192
|
+
});
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (fleetAction === "configure") {
|
|
196
|
+
const { runFleetConfigure } = await import("./global/fleet-configure.js");
|
|
197
|
+
await runFleetConfigure({
|
|
198
|
+
yes: optionsWithPolicy.yes === true,
|
|
199
|
+
json: optionsWithPolicy.json === true,
|
|
200
|
+
platforms: optionsWithPolicy.fleetPlatforms ?? null,
|
|
201
|
+
from: optionsWithPolicy.fleetFrom ?? "profile",
|
|
202
|
+
assignmentsRaw: optionsWithPolicy.fleetAssignments ?? null,
|
|
203
|
+
codexModel: optionsWithPolicy.fleetCodexModel ?? null
|
|
204
|
+
});
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (fleetAction === "models") {
|
|
208
|
+
const { runFleetModels } = await import("./global/fleet-configure.js");
|
|
209
|
+
await runFleetModels({
|
|
210
|
+
json: optionsWithPolicy.json === true,
|
|
211
|
+
profile: optionsWithPolicy.fleetProfile === true
|
|
212
|
+
});
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const { buildFleetReport, formatFleetText } = await import("./global/observability/fleet-probe.js");
|
|
216
|
+
const { printJson } = await import("./global/json-output.js");
|
|
217
|
+
const report = await buildFleetReport({
|
|
218
|
+
includeVariants: optionsWithPolicy.includeVariants === true
|
|
219
|
+
});
|
|
220
|
+
if (optionsWithPolicy.json) {
|
|
221
|
+
printJson(report);
|
|
222
|
+
} else {
|
|
223
|
+
console.log(formatFleetText(report, {
|
|
224
|
+
verbose: optionsWithPolicy.verbose === true || optionsWithPolicy.includeVariants === true
|
|
225
|
+
}));
|
|
226
|
+
}
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
142
229
|
case "intelligence":
|
|
143
230
|
await runIntelligenceCli(optionsWithPolicy, packageManifest);
|
|
144
231
|
return;
|
|
@@ -285,6 +372,12 @@ async function dispatchComponentsCommand(options, invoke) {
|
|
|
285
372
|
case "verify":
|
|
286
373
|
await runComponentsVerify({ ...options, packageRoot });
|
|
287
374
|
return;
|
|
375
|
+
case "adopt":
|
|
376
|
+
await runComponentsAdopt({ ...options, packageRoot });
|
|
377
|
+
return;
|
|
378
|
+
case "diff":
|
|
379
|
+
await runComponentsDiff({ ...options, packageRoot });
|
|
380
|
+
return;
|
|
288
381
|
case "rollback":
|
|
289
382
|
await runComponentsRollback(options);
|
|
290
383
|
return;
|
|
@@ -363,6 +456,7 @@ export function parseArgs(argv) {
|
|
|
363
456
|
const command = normalizeCommand(rawCommand);
|
|
364
457
|
const options = {
|
|
365
458
|
cwd: process.cwd(),
|
|
459
|
+
cwdExplicit: false,
|
|
366
460
|
scope: null,
|
|
367
461
|
mode: "standard",
|
|
368
462
|
modeExplicit: false,
|
|
@@ -382,6 +476,7 @@ export function parseArgs(argv) {
|
|
|
382
476
|
dryRun: false,
|
|
383
477
|
yes: false,
|
|
384
478
|
confirm: false,
|
|
479
|
+
overwriteConflicts: false,
|
|
385
480
|
preflight: true,
|
|
386
481
|
preflightExplicit: false,
|
|
387
482
|
yesExplicit: false,
|
|
@@ -419,6 +514,18 @@ export function parseArgs(argv) {
|
|
|
419
514
|
confirmDismiss: false,
|
|
420
515
|
graphifyAction: null, graphifyArgs: [], graphifyBudget: null, graphPath: null,
|
|
421
516
|
updatesAction: "check",
|
|
517
|
+
mcpAction: "serve",
|
|
518
|
+
mcpClient: "cursor",
|
|
519
|
+
fleetAction: "show",
|
|
520
|
+
fleetPlatform: null,
|
|
521
|
+
fleetAgent: null,
|
|
522
|
+
fleetPlatforms: null,
|
|
523
|
+
fleetFrom: "profile",
|
|
524
|
+
fleetAssignments: null,
|
|
525
|
+
fleetCodexModel: null,
|
|
526
|
+
fleetProfile: false,
|
|
527
|
+
includeVariants: false,
|
|
528
|
+
verbose: false,
|
|
422
529
|
base: null,
|
|
423
530
|
commit: null,
|
|
424
531
|
staged: false,
|
|
@@ -473,6 +580,8 @@ export function parseArgs(argv) {
|
|
|
473
580
|
|
|
474
581
|
if (command === "graphify") parseGraphifyAction(args, options);
|
|
475
582
|
if (command === "updates") parseUpdatesAction(args, options);
|
|
583
|
+
if (command === "mcp") parseMcpAction(args, options);
|
|
584
|
+
if (command === "fleet") parseFleetAction(args, options);
|
|
476
585
|
|
|
477
586
|
if (command === "help") {
|
|
478
587
|
while (args[0] === "all" || args[0] === "--all") {
|
|
@@ -484,7 +593,10 @@ export function parseArgs(argv) {
|
|
|
484
593
|
for (let index = 0; index < args.length; index += 1) {
|
|
485
594
|
const arg = args[index];
|
|
486
595
|
|
|
487
|
-
if (arg === "--cwd")
|
|
596
|
+
if (arg === "--cwd") {
|
|
597
|
+
options.cwd = resolve(args[++index]);
|
|
598
|
+
options.cwdExplicit = true;
|
|
599
|
+
}
|
|
488
600
|
else if (arg === "--scope") options.scope = parseScope(args[++index]);
|
|
489
601
|
else if (arg.startsWith("--scope=")) options.scope = parseScope(arg.slice("--scope=".length));
|
|
490
602
|
else if (arg === "--mode") {
|
|
@@ -518,8 +630,26 @@ export function parseArgs(argv) {
|
|
|
518
630
|
options.componentsExplicit = true;
|
|
519
631
|
} else if (arg === "--force") options.force = true;
|
|
520
632
|
else if (arg === "--dry-run") options.dryRun = true;
|
|
633
|
+
else if (arg === "--overwrite-conflicts") options.overwriteConflicts = true;
|
|
521
634
|
else if (arg === "--json") options.json = true;
|
|
522
|
-
else if (arg === "--
|
|
635
|
+
else if (arg === "--include-variants") options.includeVariants = true;
|
|
636
|
+
else if (arg === "--platforms") options.fleetPlatforms = args[++index];
|
|
637
|
+
else if (arg.startsWith("--platforms=")) options.fleetPlatforms = arg.slice("--platforms=".length);
|
|
638
|
+
else if (arg === "--from") options.fleetFrom = args[++index];
|
|
639
|
+
else if (arg.startsWith("--from=")) options.fleetFrom = arg.slice("--from=".length);
|
|
640
|
+
else if (arg === "--assignments") options.fleetAssignments = args[++index];
|
|
641
|
+
else if (arg.startsWith("--assignments=")) options.fleetAssignments = arg.slice("--assignments=".length);
|
|
642
|
+
else if (arg === "--codex-model") options.fleetCodexModel = args[++index];
|
|
643
|
+
else if (arg.startsWith("--codex-model=")) options.fleetCodexModel = arg.slice("--codex-model=".length);
|
|
644
|
+
else if (arg === "--profile") options.fleetProfile = true;
|
|
645
|
+
else if (arg === "--verbose") options.verbose = true;
|
|
646
|
+
else if (arg === "--platform") options.fleetPlatform = args[++index];
|
|
647
|
+
else if (arg.startsWith("--platform=")) options.fleetPlatform = arg.slice("--platform=".length);
|
|
648
|
+
else if (arg === "--client") {
|
|
649
|
+
options.mcpClient = args[++index];
|
|
650
|
+
} else if (arg.startsWith("--client=")) {
|
|
651
|
+
options.mcpClient = arg.slice("--client=".length);
|
|
652
|
+
} else if (arg === "--yes" || arg === "-y") {
|
|
523
653
|
options.yes = true;
|
|
524
654
|
options.yesExplicit = true;
|
|
525
655
|
} else if (arg === "--confirm") {
|
|
@@ -651,7 +781,8 @@ function parseComponentsAction(args, options) {
|
|
|
651
781
|
|
|
652
782
|
if (action === "validate") return;
|
|
653
783
|
|
|
654
|
-
if (action === "configure" || action === "verify" || action === "rollback"
|
|
784
|
+
if (action === "configure" || action === "verify" || action === "rollback"
|
|
785
|
+
|| action === "adopt" || action === "diff") {
|
|
655
786
|
const componentId = args[0];
|
|
656
787
|
if (!componentId || componentId.startsWith("-")) {
|
|
657
788
|
throw new Error(
|
|
@@ -662,7 +793,7 @@ function parseComponentsAction(args, options) {
|
|
|
662
793
|
return;
|
|
663
794
|
}
|
|
664
795
|
|
|
665
|
-
throw new Error(`Unknown components action "${action}". Use validate, init, pack, import, configure, verify, or rollback.`);
|
|
796
|
+
throw new Error(`Unknown components action "${action}". Use validate, init, pack, import, configure, verify, adopt, diff, or rollback.`);
|
|
666
797
|
}
|
|
667
798
|
|
|
668
799
|
function parsePolicyAction(args, options) {
|
|
@@ -842,6 +973,36 @@ function parseUpdatesAction(args, options) {
|
|
|
842
973
|
options.updatesAction = "check";
|
|
843
974
|
}
|
|
844
975
|
|
|
976
|
+
function parseMcpAction(args, options) {
|
|
977
|
+
const action = args[0];
|
|
978
|
+
if (!action || action.startsWith("-")) {
|
|
979
|
+
options.mcpAction = "serve";
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
if (!new Set(["serve", "install"]).has(action)) {
|
|
983
|
+
throw new Error(
|
|
984
|
+
`Unknown mcp action "${action}". Use: ${formatCliCommand("mcp")} or ${formatCliCommand("mcp install [--yes]")}`
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
args.shift();
|
|
988
|
+
options.mcpAction = action;
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
function parseFleetAction(args, options) {
|
|
992
|
+
const action = args[0];
|
|
993
|
+
if (!action || action.startsWith("-")) {
|
|
994
|
+
options.fleetAction = "show";
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
if (!new Set(["show", "set", "activity", "configure", "models"]).has(action)) {
|
|
998
|
+
throw new Error(
|
|
999
|
+
`Unknown fleet action "${action}". Use: ${formatCliCommand("fleet")}, ${formatCliCommand("fleet models")}, ${formatCliCommand("fleet configure")}, or ${formatCliCommand("fleet set --platform opencode --agent <id> --model <id>")}`
|
|
1000
|
+
);
|
|
1001
|
+
}
|
|
1002
|
+
args.shift();
|
|
1003
|
+
options.fleetAction = action === "activity" ? "show" : action;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
845
1006
|
function parsePathList(value) {
|
|
846
1007
|
if (!value) return [];
|
|
847
1008
|
return [...new Set(
|
|
@@ -889,6 +1050,9 @@ function normalizeCommand(command) {
|
|
|
889
1050
|
if (command === "alerts") return "alerts";
|
|
890
1051
|
if (command === "graphify") return "graphify";
|
|
891
1052
|
if (command === "mcp") return "mcp";
|
|
1053
|
+
if (command === "connections") return "connections";
|
|
1054
|
+
if (command === "next") return "next";
|
|
1055
|
+
if (command === "fleet") return "fleet";
|
|
892
1056
|
if (command === "intelligence" || command === "intel") return "intelligence";
|
|
893
1057
|
if (command === "setup") return "setup";
|
|
894
1058
|
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,19 @@ 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} fleet [--json] [--verbose] [--include-variants]
|
|
120
|
+
${cli} fleet models [--profile] [--json]
|
|
121
|
+
${cli} fleet configure [--platforms claude,opencode,cursor|codex] [--from profile|gentle] [--codex-model <id>] [--assignments a=b,...] [--yes] [--json]
|
|
122
|
+
${cli} fleet set --platform opencode|claude|codex --agent <id> --model <id> [--yes] [--json]
|
|
115
123
|
${cli} mcp
|
|
124
|
+
${cli} mcp install [--yes] [--json] [--client cursor]
|
|
116
125
|
${cli} install --scope=workspace [--mode minimal|standard|enterprise] (opt-in/legacy)
|
|
117
126
|
${cli} init [--mode minimal|standard|enterprise] (workspace alias)
|
|
118
127
|
|
|
@@ -157,12 +166,20 @@ Commands:
|
|
|
157
166
|
policy View or edit local operation preferences under ~/.harness/policy.json.
|
|
158
167
|
report Read-only diagnostics bundle: status, policy, adapters, diff, history.
|
|
159
168
|
components List, validate, scaffold, pack, import, or configure integrations (Engram, SDD).
|
|
169
|
+
connections Companion chips + MCP registration (IDE panel).
|
|
170
|
+
next Selected work snapshot + integration state (panel contract).
|
|
171
|
+
fleet Declared fleet floor + working activity; configure/set models across CLIs.
|
|
172
|
+
fleet models [--profile] available vs enabled per tool
|
|
173
|
+
fleet configure one plan for Claude+OpenCode+Cursor (profile)
|
|
174
|
+
fleet configure --codex-model <id> Codex only (single-default)
|
|
175
|
+
fleet set --platform opencode|claude|codex --agent <id> --model <id> [--yes]
|
|
176
|
+
mcp Serve or install MCP for agents (mcp install writes entry + snapshot rule).
|
|
160
177
|
uninstall Remove managed sections and global state. Backups are preserved.
|
|
161
178
|
init Alias for install --scope=workspace (legacy).
|
|
162
179
|
|
|
163
180
|
JSON output (--json on supported commands):
|
|
164
181
|
status, sync, doctor, adapters, explain, diff, history, history last,
|
|
165
|
-
policy (show/set/reset), report, monitor
|
|
182
|
+
policy (show/set/reset), report, monitor, connections, fleet
|
|
166
183
|
Human text remains the default. See docs/cli-reference.md for examples and field notes.
|
|
167
184
|
|
|
168
185
|
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) {
|