harnessed 3.9.0 → 3.9.1

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 CHANGED
@@ -687,21 +687,27 @@ async function checkPlanningWithFiles() {
687
687
  name: "planning-with-files plugin",
688
688
  status: "warn",
689
689
  message: "plugin directory exists but no version subdir found",
690
- fix: REMEDIATION
690
+ fix: REMEDIATION,
691
+ install_commands: INSTALL_COMMANDS
691
692
  };
692
693
  } catch {
693
694
  return {
694
695
  name: "planning-with-files plugin",
695
696
  status: "warn",
696
697
  message: "not installed (plugin cache path missing)",
697
- fix: REMEDIATION
698
+ fix: REMEDIATION,
699
+ install_commands: INSTALL_COMMANDS
698
700
  };
699
701
  }
700
702
  }
701
- var REMEDIATION;
703
+ var REMEDIATION, INSTALL_COMMANDS;
702
704
  var init_check_planning_with_files = __esm({
703
705
  "src/cli/lib/check-planning-with-files.ts"() {
704
- REMEDIATION = "install via Claude Code plugin marketplace: `claude plugin install planning-with-files` (requires >=2.2.0 per R20.15 + D-15)";
706
+ REMEDIATION = "install via `claude plugin marketplace add OthmanAdi/planning-with-files && claude plugin install planning-with-files` (requires >=2.2.0 per R20.15 + D-15)";
707
+ INSTALL_COMMANDS = [
708
+ "claude plugin marketplace add OthmanAdi/planning-with-files",
709
+ "claude plugin install planning-with-files"
710
+ ];
705
711
  }
706
712
  });
707
713
 
@@ -745,13 +751,15 @@ async function checkMattpocockSkills() {
745
751
  name: "mattpocock-skills",
746
752
  status: "warn",
747
753
  message: "not installed (plugin cache + user-skill paths both missing)",
748
- fix: REMEDIATION2
754
+ fix: REMEDIATION2,
755
+ install_commands: INSTALL_COMMANDS2
749
756
  };
750
757
  }
751
- var REMEDIATION2;
758
+ var REMEDIATION2, INSTALL_COMMANDS2;
752
759
  var init_check_mattpocock_skills = __esm({
753
760
  "src/cli/lib/check-mattpocock-skills.ts"() {
754
- 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";
761
+ REMEDIATION2 = "install via `npx skills@latest add 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";
762
+ INSTALL_COMMANDS2 = ["npx skills@latest add mattpocock/skills"];
755
763
  }
756
764
  });
757
765
 
@@ -782,25 +790,34 @@ async function checkMcpAvailability() {
782
790
  message: `all 3 installed: ${installed.join(", ")}`
783
791
  };
784
792
  }
793
+ const installCommands = missing.map((s) => SERVER_INSTALL_COMMANDS[s]);
785
794
  if (installed.length === 0) {
786
795
  return {
787
796
  name: "MCP servers (tavily/exa/chrome-devtools)",
788
797
  status: "warn",
789
798
  message: "none of 3 target MCP servers installed in ~/.claude/settings.json",
790
- 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)"
799
+ fix: "install via per-server transport-specific command (see install_commands); 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)",
800
+ install_commands: installCommands
791
801
  };
792
802
  }
793
803
  return {
794
804
  name: "MCP servers (tavily/exa/chrome-devtools)",
795
805
  status: "warn",
796
806
  message: `${installed.length}/3 installed: ${installed.join(", ")}; missing: ${missing.join(", ")}`,
797
- fix: `install missing via \`claude mcp add ${missing.join(" && claude mcp add ")}\``
807
+ fix: `install missing via per-server command (see install_commands): ${missing.join(", ")}`,
808
+ install_commands: installCommands
798
809
  };
799
810
  }
800
- var TARGET_SERVERS;
811
+ var TARGET_SERVERS, SERVER_INSTALL_COMMANDS;
801
812
  var init_check_mcp_availability = __esm({
802
813
  "src/cli/lib/check-mcp-availability.ts"() {
803
814
  TARGET_SERVERS = ["tavily-mcp", "exa-mcp", "chrome-devtools"];
815
+ SERVER_INSTALL_COMMANDS = {
816
+ "tavily-mcp": "claude mcp add tavily-remote-mcp --transport http https://mcp.tavily.com/mcp/",
817
+ "exa-mcp": "claude mcp add --transport http exa https://mcp.exa.ai/mcp",
818
+ // chrome-devtools: empirical-pending — assumed npx until dogfood confirmation.
819
+ "chrome-devtools": "npx chrome-devtools-mcp@latest"
820
+ };
804
821
  }
805
822
  });
806
823
 
@@ -1066,51 +1083,71 @@ var init_resume = __esm({
1066
1083
  // src/cli/lib/auto-install.ts
1067
1084
  var auto_install_exports = {};
1068
1085
  __export(auto_install_exports, {
1069
- extractPluginName: () => extractPluginName,
1070
1086
  runAutoInstall: () => runAutoInstall
1071
1087
  });
1072
- function extractPluginName(fix) {
1073
- const m = fix.match(/claude\s+plugin\s+install\s+([\w@\-/.]+)/);
1074
- return m?.[1] ?? null;
1075
- }
1076
1088
  async function runAutoInstall(opts) {
1077
1089
  const out = { installed: [], skipped: [], failed: [] };
1078
1090
  if (!opts.autoInstall) {
1079
1091
  return out;
1080
1092
  }
1081
1093
  const results = await Promise.all(CHECKS.map((c) => c()));
1082
- const installables = results.filter((r) => r.status === "warn" && typeof r.fix === "string").map((r) => ({ check: r, plugin: extractPluginName(r.fix ?? "") })).filter((entry) => entry.plugin !== null);
1094
+ const installables = results.filter(
1095
+ (r) => r.status === "warn" && Array.isArray(r.install_commands) && r.install_commands.length > 0
1096
+ );
1083
1097
  if (installables.length === 0) {
1084
1098
  return out;
1085
1099
  }
1086
1100
  console.log(
1087
1101
  `
1088
- \u{1F4A1} ${installables.length} optional plugin(s) missing \u2014 harnessed can install them now:`
1102
+ \u{1F4A1} ${installables.length} optional check(s) installable \u2014 harnessed can run install commands now:`
1089
1103
  );
1090
- for (const { check, plugin } of installables) {
1104
+ for (const check of installables) {
1105
+ const commands = check.install_commands;
1091
1106
  if (opts.nonInteractive) {
1092
- out.skipped.push(plugin);
1107
+ out.skipped.push(check.name);
1093
1108
  continue;
1094
1109
  }
1110
+ const preview = commands.map((c) => ` $ ${c}`).join("\n");
1111
+ console.log(`
1112
+ ${check.name}:`);
1113
+ console.log(preview);
1095
1114
  const ans = await p.confirm({
1096
- message: `Install "${plugin}" via \`claude plugin install\`? (${check.name})`,
1115
+ message: `Run ${commands.length} install command(s) for "${check.name}"?`,
1097
1116
  initialValue: true
1098
1117
  });
1099
1118
  if (p.isCancel(ans) || ans !== true) {
1100
- out.skipped.push(plugin);
1119
+ out.skipped.push(check.name);
1101
1120
  continue;
1102
1121
  }
1103
- const r = spawnSync("claude", ["plugin", "install", plugin], {
1104
- encoding: "utf8",
1105
- stdio: "inherit"
1106
- });
1107
- if (r.status === 0) {
1108
- out.installed.push(plugin);
1109
- console.log(` \u2713 installed ${plugin}`);
1110
- } else {
1111
- const reason = r.error !== void 0 ? `spawn error: ${r.error.message}` : `exit code ${r.status ?? "<unknown>"}`;
1112
- out.failed.push({ name: plugin, reason });
1113
- console.error(` \u2717 failed ${plugin} \u2014 ${reason}`);
1122
+ let chainOk = true;
1123
+ for (const cmd of commands) {
1124
+ const tokens = cmd.split(/\s+/).filter((t2) => t2.length > 0);
1125
+ const exe = tokens[0];
1126
+ const args = tokens.slice(1);
1127
+ if (exe === void 0) {
1128
+ out.failed.push({ name: check.name, reason: `empty command in install_commands` });
1129
+ chainOk = false;
1130
+ break;
1131
+ }
1132
+ const r = spawnSync(exe, args, {
1133
+ encoding: "utf8",
1134
+ stdio: "inherit",
1135
+ // Windows needs shell for `.cmd` / `.bat` exes (npx.cmd / claude.cmd
1136
+ // shims); Unix is fine either way. Pass-through to OS shell handles
1137
+ // PATH resolution + extension lookup.
1138
+ shell: true
1139
+ });
1140
+ if (r.status !== 0) {
1141
+ const reason = r.error !== void 0 ? `spawn error: ${r.error.message}` : `exit code ${r.status ?? "<unknown>"} on \`${cmd}\``;
1142
+ out.failed.push({ name: check.name, reason });
1143
+ console.error(` \u2717 failed ${check.name} \u2014 ${reason}`);
1144
+ chainOk = false;
1145
+ break;
1146
+ }
1147
+ }
1148
+ if (chainOk) {
1149
+ out.installed.push(check.name);
1150
+ console.log(` \u2713 installed ${check.name}`);
1114
1151
  }
1115
1152
  }
1116
1153
  console.log(
@@ -1127,7 +1164,7 @@ var init_auto_install = __esm({
1127
1164
 
1128
1165
  // package.json
1129
1166
  var package_default = {
1130
- version: "3.9.0"};
1167
+ version: "3.9.1"};
1131
1168
 
1132
1169
  // src/manifest/errors.ts
1133
1170
  function instancePathToKeyPath(instancePath) {