@mutmutco/codex-plugin 4.6.39 → 4.6.41

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mmi",
3
- "version": "4.6.39",
3
+ "version": "4.6.41",
4
4
  "mmiCompat": "4.x",
5
5
  "description": "MMI workflow skills and org gates delivery.",
6
6
  "author": {
package/cli/dist/main.cjs CHANGED
@@ -19611,6 +19611,48 @@ function isValidSecretKey(key) {
19611
19611
  function stripTrailingCRLF(value) {
19612
19612
  return value.replace(/\r\n$|\r$|\n$/, "");
19613
19613
  }
19614
+ function countCaptureGroups(source) {
19615
+ let count = 0;
19616
+ let inClass = false;
19617
+ for (let i = 0; i < source.length; i += 1) {
19618
+ const ch = source[i];
19619
+ if (ch === "\\") {
19620
+ i += 1;
19621
+ continue;
19622
+ }
19623
+ if (inClass) {
19624
+ if (ch === "]") inClass = false;
19625
+ continue;
19626
+ }
19627
+ if (ch === "[") {
19628
+ inClass = true;
19629
+ continue;
19630
+ }
19631
+ if (ch !== "(") continue;
19632
+ if (source[i + 1] !== "?") {
19633
+ count += 1;
19634
+ continue;
19635
+ }
19636
+ if (source[i + 2] === "<" && source[i + 3] !== "=" && source[i + 3] !== "!") count += 1;
19637
+ }
19638
+ return count;
19639
+ }
19640
+ function compileExtractRegex(source) {
19641
+ let re;
19642
+ try {
19643
+ re = new RegExp(source);
19644
+ } catch {
19645
+ return { ok: false, reason: "syntax" };
19646
+ }
19647
+ if (countCaptureGroups(source) !== 1) return { ok: false, reason: "capture-groups" };
19648
+ return { ok: true, re };
19649
+ }
19650
+ function extractSingleMatch(text, re) {
19651
+ const flags = re.flags.includes("g") ? re.flags : `${re.flags}g`;
19652
+ const all = [...text.matchAll(new RegExp(re.source, flags))];
19653
+ if (all.length !== 1) return { ok: false, count: all.length };
19654
+ return { ok: true, value: all[0][1] ?? "" };
19655
+ }
19614
19656
  var ORG_WIDE_SLUGS = /* @__PURE__ */ new Set([ORG_INFRA_SLUG, "shared", "cloudflare", "docs", "mmi-hub"]);
19615
19657
  function classifyTier(slug, _key) {
19616
19658
  return ORG_WIDE_SLUGS.has(slug) ? "org" : "project";
@@ -21231,6 +21273,64 @@ async function secretsSet(deps, key, opts) {
21231
21273
  }
21232
21274
  return putSecret(deps, key, value, opts);
21233
21275
  }
21276
+ async function secretsSetFromClipboard(deps, key, opts) {
21277
+ let value;
21278
+ try {
21279
+ if (!isValidSecretKey(key)) {
21280
+ deps.err(`invalid secret key ${JSON.stringify(key)}`);
21281
+ return false;
21282
+ }
21283
+ let re;
21284
+ if (opts.extract !== void 0) {
21285
+ const compiled = compileExtractRegex(opts.extract);
21286
+ if (!compiled.ok) {
21287
+ deps.err(
21288
+ compiled.reason === "syntax" ? "secrets set: --extract is not a valid regular expression \u2014 aborted (nothing written)" : "secrets set: --extract must contain exactly one capture group, e.g. '--token\\s+(\\S+)' \u2014 aborted (nothing written)"
21289
+ );
21290
+ return false;
21291
+ }
21292
+ re = compiled.re;
21293
+ }
21294
+ if (!deps.readClipboard) {
21295
+ deps.err("secrets set: --from-clipboard is not available in this build \u2014 aborted (nothing written)");
21296
+ return false;
21297
+ }
21298
+ let text;
21299
+ try {
21300
+ text = await deps.readClipboard();
21301
+ } catch (e) {
21302
+ deps.err(`secrets set: --from-clipboard: ${e.message}`);
21303
+ return false;
21304
+ }
21305
+ if (re) {
21306
+ const matched = extractSingleMatch(text, re);
21307
+ if (!matched.ok) {
21308
+ deps.err(
21309
+ matched.count === 0 ? "secrets set: --from-clipboard: --extract found no match (0 matches) \u2014 aborted (nothing written)" : `secrets set: --from-clipboard: --extract matched ${matched.count} times \u2014 need exactly one; aborted (nothing written)`
21310
+ );
21311
+ return false;
21312
+ }
21313
+ value = stripTrailingCRLF(matched.value);
21314
+ } else {
21315
+ value = stripTrailingCRLF(text);
21316
+ }
21317
+ if (!value) {
21318
+ deps.err(`secrets set: --from-clipboard: empty value for ${key} \u2014 aborted (nothing written)`);
21319
+ return false;
21320
+ }
21321
+ const ok = await putSecret(deps, key, value, opts);
21322
+ if (ok) deps.log(`set ${key} (${value.length} chars)`);
21323
+ return ok;
21324
+ } finally {
21325
+ if (deps.writeClipboard) {
21326
+ try {
21327
+ await deps.writeClipboard("");
21328
+ } catch (e) {
21329
+ deps.err(`secrets set: warning: could not clear the clipboard \u2014 ${e.message}`);
21330
+ }
21331
+ }
21332
+ }
21333
+ }
21234
21334
  var DECLARE_KEY_RE = /^[A-Za-z][A-Za-z0-9_]*$/;
21235
21335
  var DECLARE_STAGES = /* @__PURE__ */ new Set(["dev", "rc", "main"]);
21236
21336
  var DECLARE_CONSUMERS = /* @__PURE__ */ new Set(["runtime", "build", "lambda", "actions", "agent", "box"]);
@@ -22469,7 +22569,10 @@ async function boardDoctor(options, deps = {}) {
22469
22569
  const holderProvenDead = Boolean(
22470
22570
  evidence.marker && evidence.sessionState === "dead" && isHostSessionId(evidence.marker.session) && !evidence.openPr && !evidence.branch
22471
22571
  );
22472
- const freshMarker = evidence.sessionState === "live" || evidence.sessionState !== "dead" && evidence.markerAgeMs !== void 0 && evidence.markerAgeMs < CLAIM_MARKER_LIVE_MS;
22572
+ const freshMarker = evidence.marker ? !claimStampStaleness(evidence.marker, {
22573
+ activityAt: [evidence.lastCommentAt],
22574
+ sessionState: evidence.sessionState
22575
+ }).stale : false;
22473
22576
  const bits = [
22474
22577
  evidence.marker ? `claim marker ${describeClaimMarker(evidence.marker)} ${formatClaimAge(evidence.markerAgeMs)} old` + (evidence.sessionState ? `; local session ${evidence.sessionState}` : "") : evidence.failed.includes("comments") ? "claim marker unreadable" : "no claim marker",
22475
22578
  evidence.openPr,
@@ -23709,6 +23812,9 @@ function parseClaimReleases(body) {
23709
23812
  }
23710
23813
  return out;
23711
23814
  }
23815
+ function isClaimStampComment(body) {
23816
+ return parseClaimMarkers(body).length > 0 || parseClaimReleases(body).length > 0;
23817
+ }
23712
23818
  function renderClaimReleaseBody(release) {
23713
23819
  return `Released by \`${formatSessionIdentity(release)}\` at ${release.ts}.
23714
23820
 
@@ -23759,19 +23865,27 @@ function boardItemClaim(item) {
23759
23865
  function claimStampStaleness(marker, evidence = {}, now = Date.now()) {
23760
23866
  const times = [marker.ts, ...evidence.activityAt ?? []].map((t) => t ? Date.parse(t) : Number.NaN);
23761
23867
  const idleMs = now - Math.max(...times.filter(Number.isFinite));
23762
- return { stale: !evidence.linkedWork && idleMs >= CLAIM_STAMP_IDLE_MS, idleMs };
23868
+ if (evidence.sessionState === "live") return { stale: false, idleMs };
23869
+ if (evidence.linkedWork) return { stale: false, idleMs };
23870
+ return { stale: evidence.sessionState === "dead" || idleMs >= CLAIM_STAMP_IDLE_MS, idleMs };
23763
23871
  }
23764
23872
  function workIsLive(at, now = Date.now()) {
23765
23873
  const idle = now - Date.parse(at ?? "");
23766
23874
  return !Number.isFinite(idle) || idle < CLAIM_STAMP_IDLE_MS;
23767
23875
  }
23768
23876
  function claimFromMarker(item, marker, linked = {}, now = Date.now()) {
23877
+ const sessionState = linked.sessionState ?? probeLocalClaimSession(marker);
23769
23878
  return {
23770
23879
  marker,
23771
23880
  holder: describeClaimMarker(marker),
23772
23881
  ageMs: now - Date.parse(marker.ts),
23773
23882
  currentlyClaimed: item.assignees.length > 0 && item.status === "In Progress",
23774
- ...claimStampStaleness(marker, { activityAt: [...linked.activityAt ?? []], linkedWork: linked.linkedWork }, now)
23883
+ ...sessionState ? { sessionState } : {},
23884
+ ...claimStampStaleness(marker, {
23885
+ activityAt: [...linked.activityAt ?? []],
23886
+ linkedWork: linked.linkedWork,
23887
+ ...sessionState ? { sessionState } : {}
23888
+ }, now)
23775
23889
  };
23776
23890
  }
23777
23891
  function latestClaimMarkerAuthor(comments) {
@@ -23783,14 +23897,15 @@ function latestClaimMarkerAuthor(comments) {
23783
23897
  }
23784
23898
  return void 0;
23785
23899
  }
23786
- function classifyClaimableMarker(comments, actor, now = Date.now(), activityAt = [], viewerLogin) {
23900
+ function classifyClaimableMarker(comments, actor, now = Date.now(), activityAt = [], viewerLogin, sessionState) {
23787
23901
  const marker = comments ? latestClaimMarker(comments) : void 0;
23788
23902
  if (!marker) return { verdict: "claimable" };
23789
23903
  const markerBy = comments ? latestClaimMarkerAuthor(comments) : void 0;
23790
- if (isSeatClaimMarker(marker, actor, { viewerLogin: viewerLogin ?? markerBy, markerBy, now })) {
23904
+ const state = sessionState ?? probeLocalClaimSession(marker);
23905
+ if (isSeatClaimMarker(marker, actor, { viewerLogin: viewerLogin ?? markerBy, markerBy, now, sessionState: state })) {
23791
23906
  return { verdict: "owned", holder: describeClaimMarker(marker) };
23792
23907
  }
23793
- if (!claimStampStaleness(marker, { activityAt }, now).stale) {
23908
+ if (!claimStampStaleness(marker, { activityAt, sessionState: state }, now).stale) {
23794
23909
  return { verdict: "taken", holder: describeClaimMarker(marker) };
23795
23910
  }
23796
23911
  return { verdict: "claimable" };
@@ -23845,10 +23960,12 @@ async function markStaleClaimStamps(scope, readComments, options = {}) {
23845
23960
  markerBy: markerBy ?? (bucket === "userOwned" ? item.assignees[0] : void 0),
23846
23961
  now
23847
23962
  });
23963
+ const sessionState = (options.probeSessionState ?? probeLocalClaimSession)(marker);
23848
23964
  const prs = (options.pullRequests ?? []).filter((pr) => pr.closesIssues.some((ref) => ref.toLowerCase() === item.ref.toLowerCase()));
23849
23965
  item.claim = claimFromMarker(item, marker, {
23850
23966
  activityAt: prs.map((pr) => pr.updatedAt),
23851
- linkedWork: prs.some((pr) => !pr.updatedAt)
23967
+ linkedWork: prs.some((pr) => !pr.updatedAt),
23968
+ ...sessionState ? { sessionState } : {}
23852
23969
  }, now);
23853
23970
  if (ownSeat && bucket !== "userOwned" && bucket !== "claimable") {
23854
23971
  kept.pop();
@@ -23920,9 +24037,25 @@ async function demoteLiveClaimedClaimables(scope, client, actor = describeSessio
23920
24037
  var CLAIM_SESSION_ACTIVITY_MS = 30 * 6e4;
23921
24038
  var CLAIM_SESSION_PROBE_CACHE_MS = 6e4;
23922
24039
  var claimSessionProbeCache = /* @__PURE__ */ new Map();
23923
- function probeLocalClaimSession(marker, now = Date.now()) {
24040
+ function scanSessionTranscripts(root, matches, now) {
24041
+ const pending = [root];
24042
+ while (pending.length) {
24043
+ const dir = pending.pop();
24044
+ for (const entry of (0, import_node_fs18.readdirSync)(dir, { withFileTypes: true })) {
24045
+ const path2 = (0, import_node_path15.join)(dir, entry.name);
24046
+ if (entry.isDirectory()) pending.push(path2);
24047
+ else if (entry.isFile() && matches(entry.name.toLowerCase())) {
24048
+ return now - (0, import_node_fs18.statSync)(path2).mtimeMs <= CLAIM_SESSION_ACTIVITY_MS ? "live" : "dead";
24049
+ }
24050
+ }
24051
+ }
24052
+ return "dead";
24053
+ }
24054
+ function probeLocalClaimSession(marker, now = Date.now(), roots = {}) {
23924
24055
  if (!isHostSessionId(marker.session) || !marker.host || marker.host.toLowerCase() !== (0, import_node_os11.hostname)().toLowerCase()) return void 0;
23925
- if (!marker.surface?.toLowerCase().startsWith("claude")) return void 0;
24056
+ const surface = marker.surface?.toLowerCase() ?? "";
24057
+ const kind = surface.startsWith("claude") ? "claude" : surface.startsWith("jerv") || surface.startsWith("pi") ? "jerv" : void 0;
24058
+ if (!kind) return void 0;
23926
24059
  const cacheKey = `${marker.host.toLowerCase()}/${marker.session}`;
23927
24060
  const cached = claimSessionProbeCache.get(cacheKey);
23928
24061
  if (cached && now - cached.checkedAt <= CLAIM_SESSION_PROBE_CACHE_MS) return cached.state;
@@ -23930,21 +24063,10 @@ function probeLocalClaimSession(marker, now = Date.now()) {
23930
24063
  claimSessionProbeCache.set(cacheKey, { checkedAt: now, state });
23931
24064
  return state;
23932
24065
  };
23933
- const root = (0, import_node_path15.join)((0, import_node_os11.homedir)(), ".claude", "projects");
23934
- try {
23935
- const wanted = `${marker.session}.jsonl`.toLowerCase();
23936
- const pending = [root];
23937
- while (pending.length) {
23938
- const dir = pending.pop();
23939
- for (const entry of (0, import_node_fs18.readdirSync)(dir, { withFileTypes: true })) {
23940
- const path2 = (0, import_node_path15.join)(dir, entry.name);
23941
- if (entry.isDirectory()) pending.push(path2);
23942
- else if (entry.isFile() && entry.name.toLowerCase() === wanted) {
23943
- return remember(now - (0, import_node_fs18.statSync)(path2).mtimeMs <= CLAIM_SESSION_ACTIVITY_MS ? "live" : "dead");
23944
- }
23945
- }
23946
- }
23947
- return remember("dead");
24066
+ try {
24067
+ const session = marker.session.toLowerCase();
24068
+ const state = kind === "claude" ? scanSessionTranscripts(roots.claude ?? (0, import_node_path15.join)((0, import_node_os11.homedir)(), ".claude", "projects"), (name) => name === `${session}.jsonl`, now) : scanSessionTranscripts(roots.jerv ?? (0, import_node_path15.join)((0, import_node_os11.homedir)(), ".jerv", "agent", "sessions"), (name) => name.endsWith(`_${session}.jsonl`), now);
24069
+ return remember(state);
23948
24070
  } catch {
23949
24071
  return remember("unverifiable");
23950
24072
  }
@@ -23992,7 +24114,7 @@ async function gatherClaimLiveness(client, repo, number, fetchOpenPulls) {
23992
24114
  out.marker = latestClaimMarker(rows);
23993
24115
  if (!out.marker) out.releasedAt = latestClaimRelease(rows)?.ts;
23994
24116
  for (let i = comments.length - 1; i >= 0; i -= 1) {
23995
- if (comments[i].created_at && !latestClaimMarker([rows[i]])) {
24117
+ if (comments[i].created_at && !isClaimStampComment(rows[i].body)) {
23996
24118
  out.lastCommentAt = comments[i].created_at;
23997
24119
  break;
23998
24120
  }
@@ -24067,7 +24189,7 @@ function liveEvidenceLines(evidence, repo) {
24067
24189
  if (evidence.marker && evidence.sessionState === "live") {
24068
24190
  live.push(`claim session ${describeClaimMarker(evidence.marker)} has recent local transcript activity`);
24069
24191
  } else if (evidence.marker && evidence.sessionState !== "dead") {
24070
- const { stale, idleMs } = claimStampStaleness(evidence.marker, { activityAt: [evidence.lastCommentAt] });
24192
+ const { stale, idleMs } = claimStampStaleness(evidence.marker, { activityAt: [evidence.lastCommentAt], sessionState: evidence.sessionState });
24071
24193
  const marker = describeClaimMarker(evidence.marker);
24072
24194
  if (!stale) {
24073
24195
  live.push(evidence.lastCommentAt && Date.parse(evidence.lastCommentAt) > Date.parse(evidence.marker.ts) ? `claim marker from ${marker} is ${formatClaimAge(evidence.markerAgeMs)} old but the issue was commented ${formatClaimAge(idleMs)} ago (session not locally probeable)` : `claim marker from ${marker} is only ${formatClaimAge(evidence.markerAgeMs)} old (session not locally probeable)`);
@@ -24161,7 +24283,7 @@ async function checkLaneContest(client, item, actor = describeSessionIdentity(),
24161
24283
  }
24162
24284
  }
24163
24285
  const carry = staleWorkLines(evidence);
24164
- const staleStamp = !contested && !resume && !ownSeat && evidence.marker ? `stale claim stamp ${describeClaimMarker(evidence.marker)} (idle ${formatClaimAge(claimStampStaleness(evidence.marker, { activityAt: [evidence.lastCommentAt] }).idleMs)})${carry.length ? `; continue its ${carry.join(" and ")}` : ""}` : void 0;
24286
+ const staleStamp = !contested && !resume && !ownSeat && evidence.marker ? `stale claim stamp ${describeClaimMarker(evidence.marker)} (idle ${formatClaimAge(claimStampStaleness(evidence.marker, { activityAt: [evidence.lastCommentAt], sessionState: evidence.sessionState }).idleMs)})${carry.length ? `; continue its ${carry.join(" and ")}` : ""}` : void 0;
24165
24287
  return {
24166
24288
  contested,
24167
24289
  live,
@@ -28405,10 +28527,10 @@ var rollout_plan_default = {
28405
28527
  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)."
28406
28528
  },
28407
28529
  baseline: {
28408
- version: "4.6.39",
28409
- tag: "v4.6.39",
28410
- commit: "2669c496b69e",
28411
- npm: "@mutmutco/cli@4.6.39"
28530
+ version: "4.6.41",
28531
+ tag: "v4.6.41",
28532
+ commit: "2cf5b22abb64",
28533
+ npm: "@mutmutco/cli@4.6.41"
28412
28534
  },
28413
28535
  exitCriterion: "fleet-n-of-n",
28414
28536
  hubOnlyShortcut: "forbidden",
@@ -28425,14 +28547,14 @@ var rollout_plan_default = {
28425
28547
  repo: "mutmutco/mmi-hub",
28426
28548
  role: "canary",
28427
28549
  schedule: "train",
28428
- v3Target: "v4.6.39"
28550
+ v3Target: "v4.6.41"
28429
28551
  }
28430
28552
  ],
28431
28553
  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.",
28432
28554
  rollback: {
28433
28555
  independent: true,
28434
- mechanism: "npm dist-tag latest -> 4.6.39 and redeploy the Hub Lambda from tag v4.6.39 (2669c496b69e); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
28435
- v3Target: "v4.6.39 (@mutmutco/cli@4.6.39, tag commit 2669c496b69e \u2014 last known-good release carrying the repo-index v4-only contract)"
28556
+ mechanism: "npm dist-tag latest -> 4.6.41 and redeploy the Hub Lambda from tag v4.6.41 (2cf5b22abb64); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
28557
+ v3Target: "v4.6.41 (@mutmutco/cli@4.6.41, tag commit 2cf5b22abb64 \u2014 last known-good release carrying the repo-index v4-only contract)"
28436
28558
  }
28437
28559
  },
28438
28560
  {
@@ -47190,7 +47312,7 @@ async function assignPersistedPortRange(repo, slug, reg, opts) {
47190
47312
 
47191
47313
  // src/box-commands.ts
47192
47314
  var import_node_fs39 = require("node:fs");
47193
- var import_node_child_process12 = require("node:child_process");
47315
+ var import_node_child_process13 = require("node:child_process");
47194
47316
  var import_node_os20 = require("node:os");
47195
47317
  var import_node_path36 = require("node:path");
47196
47318
 
@@ -47418,6 +47540,7 @@ init_cli_shared();
47418
47540
 
47419
47541
  // src/secrets-commands.ts
47420
47542
  var import_node_fs37 = require("node:fs");
47543
+ var import_node_child_process12 = require("node:child_process");
47421
47544
  var import_node_path34 = require("node:path");
47422
47545
  var import_node_os19 = require("node:os");
47423
47546
  init_cli_shared();
@@ -48684,9 +48807,122 @@ function makeSecretsDeps(cfg) {
48684
48807
  slug: async () => (await repoProject(cfg)).toLowerCase(),
48685
48808
  readSecretValue: () => readSecretStdin(),
48686
48809
  log: (m) => console.log(m),
48687
- err: (m) => console.error(m)
48810
+ err: (m) => console.error(m),
48811
+ // #10056: the sanctioned clipboard handoff — read/write the OS clipboard directly, never through a
48812
+ // shell, so a pasted value cannot be re-parsed by cmd.exe/PowerShell.
48813
+ readClipboard: () => readClipboardText(),
48814
+ writeClipboard: (value) => clearClipboard(value)
48688
48815
  };
48689
48816
  }
48817
+ var CLIPBOARD_TIMEOUT_MS = 1e4;
48818
+ function clipboardReadCommands(platform2) {
48819
+ if (platform2 === "win32") return [{ cmd: "powershell", args: ["-NoProfile", "-Command", "Get-Clipboard -Raw"] }];
48820
+ if (platform2 === "darwin") return [{ cmd: "pbpaste", args: [] }];
48821
+ return [
48822
+ { cmd: "wl-paste", args: ["-n"] },
48823
+ { cmd: "xclip", args: ["-selection", "clipboard", "-o"] }
48824
+ ];
48825
+ }
48826
+ function clipboardClearCommands(platform2) {
48827
+ if (platform2 === "win32") return [{ cmd: "powershell", args: ["-NoProfile", "-Command", "Set-Clipboard -Value ' '"] }];
48828
+ if (platform2 === "darwin") return [{ cmd: "pbcopy", args: [], input: "" }];
48829
+ return [
48830
+ { cmd: "wl-copy", args: ["--clear"] },
48831
+ { cmd: "xclip", args: ["-selection", "clipboard"], input: "" }
48832
+ ];
48833
+ }
48834
+ function clipboardFailure(command, error) {
48835
+ const code = error.code;
48836
+ if (code === "ENOENT") return `${command.cmd}: not found`;
48837
+ if (typeof code === "number") return `${command.cmd}: exit ${code}`;
48838
+ return `${command.cmd}: could not run`;
48839
+ }
48840
+ function runClipboardCommand(command) {
48841
+ return new Promise((resolveRun, rejectRun) => {
48842
+ const child2 = (0, import_node_child_process12.spawn)(command.cmd, command.args, {
48843
+ shell: false,
48844
+ windowsHide: true,
48845
+ stdio: ["pipe", "pipe", "pipe"]
48846
+ });
48847
+ const out = [];
48848
+ let settled2 = false;
48849
+ const settle = (error, value) => {
48850
+ if (settled2) return;
48851
+ settled2 = true;
48852
+ clearTimeout(timer);
48853
+ if (error) rejectRun(error);
48854
+ else resolveRun(value ?? "");
48855
+ };
48856
+ const timer = setTimeout(() => {
48857
+ child2.kill();
48858
+ settle(new Error(`${command.cmd}: timed out`));
48859
+ }, CLIPBOARD_TIMEOUT_MS);
48860
+ timer.unref?.();
48861
+ child2.stdout?.on("data", (chunk) => out.push(chunk));
48862
+ child2.stderr?.on("data", () => {
48863
+ });
48864
+ child2.on("error", (e) => settle(e instanceof Error ? e : new Error(String(e))));
48865
+ child2.on("close", (code) => {
48866
+ if (code === 0) settle(void 0, Buffer.concat(out).toString("utf8"));
48867
+ else settle(Object.assign(new Error(`${command.cmd}: exit ${code}`), { code }));
48868
+ });
48869
+ child2.stdin?.on("error", () => {
48870
+ });
48871
+ child2.stdin?.end(command.input ?? "");
48872
+ });
48873
+ }
48874
+ async function readClipboardText(platform2 = process.platform) {
48875
+ const failures = [];
48876
+ for (const command of clipboardReadCommands(platform2)) {
48877
+ try {
48878
+ return await runClipboardCommand(command);
48879
+ } catch (e) {
48880
+ failures.push(clipboardFailure(command, e));
48881
+ }
48882
+ }
48883
+ throw new Error(`could not read the clipboard (${failures.join(", ")})`);
48884
+ }
48885
+ async function clearClipboard(value, platform2 = process.platform) {
48886
+ const failures = [];
48887
+ for (const command of clipboardClearCommands(platform2)) {
48888
+ try {
48889
+ await runClipboardCommand({ ...command, ...command.input !== void 0 ? { input: value } : {} });
48890
+ return;
48891
+ } catch (e) {
48892
+ failures.push(clipboardFailure(command, e));
48893
+ }
48894
+ }
48895
+ throw new Error(`${failures.join(", ")}`);
48896
+ }
48897
+ function clipboardSourceRefusal(fromClipboard, stdinHasData) {
48898
+ if (!fromClipboard || !stdinHasData) return null;
48899
+ return "secrets set: --from-clipboard conflicts with piped stdin \u2014 remove the pipe (the value comes from the clipboard), or drop --from-clipboard and pipe it";
48900
+ }
48901
+ async function stdinCarriesData(timeoutMs = 50) {
48902
+ const stdin = process.stdin;
48903
+ if (stdin.isTTY) return false;
48904
+ if (stdin.readableLength > 0) return true;
48905
+ return new Promise((resolveProbe) => {
48906
+ let settled2 = false;
48907
+ const finish = (value) => {
48908
+ if (settled2) return;
48909
+ settled2 = true;
48910
+ clearTimeout(timer);
48911
+ stdin.off("readable", onReadable);
48912
+ stdin.off("end", onEnd);
48913
+ resolveProbe(value);
48914
+ };
48915
+ const onReadable = () => {
48916
+ if (stdin.readableLength > 0) finish(true);
48917
+ };
48918
+ const onEnd = () => finish(false);
48919
+ const timer = setTimeout(() => finish(stdin.readableLength > 0), timeoutMs);
48920
+ timer.unref?.();
48921
+ stdin.once("readable", onReadable);
48922
+ stdin.once("end", onEnd);
48923
+ stdin.once("error", () => finish(false));
48924
+ });
48925
+ }
48690
48926
  async function withSecrets(run) {
48691
48927
  const cfg = await loadConfig();
48692
48928
  if (!cfg.sagaApiUrl) {
@@ -48833,10 +49069,22 @@ function registerSecretsCommands(program3) {
48833
49069
  if (!ok) process.exitCode = 1;
48834
49070
  }));
48835
49071
  const setHandler = (key, o) => withSecrets(async (d) => {
49072
+ if (o.fromClipboard) {
49073
+ const refusal = clipboardSourceRefusal(true, await stdinCarriesData());
49074
+ if (refusal) return fail(refusal);
49075
+ const ok2 = await secretsSetFromClipboard(d, key, {
49076
+ ...o.repo !== void 0 ? { repo: o.repo } : {},
49077
+ ...o.slug !== void 0 ? { slug: o.slug } : {},
49078
+ ...o.extract !== void 0 ? { extract: o.extract } : {}
49079
+ });
49080
+ if (!ok2) process.exitCode = 1;
49081
+ return;
49082
+ }
49083
+ if (o.extract !== void 0) return fail("secrets set: --extract needs --from-clipboard (it isolates the value inside copied text)");
48836
49084
  const ok = await secretsSet(d, key, o);
48837
49085
  if (!ok) process.exitCode = 1;
48838
49086
  });
48839
- secrets.command("set <key>").description("write/rotate a secret; value from stdin (never an argument). DECLARE-FIRST (#2528): the key must be a declared catalog coordinate \u2014 bare <KEY> = the stageless canonical, <stage>/<KEY> = a declared per-stage override; undeclared writes are rejected with the fix. --slug _org writes an org-infra <provider>/<KEY> coordinate (#3298) \u2014 master or an exact grant, declare-first enforced server-side").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--slug <slug>", "org-infra namespace (e.g. _org) for the value write \u2014 master or an exact grant (#3298)").action(setHandler);
49087
+ secrets.command("set <key>").description("write/rotate a secret; value from stdin (never an argument). DECLARE-FIRST (#2528): the key must be a declared catalog coordinate \u2014 bare <KEY> = the stageless canonical, <stage>/<KEY> = a declared per-stage override; undeclared writes are rejected with the fix. --slug _org writes an org-infra <provider>/<KEY> coordinate (#3298) \u2014 master or an exact grant, declare-first enforced server-side. --from-clipboard takes the value from the OS clipboard instead of stdin, extracts it with --extract, and CLEARS the clipboard afterwards \u2014 the sanctioned handoff for a secret embedded in copied text (#10056)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--slug <slug>", "org-infra namespace (e.g. _org) for the value write \u2014 master or an exact grant (#3298)").option("--from-clipboard", "read the value from the OS clipboard instead of stdin: powershell Get-Clipboard / pbpaste / wl-paste (xclip fallback). The clipboard is overwritten on EVERY path (success, no match, failed write). Conflicts with piped stdin").option("--extract <regex>", "with --from-clipboard: a regex with EXACTLY ONE capture group whose single match inside the copied text is the value, e.g. --extract '--token\\s+(\\S+)'. Zero or 2+ matches are refused (the count is reported, the text never is). Without --extract the whole clipboard, minus one trailing newline, is the value").action(setHandler);
48840
49088
  secrets.command("copy").description("copy provider keys between stages in your own project vault (audit-logged; encryption keys blocked)").requiredOption("--from <stage>", "source tier: dev, rc, or main").requiredOption("--to <stage>", "destination tier: dev, rc, or main").requiredOption("--keys <names>", "comma-separated secret names (encryption keys blocked)").option("--dry-run", "report copies without writing").option("--repo <owner/repo>", "target repo (defaults to the current repo)").action((o) => withSecrets(async (d) => {
48841
49089
  const stages = ["dev", "rc", "main"];
48842
49090
  if (!stages.includes(o.from) || !stages.includes(o.to)) {
@@ -49662,7 +49910,7 @@ var UsageError = class extends Error {
49662
49910
  var UnreadableError = class extends Error {
49663
49911
  };
49664
49912
  function hubGitShow(ref) {
49665
- const git3 = (args) => (0, import_node_child_process12.execFileSync)("git", args, { maxBuffer: 64 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
49913
+ const git3 = (args) => (0, import_node_child_process13.execFileSync)("git", args, { maxBuffer: 64 * 1024 * 1024, stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
49666
49914
  try {
49667
49915
  git3(["cat-file", "-e", `HEAD:${MANIFEST_PATH}`]);
49668
49916
  } catch {
@@ -49676,7 +49924,7 @@ function runOnBox(found, script) {
49676
49924
  try {
49677
49925
  const recipe = (0, import_node_path36.join)(dir, "recipe.sh");
49678
49926
  (0, import_node_fs39.writeFileSync)(recipe, sshRecipeScript(found, "sh -s"), "utf8");
49679
- const r = (0, import_node_child_process12.spawnSync)("bash", [recipe], { input: script, encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 18e4, windowsHide: true });
49927
+ const r = (0, import_node_child_process13.spawnSync)("bash", [recipe], { input: script, encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 18e4, windowsHide: true });
49680
49928
  if (r.status !== 0) {
49681
49929
  throw new UnreadableError(`box control: the ssh session to ${found.name} failed (exit ${r.status ?? r.signal}): ${(r.stderr || "").trim().split("\n").slice(-3).join(" | ")}`);
49682
49930
  }
@@ -54433,7 +54681,7 @@ async function runRcDataSwitch(deps, opts) {
54433
54681
  }
54434
54682
 
54435
54683
  // src/suite-train-io.ts
54436
- var import_node_child_process19 = require("node:child_process");
54684
+ var import_node_child_process20 = require("node:child_process");
54437
54685
  var import_node_path52 = require("node:path");
54438
54686
  var import_node_fs55 = require("node:fs");
54439
54687
  var import_node_path53 = require("node:path");
@@ -56022,13 +56270,13 @@ async function findInFlightHotfixVersion(deps, ctx, latestMainTag, workflows = H
56022
56270
  }
56023
56271
 
56024
56272
  // src/hotfix-coverage.ts
56025
- var import_node_child_process13 = require("node:child_process");
56273
+ var import_node_child_process14 = require("node:child_process");
56026
56274
  var CHERRY_TRAILER = /\(cherry picked from commit ([0-9a-f]{7,40})\)/g;
56027
56275
  var GIT_MAX_BUFFER = 512 * 1024 * 1024;
56028
56276
  function checkHotfixCoverage(options = {}) {
56029
56277
  const { cwd = process.cwd(), mainRef = "origin/main", rcRef = "origin/rc", manifestPaths = [] } = options;
56030
56278
  const ack = (options.ack ?? []).filter(Boolean);
56031
- const git3 = options.git ?? ((args, opts) => (0, import_node_child_process13.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: GIT_MAX_BUFFER }));
56279
+ const git3 = options.git ?? ((args, opts) => (0, import_node_child_process14.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: GIT_MAX_BUFFER }));
56032
56280
  const revList = (range) => {
56033
56281
  const out = git3(["rev-list", "--no-merges", range]).trim();
56034
56282
  return out ? out.split("\n") : [];
@@ -56096,7 +56344,7 @@ function checkHotfixCoverage(options = {}) {
56096
56344
  }
56097
56345
  function checkHotfixCarries(options) {
56098
56346
  const { cwd = process.cwd(), branch, baseRef, targets } = options;
56099
- const git3 = options.git ?? ((args, opts) => (0, import_node_child_process13.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: GIT_MAX_BUFFER }));
56347
+ const git3 = options.git ?? ((args, opts) => (0, import_node_child_process14.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"], maxBuffer: GIT_MAX_BUFFER }));
56100
56348
  const isAncestor = (sha, ref) => {
56101
56349
  try {
56102
56350
  git3(["merge-base", "--is-ancestor", sha, ref]);
@@ -57983,7 +58231,7 @@ function prTitleRefusal(title) {
57983
58231
  }
57984
58232
 
57985
58233
  // src/command-register-collaboration.ts
57986
- var import_node_child_process18 = require("node:child_process");
58234
+ var import_node_child_process19 = require("node:child_process");
57987
58235
  var import_node_fs54 = require("node:fs");
57988
58236
  var import_promises9 = require("node:fs/promises");
57989
58237
  init_clean_exit();
@@ -59521,7 +59769,7 @@ async function readAppApi(path2, runner = apiReadRunner) {
59521
59769
  return log ? Buffer.from(body, "latin1").toString("utf8") : out;
59522
59770
  }
59523
59771
  function registerApiReadCommands(program3, overrides) {
59524
- const spawn7 = overrides?.runner ?? apiReadRunner;
59772
+ const spawn8 = overrides?.runner ?? apiReadRunner;
59525
59773
  const jqRun = overrides?.jqRunner ?? systemJqRunner;
59526
59774
  let bindings = [];
59527
59775
  const runGet = async (req, o) => {
@@ -59541,7 +59789,7 @@ function registerApiReadCommands(program3, overrides) {
59541
59789
  let body;
59542
59790
  try {
59543
59791
  body = await runApiGet(
59544
- async (args, timeoutMs) => zip ? spawn7(args, ZIP_TIMEOUT_MS, env, true) : spawn7(args, timeoutMs, env),
59792
+ async (args, timeoutMs) => zip ? spawn8(args, ZIP_TIMEOUT_MS, env, true) : spawn8(args, timeoutMs, env),
59545
59793
  req.path,
59546
59794
  o.accept
59547
59795
  );
@@ -59787,7 +60035,7 @@ function registerRunLogRead(run, runner) {
59787
60035
 
59788
60036
  // src/app-read-broker.ts
59789
60037
  init_cli_shared();
59790
- var import_node_child_process14 = require("node:child_process");
60038
+ var import_node_child_process15 = require("node:child_process");
59791
60039
  var OWNER_REPO_RE = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
59792
60040
  var JSON_FIELD_RE = /^[A-Za-z0-9_,]+$/;
59793
60041
  var ID_RE = /^\d+$/;
@@ -59873,7 +60121,7 @@ function formatJqFailureMessage(code, stderr) {
59873
60121
  return `${base} \u2014 the expression is handed to jq verbatim (mmi-cli never re-quotes it), so if a shell or seat layer collapsed a backslash, use an escape-free form such as \`test("bundle[.]css")\` or \`contains("bundle.css")\`, or drop --jq and filter the JSON locally`;
59874
60122
  }
59875
60123
  var systemJqRunner = (expr, input, env, bindings) => new Promise((resolveOut, reject2) => {
59876
- const child2 = (0, import_node_child_process14.spawn)("jq", [...process.platform === "win32" ? ["--binary"] : [], "-r", "-c", ...(bindings ?? []).flatMap((b) => [b.kind, b.name, b.value]), expr], { env, stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
60124
+ const child2 = (0, import_node_child_process15.spawn)("jq", [...process.platform === "win32" ? ["--binary"] : [], "-r", "-c", ...(bindings ?? []).flatMap((b) => [b.kind, b.name, b.value]), expr], { env, stdio: ["pipe", "pipe", "pipe"], windowsHide: true });
59877
60125
  let stdout = "";
59878
60126
  let stderr = "";
59879
60127
  child2.stdout.setEncoding("utf8").on("data", (chunk) => {
@@ -61088,7 +61336,7 @@ function registerPrLifecycleCommands(program3) {
61088
61336
  }
61089
61337
 
61090
61338
  // src/review-verdict.ts
61091
- var import_node_child_process15 = require("node:child_process");
61339
+ var import_node_child_process16 = require("node:child_process");
61092
61340
  var import_node_fs49 = require("node:fs");
61093
61341
  var import_node_os25 = require("node:os");
61094
61342
  var import_node_path46 = require("node:path");
@@ -61188,8 +61436,8 @@ async function checkPrReview(number, repo, head, deps = {
61188
61436
  }
61189
61437
  function computePrPatchId(number, repo) {
61190
61438
  return new Promise((resolve8, reject2) => {
61191
- const gh2 = (0, import_node_child_process15.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
61192
- const git3 = (0, import_node_child_process15.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
61439
+ const gh2 = (0, import_node_child_process16.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
61440
+ const git3 = (0, import_node_child_process16.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
61193
61441
  let out = "";
61194
61442
  let ghErr = "";
61195
61443
  let gitErr = "";
@@ -61414,7 +61662,7 @@ async function observePrCreateClaims(body, repoOption, deps = {}) {
61414
61662
  }
61415
61663
 
61416
61664
  // src/pr-create-docs-check.ts
61417
- var import_node_child_process16 = require("node:child_process");
61665
+ var import_node_child_process17 = require("node:child_process");
61418
61666
  init_cli_shared();
61419
61667
  var GIT_TIMEOUT_MS2 = 15e3;
61420
61668
  function catFileBatch(root, ref, paths) {
@@ -61422,7 +61670,7 @@ function catFileBatch(root, ref, paths) {
61422
61670
  return new Promise((resolve8) => {
61423
61671
  const chunks = [];
61424
61672
  let settled2 = false;
61425
- const child2 = (0, import_node_child_process16.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
61673
+ const child2 = (0, import_node_child_process17.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
61426
61674
  const finish = (ok = false) => {
61427
61675
  if (settled2) return;
61428
61676
  settled2 = true;
@@ -61761,7 +62009,7 @@ var import_node_path49 = require("node:path");
61761
62009
  init_cli_shared();
61762
62010
 
61763
62011
  // src/stage-runner.ts
61764
- var import_node_child_process17 = require("node:child_process");
62012
+ var import_node_child_process18 = require("node:child_process");
61765
62013
  var import_node_fs51 = require("node:fs");
61766
62014
  var import_node_path48 = require("node:path");
61767
62015
  var import_node_net = require("node:net");
@@ -61932,7 +62180,7 @@ function stageComposeFileEnv(files) {
61932
62180
  }
61933
62181
 
61934
62182
  // src/stage-runner.ts
61935
- var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process17.execFile);
62183
+ var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process18.execFile);
61936
62184
  var DOCKER_TIMEOUT_MS = 15e3;
61937
62185
  function stageBash() {
61938
62186
  if (process.platform !== "win32") return "bash";
@@ -62576,7 +62824,7 @@ async function startStage(config = {}, opts = {}) {
62576
62824
  let up = sub(config.up.trim());
62577
62825
  if (opts.forceRecreate) up = appendForceRecreate(up);
62578
62826
  const identity = await resolveStageIdentity(cwd);
62579
- const child2 = (0, import_node_child_process17.spawn)(bash, ["-c", up], {
62827
+ const child2 = (0, import_node_child_process18.spawn)(bash, ["-c", up], {
62580
62828
  cwd,
62581
62829
  // POSIX-only: the process group exists for the group-kill in stopStage. On win32 teardown is
62582
62830
  // `taskkill /T /F` (no group needed), and detached+shell defeats windowsHide — every spawn would
@@ -63709,7 +63957,7 @@ function scheduleRelatedDiscovery(o) {
63709
63957
  try {
63710
63958
  const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
63711
63959
  if (o.repo) args.push("--repo", o.repo);
63712
- spawnDetachedSelf(args, { spawn: import_node_child_process18.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
63960
+ spawnDetachedSelf(args, { spawn: import_node_child_process19.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
63713
63961
  } catch {
63714
63962
  }
63715
63963
  }
@@ -66693,7 +66941,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
66693
66941
  if (repo === SUITE_REPO) return inTrain(repo, (deps) => rcandInCheckout(repo, deps, previousRc, rcWasAbsent));
66694
66942
  const target = await checkout(repo);
66695
66943
  return new Promise((resolveResult, reject2) => {
66696
- const child2 = (0, import_node_child_process19.fork)((0, import_node_path52.resolve)(process.argv[1]), ["devops", "suite", "member-rcand-internal", repo, previousRc ?? "", ...rcWasAbsent ? ["--rc-was-absent"] : []], {
66944
+ const child2 = (0, import_node_child_process20.fork)((0, import_node_path52.resolve)(process.argv[1]), ["devops", "suite", "member-rcand-internal", repo, previousRc ?? "", ...rcWasAbsent ? ["--rc-was-absent"] : []], {
66697
66945
  cwd: target,
66698
66946
  stdio: ["ignore", "inherit", "inherit", "ipc"],
66699
66947
  execArgv: []
@@ -67314,7 +67562,7 @@ function registerJevCommands(program3) {
67314
67562
  }
67315
67563
 
67316
67564
  // src/packages-adopt-export.ts
67317
- var import_node_child_process20 = require("node:child_process");
67565
+ var import_node_child_process21 = require("node:child_process");
67318
67566
  var import_node_fs57 = require("node:fs");
67319
67567
  var import_node_os26 = require("node:os");
67320
67568
  var import_node_path54 = require("node:path");
@@ -67971,7 +68219,7 @@ async function adoptExport(opts, deps) {
67971
68219
  (0, import_node_fs57.rmSync)(work, { recursive: true, force: true });
67972
68220
  }
67973
68221
  }
67974
- var execFileBuffer = (0, import_node_util6.promisify)(import_node_child_process20.execFile);
68222
+ var execFileBuffer = (0, import_node_util6.promisify)(import_node_child_process21.execFile);
67975
68223
  var MAX_OUTPUT = 200 * 1024 * 1024;
67976
68224
  async function findPython() {
67977
68225
  for (const bin of ["python3", "python"]) {
@@ -72537,7 +72785,7 @@ async function resolveWhoami(deps) {
72537
72785
  var import_node_path64 = require("node:path");
72538
72786
 
72539
72787
  // src/doc-refs-command-source.ts
72540
- var import_node_child_process21 = require("node:child_process");
72788
+ var import_node_child_process22 = require("node:child_process");
72541
72789
  var import_node_fs62 = require("node:fs");
72542
72790
  var import_node_path58 = require("node:path");
72543
72791
  var IN_PROCESS_SOURCE = "in-process";
@@ -72558,7 +72806,7 @@ function inventoryFromManifest(manifest, source) {
72558
72806
  collect(body?.tree);
72559
72807
  return { commandPaths, commandOptions, source };
72560
72808
  }
72561
- function readBundleManifest(bundle, exec3 = import_node_child_process21.execFileSync) {
72809
+ function readBundleManifest(bundle, exec3 = import_node_child_process22.execFileSync) {
72562
72810
  try {
72563
72811
  const text = exec3(process.execPath, [bundle, "commands", "--all", "--json"], {
72564
72812
  cwd: (0, import_node_path58.dirname)(bundle),
@@ -72727,7 +72975,7 @@ async function executeWaveLand(plan, deps) {
72727
72975
  }
72728
72976
 
72729
72977
  // src/dist-drift.ts
72730
- var import_node_child_process22 = require("node:child_process");
72978
+ var import_node_child_process23 = require("node:child_process");
72731
72979
  var import_node_crypto26 = require("node:crypto");
72732
72980
  var import_node_fs64 = require("node:fs");
72733
72981
  var import_node_os28 = require("node:os");
@@ -72873,7 +73121,7 @@ function bomPathFor(root) {
72873
73121
  }
72874
73122
  }
72875
73123
  function rebuildTo(packageRoot, outDir) {
72876
- (0, import_node_child_process22.execFileSync)(process.execPath, ["build.mjs"], {
73124
+ (0, import_node_child_process23.execFileSync)(process.execPath, ["build.mjs"], {
72877
73125
  cwd: packageRoot,
72878
73126
  env: { ...process.env, MMI_DIST_OUTDIR: outDir },
72879
73127
  windowsHide: true,
@@ -72997,9 +73245,9 @@ async function runLiveDocRefs(root, deps, live) {
72997
73245
  }
72998
73246
 
72999
73247
  // src/doc-refs-live-io.ts
73000
- var import_node_child_process23 = require("node:child_process");
73248
+ var import_node_child_process24 = require("node:child_process");
73001
73249
  var import_node_util7 = require("node:util");
73002
- var exec2 = (0, import_node_util7.promisify)(import_node_child_process23.execFile);
73250
+ var exec2 = (0, import_node_util7.promisify)(import_node_child_process24.execFile);
73003
73251
  function createRunbookLiveDeps(cliBin) {
73004
73252
  const json = async (args) => {
73005
73253
  const { stdout } = await exec2(process.execPath, [cliBin, ...args, "--json"], { windowsHide: true, timeout: 3e4, maxBuffer: 4 * 1024 * 1024 });
@@ -73310,7 +73558,7 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
73310
73558
  }
73311
73559
 
73312
73560
  // src/spawn-policy-core.ts
73313
- var import_node_child_process24 = require("node:child_process");
73561
+ var import_node_child_process25 = require("node:child_process");
73314
73562
  var import_node_fs65 = require("node:fs");
73315
73563
  var import_node_path63 = require("node:path");
73316
73564
  var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
@@ -73381,7 +73629,7 @@ function findViolationsInSource(raw) {
73381
73629
  return found;
73382
73630
  }
73383
73631
  function policedFiles(root) {
73384
- const r = (0, import_node_child_process24.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
73632
+ const r = (0, import_node_child_process25.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
73385
73633
  cwd: root,
73386
73634
  encoding: "utf8",
73387
73635
  windowsHide: true,
package/cli/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/cli",
3
- "version": "4.6.39",
3
+ "version": "4.6.41",
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",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/codex-plugin",
3
- "version": "4.6.39",
3
+ "version": "4.6.41",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",
@@ -15,7 +15,7 @@ The server exposes `/health` and `/module.js`. Register the module's bundle URL,
15
15
  1. **Single source of truth:** the source folder of `packages/mmwork-ds` in `mutmutco/MM-Work`, owned by the MM-Work Design Lead (tokens, layers, component bundle, component docs, `DESIGN.md` and its `design.json` sidecar). Never edit the kit or its copies here; a missing piece or variant is built there first, or requested via kit MCP `request_piece`.
16
16
  2. **MM Artifact on Live Docs:** Live Docs (`Canlı belgeler / MM-Work`) displays document `3a5c79df-5274-40ad-a1b5-a75e67a74dac` (ATOMIC, module `mm-work-kit`), an MM Artifact in the `design-system` format rebuilt from the kit source on every kit release: Overview, Guide (kit README + `DESIGN.md`), Tokens, Atoms, Molecules, Organisms, Templates and Files. Browse it to see every piece live.
17
17
  3. **Impeccable knows Atomic Design at boot:** `impeccable context` loads `PRODUCT.md`, `DESIGN.md` and the `design.json` sidecar in `.impeccable`, which carry the Atomic Design contract 1.1.0: `Atoms -> Molecules -> Organisms -> Templates -> Pages`, upward-only composition enforced by `npm --prefix module run lint` (or `npm run lint` inside `module/`; `mmwork-check-ui` and `mmwork-check-i18n` are bins of `@mutmutco/mmwork-ds`, so a bare `npx mmwork-check-ui` outside that project's installed `node_modules` is resolved as a package name and 404s). Pages arrange exported `@mutmutco/mmwork-ds` pieces around one template and never paint custom controls, raw `<button>`/`<input>`, `mw-*` classes, inline visual styles or raw hex/px values.
18
- 4. **Automatic propagation:** on every kit release the Hub kit-adopt workflow opens an adoption PR here that bumps `@mutmutco/mmwork-ds`, runs `mmwork-sync-impeccable`, and writes `DESIGN.md`, the `.impeccable` design manifest and `.impeccable/config.json` (`hook.enabled: true`) at the repository root, and deletes any stale copies under `module/`. These files are kit-owned: do not hand-edit them, and keep them committed even if `.impeccable/` is ignored (the adoption PR force-stages them).
18
+ 4. **Automatic propagation:** on every kit release the Hub kit-adopt workflow opens an adoption PR here that bumps `@mutmutco/mmwork-ds`, runs `mmwork-sync-impeccable`, and writes `DESIGN.md`, the `.impeccable` design manifest and `.impeccable/config.json` (`hook.enabled: true`) at the repository root, and deletes any stale copies under `module/`. These files are kit-owned: do not hand-edit them, and keep them committed even if `.impeccable/` is ignored (the adoption PR force-stages them). The adoption PR and any `kit-adopt` failure issue are Hub-owned — merge the PR or leave it for the Hub's scheduled reconcile, and leave failure issues open and unedited; a hand-closed unmerged adoption PR strands the operation until an explicit `--recover-closed-pr` dispatch retires it.
19
19
  5. **Root only:** `PRODUCT.md`, `DESIGN.md`, the `.impeccable` design manifest and `.impeccable/config.json` live only at this repository's root, never duplicated under `module/`; a copy there makes Impeccable treat `module/` as a separate root without `PRODUCT.md` and the config. Run `impeccable context` from the root. Any suite-wide propagation of these files needs an explicit intercom ACK handshake with the MM-Work Design Lead naming the files written and removed, `impeccable context` + `impeccable doctor --json` verification, and the issue/PR reference.
20
20
  6. **Front-loaded harmony (owner, 2026-10-25; Hub#8837 / MM-Work#7668):** design work runs one workflow — Front-Loaded Impeccable v4.7.0 + MM Artifacts + Live Docs (`Canlı belgeler`, `3a5c79df-5274-40ad-a1b5-a75e67a74dac`) + Atomic Design Kit (`@mutmutco/mmwork-ds`). The former local stage skill is retired; preview and verify through these tools only.
21
21