harnessed 3.5.0 → 3.6.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.
@@ -0,0 +1,34 @@
1
+ # Third-Party Notices
2
+
3
+ `harnessed` itself is licensed under the Apache License 2.0 (see `LICENSE` and
4
+ `NOTICE` at the repo root). This file enumerates third-party material whose
5
+ text — verbatim or paraphrased — is incorporated into shipped harnessed source
6
+ files. Upstream attributions for each capability *manifest* (and its installed
7
+ side effects on the user's machine) continue to be tracked separately in
8
+ `NOTICES.md` (auto-populated by `harnessed install` from each manifest's
9
+ `metadata.upstream.notice` field).
10
+
11
+ ---
12
+
13
+ ## mattpocock/skills
14
+
15
+ - **Source**: https://github.com/mattpocock/skills
16
+ - **Commit SHA pinned**: `b8be62ffacb0118fa3eaa29a0923c87c8c11985c`
17
+ - **License**: MIT
18
+ - **Used in**: `workflows/role-prompts.yaml` — paraphrased methodology
19
+ excerpts inlined into the `task-clarify`, `task-code`, and `discuss-subtask`
20
+ sub-workflow role-prompt entries (introduced in v3.6.0 Phase 1). Each
21
+ paraphrased block carries an inline attribution comment naming the source
22
+ SKILL.md path and the pinned commit SHA.
23
+ - **Excerpts paraphrased (not redistributed verbatim)**:
24
+ - `skills/engineering/grill-with-docs/SKILL.md` → `task-clarify.responsibility` + checklist
25
+ - `skills/engineering/zoom-out/SKILL.md` → `task-code.checklist`
26
+ - `skills/engineering/improve-codebase-architecture/SKILL.md` → `task-code.checklist`
27
+ - `skills/productivity/grill-me/SKILL.md` → `discuss-subtask.responsibility` + checklist
28
+ - **Full upstream license text**: preserved at
29
+ `.planning/v3.6.0/mattpocock-source/LICENSE` (not shipped in the npm
30
+ tarball; retained for audit + license-compliance evidence). The SHA
31
+ metadata + re-fetch instructions live in
32
+ `.planning/v3.6.0/mattpocock-source/SHA.txt`.
33
+ - **Scope of redistribution**: only the paraphrased excerpts above are
34
+ redistributed (no verbatim SKILL.md content ships in the npm tarball).
package/dist/cli.mjs CHANGED
@@ -621,6 +621,105 @@ var init_check_planning_with_files = __esm({
621
621
  REMEDIATION = "install via Claude Code plugin marketplace: `claude plugin install planning-with-files` (requires >=2.2.0 per R20.15 + D-15)";
622
622
  }
623
623
  });
624
+
625
+ // src/cli/lib/check-mattpocock-skills.ts
626
+ var check_mattpocock_skills_exports = {};
627
+ __export(check_mattpocock_skills_exports, {
628
+ checkMattpocockSkills: () => checkMattpocockSkills
629
+ });
630
+ async function checkMattpocockSkills() {
631
+ const pluginRoot = join(
632
+ homedir(),
633
+ ".claude",
634
+ "plugins",
635
+ "cache",
636
+ "mattpocock-skills",
637
+ "mattpocock-skills"
638
+ );
639
+ const skillRoot = join(homedir(), ".claude", "skills", "mattpocock-skills");
640
+ try {
641
+ const entries = await readdir(pluginRoot);
642
+ const versions = entries.filter((e) => /^\d+\.\d+/.test(e));
643
+ if (versions.length > 0) {
644
+ return {
645
+ name: "mattpocock-skills",
646
+ status: "pass",
647
+ message: `installed as plugin (version ${versions.join(", ")})`
648
+ };
649
+ }
650
+ } catch {
651
+ }
652
+ try {
653
+ await stat(skillRoot);
654
+ return {
655
+ name: "mattpocock-skills",
656
+ status: "pass",
657
+ message: `installed as user-skill (${skillRoot})`
658
+ };
659
+ } catch {
660
+ }
661
+ return {
662
+ name: "mattpocock-skills",
663
+ status: "warn",
664
+ message: "not installed (plugin cache + user-skill paths both missing)",
665
+ fix: REMEDIATION2
666
+ };
667
+ }
668
+ var REMEDIATION2;
669
+ var init_check_mattpocock_skills = __esm({
670
+ "src/cli/lib/check-mattpocock-skills.ts"() {
671
+ REMEDIATION2 = "install via Claude Code plugin marketplace: `claude plugin install mattpocock-skills` (or git clone https://github.com/mattpocock/skills ~/.claude/skills/mattpocock-skills); methodology fallback already inline in role-prompts.yaml per v3.6.0 Phase 1 \u2014 install is optional but enables /grill-with-docs /zoom-out etc. SlashCommand acceleration";
672
+ }
673
+ });
674
+
675
+ // src/cli/lib/check-mcp-availability.ts
676
+ var check_mcp_availability_exports = {};
677
+ __export(check_mcp_availability_exports, {
678
+ checkMcpAvailability: () => checkMcpAvailability
679
+ });
680
+ async function checkMcpAvailability() {
681
+ const settingsPath3 = join(homedir(), ".claude", "settings.json");
682
+ let installed = [];
683
+ let missing = [...TARGET_SERVERS];
684
+ try {
685
+ const raw = await readFile(settingsPath3, "utf8");
686
+ const parsed = JSON.parse(raw);
687
+ const servers = parsed.mcpServers ?? {};
688
+ const serverNames = Object.keys(servers);
689
+ installed = TARGET_SERVERS.filter(
690
+ (s) => serverNames.some((n) => n.includes(s) || s.includes(n))
691
+ );
692
+ missing = TARGET_SERVERS.filter((s) => !installed.includes(s));
693
+ } catch {
694
+ }
695
+ if (missing.length === 0) {
696
+ return {
697
+ name: "MCP servers (tavily/exa/chrome-devtools)",
698
+ status: "pass",
699
+ message: `all 3 installed: ${installed.join(", ")}`
700
+ };
701
+ }
702
+ if (installed.length === 0) {
703
+ return {
704
+ name: "MCP servers (tavily/exa/chrome-devtools)",
705
+ status: "warn",
706
+ message: "none of 3 target MCP servers installed in ~/.claude/settings.json",
707
+ fix: "install via `claude mcp add <server-name>`; harnessed routes web-search to tavily/exa per workflows/judgments/web-search-routing.yaml \u2014 without them, falls back to WebFetch/WebSearch built-in (degraded but functional)"
708
+ };
709
+ }
710
+ return {
711
+ name: "MCP servers (tavily/exa/chrome-devtools)",
712
+ status: "warn",
713
+ message: `${installed.length}/3 installed: ${installed.join(", ")}; missing: ${missing.join(", ")}`,
714
+ fix: `install missing via \`claude mcp add ${missing.join(" && claude mcp add ")}\``
715
+ };
716
+ }
717
+ var TARGET_SERVERS;
718
+ var init_check_mcp_availability = __esm({
719
+ "src/cli/lib/check-mcp-availability.ts"() {
720
+ TARGET_SERVERS = ["tavily-mcp", "exa-mcp", "chrome-devtools"];
721
+ }
722
+ });
624
723
  function statePath() {
625
724
  return harnessedFile("current-workflow.json");
626
725
  }
@@ -853,7 +952,7 @@ var init_resume = __esm({
853
952
 
854
953
  // package.json
855
954
  var package_default = {
856
- version: "3.5.0"};
955
+ version: "3.6.0"};
857
956
 
858
957
  // src/manifest/errors.ts
859
958
  function instancePathToKeyPath(instancePath) {
@@ -1704,7 +1803,7 @@ function renderHumanTable(records) {
1704
1803
  }
1705
1804
  }
1706
1805
  function pipeToJq(filterExpr, lines) {
1707
- return new Promise((resolve14, reject) => {
1806
+ return new Promise((resolve15, reject) => {
1708
1807
  const child = spawn("jq", [filterExpr], {
1709
1808
  stdio: ["pipe", "inherit", "inherit"],
1710
1809
  windowsHide: true
@@ -1713,12 +1812,12 @@ function pipeToJq(filterExpr, lines) {
1713
1812
  const e = err2;
1714
1813
  if (e.code === "ENOENT") {
1715
1814
  console.error(t("audit_log.jq_missing"));
1716
- resolve14(1);
1815
+ resolve15(1);
1717
1816
  } else {
1718
1817
  reject(err2);
1719
1818
  }
1720
1819
  });
1721
- child.on("close", (code) => resolve14(code ?? 0));
1820
+ child.on("close", (code) => resolve15(code ?? 0));
1722
1821
  child.stdin.write(lines.join("\n"));
1723
1822
  child.stdin.end();
1724
1823
  });
@@ -2026,18 +2125,26 @@ async function checkAgentTeamsEnv() {
2026
2125
  async function checkPlanningPlugin() {
2027
2126
  return (await Promise.resolve().then(() => (init_check_planning_with_files(), check_planning_with_files_exports))).checkPlanningWithFiles();
2028
2127
  }
2128
+ async function checkMattpocockSkillsInstall() {
2129
+ return (await Promise.resolve().then(() => (init_check_mattpocock_skills(), check_mattpocock_skills_exports))).checkMattpocockSkills();
2130
+ }
2131
+ async function checkMcpAvailabilityCheck() {
2132
+ return (await Promise.resolve().then(() => (init_check_mcp_availability(), check_mcp_availability_exports))).checkMcpAvailability();
2133
+ }
2029
2134
  function registerDoctor(program2) {
2030
2135
  program2.command("doctor").description(
2031
- "Preflight checks (Node / MCP scope / jq / Win bash / origin URL / gstack prefix / deprecations / token budget / Agent Teams / planning-with-files)"
2136
+ "Preflight checks (Node / MCP scope / jq / Win bash / origin URL / gstack prefix / deprecations / token budget / Agent Teams / planning-with-files / mattpocock-skills / MCP availability)"
2032
2137
  ).option("--json", "output JSON instead of human-readable").action(async (opts) => {
2033
- const [mcp, origin, gstack, dep, tok, at, ppwf] = await Promise.all([
2138
+ const [mcp, origin, gstack, dep, tok, at, ppwf, matt, mcpAvail] = await Promise.all([
2034
2139
  checkMcpScope(),
2035
2140
  checkOriginUrl(),
2036
2141
  checkGstackPrefix(),
2037
2142
  checkDeprecations2(),
2038
2143
  checkTokenBudget2(),
2039
2144
  checkAgentTeamsEnv(),
2040
- checkPlanningPlugin()
2145
+ checkPlanningPlugin(),
2146
+ checkMattpocockSkillsInstall(),
2147
+ checkMcpAvailabilityCheck()
2041
2148
  ]);
2042
2149
  const results = [
2043
2150
  checkNodeVersion(),
@@ -2049,7 +2156,9 @@ function registerDoctor(program2) {
2049
2156
  dep,
2050
2157
  tok,
2051
2158
  at,
2052
- ppwf
2159
+ ppwf,
2160
+ matt,
2161
+ mcpAvail
2053
2162
  ];
2054
2163
  const hasFail = results.some((r) => r.status === "fail");
2055
2164
  const hasWarn = results.some((r) => r.status === "warn");
@@ -2530,6 +2639,22 @@ var JudgmentRulesFile = Type.Object(
2530
2639
  { additionalProperties: false }
2531
2640
  );
2532
2641
  Type.Union([JudgmentTriggersFile, JudgmentRulesFile]);
2642
+ var UserOverrideEntry = Type.Object(
2643
+ {
2644
+ id: Type.String({ minLength: 1 }),
2645
+ // kebab-case (e.g. 'brainstorm', 'arch-review')
2646
+ keywords: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
2647
+ triggers: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 })
2648
+ },
2649
+ { additionalProperties: false }
2650
+ );
2651
+ var UserOverridesFile = Type.Object(
2652
+ {
2653
+ schema_version: Type.Literal("harnessed.user-overrides.v1"),
2654
+ overrides: Type.Array(UserOverrideEntry, { minItems: 1 })
2655
+ },
2656
+ { additionalProperties: false }
2657
+ );
2533
2658
 
2534
2659
  // src/workflow/judgmentResolver.ts
2535
2660
  var TriggerNotFoundError = class extends Error {
@@ -2544,6 +2669,10 @@ var TriggerNotFoundError = class extends Error {
2544
2669
  };
2545
2670
  var _fileCache = /* @__PURE__ */ new Map();
2546
2671
  async function resolveJudgmentGate(gateRef, context, packageRoot) {
2672
+ const userOverrides = context.user_overrides;
2673
+ if (Array.isArray(userOverrides) && userOverrides.includes(gateRef)) {
2674
+ return true;
2675
+ }
2547
2676
  const parts = gateRef.split(".");
2548
2677
  if (parts.length !== 4 || parts[0] !== "judgments") {
2549
2678
  throw new Error(`Invalid gate ref: ${gateRef}`);
@@ -3193,13 +3322,33 @@ Five triggers (any one suffices):
3193
3322
  5. **fullstack_three_way** \u2014 the task is a synchronized fullstack push (frontend + backend + tests) requiring API contract alignment across three roles simultaneously.
3194
3323
 
3195
3324
  If none of the five apply, omit \`needs_teams_escalation\` (defaults to false) and proceed normally.`;
3325
+ var TRANSPARENT_SKIP_RULES = `When you encounter a phase gate or routing decision where the input context is missing key fields, default-valued, or contradictory, do NOT proceed silently. Instead, skip the phase and emit a one-line transparent explanation:
3326
+
3327
+ "Skipped <phase>, because <reason>. Tell me if you actually need it."
3328
+ (\u4E2D\u6587: "\u8FD9\u6B21\u8DF3\u8FC7\u4E86 <phase>, \u56E0\u4E3A <reason>. \u5982\u679C\u4F60\u8BA4\u4E3A\u9700\u8981\u8BF7\u660E\u8BF4.")
3329
+
3330
+ This applies to: strategic-layer review skip / phase-layer clarification skip / subtask-brainstorming skip / TDD enforcement skip / Agent Teams escalation skip. Chain-isolation rule: skipping one layer does NOT mandate skipping subsequent layers \u2014 each layer is independently evaluated.`;
3331
+ var AGENT_TEAMS_PREVENTION_RULES = `If you signal needs_teams_escalation=true, ALSO advise the user on these 4 Agent Teams prevention rules in your escalation_reason or summary (the user will be the one calling TeamCreate / SendMessage / TeamDelete; remind them upfront):
3332
+
3333
+ 1. **Session-scoped**: Teams live only in the current Claude Code session. \`/resume\` loses all teammates. Do not treat teams as persistent state \u2014 finish team work within one session.
3334
+
3335
+ 2. **Cleanup mandatory**: Before session ends, send \`SendMessage(to=<teammate>, content="shutdown_request")\` to each teammate, then call \`TeamDelete\`. Orphan teammates consume resources. This is a hard rule, not advisory.
3336
+
3337
+ 3. **Token cost estimation**: Before creating a team, estimate \`team_cost \u2248 N_teammates \xD7 N_rounds \xD7 avg_tokens_per_round + N_teammates \xD7 initial_brief_tokens\`. Compare to subagent fan-out cost (\`\u2248 N_subagents \xD7 (initial_brief + summary_tokens)\`). Only open a team when \`team_cost < 2 \xD7 subagent_cost\` \u2014 otherwise prefer fan-out.
3338
+
3339
+ 4. **Brief must be self-contained**: Each teammate launches WITHOUT main-session context. The Agent() prompt must include enough background, file paths, success criteria, and counter-positions so the teammate can work independently. Generic prompts produce shallow output.`;
3340
+ var CRITICAL_SYSTEM_REMINDER = `${ESCALATION_RULES}
3341
+
3342
+ ${TRANSPARENT_SKIP_RULES}
3343
+
3344
+ ${AGENT_TEAMS_PREVENTION_RULES}`;
3196
3345
  function buildAgentDef(skillName, rolePrompts, workflowName, modelTierOverride) {
3197
3346
  const rp = rolePrompts?.[skillName] ?? (workflowName ? rolePrompts?.[workflowName] : void 0);
3198
3347
  if (!rp) {
3199
3348
  return {
3200
3349
  description: `harnessed workflow phase: ${skillName}`,
3201
3350
  prompt: `You are executing the '${skillName}' workflow phase. Follow the phase intent and emit a structured COMPLETE signal when done.`,
3202
- criticalSystemReminder_EXPERIMENTAL: ESCALATION_RULES,
3351
+ criticalSystemReminder_EXPERIMENTAL: CRITICAL_SYSTEM_REMINDER,
3203
3352
  ...modelTierOverride ? { model: modelTierOverride } : {}
3204
3353
  };
3205
3354
  }
@@ -3220,7 +3369,7 @@ ${rp.checklist.map((c, i) => ` ${i + 1}. ${c}`).join("\n")}` : "";
3220
3369
  return {
3221
3370
  description: rp.description,
3222
3371
  prompt,
3223
- criticalSystemReminder_EXPERIMENTAL: ESCALATION_RULES,
3372
+ criticalSystemReminder_EXPERIMENTAL: CRITICAL_SYSTEM_REMINDER,
3224
3373
  ...modelTierOverride ? { model: modelTierOverride } : {}
3225
3374
  };
3226
3375
  }
@@ -3436,6 +3585,46 @@ function getPackageRoot() {
3436
3585
  }
3437
3586
  return resolve(thisDir, "..", "..", "..");
3438
3587
  }
3588
+ async function loadUserOverrides(packageRoot) {
3589
+ const yamlPath = resolve(packageRoot, "workflows", "judgments", "user-overrides.yaml");
3590
+ let raw;
3591
+ try {
3592
+ raw = await readFile(yamlPath, "utf8");
3593
+ } catch {
3594
+ return [];
3595
+ }
3596
+ let parsed;
3597
+ try {
3598
+ parsed = parse(raw);
3599
+ } catch {
3600
+ return [];
3601
+ }
3602
+ if (!Value.Check(UserOverridesFile, parsed)) {
3603
+ return [];
3604
+ }
3605
+ const valid = parsed;
3606
+ return valid.overrides.map((o) => ({
3607
+ id: o.id,
3608
+ keywords: [...o.keywords],
3609
+ triggers: [...o.triggers]
3610
+ }));
3611
+ }
3612
+ function extractMatchedTriggers(userText, overrides) {
3613
+ if (!userText || overrides.length === 0) return [];
3614
+ const haystack = userText.toLowerCase();
3615
+ const matched = /* @__PURE__ */ new Set();
3616
+ for (const entry of overrides) {
3617
+ for (const kw of entry.keywords) {
3618
+ if (haystack.includes(kw.toLowerCase())) {
3619
+ for (const trigger of entry.triggers) matched.add(trigger);
3620
+ break;
3621
+ }
3622
+ }
3623
+ }
3624
+ return [...matched];
3625
+ }
3626
+
3627
+ // src/cli/run.ts
3439
3628
  var PACKAGE_ROOT = getPackageRoot();
3440
3629
  var WORKFLOWS_DIR = join(PACKAGE_ROOT, "workflows");
3441
3630
  var _autoChainCache = null;
@@ -3473,11 +3662,19 @@ function registerRun(program2) {
3473
3662
  );
3474
3663
  process.exit(2);
3475
3664
  }
3665
+ const overrides = await loadUserOverrides(PACKAGE_ROOT);
3666
+ const matchedTriggers = extractMatchedTriggers(task, overrides);
3667
+ if (matchedTriggers.length > 0) {
3668
+ console.error(
3669
+ `\u2139 user-override detected: ${matchedTriggers.length} trigger(s) forced fires=true via keyword match (${matchedTriggers.join(", ")})`
3670
+ );
3671
+ }
3476
3672
  const gateContext = {
3477
3673
  task,
3478
3674
  ...raw.model ? { modelOverride: raw.model } : {},
3479
3675
  ...raw.maxIterations ? { maxIterations: raw.maxIterations } : {},
3480
- ...raw.staged ? { staged: true } : {}
3676
+ ...raw.staged ? { staged: true } : {},
3677
+ ...matchedTriggers.length > 0 ? { user_overrides: matchedTriggers } : {}
3481
3678
  };
3482
3679
  if (raw.dryRun) {
3483
3680
  console.log(JSON.stringify({ workflow: name, yamlPath, gateContext }, null, 2));
@@ -4052,7 +4249,7 @@ async function isPluginRegistered(pluginName) {
4052
4249
  return Object.keys(plugins).some((k) => k.split("@")[0] === pluginName);
4053
4250
  }
4054
4251
  function runArgs(claudeArgs, cwd, timeoutMs = 15e3) {
4055
- return new Promise((resolve14) => {
4252
+ return new Promise((resolve15) => {
4056
4253
  const isWin = process.platform === "win32";
4057
4254
  const child = isWin ? spawn("cmd.exe", ["/c", "claude", ...claudeArgs], { cwd, windowsHide: true }) : spawn("claude", claudeArgs, { cwd, shell: false });
4058
4255
  let stderr = "";
@@ -4061,15 +4258,15 @@ function runArgs(claudeArgs, cwd, timeoutMs = 15e3) {
4061
4258
  });
4062
4259
  const timer = setTimeout(() => {
4063
4260
  child.kill("SIGKILL");
4064
- resolve14({ exitCode: -1, stderr: `${stderr}[timeout after ${timeoutMs}ms]` });
4261
+ resolve15({ exitCode: -1, stderr: `${stderr}[timeout after ${timeoutMs}ms]` });
4065
4262
  }, timeoutMs);
4066
4263
  child.on("error", (e) => {
4067
4264
  clearTimeout(timer);
4068
- resolve14({ exitCode: -1, stderr: `${stderr}${e.message}` });
4265
+ resolve15({ exitCode: -1, stderr: `${stderr}${e.message}` });
4069
4266
  });
4070
4267
  child.on("close", (code) => {
4071
4268
  clearTimeout(timer);
4072
- resolve14({ exitCode: code ?? -1, stderr });
4269
+ resolve15({ exitCode: code ?? -1, stderr });
4073
4270
  });
4074
4271
  });
4075
4272
  }
@@ -4248,10 +4445,10 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
4248
4445
  child.stderr?.setEncoding("utf8").on("data", (chunk) => {
4249
4446
  stderr += chunk;
4250
4447
  });
4251
- return await new Promise((resolve14) => {
4448
+ return await new Promise((resolve15) => {
4252
4449
  const timer = setTimeout(() => {
4253
4450
  child.kill("SIGKILL");
4254
- resolve14({
4451
+ resolve15({
4255
4452
  ok: false,
4256
4453
  phase: "spawn",
4257
4454
  error: {
@@ -4266,7 +4463,7 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
4266
4463
  }, effectiveTimeoutMs);
4267
4464
  child.on("error", (err2) => {
4268
4465
  clearTimeout(timer);
4269
- resolve14({
4466
+ resolve15({
4270
4467
  ok: false,
4271
4468
  phase: "spawn",
4272
4469
  error: {
@@ -4281,14 +4478,14 @@ async function spawnCmd(ctx, cmd, args, timeoutMs) {
4281
4478
  });
4282
4479
  child.on("close", (code) => {
4283
4480
  clearTimeout(timer);
4284
- resolve14({ ok: true, exitCode: code ?? -1, stdout: stdout2, stderr });
4481
+ resolve15({ ok: true, exitCode: code ?? -1, stdout: stdout2, stderr });
4285
4482
  });
4286
4483
  });
4287
4484
  }
4288
4485
 
4289
4486
  // src/installers/gitCloneWithSetup.ts
4290
4487
  function gitRevParseHead(cwd, timeoutMs = 1e4) {
4291
- return new Promise((resolve14) => {
4488
+ return new Promise((resolve15) => {
4292
4489
  const isWin = process.platform === "win32";
4293
4490
  const child = isWin ? spawn("cmd.exe", ["/c", "git", "rev-parse", "HEAD"], { cwd, windowsHide: true }) : spawn("git", ["rev-parse", "HEAD"], { cwd, shell: false });
4294
4491
  let stdout2 = "";
@@ -4297,15 +4494,15 @@ function gitRevParseHead(cwd, timeoutMs = 1e4) {
4297
4494
  });
4298
4495
  const timer = setTimeout(() => {
4299
4496
  child.kill("SIGKILL");
4300
- resolve14({ sha: "", exit: -1 });
4497
+ resolve15({ sha: "", exit: -1 });
4301
4498
  }, timeoutMs);
4302
4499
  child.on("error", () => {
4303
4500
  clearTimeout(timer);
4304
- resolve14({ sha: "", exit: -1 });
4501
+ resolve15({ sha: "", exit: -1 });
4305
4502
  });
4306
4503
  child.on("close", (code) => {
4307
4504
  clearTimeout(timer);
4308
- resolve14({ sha: stdout2.trim(), exit: code ?? -1 });
4505
+ resolve15({ sha: stdout2.trim(), exit: code ?? -1 });
4309
4506
  });
4310
4507
  });
4311
4508
  }
@@ -6238,7 +6435,7 @@ var uninstallNpmCli = async (ctx) => {
6238
6435
  const m = install.cmd.match(/npm\s+(?:install|i)\s+(?:-g\s+)?(\S+)/);
6239
6436
  const pkg = m?.[1] ?? ctx.manifest.metadata.upstream.source;
6240
6437
  const isWin = process.platform === "win32";
6241
- const result = await new Promise((resolve14) => {
6438
+ const result = await new Promise((resolve15) => {
6242
6439
  const child = isWin ? spawn("cmd.exe", ["/c", "npm", "uninstall", "-g", pkg], { windowsHide: true }) : spawn("npm", ["uninstall", "-g", pkg], { shell: false });
6243
6440
  let stderr = "";
6244
6441
  child.stderr?.setEncoding("utf8").on("data", (c) => {
@@ -6246,15 +6443,15 @@ var uninstallNpmCli = async (ctx) => {
6246
6443
  });
6247
6444
  const timer = setTimeout(() => {
6248
6445
  child.kill("SIGKILL");
6249
- resolve14({ exitCode: -1, stderr: `${stderr}[timeout]` });
6446
+ resolve15({ exitCode: -1, stderr: `${stderr}[timeout]` });
6250
6447
  }, 3e4);
6251
6448
  child.on("error", (e) => {
6252
6449
  clearTimeout(timer);
6253
- resolve14({ exitCode: -1, stderr: e.message });
6450
+ resolve15({ exitCode: -1, stderr: e.message });
6254
6451
  });
6255
6452
  child.on("close", (code) => {
6256
6453
  clearTimeout(timer);
6257
- resolve14({ exitCode: code ?? -1, stderr });
6454
+ resolve15({ exitCode: code ?? -1, stderr });
6258
6455
  });
6259
6456
  });
6260
6457
  if (result.exitCode !== 0) {