harnessed 3.9.16 → 3.9.18
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.mjs +234 -93
- package/dist/cli.mjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/messages/en.json +16 -2
- package/package.json +1 -1
- package/workflows/README.md +2 -2
- package/workflows/SCHEMA.md +24 -58
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawnSync, spawn, execSync } from 'child_process';
|
|
3
3
|
import { existsSync, mkdirSync, renameSync, writeFileSync, readFileSync, readdirSync } from 'fs';
|
|
4
|
-
import { join, dirname, resolve, relative } from 'path';
|
|
4
|
+
import { join, dirname, resolve, sep, relative } from 'path';
|
|
5
5
|
import { homedir } from 'os';
|
|
6
6
|
import { readFile, readdir, unlink, writeFile, stat, rm, cp, mkdir, access, rename } from 'fs/promises';
|
|
7
7
|
import { Type } from '@sinclair/typebox';
|
|
@@ -287,25 +287,25 @@ var init_schemaVersion = __esm({
|
|
|
287
287
|
routeDecisionLog: "harnessed.route-decision-log.v1",
|
|
288
288
|
checkpoint: "harnessed.checkpoint.v1",
|
|
289
289
|
currentWorkflow: "harnessed.current-workflow.v1",
|
|
290
|
-
// ← Phase 3.1 W1 T1.1 ADD
|
|
290
|
+
// ← Phase 3.1 W1 T1.1 ADD (D-02 KARPATHY 3-state)
|
|
291
291
|
config: "harnessed.config.v1",
|
|
292
|
-
// ← Phase 3.2 W1 T1.1 ADD
|
|
292
|
+
// ← Phase 3.2 W1 T1.1 ADD (D-01 PROBE gstack_prefix store)
|
|
293
293
|
governance: "harnessed.governance.v1",
|
|
294
|
-
// ← Phase 3.2 W1 T1.1 ADD
|
|
294
|
+
// ← Phase 3.2 W1 T1.1 ADD (D-04 PUSH veto status)
|
|
295
295
|
aliases: "harnessed.aliases.v1",
|
|
296
|
-
// ← Phase 3.3 W1 T1.1 ADD
|
|
296
|
+
// ← Phase 3.3 W1 T1.1 ADD (D-01 RICH)
|
|
297
297
|
knownGood: "harnessed.known-good.v1",
|
|
298
|
-
// ← Phase 3.3 W1 T1.1 ADD
|
|
298
|
+
// ← Phase 3.3 W1 T1.1 ADD (D-03 YAML manifest)
|
|
299
299
|
capabilities: "harnessed.capabilities.v1",
|
|
300
|
-
// ← Phase v2.0-2.3 W0 ADD
|
|
300
|
+
// ← Phase v2.0-2.3 W0 ADD (R20.2 flat yaml capabilities manifest validate)
|
|
301
301
|
judgment: "harnessed.judgment.v1",
|
|
302
|
-
// ← Phase v2.0-2.3 W0 ADD
|
|
302
|
+
// ← Phase v2.0-2.3 W0 ADD (R20.4 multi-file judgments validate)
|
|
303
303
|
workflow: "harnessed.workflow.v2",
|
|
304
|
-
// ← Phase v2.0-2.4 W0 T2.4.W0.1 ADD
|
|
304
|
+
// ← Phase v2.0-2.4 W0 T2.4.W0.1 ADD (R20.1+R20.2+R20.9 workflow.yaml v2)
|
|
305
305
|
workflow_v3: "harnessed.workflow.v3",
|
|
306
|
-
// ← Phase v3.0-3.3 W0 T3.3.W0.11 ADD
|
|
306
|
+
// ← Phase v3.0-3.3 W0 T3.3.W0.11 ADD (D-09 disciplines_applied + D-05 tools_available + master delegates_to per Pattern A B.1 LOCK)
|
|
307
307
|
discipline: "harnessed.discipline.v1"
|
|
308
|
-
// ← Phase v3.0-3.3 W0 T3.3.W0.11 ADD
|
|
308
|
+
// ← Phase v3.0-3.3 W0 T3.3.W0.11 ADD (D-09 L0 Discipline Substrate, sister judgment.v1 multi-file pattern)
|
|
309
309
|
};
|
|
310
310
|
Type.Union([
|
|
311
311
|
Type.Literal(SCHEMA_VERSIONS.routingSnapshot),
|
|
@@ -316,25 +316,25 @@ var init_schemaVersion = __esm({
|
|
|
316
316
|
Type.Literal(SCHEMA_VERSIONS.routeDecisionLog),
|
|
317
317
|
Type.Literal(SCHEMA_VERSIONS.checkpoint),
|
|
318
318
|
Type.Literal(SCHEMA_VERSIONS.currentWorkflow),
|
|
319
|
-
// ← Phase 3.1 W1 T1.1 ADD
|
|
319
|
+
// ← Phase 3.1 W1 T1.1 ADD
|
|
320
320
|
Type.Literal(SCHEMA_VERSIONS.config),
|
|
321
|
-
// ← Phase 3.2 W1 T1.1 ADD
|
|
321
|
+
// ← Phase 3.2 W1 T1.1 ADD
|
|
322
322
|
Type.Literal(SCHEMA_VERSIONS.governance),
|
|
323
|
-
// ← Phase 3.2 W1 T1.1 ADD
|
|
323
|
+
// ← Phase 3.2 W1 T1.1 ADD
|
|
324
324
|
Type.Literal(SCHEMA_VERSIONS.aliases),
|
|
325
|
-
// ← Phase 3.3 W1 T1.1 ADD
|
|
325
|
+
// ← Phase 3.3 W1 T1.1 ADD
|
|
326
326
|
Type.Literal(SCHEMA_VERSIONS.knownGood),
|
|
327
|
-
// ← Phase 3.3 W1 T1.1 ADD
|
|
327
|
+
// ← Phase 3.3 W1 T1.1 ADD
|
|
328
328
|
Type.Literal(SCHEMA_VERSIONS.capabilities),
|
|
329
|
-
// ← Phase v2.0-2.3 W0 ADD
|
|
329
|
+
// ← Phase v2.0-2.3 W0 ADD
|
|
330
330
|
Type.Literal(SCHEMA_VERSIONS.judgment),
|
|
331
|
-
// ← Phase v2.0-2.3 W0 ADD
|
|
331
|
+
// ← Phase v2.0-2.3 W0 ADD
|
|
332
332
|
Type.Literal(SCHEMA_VERSIONS.workflow),
|
|
333
|
-
// ← Phase v2.0-2.4 W0 T2.4.W0.1 ADD
|
|
333
|
+
// ← Phase v2.0-2.4 W0 T2.4.W0.1 ADD (first .v2 in union)
|
|
334
334
|
Type.Literal(SCHEMA_VERSIONS.workflow_v3),
|
|
335
|
-
// ← Phase v3.0-3.3 W0 T3.3.W0.11 ADD
|
|
335
|
+
// ← Phase v3.0-3.3 W0 T3.3.W0.11 ADD (first .v3 in union)
|
|
336
336
|
Type.Literal(SCHEMA_VERSIONS.discipline)
|
|
337
|
-
// ← Phase v3.0-3.3 W0 T3.3.W0.11 ADD
|
|
337
|
+
// ← Phase v3.0-3.3 W0 T3.3.W0.11 ADD
|
|
338
338
|
]);
|
|
339
339
|
}
|
|
340
340
|
});
|
|
@@ -1218,7 +1218,7 @@ var init_auto_install = __esm({
|
|
|
1218
1218
|
|
|
1219
1219
|
// package.json
|
|
1220
1220
|
var package_default = {
|
|
1221
|
-
version: "3.9.
|
|
1221
|
+
version: "3.9.18"};
|
|
1222
1222
|
|
|
1223
1223
|
// src/manifest/errors.ts
|
|
1224
1224
|
function instancePathToKeyPath(instancePath) {
|
|
@@ -2057,9 +2057,9 @@ function redactRecord(r) {
|
|
|
2057
2057
|
}
|
|
2058
2058
|
function renderHumanTable(records) {
|
|
2059
2059
|
const header = `${"ts".padEnd(19)} | ${"phase".padEnd(6)} | ${"category".padEnd(11)} | ${"matched_rule_id".padEnd(20)} | outcome`;
|
|
2060
|
-
const
|
|
2060
|
+
const sep2 = `${"-".repeat(19)}-+-${"-".repeat(6)}-+-${"-".repeat(11)}-+-${"-".repeat(20)}-+--------`;
|
|
2061
2061
|
console.log(header);
|
|
2062
|
-
console.log(
|
|
2062
|
+
console.log(sep2);
|
|
2063
2063
|
for (const r of records) {
|
|
2064
2064
|
const ts = r.ts.slice(0, 19);
|
|
2065
2065
|
const phase = r.phase.padEnd(6);
|
|
@@ -2069,7 +2069,7 @@ function renderHumanTable(records) {
|
|
|
2069
2069
|
}
|
|
2070
2070
|
}
|
|
2071
2071
|
function pipeToJq(filterExpr, lines) {
|
|
2072
|
-
return new Promise((
|
|
2072
|
+
return new Promise((resolve14, reject) => {
|
|
2073
2073
|
const child = spawn("jq", [filterExpr], {
|
|
2074
2074
|
stdio: ["pipe", "inherit", "inherit"],
|
|
2075
2075
|
windowsHide: true
|
|
@@ -2078,12 +2078,12 @@ function pipeToJq(filterExpr, lines) {
|
|
|
2078
2078
|
const e = err2;
|
|
2079
2079
|
if (e.code === "ENOENT") {
|
|
2080
2080
|
console.error(t("audit_log.jq_missing"));
|
|
2081
|
-
|
|
2081
|
+
resolve14(1);
|
|
2082
2082
|
} else {
|
|
2083
2083
|
reject(err2);
|
|
2084
2084
|
}
|
|
2085
2085
|
});
|
|
2086
|
-
child.on("close", (code) =>
|
|
2086
|
+
child.on("close", (code) => resolve14(code ?? 0));
|
|
2087
2087
|
child.stdin.write(lines.join("\n"));
|
|
2088
2088
|
child.stdin.end();
|
|
2089
2089
|
});
|
|
@@ -2740,10 +2740,10 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
|
|
|
2740
2740
|
child.stderr?.setEncoding("utf8").on("data", (chunk) => {
|
|
2741
2741
|
stderr += chunk;
|
|
2742
2742
|
});
|
|
2743
|
-
return await new Promise((
|
|
2743
|
+
return await new Promise((resolve14) => {
|
|
2744
2744
|
const timer = setTimeout(() => {
|
|
2745
2745
|
child.kill("SIGKILL");
|
|
2746
|
-
|
|
2746
|
+
resolve14({
|
|
2747
2747
|
ok: false,
|
|
2748
2748
|
phase: "spawn",
|
|
2749
2749
|
error: {
|
|
@@ -2758,7 +2758,7 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
|
|
|
2758
2758
|
}, effectiveTimeoutMs);
|
|
2759
2759
|
child.on("error", (err2) => {
|
|
2760
2760
|
clearTimeout(timer);
|
|
2761
|
-
|
|
2761
|
+
resolve14({
|
|
2762
2762
|
ok: false,
|
|
2763
2763
|
phase: "spawn",
|
|
2764
2764
|
error: {
|
|
@@ -2773,7 +2773,7 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
|
|
|
2773
2773
|
});
|
|
2774
2774
|
child.on("close", (code) => {
|
|
2775
2775
|
clearTimeout(timer);
|
|
2776
|
-
|
|
2776
|
+
resolve14({ ok: true, exitCode: code ?? -1, stdout: stdout2, stderr });
|
|
2777
2777
|
});
|
|
2778
2778
|
});
|
|
2779
2779
|
}
|
|
@@ -2871,7 +2871,7 @@ async function isAlreadyInstalled(ctx, opts = {}) {
|
|
|
2871
2871
|
// src/installers/ccPluginMarketplace.ts
|
|
2872
2872
|
init_readClaudeConfig();
|
|
2873
2873
|
function runArgs(claudeArgs, cwd, timeoutMs = 15e3) {
|
|
2874
|
-
return new Promise((
|
|
2874
|
+
return new Promise((resolve14) => {
|
|
2875
2875
|
const isWin = process.platform === "win32";
|
|
2876
2876
|
const child = isWin ? spawn("cmd.exe", ["/c", "claude", ...claudeArgs], { cwd, windowsHide: true }) : spawn("claude", claudeArgs, { cwd, shell: false });
|
|
2877
2877
|
let stderr = "";
|
|
@@ -2880,15 +2880,15 @@ function runArgs(claudeArgs, cwd, timeoutMs = 15e3) {
|
|
|
2880
2880
|
});
|
|
2881
2881
|
const timer = setTimeout(() => {
|
|
2882
2882
|
child.kill("SIGKILL");
|
|
2883
|
-
|
|
2883
|
+
resolve14({ exitCode: -1, stderr: `${stderr}[timeout after ${timeoutMs}ms]` });
|
|
2884
2884
|
}, timeoutMs);
|
|
2885
2885
|
child.on("error", (e) => {
|
|
2886
2886
|
clearTimeout(timer);
|
|
2887
|
-
|
|
2887
|
+
resolve14({ exitCode: -1, stderr: `${stderr}${e.message}` });
|
|
2888
2888
|
});
|
|
2889
2889
|
child.on("close", (code) => {
|
|
2890
2890
|
clearTimeout(timer);
|
|
2891
|
-
|
|
2891
|
+
resolve14({ exitCode: code ?? -1, stderr });
|
|
2892
2892
|
});
|
|
2893
2893
|
});
|
|
2894
2894
|
}
|
|
@@ -3034,7 +3034,7 @@ ${newEntry}
|
|
|
3034
3034
|
return { ok: true, backupId: bk.backupId, appliedFiles: [settingsFile] };
|
|
3035
3035
|
};
|
|
3036
3036
|
function gitRevParseHead(cwd, timeoutMs = 1e4) {
|
|
3037
|
-
return new Promise((
|
|
3037
|
+
return new Promise((resolve14) => {
|
|
3038
3038
|
const isWin = process.platform === "win32";
|
|
3039
3039
|
const child = isWin ? spawn("cmd.exe", ["/c", "git", "rev-parse", "HEAD"], { cwd, windowsHide: true }) : spawn("git", ["rev-parse", "HEAD"], { cwd, shell: false });
|
|
3040
3040
|
let stdout2 = "";
|
|
@@ -3043,15 +3043,15 @@ function gitRevParseHead(cwd, timeoutMs = 1e4) {
|
|
|
3043
3043
|
});
|
|
3044
3044
|
const timer = setTimeout(() => {
|
|
3045
3045
|
child.kill("SIGKILL");
|
|
3046
|
-
|
|
3046
|
+
resolve14({ sha: "", exit: -1 });
|
|
3047
3047
|
}, timeoutMs);
|
|
3048
3048
|
child.on("error", () => {
|
|
3049
3049
|
clearTimeout(timer);
|
|
3050
|
-
|
|
3050
|
+
resolve14({ sha: "", exit: -1 });
|
|
3051
3051
|
});
|
|
3052
3052
|
child.on("close", (code) => {
|
|
3053
3053
|
clearTimeout(timer);
|
|
3054
|
-
|
|
3054
|
+
resolve14({ sha: stdout2.trim(), exit: code ?? -1 });
|
|
3055
3055
|
});
|
|
3056
3056
|
});
|
|
3057
3057
|
}
|
|
@@ -3608,13 +3608,6 @@ var installNpmCli = async (ctx) => {
|
|
|
3608
3608
|
await updateInstalled(ctx.cwd, ctx.manifest.metadata.name, install.npm_version, "");
|
|
3609
3609
|
return { ok: true, backupId: bk.backupId, appliedFiles: [] };
|
|
3610
3610
|
};
|
|
3611
|
-
function extractSkillName2(cmd, fallback) {
|
|
3612
|
-
const m = cmd.match(/\bskills(?:@\S+)?\s+add\s+(\S+)/i);
|
|
3613
|
-
if (!m || m[1] === void 0) return fallback;
|
|
3614
|
-
const ref = m[1];
|
|
3615
|
-
const seg = ref.split("/");
|
|
3616
|
-
return seg[seg.length - 1] ?? fallback;
|
|
3617
|
-
}
|
|
3618
3611
|
var installNpxSkillInstaller = async (ctx) => {
|
|
3619
3612
|
const install = ctx.manifest.spec.install;
|
|
3620
3613
|
if (install.method !== "npx-skill-installer") {
|
|
@@ -3655,7 +3648,7 @@ var installNpxSkillInstaller = async (ctx) => {
|
|
|
3655
3648
|
};
|
|
3656
3649
|
}
|
|
3657
3650
|
const name = ctx.manifest.metadata.name;
|
|
3658
|
-
const skillSegment =
|
|
3651
|
+
const skillSegment = extractSkillName(install.cmd, name);
|
|
3659
3652
|
const skillDir = join(homedir(), ".claude", "skills", skillSegment);
|
|
3660
3653
|
const skillMdPath = join(skillDir, "SKILL.md");
|
|
3661
3654
|
const plan = {
|
|
@@ -5455,8 +5448,10 @@ function registerRun(program2) {
|
|
|
5455
5448
|
`\u2139 user-override detected: ${matchedTriggers.length} trigger(s) forced fires=true via keyword match (${matchedTriggers.join(", ")})`
|
|
5456
5449
|
);
|
|
5457
5450
|
}
|
|
5451
|
+
const stage = name.includes("-") ? name.split("-")[0] ?? "" : name;
|
|
5458
5452
|
const gateContext = {
|
|
5459
5453
|
task,
|
|
5454
|
+
phase: { stage, is_critical_module: true },
|
|
5460
5455
|
...raw.model ? { modelOverride: raw.model } : {},
|
|
5461
5456
|
...raw.maxIterations ? { maxIterations: raw.maxIterations } : {},
|
|
5462
5457
|
...raw.staged ? { staged: true } : {},
|
|
@@ -6036,11 +6031,7 @@ async function renderAllSkills(skillNames, skillsBase, workflowsDir, homedirOver
|
|
|
6036
6031
|
return { results, aggregatedWarnings: [...warningSet] };
|
|
6037
6032
|
}
|
|
6038
6033
|
init_checkAgentTeams();
|
|
6039
|
-
var FLAT_LEGACY_KEEP = /* @__PURE__ */ new Set([
|
|
6040
|
-
"research",
|
|
6041
|
-
"retro",
|
|
6042
|
-
"auto"
|
|
6043
|
-
]);
|
|
6034
|
+
var FLAT_LEGACY_KEEP = /* @__PURE__ */ new Set(["research", "retro", "auto"]);
|
|
6044
6035
|
var FLAT_TOP_LEVEL_MASTERS = /* @__PURE__ */ new Set(["auto"]);
|
|
6045
6036
|
var NON_WORKFLOW_DIRS = /* @__PURE__ */ new Set(["disciplines", "judgments"]);
|
|
6046
6037
|
async function scanWorkflowsNested(workflowsDir, entries) {
|
|
@@ -6271,15 +6262,16 @@ function registerSetup(program2) {
|
|
|
6271
6262
|
const writtenCount = cmdResult.results.filter((r) => r.written).length;
|
|
6272
6263
|
const skippedCount = cmdResult.results.filter((r) => !r.written && r.warning).length;
|
|
6273
6264
|
if (writtenCount > 0 || skippedCount > 0) {
|
|
6274
|
-
console.log(
|
|
6275
|
-
` generated ${writtenCount} commands/<x>.md file(s) (${skippedCount} skipped)`
|
|
6276
|
-
);
|
|
6265
|
+
console.log(` generated ${writtenCount} commands/<x>.md file(s) (${skippedCount} skipped)`);
|
|
6277
6266
|
}
|
|
6278
6267
|
await enableAgentTeamsInSettings();
|
|
6279
6268
|
await enableUserLangInSettings(raw.userLang);
|
|
6280
6269
|
const manifestPaths = await listBaseManifests2(pkgRoot);
|
|
6281
6270
|
const forceFirstPass = raw.updateInstalled === true;
|
|
6282
|
-
const b = await runStepBInstall(manifestPaths, {
|
|
6271
|
+
const b = await runStepBInstall(manifestPaths, {
|
|
6272
|
+
updateInstalled: forceFirstPass,
|
|
6273
|
+
quiet: true
|
|
6274
|
+
});
|
|
6283
6275
|
const stepBMs = (b.elapsedMs / 1e3).toFixed(1);
|
|
6284
6276
|
console.log(
|
|
6285
6277
|
t("setup.step_b_complete", {
|
|
@@ -6291,8 +6283,7 @@ function registerSetup(program2) {
|
|
|
6291
6283
|
})
|
|
6292
6284
|
);
|
|
6293
6285
|
for (const n of b.installed) console.log(` [B] installed ${n}`);
|
|
6294
|
-
for (const n of b.alreadyInstalled)
|
|
6295
|
-
console.log(` [B] already-installed ${n}`);
|
|
6286
|
+
for (const n of b.alreadyInstalled) console.log(` [B] already-installed ${n}`);
|
|
6296
6287
|
for (const s of b.skipped) console.log(` [B] skipped ${s.name} \u2014 ${s.reason}`);
|
|
6297
6288
|
for (const n of b.failed) console.error(` [B] failed ${n}`);
|
|
6298
6289
|
if (!forceFirstPass && !dryRun && raw.nonInteractive !== true && b.alreadyInstalled.length > 0) {
|
|
@@ -6382,6 +6373,7 @@ function registerStatus(program2) {
|
|
|
6382
6373
|
}
|
|
6383
6374
|
});
|
|
6384
6375
|
}
|
|
6376
|
+
init_harnessedRoot();
|
|
6385
6377
|
init_path_guard();
|
|
6386
6378
|
|
|
6387
6379
|
// src/uninstallers/lib/runOrPreview.ts
|
|
@@ -6567,7 +6559,7 @@ var uninstallNpmCli = async (ctx) => {
|
|
|
6567
6559
|
const m = install.cmd.match(/npm\s+(?:install|i)\s+(?:-g\s+)?(\S+)/);
|
|
6568
6560
|
const pkg = m?.[1] ?? ctx.manifest.metadata.upstream.source;
|
|
6569
6561
|
const isWin = process.platform === "win32";
|
|
6570
|
-
const result = await new Promise((
|
|
6562
|
+
const result = await new Promise((resolve14) => {
|
|
6571
6563
|
const child = isWin ? spawn("cmd.exe", ["/c", "npm", "uninstall", "-g", pkg], { windowsHide: true }) : spawn("npm", ["uninstall", "-g", pkg], { shell: false });
|
|
6572
6564
|
let stderr = "";
|
|
6573
6565
|
child.stderr?.setEncoding("utf8").on("data", (c) => {
|
|
@@ -6575,15 +6567,15 @@ var uninstallNpmCli = async (ctx) => {
|
|
|
6575
6567
|
});
|
|
6576
6568
|
const timer = setTimeout(() => {
|
|
6577
6569
|
child.kill("SIGKILL");
|
|
6578
|
-
|
|
6570
|
+
resolve14({ exitCode: -1, stderr: `${stderr}[timeout]` });
|
|
6579
6571
|
}, 3e4);
|
|
6580
6572
|
child.on("error", (e) => {
|
|
6581
6573
|
clearTimeout(timer);
|
|
6582
|
-
|
|
6574
|
+
resolve14({ exitCode: -1, stderr: e.message });
|
|
6583
6575
|
});
|
|
6584
6576
|
child.on("close", (code) => {
|
|
6585
6577
|
clearTimeout(timer);
|
|
6586
|
-
|
|
6578
|
+
resolve14({ exitCode: code ?? -1, stderr });
|
|
6587
6579
|
});
|
|
6588
6580
|
});
|
|
6589
6581
|
if (result.exitCode !== 0) {
|
|
@@ -6595,13 +6587,6 @@ var uninstallNpmCli = async (ctx) => {
|
|
|
6595
6587
|
}
|
|
6596
6588
|
return { ok: true, removedPaths: [pkg] };
|
|
6597
6589
|
};
|
|
6598
|
-
function extractSkillName3(cmd, fallback) {
|
|
6599
|
-
const m = cmd.match(/\bskills(?:@\S+)?\s+add\s+(\S+)/i);
|
|
6600
|
-
if (!m || m[1] === void 0) return fallback;
|
|
6601
|
-
const ref = m[1];
|
|
6602
|
-
const seg = ref.split("/");
|
|
6603
|
-
return seg[seg.length - 1] ?? fallback;
|
|
6604
|
-
}
|
|
6605
6590
|
var uninstallNpxSkillInstaller = async (ctx) => {
|
|
6606
6591
|
const install = ctx.manifest.spec.install;
|
|
6607
6592
|
if (install.method !== "npx-skill-installer") {
|
|
@@ -6610,7 +6595,7 @@ var uninstallNpxSkillInstaller = async (ctx) => {
|
|
|
6610
6595
|
const abort = dryRunGate(ctx);
|
|
6611
6596
|
if (abort) return abort;
|
|
6612
6597
|
const name = ctx.manifest.metadata.name;
|
|
6613
|
-
const skillName =
|
|
6598
|
+
const skillName = extractSkillName(install.cmd, name);
|
|
6614
6599
|
const skillDir = join(homedir(), ".claude", "skills", skillName);
|
|
6615
6600
|
await rm(skillDir, { recursive: true, force: true, maxRetries: 3 });
|
|
6616
6601
|
return { ok: true, removedPaths: [skillDir] };
|
|
@@ -6632,21 +6617,177 @@ async function runUninstall(manifest, opts) {
|
|
|
6632
6617
|
}
|
|
6633
6618
|
|
|
6634
6619
|
// src/cli/uninstall.ts
|
|
6620
|
+
async function discoverCommandFiles(commandsDir) {
|
|
6621
|
+
const owned = [];
|
|
6622
|
+
let entries;
|
|
6623
|
+
try {
|
|
6624
|
+
entries = await readdir(commandsDir);
|
|
6625
|
+
} catch {
|
|
6626
|
+
return owned;
|
|
6627
|
+
}
|
|
6628
|
+
for (const entry of entries) {
|
|
6629
|
+
if (!entry.endsWith(".md")) continue;
|
|
6630
|
+
const p5 = join(commandsDir, entry);
|
|
6631
|
+
try {
|
|
6632
|
+
const content = await readFile(p5, "utf8");
|
|
6633
|
+
if (shouldOverwriteFile(content)) owned.push(p5);
|
|
6634
|
+
} catch {
|
|
6635
|
+
}
|
|
6636
|
+
}
|
|
6637
|
+
return owned;
|
|
6638
|
+
}
|
|
6639
|
+
async function checkSettingsEnv(settingsPath3) {
|
|
6640
|
+
try {
|
|
6641
|
+
const raw = await readFile(settingsPath3, "utf8");
|
|
6642
|
+
const data = JSON.parse(raw);
|
|
6643
|
+
const env = data.env ?? {};
|
|
6644
|
+
return {
|
|
6645
|
+
hasAgentTeams: "CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS" in env,
|
|
6646
|
+
hasUserLang: "HARNESSED_USER_LANG" in env
|
|
6647
|
+
};
|
|
6648
|
+
} catch {
|
|
6649
|
+
return { hasAgentTeams: false, hasUserLang: false };
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6652
|
+
async function removeSettingsEnv(settingsPath3) {
|
|
6653
|
+
const raw = await readFile(settingsPath3, "utf8");
|
|
6654
|
+
const data = JSON.parse(raw);
|
|
6655
|
+
const env = data.env ?? {};
|
|
6656
|
+
let changed = false;
|
|
6657
|
+
if ("CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS" in env) {
|
|
6658
|
+
delete env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
|
|
6659
|
+
changed = true;
|
|
6660
|
+
}
|
|
6661
|
+
if ("HARNESSED_USER_LANG" in env) {
|
|
6662
|
+
delete env.HARNESSED_USER_LANG;
|
|
6663
|
+
changed = true;
|
|
6664
|
+
}
|
|
6665
|
+
if (!changed) return false;
|
|
6666
|
+
if (Object.keys(env).length === 0) delete data.env;
|
|
6667
|
+
else data.env = env;
|
|
6668
|
+
await writeFile(settingsPath3, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
6669
|
+
return true;
|
|
6670
|
+
}
|
|
6671
|
+
async function runUnifiedUninstall(home, dryRun) {
|
|
6672
|
+
const commandsDir = join(home, ".claude", "commands");
|
|
6673
|
+
const skillsDir = join(home, ".claude", "skills");
|
|
6674
|
+
const settingsPath3 = join(home, ".claude", "settings.json");
|
|
6675
|
+
const harnessedRoot = getHarnessedRoot();
|
|
6676
|
+
const pkgRoot = getPackageRoot();
|
|
6677
|
+
let workflowNames = [];
|
|
6678
|
+
try {
|
|
6679
|
+
const wfEntries = await readdir(resolve(pkgRoot, "workflows"));
|
|
6680
|
+
const scanResult = await scanWorkflowsNested(resolve(pkgRoot, "workflows"), wfEntries);
|
|
6681
|
+
workflowNames = scanResult.workflows.map((w) => w.name);
|
|
6682
|
+
} catch {
|
|
6683
|
+
}
|
|
6684
|
+
const commandFiles = await discoverCommandFiles(commandsDir);
|
|
6685
|
+
const settingsEnv = await checkSettingsEnv(settingsPath3);
|
|
6686
|
+
const hasSettingsChanges = settingsEnv.hasAgentTeams || settingsEnv.hasUserLang;
|
|
6687
|
+
const skillDirs = [];
|
|
6688
|
+
for (const name of workflowNames) {
|
|
6689
|
+
const dir = join(skillsDir, name);
|
|
6690
|
+
try {
|
|
6691
|
+
await stat(dir);
|
|
6692
|
+
skillDirs.push(dir);
|
|
6693
|
+
} catch {
|
|
6694
|
+
}
|
|
6695
|
+
}
|
|
6696
|
+
const discoverable = commandFiles.length + skillDirs.length + (hasSettingsChanges ? 1 : 0);
|
|
6697
|
+
if (discoverable === 0) {
|
|
6698
|
+
console.log(t("uninstall.unified.nothing"));
|
|
6699
|
+
process.exit(0);
|
|
6700
|
+
}
|
|
6701
|
+
console.log(t("uninstall.unified.header"));
|
|
6702
|
+
if (commandFiles.length > 0)
|
|
6703
|
+
console.log(t("uninstall.unified.commands", { count: commandFiles.length }));
|
|
6704
|
+
if (skillDirs.length > 0) console.log(t("uninstall.unified.skills", { count: skillDirs.length }));
|
|
6705
|
+
if (hasSettingsChanges) console.log(t("uninstall.unified.settings"));
|
|
6706
|
+
console.log(t("uninstall.unified.state_dir"));
|
|
6707
|
+
console.log(t("uninstall.unified.upstream_note"));
|
|
6708
|
+
if (dryRun) {
|
|
6709
|
+
console.log(t("uninstall.unified.dry_run_hint"));
|
|
6710
|
+
process.exit(2);
|
|
6711
|
+
}
|
|
6712
|
+
const answer = await p.confirm({
|
|
6713
|
+
message: t("uninstall.unified.confirm"),
|
|
6714
|
+
initialValue: false
|
|
6715
|
+
});
|
|
6716
|
+
if (p.isCancel(answer) || answer === false) {
|
|
6717
|
+
console.error(t("uninstall.cancelled"));
|
|
6718
|
+
process.exit(2);
|
|
6719
|
+
}
|
|
6720
|
+
console.log(t("uninstall.unified.removing"));
|
|
6721
|
+
const failures = [];
|
|
6722
|
+
let removedCommands = 0;
|
|
6723
|
+
for (const path of commandFiles) {
|
|
6724
|
+
try {
|
|
6725
|
+
await rm(path, { force: true });
|
|
6726
|
+
removedCommands++;
|
|
6727
|
+
} catch (e) {
|
|
6728
|
+
failures.push(`${path}: ${e.message}`);
|
|
6729
|
+
}
|
|
6730
|
+
}
|
|
6731
|
+
let removedSkills = 0;
|
|
6732
|
+
for (const dir of skillDirs) {
|
|
6733
|
+
try {
|
|
6734
|
+
await rm(dir, { recursive: true, force: true });
|
|
6735
|
+
removedSkills++;
|
|
6736
|
+
} catch (e) {
|
|
6737
|
+
failures.push(`${dir}: ${e.message}`);
|
|
6738
|
+
}
|
|
6739
|
+
}
|
|
6740
|
+
let removedSettings = false;
|
|
6741
|
+
if (hasSettingsChanges) {
|
|
6742
|
+
try {
|
|
6743
|
+
removedSettings = await removeSettingsEnv(settingsPath3);
|
|
6744
|
+
} catch (e) {
|
|
6745
|
+
failures.push(`${settingsPath3}: ${e.message}`);
|
|
6746
|
+
}
|
|
6747
|
+
}
|
|
6748
|
+
const normalizedRoot = resolve(harnessedRoot);
|
|
6749
|
+
const claudeDir = join(home, ".claude");
|
|
6750
|
+
if (!normalizedRoot.startsWith(resolve(claudeDir) + sep)) {
|
|
6751
|
+
console.error(`error: state dir ${harnessedRoot} is not under ${claudeDir} \u2014 refusing`);
|
|
6752
|
+
process.exit(1);
|
|
6753
|
+
}
|
|
6754
|
+
let removedStateDir = false;
|
|
6755
|
+
try {
|
|
6756
|
+
await rm(harnessedRoot, { recursive: true, force: true });
|
|
6757
|
+
removedStateDir = true;
|
|
6758
|
+
} catch (e) {
|
|
6759
|
+
failures.push(`${harnessedRoot}: ${e.message}`);
|
|
6760
|
+
}
|
|
6761
|
+
if (removedCommands > 0)
|
|
6762
|
+
console.log(t("uninstall.unified.removed_commands", { count: removedCommands }));
|
|
6763
|
+
if (removedSkills > 0)
|
|
6764
|
+
console.log(t("uninstall.unified.removed_skills", { count: removedSkills }));
|
|
6765
|
+
if (removedSettings) console.log(t("uninstall.unified.removed_settings"));
|
|
6766
|
+
if (removedStateDir) console.log(t("uninstall.unified.removed_state_dir"));
|
|
6767
|
+
if (failures.length > 0) {
|
|
6768
|
+
console.error(t("uninstall.unified.partial_failure", { count: failures.length }));
|
|
6769
|
+
for (const f of failures) console.error(` ${f}`);
|
|
6770
|
+
}
|
|
6771
|
+
console.log(t("uninstall.unified.complete"));
|
|
6772
|
+
process.exit(0);
|
|
6773
|
+
}
|
|
6635
6774
|
function registerUninstall(program2) {
|
|
6636
|
-
program2.command("uninstall
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
process.exit(2);
|
|
6775
|
+
program2.command("uninstall [name]").description(
|
|
6776
|
+
"Uninstall an upstream by name, or remove all harnessed own files when no name given"
|
|
6777
|
+
).option("--dry-run", "preview only \u2014 do not delete files").action(async (name, raw) => {
|
|
6778
|
+
const dryRun = raw.dryRun === true;
|
|
6779
|
+
if (!name) {
|
|
6780
|
+
await runUnifiedUninstall(homedir(), dryRun);
|
|
6781
|
+
return;
|
|
6644
6782
|
}
|
|
6645
6783
|
const { resolveAlias: resolveAlias2 } = await Promise.resolve().then(() => (init_aliases(), aliases_exports));
|
|
6646
6784
|
const resolvedName = resolveAlias2(name) ?? name;
|
|
6647
6785
|
checkPathSafe(resolvedName);
|
|
6648
6786
|
const manifestPath = resolve(getPackageRoot(), `manifests/tools/${resolvedName}.yaml`);
|
|
6649
|
-
const skillPackPath = resolve(
|
|
6787
|
+
const skillPackPath = resolve(
|
|
6788
|
+
getPackageRoot(),
|
|
6789
|
+
`manifests/skill-packs/${resolvedName}.yaml`
|
|
6790
|
+
);
|
|
6650
6791
|
let yamlSrc;
|
|
6651
6792
|
let chosenPath = manifestPath;
|
|
6652
6793
|
try {
|
|
@@ -6668,25 +6809,25 @@ ${t("install.manifest_not_found.fix", { name: resolvedName })}`
|
|
|
6668
6809
|
for (const e of v.errors) console.error(`error: ${e.message} at ${e.path}`);
|
|
6669
6810
|
process.exit(1);
|
|
6670
6811
|
}
|
|
6671
|
-
const method = v.manifest.spec.install.method;
|
|
6672
|
-
const dryRun = raw.dryRun === true;
|
|
6673
6812
|
if (dryRun) {
|
|
6674
|
-
console.log(
|
|
6813
|
+
console.log(
|
|
6814
|
+
t("uninstall.dry_run.preview", {
|
|
6815
|
+
name: resolvedName,
|
|
6816
|
+
method: v.manifest.spec.install.method
|
|
6817
|
+
})
|
|
6818
|
+
);
|
|
6675
6819
|
console.log(t("uninstall.dry_run.run_hint"));
|
|
6676
6820
|
process.exit(2);
|
|
6677
6821
|
}
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
process.exit(2);
|
|
6686
|
-
}
|
|
6822
|
+
const answer = await p.confirm({
|
|
6823
|
+
message: t("uninstall.confirm.prompt", { name: resolvedName }),
|
|
6824
|
+
initialValue: false
|
|
6825
|
+
});
|
|
6826
|
+
if (p.isCancel(answer) || answer === false) {
|
|
6827
|
+
console.error(t("uninstall.cancelled"));
|
|
6828
|
+
process.exit(2);
|
|
6687
6829
|
}
|
|
6688
|
-
const
|
|
6689
|
-
const result = await runUninstall(v.manifest, opts);
|
|
6830
|
+
const result = await runUninstall(v.manifest, { apply: true, dryRun: false, yes: true });
|
|
6690
6831
|
if ("aborted" in result) {
|
|
6691
6832
|
console.error(t("install.aborted", { reason: result.reason }));
|
|
6692
6833
|
process.exit(2);
|