@mutmutco/cli 4.2.2 → 4.2.3

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 +115 -44
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -3416,7 +3416,7 @@ var program = new Command();
3416
3416
  // src/index.ts
3417
3417
  var import_promises8 = require("node:fs/promises");
3418
3418
  var import_node_fs43 = require("node:fs");
3419
- var import_node_child_process19 = require("node:child_process");
3419
+ var import_node_child_process20 = require("node:child_process");
3420
3420
 
3421
3421
  // src/cli-shared.ts
3422
3422
  var import_node_child_process3 = require("node:child_process");
@@ -11802,10 +11802,10 @@ var rollout_plan_default = {
11802
11802
  note: "The v4.0.0 stamp happens at cut time (D6e #4463); until then the candidate is the origin/development head artifacts (built cli/dist + npm pack), identity proven by dist content hash (D6a)."
11803
11803
  },
11804
11804
  baseline: {
11805
- version: "4.2.2",
11806
- tag: "v4.2.2",
11807
- commit: "c347a86b94cc",
11808
- npm: "@mutmutco/cli@4.2.2"
11805
+ version: "4.2.3",
11806
+ tag: "v4.2.3",
11807
+ commit: "a54078f2ac92",
11808
+ npm: "@mutmutco/cli@4.2.3"
11809
11809
  },
11810
11810
  exitCriterion: "fleet-n-of-n",
11811
11811
  hubOnlyShortcut: "forbidden",
@@ -11822,14 +11822,14 @@ var rollout_plan_default = {
11822
11822
  repo: "mutmutco/mmi-hub",
11823
11823
  role: "canary",
11824
11824
  schedule: "train",
11825
- v3Target: "v4.2.2"
11825
+ v3Target: "v4.2.3"
11826
11826
  }
11827
11827
  ],
11828
11828
  rollbackTrigger: "Any red inside the post-contract soak window: `devops train gate` FAIL attributable to the v4 doors, Hub endpoint health probe failure, a pre-v4 client admitted instead of receiving actionable HTTP 426, or npm consumer install/doctor failure on the v4-only dist.",
11829
11829
  rollback: {
11830
11830
  independent: true,
11831
- mechanism: "npm dist-tag latest -> 4.2.2 and redeploy the Hub Lambda from tag v4.2.2 (c347a86b94cc); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
11832
- v3Target: "v4.2.2 (@mutmutco/cli@4.2.2, tag commit c347a86b94cc \u2014 last known-good release carrying the repo-index v4-only contract)"
11831
+ mechanism: "npm dist-tag latest -> 4.2.3 and redeploy the Hub Lambda from tag v4.2.3 (a54078f2ac92); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
11832
+ v3Target: "v4.2.3 (@mutmutco/cli@4.2.3, tag commit a54078f2ac92 \u2014 last known-good release carrying the repo-index v4-only contract)"
11833
11833
  }
11834
11834
  },
11835
11835
  {
@@ -24031,6 +24031,11 @@ function renderSweep(r) {
24031
24031
 
24032
24032
  // src/hotfix-apply.ts
24033
24033
  var HOTFIX_RELEASE_WORKFLOWS = ["deploy.yml", "publish.yml"];
24034
+ function hotfixStatusWorkflows(deployModel) {
24035
+ if (deployModel === "registry-publish") return ["publish.yml"];
24036
+ if (deployModel === void 0 || deployModel === "hub-serverless" || deployModel === "tenant-container" || deployModel === "solo-container") return HOTFIX_RELEASE_WORKFLOWS;
24037
+ return [];
24038
+ }
24034
24039
  var HOTFIX_RUN_FIND_ATTEMPTS = 10;
24035
24040
  var HOTFIX_RUN_FIND_DELAY_MS = 15e3;
24036
24041
  var HOTFIX_VERIFY_ATTEMPTS = 5;
@@ -24666,29 +24671,35 @@ async function runHotfixStatus(deps, versionInput) {
24666
24671
  const work = (async () => {
24667
24672
  const ctx = await buildTrainApplyContext(deps);
24668
24673
  await deps.run("git", ["fetch", "origin", "--tags"]);
24674
+ let workflows = HOTFIX_RELEASE_WORKFLOWS;
24675
+ let warnings = [];
24676
+ try {
24677
+ workflows = hotfixStatusWorkflows(await resolveHotfixDeployModel(deps, ctx));
24678
+ } catch (e) {
24679
+ warnings = [`deploy model unverified (${e.message ?? e}) \u2014 probed the default deploy.yml+publish.yml run list, so an unproven run may hold the verdict at unverified`];
24680
+ }
24669
24681
  let tag;
24670
24682
  let version;
24671
- let warnings = [];
24672
24683
  if (versionInput) {
24673
24684
  ({ tag, version } = normalizeHotfixVersion(versionInput));
24674
24685
  } else {
24675
24686
  const latest = await deps.run("git", ["tag", "--list", "v[0-9]*.[0-9]*.[0-9]*", "--merged", "origin/main", "--sort=-v:refname"]).then((out) => out.split("\n").map((s) => s.trim()).find((t) => /^v\d+\.\d+\.\d+$/.test(t)));
24676
24687
  if (latest) {
24677
- const latestFacts = await gatherHotfixFacts(deps, ctx, latest, latest.slice(1));
24688
+ const latestFacts = await gatherHotfixFacts(deps, ctx, latest, latest.slice(1), workflows);
24678
24689
  const latestDerived = deriveHotfixState(latestFacts);
24679
24690
  if (latestDerived.state !== "complete") {
24680
24691
  return { ...ctx, command: "hotfix-status", ...latestFacts, ...latestDerived, warnings };
24681
24692
  }
24682
24693
  }
24683
- const found = await findInFlightHotfixVersion(deps, ctx, latest);
24684
- warnings = supersededHotfixWarnings(found.superseded, latest);
24694
+ const found = await findInFlightHotfixVersion(deps, ctx, latest, workflows);
24695
+ warnings = [...warnings, ...supersededHotfixWarnings(found.superseded, latest)];
24685
24696
  if (found.inFlight) {
24686
24697
  ({ tag, version } = found.inFlight);
24687
24698
  } else {
24688
24699
  ({ tag, version } = await deriveHotfixVersion(deps));
24689
24700
  }
24690
24701
  }
24691
- const facts = await gatherHotfixFacts(deps, ctx, tag, version);
24702
+ const facts = await gatherHotfixFacts(deps, ctx, tag, version, workflows);
24692
24703
  return { ...ctx, command: "hotfix-status", ...facts, ...deriveHotfixState(facts), warnings };
24693
24704
  })();
24694
24705
  let timer;
@@ -24707,7 +24718,7 @@ async function runHotfixStatus(deps, versionInput) {
24707
24718
  if (timer) clearTimeout(timer);
24708
24719
  }
24709
24720
  }
24710
- async function gatherHotfixFacts(deps, ctx, tag, version) {
24721
+ async function gatherHotfixFacts(deps, ctx, tag, version, workflows = HOTFIX_RELEASE_WORKFLOWS) {
24711
24722
  const branchExists = Boolean(clean3(await deps.run("git", ["ls-remote", "origin", `refs/heads/${hotfixBranch(tag)}`])));
24712
24723
  const pr2 = await findHotfixPr(deps, ctx, tag);
24713
24724
  const remoteTag = clean3(await deps.run("git", ["ls-remote", "origin", `refs/tags/${tag}`]));
@@ -24716,7 +24727,7 @@ async function gatherHotfixFacts(deps, ctx, tag, version) {
24716
24727
  const releaseExists = await hotfixReleaseExists(deps, ctx, tag);
24717
24728
  const runs = [];
24718
24729
  if (releaseExists && tagSha) {
24719
- for (const workflow of HOTFIX_RELEASE_WORKFLOWS) {
24730
+ for (const workflow of workflows) {
24720
24731
  try {
24721
24732
  const out = await deps.run("gh", [
24722
24733
  "run",
@@ -24772,7 +24783,7 @@ function supersededHotfixWarnings(superseded, latestMainTag) {
24772
24783
  if (superseded.length === 0) return [];
24773
24784
  return [`skipped superseded hotfix marker(s) ${superseded.join(", ")} \u2014 merged to main but never released and at/below the latest released tag ${latestMainTag ?? "(none)"}; later releases already absorbed them (#976). Not actionable \u2014 run mmi-cli devops hotfix start for a new fix.`];
24774
24785
  }
24775
- async function findInFlightHotfixVersion(deps, ctx, latestMainTag) {
24786
+ async function findInFlightHotfixVersion(deps, ctx, latestMainTag, workflows = HOTFIX_RELEASE_WORKFLOWS) {
24776
24787
  const tags = /* @__PURE__ */ new Set();
24777
24788
  const out = await deps.run("gh", [
24778
24789
  "pr",
@@ -24802,13 +24813,13 @@ async function findInFlightHotfixVersion(deps, ctx, latestMainTag) {
24802
24813
  const fresh = latestMainTag ? sorted.filter((t) => compareHotfixVersions(t, latestMainTag) > 0) : sorted;
24803
24814
  for (const tag of fresh) {
24804
24815
  const version = tag.slice(1);
24805
- const facts = await gatherHotfixFacts(deps, ctx, tag, version);
24816
+ const facts = await gatherHotfixFacts(deps, ctx, tag, version, workflows);
24806
24817
  if (deriveHotfixState(facts).state !== "complete") return { inFlight: { tag, version }, superseded: [] };
24807
24818
  }
24808
24819
  const stale = latestMainTag ? sorted.filter((t) => compareHotfixVersions(t, latestMainTag) <= 0) : [];
24809
24820
  const superseded = [];
24810
24821
  for (const tag of stale) {
24811
- const facts = await gatherHotfixFacts(deps, ctx, tag, tag.slice(1));
24822
+ const facts = await gatherHotfixFacts(deps, ctx, tag, tag.slice(1), workflows);
24812
24823
  if (deriveHotfixState(facts).state !== "complete") superseded.push(tag);
24813
24824
  }
24814
24825
  return { inFlight: null, superseded };
@@ -32419,7 +32430,53 @@ async function fetchRestCorePool(gh = defaultGhApi) {
32419
32430
  }
32420
32431
 
32421
32432
  // src/pr-create-docs-check.ts
32433
+ var import_node_child_process18 = require("node:child_process");
32422
32434
  var GIT_TIMEOUT_MS2 = 15e3;
32435
+ function catFileBatch(root, ref, paths) {
32436
+ if (paths.length === 0) return Promise.resolve([]);
32437
+ return new Promise((resolve6) => {
32438
+ const chunks = [];
32439
+ let settled = false;
32440
+ const child2 = (0, import_node_child_process18.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
32441
+ const finish = () => {
32442
+ if (settled) return;
32443
+ settled = true;
32444
+ clearTimeout(timer);
32445
+ resolve6(parseCatFileBatch(Buffer.concat(chunks), paths.length));
32446
+ };
32447
+ const timer = setTimeout(() => {
32448
+ child2.kill("SIGKILL");
32449
+ finish();
32450
+ }, GIT_TIMEOUT_MS2);
32451
+ timer.unref?.();
32452
+ child2.stdout.on("data", (c) => chunks.push(c));
32453
+ child2.on("error", finish);
32454
+ child2.stdin.on("error", () => {
32455
+ });
32456
+ child2.on("close", finish);
32457
+ child2.stdin.end(paths.map((path2) => `${ref}:${path2}
32458
+ `).join(""));
32459
+ });
32460
+ }
32461
+ function parseCatFileBatch(out, expected) {
32462
+ const results = [];
32463
+ let at = 0;
32464
+ while (results.length < expected) {
32465
+ const eol = out.indexOf(10, at);
32466
+ if (eol === -1) break;
32467
+ const header = out.toString("utf8", at, eol);
32468
+ at = eol + 1;
32469
+ if (header.endsWith(" missing")) {
32470
+ results.push(void 0);
32471
+ continue;
32472
+ }
32473
+ const size = Number(header.slice(header.lastIndexOf(" ") + 1));
32474
+ if (!Number.isInteger(size) || size < 0 || at + size > out.length) break;
32475
+ results.push(out.toString("utf8", at, at + size));
32476
+ at = at + size + 1;
32477
+ }
32478
+ return results;
32479
+ }
32423
32480
  function createPrCreateDocsIndexDeps() {
32424
32481
  return {
32425
32482
  worktreeRoot: async () => {
@@ -32448,20 +32505,13 @@ function createPrCreateDocsIndexDeps() {
32448
32505
  },
32449
32506
  listDocsAtRef: async (root, ref) => {
32450
32507
  try {
32451
- const { stdout } = await execFileP2("git", ["-C", root, "ls-tree", "-r", "--name-only", ref, "--", "docs"], { timeout: GIT_TIMEOUT_MS2 });
32452
- return stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
32508
+ const { stdout } = await execFileP2("git", ["-C", root, "ls-tree", "-r", "-z", "--name-only", ref, "--", "docs"], { timeout: GIT_TIMEOUT_MS2 });
32509
+ return stdout.split("\0").filter(Boolean);
32453
32510
  } catch {
32454
32511
  return [];
32455
32512
  }
32456
32513
  },
32457
- readAtRef: async (root, ref, path2) => {
32458
- try {
32459
- const { stdout } = await execFileP2("git", ["-C", root, "show", `${ref}:${path2}`], { timeout: GIT_TIMEOUT_MS2 });
32460
- return stdout;
32461
- } catch {
32462
- return void 0;
32463
- }
32464
- }
32514
+ readManyAtRef: (root, ref, paths) => catFileBatch(root, ref, paths)
32465
32515
  };
32466
32516
  }
32467
32517
  async function checkDocsIndexAtHead(opts, deps) {
@@ -32476,10 +32526,10 @@ async function checkDocsIndexAtHead(opts, deps) {
32476
32526
  const paths = await deps.listDocsAtRef(root, ref);
32477
32527
  if (!paths.includes(DOCS_INDEX_PATH)) return void 0;
32478
32528
  const relDocs = paths.filter((p) => p.startsWith("docs/") && p.endsWith(".md")).map((p) => p.slice("docs/".length)).filter(isRoutableDocsPath);
32479
- const [indexContent, docContents] = await Promise.all([
32480
- deps.readAtRef(root, ref, DOCS_INDEX_PATH),
32481
- Promise.all(relDocs.map((rel) => deps.readAtRef(root, ref, `docs/${rel}`)))
32482
- ]);
32529
+ const contents = await deps.readManyAtRef(root, ref, [DOCS_INDEX_PATH, ...relDocs.map((rel) => `docs/${rel}`)]);
32530
+ const [indexContent, ...docContents] = contents;
32531
+ if (contents.length !== relDocs.length + 1) return void 0;
32532
+ if (indexContent === void 0 || docContents.some((c) => c === void 0)) return void 0;
32483
32533
  const contentByPath = new Map(relDocs.map((rel, i) => [rel, docContents[i] ?? ""]));
32484
32534
  const atRefDeps = {
32485
32535
  listDocs: () => relDocs,
@@ -32495,7 +32545,7 @@ async function checkDocsIndexAtHead(opts, deps) {
32495
32545
  }
32496
32546
  return {
32497
32547
  ok: false,
32498
- detail: `${DOCS_INDEX_PATH} is stale at the commit this PR would open from \u2014 it no longer matches the docs/ tree there`,
32548
+ detail: `${DOCS_INDEX_PATH} is stale at the commit this PR would open from \u2014 it no longer matches the docs/ tree there (checked ${ref} over ${relDocs.length} indexed doc${relDocs.length === 1 ? "" : "s"})`,
32499
32549
  fix: "run `mmi-cli oracle docs index --write`, commit docs/index.md, and push again before retrying `pr create`"
32500
32550
  };
32501
32551
  }
@@ -36637,6 +36687,9 @@ function diagnoseSurface(evidence) {
36637
36687
  if (evidence.manifest === "invalid") return { ...base, state: "corrupt" };
36638
36688
  if (!evidence.releasedVersion) return { ...base, state: "freshness-unknown" };
36639
36689
  if (evidence.installedVersion && evidence.releasedVersion && compareVersions(evidence.installedVersion, evidence.releasedVersion) < 0) {
36690
+ if (evidence.stagedVersion && evidence.stagedVersion === evidence.releasedVersion) {
36691
+ return { ...base, state: "staged" };
36692
+ }
36640
36693
  return { ...base, state: "stale" };
36641
36694
  }
36642
36695
  return { ...base, state: "clean" };
@@ -36647,14 +36700,16 @@ function reloadInstruction(descriptor) {
36647
36700
  return `${verb} ${descriptor.displayName}`;
36648
36701
  }
36649
36702
  function planSurfaceRepair(diagnosis) {
36650
- if (diagnosis.state === "clean" || diagnosis.state === "pending-reload" || diagnosis.state === "skipped" || diagnosis.state === "freshness-unknown") return null;
36703
+ if (diagnosis.state === "clean" || diagnosis.state === "pending-reload" || diagnosis.state === "staged" || diagnosis.state === "skipped" || diagnosis.state === "freshness-unknown") return null;
36651
36704
  const descriptor = diagnosis.descriptor;
36652
36705
  if (descriptor.repairOwner === "mmi-hub") {
36653
36706
  return {
36654
36707
  supported: false,
36655
36708
  owner: "mmi-hub",
36656
36709
  changes: [],
36657
- instruction: `run \`mmi-hub update\` to converge the MMI-managed Hermes plugin, then ${reloadInstruction(descriptor)}`
36710
+ // #5833: name the SURFACE this row is about — the literal "Hermes plugin" sent every other
36711
+ // mmi-hub-owned surface (Claude Code included) chasing a different host that was already current.
36712
+ instruction: `run \`mmi-hub update\` to converge the MMI-managed ${descriptor.displayName} plugin, then ${reloadInstruction(descriptor)}`
36658
36713
  };
36659
36714
  }
36660
36715
  if (descriptor.repairOwner !== "mmi-cli") {
@@ -36681,6 +36736,8 @@ function buildSurfaceDoctorCheck(diagnosis) {
36681
36736
  skipped: "skipped \u2014 host not active",
36682
36737
  clean: diagnosis.repairDetail ? `clean \u2014 repaired and verified (${diagnosis.repairDetail})` : `clean${versions ? ` \u2014 ${versions}` : ""}`,
36683
36738
  "pending-reload": `pending ${descriptor.token === "hermes" ? "fresh process" : descriptor.reload === "workspace" ? "reload" : "restart"} \u2014 repaired to ${diagnosis.releasedVersion}, but ${diagnosis.installedVersion} is still the version this host has loaded${diagnosis.repairDetail ? ` (${diagnosis.repairDetail})` : ""}`,
36739
+ // #5833: the update already staged the released tree; the wording mirrors `mmi-hub status`.
36740
+ staged: `loaded ${diagnosis.installedVersion}; staged ${diagnosis.releasedVersion} for next launch \u2014 ${descriptor.token === "hermes" ? "start a fresh process" : descriptor.reload === "workspace" ? "reload" : "restart"} ${descriptor.displayName} to converge`,
36684
36741
  "freshness-unknown": `${diagnosis.installedVersion ?? "installed"} \u2014 freshness UNKNOWN, the published version could not be read`,
36685
36742
  stale: `stale${versions ? ` \u2014 ${versions}` : ""}`,
36686
36743
  missing: "missing \u2014 no install record",
@@ -36692,14 +36749,14 @@ function buildSurfaceDoctorCheck(diagnosis) {
36692
36749
  id: `${descriptor.token}-plugin`,
36693
36750
  surface: descriptor.token,
36694
36751
  state,
36695
- ok: state === "clean" || state === "skipped" || state === "pending-reload",
36752
+ ok: state === "clean" || state === "skipped" || state === "pending-reload" || state === "staged",
36696
36753
  ...state === "freshness-unknown" ? { reportOnly: true } : {},
36697
- // Nothing is broken, so this is not a ✗ — but it is the one OK row an operator must act on, and the
36754
+ // Nothing is broken, so this is not a ✗ — but these are the OK rows an operator must act on, and the
36698
36755
  // short default lane and the SessionStart banner both filter to failures unless a row says otherwise.
36699
- ...state === "pending-reload" ? { warn: true } : {},
36756
+ ...state === "pending-reload" || state === "staged" ? { warn: true } : {},
36700
36757
  label: `${descriptor.displayName} plugin`,
36701
36758
  detail: detailByState[state],
36702
- ...plan ? { fix: plan.instruction } : state === "pending-reload" ? { fix: reloadInstruction(descriptor) } : state === "freshness-unknown" ? { fix: "check `mmi-cli --version` against `npm view @mutmutco/cli version`, then rerun doctor" } : {},
36759
+ ...plan ? { fix: plan.instruction } : state === "pending-reload" || state === "staged" ? { fix: reloadInstruction(descriptor) } : state === "freshness-unknown" ? { fix: "check `mmi-cli --version` against `npm view @mutmutco/cli version`, then rerun doctor" } : {},
36703
36760
  verbose: [
36704
36761
  // The three numbers the legacy builder used to print. They belong here now that this is the only
36705
36762
  // plugin row, and a report that names a state without naming the versions behind it is not evidence.
@@ -37807,7 +37864,7 @@ function ghAccountCaveat(announcedLogin, accounts) {
37807
37864
  var import_node_fs42 = require("node:fs");
37808
37865
  var import_node_os18 = require("node:os");
37809
37866
  var import_node_path39 = require("node:path");
37810
- var import_node_child_process18 = require("node:child_process");
37867
+ var import_node_child_process19 = require("node:child_process");
37811
37868
  var import_node_util8 = require("node:util");
37812
37869
 
37813
37870
  // src/discard-sink.ts
@@ -37816,13 +37873,13 @@ function nodeDiscardSinkPath(platform2 = process.platform) {
37816
37873
  }
37817
37874
 
37818
37875
  // src/doctor-io.ts
37819
- var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process18.execFile);
37876
+ var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process19.execFile);
37820
37877
  function execFileCapture(file, args, opts = {}) {
37821
37878
  const sink = nodeDiscardSinkPath();
37822
37879
  const inFd = (0, import_node_fs42.openSync)(sink, "r");
37823
37880
  const errFd = (0, import_node_fs42.openSync)(sink, "w");
37824
37881
  try {
37825
- return (0, import_node_child_process18.execFileSync)(file, args, {
37882
+ return (0, import_node_child_process19.execFileSync)(file, args, {
37826
37883
  ...opts,
37827
37884
  encoding: "utf8",
37828
37885
  stdio: [inFd, "pipe", errFd]
@@ -37833,6 +37890,18 @@ function execFileCapture(file, args, opts = {}) {
37833
37890
  }
37834
37891
  }
37835
37892
  var MMI_PLUGIN_ID2 = "mmi@mutmutco";
37893
+ function stagedClaudePluginVersion() {
37894
+ try {
37895
+ const stagingRoot = (0, import_node_path39.join)((0, import_node_os18.homedir)(), ".claude", "plugins", "staging");
37896
+ const record = JSON.parse((0, import_node_fs42.readFileSync)((0, import_node_path39.join)(stagingRoot, "launch-target.json"), "utf8"));
37897
+ if (typeof record.target !== "string" || typeof record.incoming !== "string") return void 0;
37898
+ const manifest = JSON.parse((0, import_node_fs42.readFileSync)((0, import_node_path39.join)(record.incoming, ".claude-plugin", "plugin.json"), "utf8"));
37899
+ if (typeof manifest.version !== "string") return void 0;
37900
+ return manifest.version === record.target ? record.target : void 0;
37901
+ } catch {
37902
+ return void 0;
37903
+ }
37904
+ }
37836
37905
  function installedClaudePluginVersion() {
37837
37906
  try {
37838
37907
  const file = JSON.parse(
@@ -38091,6 +38160,7 @@ function mmiDoctorDeps(opts = {}) {
38091
38160
  const hermes = token === "hermes" ? readHermesPluginEvidence(process.env) : void 0;
38092
38161
  const kimi = token === "kimi" ? kimiPluginHostEvidence(surfaceConfigRoot("kimi")) : void 0;
38093
38162
  const installedVersion = hermes?.installedVersion ?? installedSurfacePluginVersion(runtimeSurface);
38163
+ const stagedVersion = token === "claude" ? stagedClaudePluginVersion() : void 0;
38094
38164
  surfaceEvidence = {
38095
38165
  descriptor,
38096
38166
  // Hermes' root is the host evidence: a configured but uninstalled MMI tree is missing, while an
@@ -38102,7 +38172,8 @@ function mmiDoctorDeps(opts = {}) {
38102
38172
  manifest: hermes?.manifest ?? (installedVersion ? "valid" : snapshot.installRecordPresent ? "invalid" : "missing"),
38103
38173
  guardState: buildPluginGuardDecision(snapshot).state,
38104
38174
  ...kimi?.receipt ? { receipt: kimi.receipt } : {},
38105
- ...installedVersion ? { installedVersion } : {}
38175
+ ...installedVersion ? { installedVersion } : {},
38176
+ ...stagedVersion ? { stagedVersion } : {}
38106
38177
  };
38107
38178
  return surfaceEvidence;
38108
38179
  };
@@ -38751,7 +38822,7 @@ function scheduleRelatedDiscovery(o) {
38751
38822
  try {
38752
38823
  const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
38753
38824
  if (o.repo) args.push("--repo", o.repo);
38754
- spawnDetachedSelf(args, { spawn: import_node_child_process19.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
38825
+ spawnDetachedSelf(args, { spawn: import_node_child_process20.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
38755
38826
  } catch {
38756
38827
  }
38757
38828
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.2.2",
3
+ "version": "4.2.3",
4
4
  "description": "MMI Future CLI — the org dev toolbox and shared cross-IDE engine for every registry-declared MMI coding surface.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",