harnessed 3.9.0 → 3.9.2

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,35 @@ 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: official Claude marketplace direct install (v3.9.2 dogfood
819
+ // confirmed — was assumed npx in v3.9.1 SPEC, corrected to official marketplace).
820
+ "chrome-devtools": "claude plugin install chrome-devtools-mcp"
821
+ };
804
822
  }
805
823
  });
806
824
 
@@ -1066,51 +1084,71 @@ var init_resume = __esm({
1066
1084
  // src/cli/lib/auto-install.ts
1067
1085
  var auto_install_exports = {};
1068
1086
  __export(auto_install_exports, {
1069
- extractPluginName: () => extractPluginName,
1070
1087
  runAutoInstall: () => runAutoInstall
1071
1088
  });
1072
- function extractPluginName(fix) {
1073
- const m = fix.match(/claude\s+plugin\s+install\s+([\w@\-/.]+)/);
1074
- return m?.[1] ?? null;
1075
- }
1076
1089
  async function runAutoInstall(opts) {
1077
1090
  const out = { installed: [], skipped: [], failed: [] };
1078
1091
  if (!opts.autoInstall) {
1079
1092
  return out;
1080
1093
  }
1081
1094
  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);
1095
+ const installables = results.filter(
1096
+ (r) => r.status === "warn" && Array.isArray(r.install_commands) && r.install_commands.length > 0
1097
+ );
1083
1098
  if (installables.length === 0) {
1084
1099
  return out;
1085
1100
  }
1086
1101
  console.log(
1087
1102
  `
1088
- \u{1F4A1} ${installables.length} optional plugin(s) missing \u2014 harnessed can install them now:`
1103
+ \u{1F4A1} ${installables.length} optional check(s) installable \u2014 harnessed can run install commands now:`
1089
1104
  );
1090
- for (const { check, plugin } of installables) {
1105
+ for (const check of installables) {
1106
+ const commands = check.install_commands;
1091
1107
  if (opts.nonInteractive) {
1092
- out.skipped.push(plugin);
1108
+ out.skipped.push(check.name);
1093
1109
  continue;
1094
1110
  }
1111
+ const preview = commands.map((c) => ` $ ${c}`).join("\n");
1112
+ console.log(`
1113
+ ${check.name}:`);
1114
+ console.log(preview);
1095
1115
  const ans = await p.confirm({
1096
- message: `Install "${plugin}" via \`claude plugin install\`? (${check.name})`,
1116
+ message: `Run ${commands.length} install command(s) for "${check.name}"?`,
1097
1117
  initialValue: true
1098
1118
  });
1099
1119
  if (p.isCancel(ans) || ans !== true) {
1100
- out.skipped.push(plugin);
1120
+ out.skipped.push(check.name);
1101
1121
  continue;
1102
1122
  }
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}`);
1123
+ let chainOk = true;
1124
+ for (const cmd of commands) {
1125
+ const tokens = cmd.split(/\s+/).filter((t2) => t2.length > 0);
1126
+ const exe = tokens[0];
1127
+ const args = tokens.slice(1);
1128
+ if (exe === void 0) {
1129
+ out.failed.push({ name: check.name, reason: `empty command in install_commands` });
1130
+ chainOk = false;
1131
+ break;
1132
+ }
1133
+ const r = spawnSync(exe, args, {
1134
+ encoding: "utf8",
1135
+ stdio: "inherit",
1136
+ // Windows needs shell for `.cmd` / `.bat` exes (npx.cmd / claude.cmd
1137
+ // shims); Unix is fine either way. Pass-through to OS shell handles
1138
+ // PATH resolution + extension lookup.
1139
+ shell: true
1140
+ });
1141
+ if (r.status !== 0) {
1142
+ const reason = r.error !== void 0 ? `spawn error: ${r.error.message}` : `exit code ${r.status ?? "<unknown>"} on \`${cmd}\``;
1143
+ out.failed.push({ name: check.name, reason });
1144
+ console.error(` \u2717 failed ${check.name} \u2014 ${reason}`);
1145
+ chainOk = false;
1146
+ break;
1147
+ }
1148
+ }
1149
+ if (chainOk) {
1150
+ out.installed.push(check.name);
1151
+ console.log(` \u2713 installed ${check.name}`);
1114
1152
  }
1115
1153
  }
1116
1154
  console.log(
@@ -1127,7 +1165,7 @@ var init_auto_install = __esm({
1127
1165
 
1128
1166
  // package.json
1129
1167
  var package_default = {
1130
- version: "3.9.0"};
1168
+ version: "3.9.2"};
1131
1169
 
1132
1170
  // src/manifest/errors.ts
1133
1171
  function instancePathToKeyPath(instancePath) {