@mutmutco/cli 3.53.0 → 3.54.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.
Files changed (2) hide show
  1. package/dist/main.cjs +73 -1
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -9108,6 +9108,7 @@ function cachedReadNote(cachedAt, now = Date.now()) {
9108
9108
  // src/marketplace-autoupdate.ts
9109
9109
  var KNOWN_MARKETPLACES_RELATIVE = [".claude", "plugins", "known_marketplaces.json"];
9110
9110
  var MMI_MARKETPLACE_NAME = "mutmutco";
9111
+ var JERV_MARKETPLACE_NAME = "jervaise";
9111
9112
  function readFileSyncSafe(path2, read) {
9112
9113
  try {
9113
9114
  return read(path2, "utf8");
@@ -9144,6 +9145,49 @@ function resolveAutoUpdate(probe) {
9144
9145
  reason: "undeclared \u2014 third-party marketplaces are OFF by default, so nothing auto-updates and no update notice ever prints"
9145
9146
  };
9146
9147
  }
9148
+ function captureMarketplacePins(raw, names) {
9149
+ const out = /* @__PURE__ */ new Map();
9150
+ for (const name of names) {
9151
+ const { registered, declared, ref } = readKnownMarketplace(raw, name);
9152
+ if (!registered) continue;
9153
+ const pins = {
9154
+ ...typeof declared === "boolean" ? { autoUpdate: declared } : {},
9155
+ ...ref ? { ref } : {}
9156
+ };
9157
+ if (Object.keys(pins).length) out.set(name, pins);
9158
+ }
9159
+ return out;
9160
+ }
9161
+ function restoreMarketplacePins(raw, pins) {
9162
+ if (!raw || pins.size === 0) return null;
9163
+ let parsed;
9164
+ try {
9165
+ parsed = JSON.parse(raw);
9166
+ } catch {
9167
+ return null;
9168
+ }
9169
+ if (!parsed || typeof parsed !== "object") return null;
9170
+ const root = parsed;
9171
+ let changed = false;
9172
+ for (const [name, want] of pins) {
9173
+ const entry = root[name];
9174
+ if (!entry || typeof entry !== "object") continue;
9175
+ const e = entry;
9176
+ if (typeof want.autoUpdate === "boolean" && e.autoUpdate !== want.autoUpdate) {
9177
+ e.autoUpdate = want.autoUpdate;
9178
+ changed = true;
9179
+ }
9180
+ if (want.ref && e.source && typeof e.source === "object") {
9181
+ const source = e.source;
9182
+ if (source.ref !== want.ref) {
9183
+ source.ref = want.ref;
9184
+ changed = true;
9185
+ }
9186
+ }
9187
+ }
9188
+ return changed ? `${JSON.stringify(root, null, 2)}
9189
+ ` : null;
9190
+ }
9147
9191
  function readKnownMarketplace(raw, name) {
9148
9192
  if (!raw) return { registered: false };
9149
9193
  let parsed;
@@ -22742,12 +22786,40 @@ async function healClaudePluginForDoctor(surface = detectSurface(process.env)) {
22742
22786
  return { ok: false, detail: `not a Claude surface (${surface}) \u2014 no Hub-shipped plugin to reinstall` };
22743
22787
  }
22744
22788
  const steps = [];
22789
+ const pinsPath = (0, import_node_path26.join)((0, import_node_os6.homedir)(), ...KNOWN_MARKETPLACES_RELATIVE);
22790
+ const before = readKnownMarketplacesFile(pinsPath);
22791
+ const pins = captureMarketplacePins(before, [MMI_MARKETPLACE_NAME, JERV_MARKETPLACE_NAME]);
22745
22792
  const ok = await applyPluginHeal(surface, (msg) => steps.push(msg.trim()));
22793
+ const restored = ok ? restoreMarketplacePinsOnDisk(pinsPath, pins) : void 0;
22746
22794
  return {
22747
22795
  ok,
22748
- detail: ok ? "marketplace remove \u2192 add \u2192 install succeeded" : `\`claude plugin\` reinstall failed or was skipped${steps.length ? ` (${steps[steps.length - 1]})` : ""}`
22796
+ detail: ok ? `marketplace remove \u2192 add \u2192 install succeeded${restored ? `; ${restored}` : ""}` : `\`claude plugin\` reinstall failed or was skipped${steps.length ? ` (${steps[steps.length - 1]})` : ""}`
22749
22797
  };
22750
22798
  }
22799
+ function readKnownMarketplacesFile(path2) {
22800
+ try {
22801
+ return (0, import_node_fs28.existsSync)(path2) ? (0, import_node_fs28.readFileSync)(path2, "utf8") : void 0;
22802
+ } catch {
22803
+ return void 0;
22804
+ }
22805
+ }
22806
+ function restoreMarketplacePinsOnDisk(path2, pins) {
22807
+ if (pins.size === 0) return void 0;
22808
+ const after = readKnownMarketplacesFile(path2);
22809
+ const next = restoreMarketplacePins(after, pins);
22810
+ if (next === null) return void 0;
22811
+ try {
22812
+ (0, import_node_fs28.writeFileSync)(path2, next, "utf8");
22813
+ } catch {
22814
+ return `could NOT restore ${[...pins.keys()].join(", ")} \u2014 re-pin by hand`;
22815
+ }
22816
+ const verify = readKnownMarketplacesFile(path2);
22817
+ const failed = [...pins].filter(([name, want]) => {
22818
+ const got = readKnownMarketplace(verify, name);
22819
+ return typeof want.autoUpdate === "boolean" && got.declared !== want.autoUpdate || want.ref !== void 0 && got.ref !== want.ref;
22820
+ });
22821
+ return failed.length ? `restore did NOT take for ${failed.map(([n]) => n).join(", ")} \u2014 re-pin by hand` : `re-pinned ${[...pins.keys()].join(", ")} (auto-update + catalog ref survive the reinstall)`;
22822
+ }
22751
22823
  async function runGuard(readOrigin) {
22752
22824
  try {
22753
22825
  const surface = detectSurface(process.env);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "3.53.0",
3
+ "version": "3.54.0",
4
4
  "description": "MMI Future CLI — the org dev toolbox (board, registry, keyless secrets, release train, bootstrap, doctor) and the cross-IDE engine the plugin's session-start hook drives.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",