sandstream-kit 1.8.0 → 1.11.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/dist/cli.js +80 -5
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +10 -0
- package/dist/config.js +8 -1
- package/dist/config.js.map +1 -1
- package/dist/fix.js +3 -1
- package/dist/fix.js.map +1 -1
- package/dist/heal.d.ts +7 -0
- package/dist/heal.js +45 -5
- package/dist/heal.js.map +1 -1
- package/dist/install.d.ts +15 -2
- package/dist/install.js +18 -2
- package/dist/install.js.map +1 -1
- package/dist/memory/hook.js +32 -4
- package/dist/memory/hook.js.map +1 -1
- package/dist/triage-gate.d.ts +51 -0
- package/dist/triage-gate.js +96 -0
- package/dist/triage-gate.js.map +1 -0
- package/dist/triage.d.ts +7 -0
- package/dist/triage.js +31 -5
- package/dist/triage.js.map +1 -1
- package/dist/update-check.d.ts +9 -0
- package/dist/update-check.js +35 -2
- package/dist/update-check.js.map +1 -1
- package/package.json +3 -2
- package/skills/triage/SKILL.md +42 -0
- package/skills/triage/scripts/triage.py +300 -0
package/dist/cli.js
CHANGED
|
@@ -87,7 +87,10 @@ async function cmdHeal() {
|
|
|
87
87
|
console.log(`${c.bold}${c.cyan}kit heal${c.reset}${dryRun ? `${c.dim} (dry-run)${c.reset}` : ""}`);
|
|
88
88
|
console.log(`${c.dim}${"─".repeat(50)}${c.reset}\n`);
|
|
89
89
|
const { runHeal } = await import("./heal.js");
|
|
90
|
-
|
|
90
|
+
// Progress goes to stderr: live feedback for a human watching, without
|
|
91
|
+
// polluting the machine-readable proposals on stdout (--agent).
|
|
92
|
+
const res = await runHeal({ dryRun, onProgress: (m) => console.error(`${c.dim}${m}${c.reset}`) });
|
|
93
|
+
console.log();
|
|
91
94
|
if (dryRun) {
|
|
92
95
|
if (res.plannedSafe.length > 0) {
|
|
93
96
|
console.log(`${c.bold}Would auto-fix (safe):${c.reset}`);
|
|
@@ -322,6 +325,25 @@ async function cmdCheck() {
|
|
|
322
325
|
console.log();
|
|
323
326
|
}
|
|
324
327
|
printSummary(toolResults, serviceResults, secretResults.keys, securityResults);
|
|
328
|
+
// Surface a stale kit (a newer published version) as a warn — a stale CLI
|
|
329
|
+
// can carry already-fixed bugs. Gated by [update].check; checkForUpdate
|
|
330
|
+
// also self-skips in CI and with KIT_NO_UPDATE_CHECK=1, and returns null
|
|
331
|
+
// when already on latest or the check fails.
|
|
332
|
+
if (config.update?.check !== false) {
|
|
333
|
+
const { checkForUpdate } = await import("./update-check.js");
|
|
334
|
+
const u = await checkForUpdate(KIT_VERSION);
|
|
335
|
+
if (u) {
|
|
336
|
+
if (config.update?.auto === true) {
|
|
337
|
+
// Opt-in auto-update — still WATERTIGHT: selfUpgrade triages kit's own
|
|
338
|
+
// package and installs ONLY on a triage PASS. Never installs on fail.
|
|
339
|
+
console.log(`${c.yellow}! kit ${u.current} → ${u.latest} — auto-update on, triaging before install…${c.reset}`);
|
|
340
|
+
await selfUpgrade();
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
console.log(`${c.yellow}! kit ${u.current} → ${u.latest} available${c.reset} ${c.dim}— run ${c.reset}${c.bold}kit upgrade --self${c.reset}${c.dim} (triages before installing)${c.reset}\n`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
325
347
|
return allOk;
|
|
326
348
|
});
|
|
327
349
|
}
|
|
@@ -425,27 +447,46 @@ async function cmdInstall() {
|
|
|
425
447
|
return true;
|
|
426
448
|
}
|
|
427
449
|
const toolsConfig = config.tools;
|
|
450
|
+
// WATERTIGHT: kit triages every third-party tool before installing it. The
|
|
451
|
+
// `--no-triage` override is a deliberate, audited security action — it must
|
|
452
|
+
// hold a one-shot elevation, or the install is refused.
|
|
453
|
+
let skipTriage = false;
|
|
454
|
+
if (hasFlag(process.argv, "--no-triage")) {
|
|
455
|
+
const elev = await consumeElevation("tools.install.no-triage");
|
|
456
|
+
if (!elev.ok) {
|
|
457
|
+
console.error(`${c.red}✗ --no-triage refused: ${elev.reason}${c.reset}`);
|
|
458
|
+
console.error(`${c.dim}Run 'kit auth elevate --scope tools.install.no-triage' first, or drop --no-triage to let triage run.${c.reset}`);
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
skipTriage = true;
|
|
462
|
+
console.log(`${c.yellow}⚠ --no-triage: triage gate bypassed (elevation consumed, audit-logged)${c.reset}`);
|
|
463
|
+
}
|
|
428
464
|
console.log(`${c.bold}${c.cyan}Installing tools via mise...${c.reset}\n`);
|
|
429
465
|
return await withGovernance(config, {
|
|
430
466
|
operation: "tools.install",
|
|
431
467
|
operationType: "write",
|
|
432
468
|
metadata: {
|
|
433
469
|
tools: Object.keys(toolsConfig),
|
|
470
|
+
skipTriage,
|
|
434
471
|
},
|
|
435
472
|
}, async () => {
|
|
436
|
-
const results = await installTools(toolsConfig);
|
|
473
|
+
const results = await installTools(toolsConfig, undefined, { skipTriage });
|
|
437
474
|
let allOk = true;
|
|
438
475
|
for (const r of results) {
|
|
439
476
|
const icon = r.action === "failed"
|
|
440
477
|
? `${c.red}✗${c.reset}`
|
|
441
|
-
:
|
|
478
|
+
: r.action === "blocked"
|
|
479
|
+
? `${c.yellow}⛔${c.reset}`
|
|
480
|
+
: `${c.green}✓${c.reset}`;
|
|
442
481
|
const label = r.action === "already_ok"
|
|
443
482
|
? `${c.dim}already installed${c.reset}`
|
|
444
483
|
: r.action === "installed"
|
|
445
484
|
? `${c.green}installed${c.reset}`
|
|
446
|
-
:
|
|
485
|
+
: r.action === "blocked"
|
|
486
|
+
? `${c.yellow}blocked by triage${c.reset}`
|
|
487
|
+
: `${c.red}failed${c.reset}`;
|
|
447
488
|
console.log(` ${icon} ${r.name} ${label} ${c.dim}${r.detail}${c.reset}`);
|
|
448
|
-
if (r.action === "failed")
|
|
489
|
+
if (r.action === "failed" || r.action === "blocked")
|
|
449
490
|
allOk = false;
|
|
450
491
|
}
|
|
451
492
|
console.log();
|
|
@@ -1033,9 +1074,43 @@ async function cmdGovernance() {
|
|
|
1033
1074
|
console.log();
|
|
1034
1075
|
return true;
|
|
1035
1076
|
}
|
|
1077
|
+
/**
|
|
1078
|
+
* Governed self-upgrade: kit triages its OWN npm package before installing a new
|
|
1079
|
+
* version of itself. WATERTIGHT — an untriaged kit is never installed; offline /
|
|
1080
|
+
* triage-unavailable → blocked (fail-closed). The raw `npm i -g sandstream-kit`
|
|
1081
|
+
* is still available to the user, but that path is outside kit's governance.
|
|
1082
|
+
*/
|
|
1083
|
+
async function selfUpgrade() {
|
|
1084
|
+
const { gateInstall } = await import("./triage-gate.js");
|
|
1085
|
+
console.log(`${c.dim}Triaging sandstream-kit before upgrading itself…${c.reset}`);
|
|
1086
|
+
const verdict = await gateInstall("npm:sandstream-kit");
|
|
1087
|
+
if (verdict.decision === "blocked") {
|
|
1088
|
+
console.error(`${c.red}✗ self-upgrade blocked: ${verdict.reason}${c.reset}`);
|
|
1089
|
+
console.error(`${c.dim}kit will not install an untriaged version of itself. Get online with the triage skill installed, then retry.${c.reset}`);
|
|
1090
|
+
return false;
|
|
1091
|
+
}
|
|
1092
|
+
console.log(`${c.green}✓${c.reset} ${verdict.reason} — upgrading…\n`);
|
|
1093
|
+
try {
|
|
1094
|
+
const { exec } = await import("./utils/exec.js");
|
|
1095
|
+
await exec("npm", ["install", "-g", "sandstream-kit@latest"], {
|
|
1096
|
+
timeout: 180_000,
|
|
1097
|
+
env: { ...process.env },
|
|
1098
|
+
});
|
|
1099
|
+
console.log(`\n${c.green}${c.bold}✓ kit upgraded${c.reset} — run ${c.bold}kit --version${c.reset} to confirm.`);
|
|
1100
|
+
return true;
|
|
1101
|
+
}
|
|
1102
|
+
catch (err) {
|
|
1103
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1104
|
+
console.error(`${c.red}✗ npm install failed: ${msg.split("\n")[0]}${c.reset}`);
|
|
1105
|
+
return false;
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1036
1108
|
async function cmdUpgrade() {
|
|
1037
1109
|
console.log(`${c.bold}${c.cyan}kit upgrade${c.reset}`);
|
|
1038
1110
|
console.log(`${c.dim}${"─".repeat(50)}${c.reset}\n`);
|
|
1111
|
+
if (hasFlag(process.argv, "--self")) {
|
|
1112
|
+
return await selfUpgrade();
|
|
1113
|
+
}
|
|
1039
1114
|
const config = await loadConfig(resolveConfigPath());
|
|
1040
1115
|
// Update skills lock
|
|
1041
1116
|
const skills = {};
|