@mutmutco/cli 3.105.2 → 3.105.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.
- package/dist/main.cjs +275 -146
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -5000,7 +5000,7 @@ var program = new Command();
|
|
|
5000
5000
|
|
|
5001
5001
|
// src/index.ts
|
|
5002
5002
|
var import_promises11 = require("node:fs/promises");
|
|
5003
|
-
var
|
|
5003
|
+
var import_node_fs42 = require("node:fs");
|
|
5004
5004
|
var import_node_child_process19 = require("node:child_process");
|
|
5005
5005
|
|
|
5006
5006
|
// src/cli-shared.ts
|
|
@@ -8590,7 +8590,7 @@ function commandLadderHint() {
|
|
|
8590
8590
|
}
|
|
8591
8591
|
|
|
8592
8592
|
// src/index.ts
|
|
8593
|
-
var
|
|
8593
|
+
var import_node_path40 = require("node:path");
|
|
8594
8594
|
|
|
8595
8595
|
// src/merge-ci-policy.ts
|
|
8596
8596
|
function resolveMergeCiPolicy(input) {
|
|
@@ -15206,7 +15206,7 @@ async function executeWaveLand(plan, deps, opts = { preserveWorktree: true }) {
|
|
|
15206
15206
|
}
|
|
15207
15207
|
|
|
15208
15208
|
// src/index.ts
|
|
15209
|
-
var
|
|
15209
|
+
var import_node_os17 = require("node:os");
|
|
15210
15210
|
|
|
15211
15211
|
// src/board.ts
|
|
15212
15212
|
var import_node_child_process9 = require("node:child_process");
|
|
@@ -18832,13 +18832,25 @@ function liveEvidenceLines(evidence, repo) {
|
|
|
18832
18832
|
if (evidence.branch) live.push(`live branch ${evidence.branch} on ${repo}`);
|
|
18833
18833
|
return live;
|
|
18834
18834
|
}
|
|
18835
|
-
function
|
|
18836
|
-
|
|
18835
|
+
function sameClaimHost(a, b) {
|
|
18836
|
+
return Boolean(a && b && a.toLowerCase() === b.toLowerCase());
|
|
18837
|
+
}
|
|
18838
|
+
function laneOwnership(marker, current) {
|
|
18839
|
+
if (!marker) return "unknown";
|
|
18840
|
+
if (marker.session && current.session) {
|
|
18841
|
+
return marker.session === current.session ? "mine" : "other";
|
|
18842
|
+
}
|
|
18843
|
+
if (marker.surface && current.surface && marker.surface !== current.surface) return "other";
|
|
18844
|
+
if (marker.host && current.host && !sameClaimHost(marker.host, current.host)) return "other";
|
|
18845
|
+
if (marker.surface && current.surface && marker.surface === current.surface && marker.host && current.host && sameClaimHost(marker.host, current.host)) {
|
|
18846
|
+
return "mine";
|
|
18847
|
+
}
|
|
18837
18848
|
return "unknown";
|
|
18838
18849
|
}
|
|
18839
18850
|
async function checkLaneContest(client, item) {
|
|
18840
18851
|
const evidence = await gatherClaimLiveness(client, item.repository, item.number, openPullsFetcher(client));
|
|
18841
|
-
const
|
|
18852
|
+
const actor = describeActor({ env: process.env, surface: detectSurface(process.env), cwd: process.cwd() });
|
|
18853
|
+
const ownership = laneOwnership(evidence.marker, actor);
|
|
18842
18854
|
const live = ownership === "mine" ? [] : liveEvidenceLines(evidence, item.repository);
|
|
18843
18855
|
const unverifiable = ownership === "mine" ? [] : evidence.failed;
|
|
18844
18856
|
return {
|
|
@@ -28179,10 +28191,10 @@ function registerBoardCommands(program3) {
|
|
|
28179
28191
|
}
|
|
28180
28192
|
|
|
28181
28193
|
// src/merge-cleanup.ts
|
|
28182
|
-
var
|
|
28194
|
+
var import_node_fs35 = require("node:fs");
|
|
28183
28195
|
var import_promises8 = require("node:fs/promises");
|
|
28184
|
-
var
|
|
28185
|
-
var
|
|
28196
|
+
var import_node_path34 = require("node:path");
|
|
28197
|
+
var import_node_os13 = require("node:os");
|
|
28186
28198
|
var import_node_child_process17 = require("node:child_process");
|
|
28187
28199
|
|
|
28188
28200
|
// src/board-advance.ts
|
|
@@ -28348,6 +28360,117 @@ function makeDeferredWorktreeStore(registryPath, lockOpts = {}) {
|
|
|
28348
28360
|
};
|
|
28349
28361
|
}
|
|
28350
28362
|
|
|
28363
|
+
// src/jerv-cli-spawn.ts
|
|
28364
|
+
var import_node_fs34 = require("node:fs");
|
|
28365
|
+
var import_node_os12 = require("node:os");
|
|
28366
|
+
var import_node_path33 = require("node:path");
|
|
28367
|
+
var WIN_NAMES = ["jerv-cli.cmd", "jerv-cli.exe", "jerv-cli"];
|
|
28368
|
+
var POSIX_NAMES = ["jerv-cli"];
|
|
28369
|
+
var JERV_CLI_ENTRY = (0, import_node_path33.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
|
|
28370
|
+
function pathEnvEntries(pathEnv, platform2 = process.platform) {
|
|
28371
|
+
if (platform2 !== "win32") {
|
|
28372
|
+
return pathEnv.split(import_node_path33.delimiter).map((e) => e.trim()).filter(Boolean);
|
|
28373
|
+
}
|
|
28374
|
+
if (pathEnv.includes(";")) {
|
|
28375
|
+
return pathEnv.split(";").map((e) => e.trim()).filter(Boolean);
|
|
28376
|
+
}
|
|
28377
|
+
const looksUnix = pathEnv.startsWith("/") || /(?:^|:)\/[a-zA-Z]\//.test(pathEnv);
|
|
28378
|
+
if (looksUnix && pathEnv.includes(":")) {
|
|
28379
|
+
return pathEnv.split(":").map((e) => e.trim()).filter(Boolean);
|
|
28380
|
+
}
|
|
28381
|
+
return pathEnv.trim() ? [pathEnv.trim()] : [];
|
|
28382
|
+
}
|
|
28383
|
+
function normalizeSpawnPathEntry(entry, platform2 = process.platform) {
|
|
28384
|
+
const trimmed = entry.trim();
|
|
28385
|
+
if (!trimmed) return void 0;
|
|
28386
|
+
if (platform2 !== "win32") return trimmed;
|
|
28387
|
+
const msys = /^\/([a-zA-Z])\/(.*)$/.exec(trimmed.replace(/\\/g, "/"));
|
|
28388
|
+
if (msys) return `${msys[1].toUpperCase()}:\\${msys[2].replace(/\//g, "\\")}`;
|
|
28389
|
+
return trimmed;
|
|
28390
|
+
}
|
|
28391
|
+
function jervCliCandidateDirs(env = process.env, home = (0, import_node_os12.homedir)(), platform2 = process.platform) {
|
|
28392
|
+
const seen = /* @__PURE__ */ new Set();
|
|
28393
|
+
const out = [];
|
|
28394
|
+
const push = (dir) => {
|
|
28395
|
+
if (!dir) return;
|
|
28396
|
+
const key = platform2 === "win32" ? dir.toLowerCase() : dir;
|
|
28397
|
+
if (seen.has(key)) return;
|
|
28398
|
+
seen.add(key);
|
|
28399
|
+
out.push(dir);
|
|
28400
|
+
};
|
|
28401
|
+
for (const entry of pathEnvEntries(env.PATH ?? "", platform2)) {
|
|
28402
|
+
push(normalizeSpawnPathEntry(entry, platform2));
|
|
28403
|
+
}
|
|
28404
|
+
if (platform2 === "win32") {
|
|
28405
|
+
if (env.APPDATA) push((0, import_node_path33.join)(env.APPDATA, "npm"));
|
|
28406
|
+
if (env.LOCALAPPDATA) push((0, import_node_path33.join)(env.LOCALAPPDATA, "npm"));
|
|
28407
|
+
} else {
|
|
28408
|
+
push((0, import_node_path33.join)(home, ".local", "bin"));
|
|
28409
|
+
}
|
|
28410
|
+
return out;
|
|
28411
|
+
}
|
|
28412
|
+
function jervCliCandidatePaths(env = process.env, home = (0, import_node_os12.homedir)(), platform2 = process.platform) {
|
|
28413
|
+
const names = platform2 === "win32" ? WIN_NAMES : POSIX_NAMES;
|
|
28414
|
+
const out = [];
|
|
28415
|
+
for (const dir of jervCliCandidateDirs(env, home, platform2)) {
|
|
28416
|
+
for (const name of names) out.push((0, import_node_path33.join)(dir, name));
|
|
28417
|
+
}
|
|
28418
|
+
return out;
|
|
28419
|
+
}
|
|
28420
|
+
function resolveJervCliPath(env = process.env, home = (0, import_node_os12.homedir)(), platform2 = process.platform, exists = import_node_fs34.existsSync) {
|
|
28421
|
+
for (const candidate of jervCliCandidatePaths(env, home, platform2)) {
|
|
28422
|
+
if (exists(candidate)) return candidate;
|
|
28423
|
+
}
|
|
28424
|
+
return void 0;
|
|
28425
|
+
}
|
|
28426
|
+
function resolveJervCliNodeEntry(shimPath, exists = import_node_fs34.existsSync) {
|
|
28427
|
+
const entry = (0, import_node_path33.join)((0, import_node_path33.dirname)(shimPath), JERV_CLI_ENTRY);
|
|
28428
|
+
return exists(entry) ? entry : void 0;
|
|
28429
|
+
}
|
|
28430
|
+
function jervCliExecFileArgs(args, opts = {}) {
|
|
28431
|
+
const platform2 = opts.platform ?? process.platform;
|
|
28432
|
+
const exists = opts.exists ?? import_node_fs34.existsSync;
|
|
28433
|
+
const resolved = resolveJervCliPath(opts.env ?? process.env, opts.home ?? (0, import_node_os12.homedir)(), platform2, exists);
|
|
28434
|
+
if (resolved) {
|
|
28435
|
+
const entry = resolveJervCliNodeEntry(resolved, exists);
|
|
28436
|
+
if (entry) {
|
|
28437
|
+
return { file: opts.execPath ?? process.execPath, args: [entry, ...args], via: "node-entry" };
|
|
28438
|
+
}
|
|
28439
|
+
}
|
|
28440
|
+
const bin = resolved ?? "jerv-cli";
|
|
28441
|
+
if (platform2 === "win32") {
|
|
28442
|
+
return { file: "cmd.exe", args: ["/c", bin, ...args], via: resolved ? "cmd-shim" : "bare" };
|
|
28443
|
+
}
|
|
28444
|
+
return { file: bin, args: [...args], via: resolved ? "posix" : "bare" };
|
|
28445
|
+
}
|
|
28446
|
+
function formatJervCliSpawnFailure(err, plan, candidates) {
|
|
28447
|
+
const base = (err.stderr?.trim() || err.message.trim()).split("\n")[0] || "spawn failed";
|
|
28448
|
+
const code = err.code;
|
|
28449
|
+
if (code !== "ENOENT" && !/\bENOENT\b/i.test(base)) return base;
|
|
28450
|
+
const tried = candidates.length > 0 ? candidates.join(" | ") : "(no candidates)";
|
|
28451
|
+
return `${base} [via=${plan.via} file=${plan.file}; tried: ${tried}]`;
|
|
28452
|
+
}
|
|
28453
|
+
function isEnoent(err) {
|
|
28454
|
+
const code = err.code;
|
|
28455
|
+
if (code === "ENOENT") return true;
|
|
28456
|
+
return /\bENOENT\b/i.test(err.message ?? "");
|
|
28457
|
+
}
|
|
28458
|
+
function execJervCli(args, options = {}) {
|
|
28459
|
+
const env = options.env ?? process.env;
|
|
28460
|
+
const candidates = jervCliCandidatePaths(env);
|
|
28461
|
+
const plan = jervCliExecFileArgs(args, { env });
|
|
28462
|
+
return execFileP2(plan.file, plan.args, options).catch((err) => {
|
|
28463
|
+
if (!isEnoent(err)) throw err;
|
|
28464
|
+
const wrapped = new Error(formatJervCliSpawnFailure(err, plan, candidates));
|
|
28465
|
+
Object.assign(wrapped, {
|
|
28466
|
+
code: "ENOENT",
|
|
28467
|
+
stderr: err.stderr,
|
|
28468
|
+
cause: err
|
|
28469
|
+
});
|
|
28470
|
+
throw wrapped;
|
|
28471
|
+
});
|
|
28472
|
+
}
|
|
28473
|
+
|
|
28351
28474
|
// src/merge-cleanup.ts
|
|
28352
28475
|
var GC_GH_TIMEOUT_MS2 = 2e4;
|
|
28353
28476
|
async function advanceClosedIssuesToDone2(prNumber, repoOption) {
|
|
@@ -28466,7 +28589,8 @@ function assertPrMergeHousekeepingClean(startingPath, context, options = {}) {
|
|
|
28466
28589
|
if (verdict.blocked) throw new Error(verdict.reason);
|
|
28467
28590
|
return housekeeping;
|
|
28468
28591
|
}
|
|
28469
|
-
|
|
28592
|
+
var defaultLeaseCloseExec = (_cmd, args) => execJervCli(args, { timeout: GIT_TIMEOUT_MS });
|
|
28593
|
+
async function bestEffortLeaseClose(wtPath, exec = defaultLeaseCloseExec) {
|
|
28470
28594
|
const step = "close jerv worktree lease";
|
|
28471
28595
|
try {
|
|
28472
28596
|
await exec("jerv-cli", ["lease", "close", "--ref", wtPath]);
|
|
@@ -28489,7 +28613,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
|
|
|
28489
28613
|
);
|
|
28490
28614
|
const repoRoot2 = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
|
|
28491
28615
|
const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
|
|
28492
|
-
const primaryRepoRoot = worktreeGitRoot ? (0,
|
|
28616
|
+
const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path34.dirname)((0, import_node_path34.dirname)(worktreeGitRoot)) : repoRoot2;
|
|
28493
28617
|
const gcActor = describeActor({ env: process.env, surface: detectSurface(process.env), cwd: process.cwd() });
|
|
28494
28618
|
const owners = readWorktreeOwners(primaryRepoRoot);
|
|
28495
28619
|
const removalNow = Date.now();
|
|
@@ -28520,7 +28644,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
|
|
|
28520
28644
|
const cleanup = await cleanupPrMergeLocalBranch(branch.branch, {
|
|
28521
28645
|
beforeWorktrees,
|
|
28522
28646
|
startingPath: branch.worktreePath,
|
|
28523
|
-
pathExists: (p) => (0,
|
|
28647
|
+
pathExists: (p) => (0, import_node_fs35.existsSync)(p),
|
|
28524
28648
|
execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
|
|
28525
28649
|
teardownWorktreeStage,
|
|
28526
28650
|
deferredStore,
|
|
@@ -28549,7 +28673,7 @@ async function applyGcPlan(plan, remote, opts = {}) {
|
|
|
28549
28673
|
let removalAttempted = false;
|
|
28550
28674
|
try {
|
|
28551
28675
|
const cleanupTarget = resolveSafeSiblingWorktreeCleanupTarget(wt.path, siblingRoot, {
|
|
28552
|
-
realpath: (path2) => (0,
|
|
28676
|
+
realpath: (path2) => (0, import_node_fs35.realpathSync)(path2)
|
|
28553
28677
|
});
|
|
28554
28678
|
if (!cleanupTarget.ok) {
|
|
28555
28679
|
result.failed.push(`${wt.path}: ${cleanupTarget.reason}`);
|
|
@@ -28636,13 +28760,13 @@ async function composeOverrideBodyFile(prNumber, repoArgs, gh) {
|
|
|
28636
28760
|
const commits = JSON.parse(raw).commits ?? [];
|
|
28637
28761
|
const body = squashBodyWithOverride(commits.map((c) => ({ headline: c.messageHeadline ?? "", body: c.messageBody ?? "" })), process.cwd());
|
|
28638
28762
|
if (!body) return void 0;
|
|
28639
|
-
const dir = (0,
|
|
28640
|
-
const path2 = (0,
|
|
28641
|
-
(0,
|
|
28763
|
+
const dir = (0, import_node_fs35.mkdtempSync)((0, import_node_path34.join)((0, import_node_os13.tmpdir)(), "mmi-squash-body-"));
|
|
28764
|
+
const path2 = (0, import_node_path34.join)(dir, "body.txt");
|
|
28765
|
+
(0, import_node_fs35.writeFileSync)(path2, `${body}
|
|
28642
28766
|
`, "utf8");
|
|
28643
28767
|
return { path: path2, cleanup: () => {
|
|
28644
28768
|
try {
|
|
28645
|
-
(0,
|
|
28769
|
+
(0, import_node_fs35.rmSync)(dir, { recursive: true, force: true });
|
|
28646
28770
|
} catch {
|
|
28647
28771
|
}
|
|
28648
28772
|
} };
|
|
@@ -28764,13 +28888,13 @@ var realWorktreeDirRemover = {
|
|
|
28764
28888
|
probe: (p) => {
|
|
28765
28889
|
let st;
|
|
28766
28890
|
try {
|
|
28767
|
-
st = (0,
|
|
28891
|
+
st = (0, import_node_fs35.lstatSync)(p);
|
|
28768
28892
|
} catch {
|
|
28769
28893
|
return null;
|
|
28770
28894
|
}
|
|
28771
28895
|
if (st.isSymbolicLink()) return "link";
|
|
28772
28896
|
try {
|
|
28773
|
-
(0,
|
|
28897
|
+
(0, import_node_fs35.readlinkSync)(p);
|
|
28774
28898
|
return "link";
|
|
28775
28899
|
} catch {
|
|
28776
28900
|
}
|
|
@@ -28778,7 +28902,7 @@ var realWorktreeDirRemover = {
|
|
|
28778
28902
|
},
|
|
28779
28903
|
readdir: (p) => {
|
|
28780
28904
|
try {
|
|
28781
|
-
return (0,
|
|
28905
|
+
return (0, import_node_fs35.readdirSync)(p);
|
|
28782
28906
|
} catch {
|
|
28783
28907
|
return [];
|
|
28784
28908
|
}
|
|
@@ -28787,9 +28911,9 @@ var realWorktreeDirRemover = {
|
|
|
28787
28911
|
// leaving the target); a file symlink with unlink. rmdir first, fall back to unlink.
|
|
28788
28912
|
detachLink: (p) => {
|
|
28789
28913
|
try {
|
|
28790
|
-
(0,
|
|
28914
|
+
(0, import_node_fs35.rmdirSync)(p);
|
|
28791
28915
|
} catch {
|
|
28792
|
-
(0,
|
|
28916
|
+
(0, import_node_fs35.unlinkSync)(p);
|
|
28793
28917
|
}
|
|
28794
28918
|
},
|
|
28795
28919
|
removeTree: (p) => (0, import_promises8.rm)(p, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 })
|
|
@@ -28822,9 +28946,9 @@ async function worktreeHasStageState(worktreePath) {
|
|
|
28822
28946
|
}
|
|
28823
28947
|
}
|
|
28824
28948
|
function stageStateFileBelongsToWorktree(statePath, worktreePath) {
|
|
28825
|
-
if (!(0,
|
|
28949
|
+
if (!(0, import_node_fs35.existsSync)(statePath)) return false;
|
|
28826
28950
|
try {
|
|
28827
|
-
const state = JSON.parse((0,
|
|
28951
|
+
const state = JSON.parse((0, import_node_fs35.readFileSync)(statePath, "utf8"));
|
|
28828
28952
|
const recordedCwd = typeof state.identity?.cwd === "string" ? state.identity.cwd : typeof state.cwd === "string" ? state.cwd : "";
|
|
28829
28953
|
return Boolean(recordedCwd && isPathUnderDirectory(recordedCwd, worktreePath));
|
|
28830
28954
|
} catch {
|
|
@@ -29155,9 +29279,9 @@ async function checkDocsIndexAtHead(opts, deps) {
|
|
|
29155
29279
|
}
|
|
29156
29280
|
|
|
29157
29281
|
// src/worktree-lifecycle-commands.ts
|
|
29158
|
-
var
|
|
29282
|
+
var import_node_fs36 = require("node:fs");
|
|
29159
29283
|
var import_promises9 = require("node:fs/promises");
|
|
29160
|
-
var
|
|
29284
|
+
var import_node_path35 = require("node:path");
|
|
29161
29285
|
var GH_TIMEOUT_MS = 2e4;
|
|
29162
29286
|
var STALE_PR_LOOKUP_LIMIT = 20;
|
|
29163
29287
|
var DEFAULT_BASE = "origin/development";
|
|
@@ -29304,7 +29428,7 @@ function classifyStaleLeaks(input) {
|
|
|
29304
29428
|
var defaultOrphanDirScanDeps = {
|
|
29305
29429
|
listDirs: (root) => {
|
|
29306
29430
|
try {
|
|
29307
|
-
return (0,
|
|
29431
|
+
return (0, import_node_fs36.readdirSync)(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => (0, import_node_path35.join)(root, e.name));
|
|
29308
29432
|
} catch {
|
|
29309
29433
|
return [];
|
|
29310
29434
|
}
|
|
@@ -29460,13 +29584,13 @@ function registerWorktreeCommands(program3) {
|
|
|
29460
29584
|
const detached = headBorn && !symbolicBranch;
|
|
29461
29585
|
const branch = symbolicBranch || (detached ? "HEAD" : "");
|
|
29462
29586
|
if (!wtPath || !branch) return fail("worktree land: not inside a git worktree");
|
|
29463
|
-
const gitFile = (0,
|
|
29464
|
-
const isLinked = (0,
|
|
29587
|
+
const gitFile = (0, import_node_path35.join)(wtPath, ".git");
|
|
29588
|
+
const isLinked = (0, import_node_fs36.existsSync)(gitFile) && (0, import_node_fs36.statSync)(gitFile).isFile();
|
|
29465
29589
|
if (apply && !isLinked) {
|
|
29466
29590
|
return fail("worktree land: run from inside the linked worktree you want to land (this is the primary checkout)");
|
|
29467
29591
|
}
|
|
29468
29592
|
const commonDir = (await execFileP2("git", ["rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim();
|
|
29469
|
-
const primaryCheckout = commonDir ? (0,
|
|
29593
|
+
const primaryCheckout = commonDir ? (0, import_node_path35.dirname)(commonDir) : wtPath;
|
|
29470
29594
|
const localBranchNames = await execFileP2("git", ["-C", primaryCheckout, "for-each-ref", "--format=%(refname:short)", "refs/heads"], { timeout: GIT_TIMEOUT_MS }).then(({ stdout }) => new Set((stdout || "").split("\n").map((l) => l.trim()).filter(Boolean))).catch(() => void 0);
|
|
29471
29595
|
const orphan = classifyOrphanedWorktree({
|
|
29472
29596
|
branch,
|
|
@@ -29675,10 +29799,10 @@ async function gatherWorktreeContext() {
|
|
|
29675
29799
|
if (s) stages.push({ path: wt.path, port: s.port });
|
|
29676
29800
|
}
|
|
29677
29801
|
const worktreeGitRoot = await currentRepoWorktreeGitRoot(repoRoot2);
|
|
29678
|
-
const primaryRepoRoot = worktreeGitRoot ? (0,
|
|
29802
|
+
const primaryRepoRoot = worktreeGitRoot ? (0, import_node_path35.dirname)((0, import_node_path35.dirname)(worktreeGitRoot)) : repoRoot2;
|
|
29679
29803
|
const wtRoot = siblingMmiWorktreesRoot(primaryRepoRoot);
|
|
29680
29804
|
let orphanDirs = [];
|
|
29681
|
-
if ((0,
|
|
29805
|
+
if ((0, import_node_fs36.existsSync)(wtRoot)) {
|
|
29682
29806
|
orphanDirs = scanOrphanDirs(wtRoot, worktreeGitRoot, {
|
|
29683
29807
|
...defaultOrphanDirScanDeps,
|
|
29684
29808
|
listDirs: (root) => worktreeScanDirs(root, primaryRepoRoot, defaultOrphanDirScanDeps.listDirs, isRepoCheckoutDir)
|
|
@@ -29704,7 +29828,7 @@ ${err.stderr ?? ""}`;
|
|
|
29704
29828
|
}
|
|
29705
29829
|
|
|
29706
29830
|
// src/issue-commands.ts
|
|
29707
|
-
var
|
|
29831
|
+
var import_node_fs37 = require("node:fs");
|
|
29708
29832
|
var import_node_crypto7 = require("node:crypto");
|
|
29709
29833
|
var ghRunner = async (args, timeoutMs) => (await execFileP2("gh", args, { timeout: timeoutMs })).stdout;
|
|
29710
29834
|
var ReparentConflictError = class extends Error {
|
|
@@ -29722,7 +29846,7 @@ async function editIssue(client, options, deps = {}) {
|
|
|
29722
29846
|
const url = `https://github.com/${repo}/issues/${parsed.number}`;
|
|
29723
29847
|
const patch = {};
|
|
29724
29848
|
let bodyChanged = false;
|
|
29725
|
-
const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0,
|
|
29849
|
+
const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs37.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
|
|
29726
29850
|
if (options.titleFile !== void 0) {
|
|
29727
29851
|
patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
|
|
29728
29852
|
} else if (options.title !== void 0) {
|
|
@@ -30327,7 +30451,7 @@ function extendCreateCommand(issue2, batchAttach) {
|
|
|
30327
30451
|
if (opts.batch) {
|
|
30328
30452
|
let specs;
|
|
30329
30453
|
try {
|
|
30330
|
-
const raw = (0,
|
|
30454
|
+
const raw = (0, import_node_fs37.readFileSync)(opts.batch, "utf8");
|
|
30331
30455
|
specs = JSON.parse(raw);
|
|
30332
30456
|
if (!Array.isArray(specs)) throw new Error("batch file must contain a JSON array");
|
|
30333
30457
|
} catch (e) {
|
|
@@ -30402,8 +30526,8 @@ ${lines}`, {
|
|
|
30402
30526
|
}
|
|
30403
30527
|
|
|
30404
30528
|
// src/train-commands.ts
|
|
30405
|
-
var
|
|
30406
|
-
var
|
|
30529
|
+
var import_node_fs38 = require("node:fs");
|
|
30530
|
+
var import_node_path36 = require("node:path");
|
|
30407
30531
|
|
|
30408
30532
|
// src/train-status.ts
|
|
30409
30533
|
function buildTrainStatusReport(input) {
|
|
@@ -30443,7 +30567,7 @@ function formatTrainStatus(r) {
|
|
|
30443
30567
|
// src/train-commands.ts
|
|
30444
30568
|
function readRepoVersion() {
|
|
30445
30569
|
try {
|
|
30446
|
-
return JSON.parse((0,
|
|
30570
|
+
return JSON.parse((0, import_node_fs38.readFileSync)((0, import_node_path36.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
|
|
30447
30571
|
} catch {
|
|
30448
30572
|
return void 0;
|
|
30449
30573
|
}
|
|
@@ -30589,9 +30713,9 @@ function registerDeployCommands(program3) {
|
|
|
30589
30713
|
}
|
|
30590
30714
|
|
|
30591
30715
|
// src/discovery-commands.ts
|
|
30592
|
-
var
|
|
30593
|
-
var
|
|
30594
|
-
var
|
|
30716
|
+
var import_node_fs39 = require("node:fs");
|
|
30717
|
+
var import_node_os14 = require("node:os");
|
|
30718
|
+
var import_node_path37 = require("node:path");
|
|
30595
30719
|
var GC_GH_TIMEOUT_MS3 = 2e4;
|
|
30596
30720
|
async function collectStatus() {
|
|
30597
30721
|
const repo = await resolveRepo();
|
|
@@ -30779,10 +30903,10 @@ async function collectOnboardStatus(opts = {}) {
|
|
|
30779
30903
|
else if (top) nextCommand = `mmi-cli board claim ${top.number} # ${top.title}`;
|
|
30780
30904
|
else nextCommand = "mmi-cli board read \u2014 no claimable items found";
|
|
30781
30905
|
}
|
|
30782
|
-
const home = (0,
|
|
30906
|
+
const home = (0, import_node_os14.homedir)();
|
|
30783
30907
|
const plugin = onboardPluginGate({
|
|
30784
|
-
readKnown: () => readFileSyncSafe((0,
|
|
30785
|
-
readSettings: () => readFileSyncSafe((0,
|
|
30908
|
+
readKnown: () => readFileSyncSafe((0, import_node_path37.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs39.readFileSync),
|
|
30909
|
+
readSettings: () => readFileSyncSafe((0, import_node_path37.join)(home, ".claude", "settings.json"), import_node_fs39.readFileSync)
|
|
30786
30910
|
});
|
|
30787
30911
|
return { track, board, registry: registry2, secrets, plugin, estateCli, nextCommand };
|
|
30788
30912
|
}
|
|
@@ -31686,19 +31810,19 @@ function registerSessionReport(program3) {
|
|
|
31686
31810
|
}
|
|
31687
31811
|
|
|
31688
31812
|
// src/plugin-release-catchup.ts
|
|
31689
|
-
var
|
|
31690
|
-
var
|
|
31691
|
-
var
|
|
31813
|
+
var import_node_fs40 = require("node:fs");
|
|
31814
|
+
var import_node_path38 = require("node:path");
|
|
31815
|
+
var import_node_os15 = require("node:os");
|
|
31692
31816
|
var RELEASE_CATCHUP_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
31693
31817
|
var RELEASE_CATCHUP_DISABLE_ENV = "MMI_NO_RELEASE_CATCHUP";
|
|
31694
31818
|
function releaseCatchupStatePath(env = process.env) {
|
|
31695
31819
|
if (env.MMI_RELEASE_CATCHUP_STATE) return env.MMI_RELEASE_CATCHUP_STATE;
|
|
31696
31820
|
if (process.platform === "win32") {
|
|
31697
|
-
const base2 = env.LOCALAPPDATA || (0,
|
|
31698
|
-
return (0,
|
|
31821
|
+
const base2 = env.LOCALAPPDATA || (0, import_node_path38.join)((0, import_node_os15.homedir)(), "AppData", "Local");
|
|
31822
|
+
return (0, import_node_path38.join)(base2, "MMI Future", "mmi-cli", "release-catchup.json");
|
|
31699
31823
|
}
|
|
31700
|
-
const base = env.XDG_STATE_HOME || (0,
|
|
31701
|
-
return (0,
|
|
31824
|
+
const base = env.XDG_STATE_HOME || (0, import_node_path38.join)((0, import_node_os15.homedir)(), ".local", "state");
|
|
31825
|
+
return (0, import_node_path38.join)(base, "mmi-cli", "release-catchup.json");
|
|
31702
31826
|
}
|
|
31703
31827
|
function releaseCatchupDue(state, now, force = false) {
|
|
31704
31828
|
if (force) return true;
|
|
@@ -31708,7 +31832,7 @@ function releaseCatchupDue(state, now, force = false) {
|
|
|
31708
31832
|
function newestCachedPluginVersion(home) {
|
|
31709
31833
|
let names;
|
|
31710
31834
|
try {
|
|
31711
|
-
names = (0,
|
|
31835
|
+
names = (0, import_node_fs40.readdirSync)(pluginCacheRoot(home));
|
|
31712
31836
|
} catch {
|
|
31713
31837
|
return void 0;
|
|
31714
31838
|
}
|
|
@@ -31716,15 +31840,15 @@ function newestCachedPluginVersion(home) {
|
|
|
31716
31840
|
}
|
|
31717
31841
|
function marketplaceClonePath(home) {
|
|
31718
31842
|
try {
|
|
31719
|
-
const parsed = JSON.parse((0,
|
|
31843
|
+
const parsed = JSON.parse((0, import_node_fs40.readFileSync)((0, import_node_path38.join)(home, ".claude", "plugins", "known_marketplaces.json"), "utf8"));
|
|
31720
31844
|
if (parsed.mutmutco?.installLocation) return parsed.mutmutco.installLocation;
|
|
31721
31845
|
} catch {
|
|
31722
31846
|
}
|
|
31723
|
-
return (0,
|
|
31847
|
+
return (0, import_node_path38.join)(home, ".claude", "plugins", "marketplaces", "mutmutco");
|
|
31724
31848
|
}
|
|
31725
31849
|
function readCatalogVersion(home) {
|
|
31726
31850
|
try {
|
|
31727
|
-
const parsed = JSON.parse((0,
|
|
31851
|
+
const parsed = JSON.parse((0, import_node_fs40.readFileSync)((0, import_node_path38.join)(marketplaceClonePath(home), ".claude-plugin", "marketplace.json"), "utf8"));
|
|
31728
31852
|
return parsed.plugins?.find((p) => p.name === "mmi")?.version;
|
|
31729
31853
|
} catch {
|
|
31730
31854
|
return void 0;
|
|
@@ -31732,7 +31856,7 @@ function readCatalogVersion(home) {
|
|
|
31732
31856
|
}
|
|
31733
31857
|
function readMmiInstallRecord(home) {
|
|
31734
31858
|
try {
|
|
31735
|
-
const parsed = JSON.parse((0,
|
|
31859
|
+
const parsed = JSON.parse((0, import_node_fs40.readFileSync)((0, import_node_path38.join)(home, ".claude", "plugins", "installed_plugins.json"), "utf8"));
|
|
31736
31860
|
const record = parsed.plugins?.["mmi@mutmutco"]?.[0];
|
|
31737
31861
|
return record?.version ? { version: record.version, gitCommitSha: record.gitCommitSha } : void 0;
|
|
31738
31862
|
} catch {
|
|
@@ -31741,7 +31865,7 @@ function readMmiInstallRecord(home) {
|
|
|
31741
31865
|
}
|
|
31742
31866
|
async function runReleaseCatchup(home, env, deps, opts = {}) {
|
|
31743
31867
|
if (env[RELEASE_CATCHUP_DISABLE_ENV]) return { ok: true, skipped: true, detail: `disabled via ${RELEASE_CATCHUP_DISABLE_ENV}` };
|
|
31744
|
-
if (!(0,
|
|
31868
|
+
if (!(0, import_node_fs40.existsSync)(pluginCacheRoot(home))) return { ok: true, skipped: true, detail: "no mmi plugin cache on this machine \u2014 nothing to catch up" };
|
|
31745
31869
|
const statePath = releaseCatchupStatePath(env);
|
|
31746
31870
|
const state = deps.readState(statePath);
|
|
31747
31871
|
if (!releaseCatchupDue(state, deps.now(), opts.force)) {
|
|
@@ -31766,8 +31890,8 @@ async function runReleaseCatchup(home, env, deps, opts = {}) {
|
|
|
31766
31890
|
return { ok: false, detail: `released ${latest} but the install record could not be cleared \u2014 nothing changed (record still ${prior.version})` };
|
|
31767
31891
|
}
|
|
31768
31892
|
const installed = await deps.runClaude(["plugin", "install", "mmi@mutmutco"], "claude plugin install mmi@mutmutco");
|
|
31769
|
-
const payload = (0,
|
|
31770
|
-
if (!installed || !(0,
|
|
31893
|
+
const payload = (0, import_node_path38.join)(pluginCacheRoot(home), latest, ".pi-plugin");
|
|
31894
|
+
if (!installed || !(0, import_node_fs40.existsSync)(payload)) {
|
|
31771
31895
|
const why = installed ? `install of ${latest} did not produce a verifiable .pi-plugin payload` : `install of ${latest} failed`;
|
|
31772
31896
|
if (!prior) return { ok: false, detail: `${why}; no prior record to restore` };
|
|
31773
31897
|
const rollback = await restorePriorRecord(home, prior, deps);
|
|
@@ -31795,7 +31919,7 @@ async function restorePriorRecord(home, prior, deps) {
|
|
|
31795
31919
|
}
|
|
31796
31920
|
function shouldSpawnReleaseCatchup(home, env, readState2, now = Date.now()) {
|
|
31797
31921
|
if (env[RELEASE_CATCHUP_DISABLE_ENV]) return false;
|
|
31798
|
-
if (!(0,
|
|
31922
|
+
if (!(0, import_node_fs40.existsSync)(pluginCacheRoot(home))) return false;
|
|
31799
31923
|
return releaseCatchupDue(readState2(releaseCatchupStatePath(env)), now);
|
|
31800
31924
|
}
|
|
31801
31925
|
function defaultRegistrationHeal(home, env) {
|
|
@@ -33841,17 +33965,17 @@ function parseOriginRepo(remoteUrl) {
|
|
|
33841
33965
|
}
|
|
33842
33966
|
function ghHostsConfigPath(env, platform2) {
|
|
33843
33967
|
const sep3 = platform2 === "win32" ? "\\" : "/";
|
|
33844
|
-
const
|
|
33968
|
+
const join36 = (...parts) => parts.join(sep3);
|
|
33845
33969
|
const explicit = env.GH_CONFIG_DIR?.trim();
|
|
33846
|
-
if (explicit) return
|
|
33970
|
+
if (explicit) return join36(explicit, "hosts.yml");
|
|
33847
33971
|
if (platform2 === "win32") {
|
|
33848
33972
|
const appData = (env.AppData ?? env.APPDATA)?.trim();
|
|
33849
|
-
return appData ?
|
|
33973
|
+
return appData ? join36(appData, "GitHub CLI", "hosts.yml") : void 0;
|
|
33850
33974
|
}
|
|
33851
33975
|
const xdg = env.XDG_CONFIG_HOME?.trim();
|
|
33852
|
-
if (xdg) return
|
|
33976
|
+
if (xdg) return join36(xdg, "gh", "hosts.yml");
|
|
33853
33977
|
const home = env.HOME?.trim();
|
|
33854
|
-
return home ?
|
|
33978
|
+
return home ? join36(home, ".config", "gh", "hosts.yml") : void 0;
|
|
33855
33979
|
}
|
|
33856
33980
|
function parseGhHostsAccounts(yaml, host = "github.com") {
|
|
33857
33981
|
let hostIndent = null;
|
|
@@ -33901,9 +34025,9 @@ function ghAccountCaveat(announcedLogin, accounts) {
|
|
|
33901
34025
|
}
|
|
33902
34026
|
|
|
33903
34027
|
// src/doctor-io.ts
|
|
33904
|
-
var
|
|
33905
|
-
var
|
|
33906
|
-
var
|
|
34028
|
+
var import_node_fs41 = require("node:fs");
|
|
34029
|
+
var import_node_os16 = require("node:os");
|
|
34030
|
+
var import_node_path39 = require("node:path");
|
|
33907
34031
|
var import_node_child_process18 = require("node:child_process");
|
|
33908
34032
|
var import_node_util8 = require("node:util");
|
|
33909
34033
|
var execFileP6 = (0, import_node_util8.promisify)(import_node_child_process18.execFile);
|
|
@@ -33911,7 +34035,7 @@ var MMI_PLUGIN_ID2 = "mmi@mutmutco";
|
|
|
33911
34035
|
function installedClaudePluginVersion() {
|
|
33912
34036
|
try {
|
|
33913
34037
|
const file = JSON.parse(
|
|
33914
|
-
(0,
|
|
34038
|
+
(0, import_node_fs41.readFileSync)((0, import_node_path39.join)((0, import_node_os16.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
|
|
33915
34039
|
);
|
|
33916
34040
|
const versions = (file.plugins?.[MMI_PLUGIN_ID2] ?? []).map((r) => r.version).filter((v) => Boolean(v));
|
|
33917
34041
|
if (versions.length === 0) return void 0;
|
|
@@ -33922,7 +34046,7 @@ function installedClaudePluginVersion() {
|
|
|
33922
34046
|
}
|
|
33923
34047
|
function manifestVersion(path2) {
|
|
33924
34048
|
try {
|
|
33925
|
-
const manifest = JSON.parse((0,
|
|
34049
|
+
const manifest = JSON.parse((0, import_node_fs41.readFileSync)(path2, "utf8"));
|
|
33926
34050
|
return typeof manifest.version === "string" && manifest.version.trim() ? manifest.version.trim() : void 0;
|
|
33927
34051
|
} catch {
|
|
33928
34052
|
return void 0;
|
|
@@ -33932,22 +34056,22 @@ function installedSurfacePluginVersion(surface) {
|
|
|
33932
34056
|
const token = surfaceToken(surface);
|
|
33933
34057
|
if (token === "kilo") {
|
|
33934
34058
|
try {
|
|
33935
|
-
const stamp = (0,
|
|
34059
|
+
const stamp = (0, import_node_fs41.readFileSync)((0, import_node_path39.join)((0, import_node_os16.homedir)(), ".kilo", ".mmi-kilo-version"), "utf8").trim();
|
|
33936
34060
|
return stamp || void 0;
|
|
33937
34061
|
} catch {
|
|
33938
34062
|
return void 0;
|
|
33939
34063
|
}
|
|
33940
34064
|
}
|
|
33941
34065
|
if (token === "cursor") {
|
|
33942
|
-
return manifestVersion((0,
|
|
34066
|
+
return manifestVersion((0, import_node_path39.join)(cursorLocalPluginRoot(), ".cursor-plugin", "plugin.json"));
|
|
33943
34067
|
}
|
|
33944
34068
|
if (token === "jervcode") {
|
|
33945
34069
|
const entry = mmiPiWrapperEntry();
|
|
33946
34070
|
if (!entry) return void 0;
|
|
33947
|
-
return manifestVersion((0,
|
|
34071
|
+
return manifestVersion((0, import_node_path39.join)(decodeURIComponent(entry.replace(/^file:\/\/\/?/, "")), "package.json"));
|
|
33948
34072
|
}
|
|
33949
34073
|
if (token === "kimi") {
|
|
33950
|
-
return manifestVersion((0,
|
|
34074
|
+
return manifestVersion((0, import_node_path39.join)(surfaceConfigRoot(surface), "plugins", "managed", "mmi", ".kimi-plugin", "plugin.json"));
|
|
33951
34075
|
}
|
|
33952
34076
|
if (token === "claude") return installedClaudePluginVersion();
|
|
33953
34077
|
if (token !== "codex") return void 0;
|
|
@@ -33985,13 +34109,13 @@ function worktreeRootSync() {
|
|
|
33985
34109
|
}
|
|
33986
34110
|
var gitignorePath = () => {
|
|
33987
34111
|
const root = worktreeRootSync();
|
|
33988
|
-
return root === null ? null : (0,
|
|
34112
|
+
return root === null ? null : (0, import_node_path39.join)(root, ".gitignore");
|
|
33989
34113
|
};
|
|
33990
34114
|
function readGitignore() {
|
|
33991
34115
|
const path2 = gitignorePath();
|
|
33992
34116
|
if (path2 === null) return null;
|
|
33993
34117
|
try {
|
|
33994
|
-
return (0,
|
|
34118
|
+
return (0, import_node_fs41.readFileSync)(path2, "utf8");
|
|
33995
34119
|
} catch {
|
|
33996
34120
|
return null;
|
|
33997
34121
|
}
|
|
@@ -34000,7 +34124,7 @@ function writeGitignore(content) {
|
|
|
34000
34124
|
const path2 = gitignorePath();
|
|
34001
34125
|
if (path2 === null) return false;
|
|
34002
34126
|
try {
|
|
34003
|
-
(0,
|
|
34127
|
+
(0, import_node_fs41.writeFileSync)(path2, content, "utf8");
|
|
34004
34128
|
return true;
|
|
34005
34129
|
} catch {
|
|
34006
34130
|
return false;
|
|
@@ -34024,7 +34148,7 @@ async function repoRoot() {
|
|
|
34024
34148
|
}
|
|
34025
34149
|
function hasRepoLocalWorktrees() {
|
|
34026
34150
|
const root = worktreeRootSync();
|
|
34027
|
-
return root !== null && (0,
|
|
34151
|
+
return root !== null && (0, import_node_fs41.existsSync)((0, import_node_path39.join)(root, ".worktrees"));
|
|
34028
34152
|
}
|
|
34029
34153
|
|
|
34030
34154
|
// src/index.ts
|
|
@@ -34043,8 +34167,8 @@ ${r.stderr ?? ""}`).catch(() => "");
|
|
|
34043
34167
|
function ghMultiAccountCaveat(announcedLogin) {
|
|
34044
34168
|
try {
|
|
34045
34169
|
const hostsPath = ghHostsConfigPath(process.env, process.platform);
|
|
34046
|
-
if (!hostsPath || !(0,
|
|
34047
|
-
return ghAccountCaveat(announcedLogin, parseGhHostsAccounts((0,
|
|
34170
|
+
if (!hostsPath || !(0, import_node_fs42.existsSync)(hostsPath)) return void 0;
|
|
34171
|
+
return ghAccountCaveat(announcedLogin, parseGhHostsAccounts((0, import_node_fs42.readFileSync)(hostsPath, "utf8")));
|
|
34048
34172
|
} catch {
|
|
34049
34173
|
return void 0;
|
|
34050
34174
|
}
|
|
@@ -34052,12 +34176,12 @@ function ghMultiAccountCaveat(announcedLogin) {
|
|
|
34052
34176
|
var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
|
|
34053
34177
|
var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
|
|
34054
34178
|
function envHealLockPath(home) {
|
|
34055
|
-
return (0,
|
|
34179
|
+
return (0, import_node_path40.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
|
|
34056
34180
|
}
|
|
34057
34181
|
async function withEnvHealLock(what, run) {
|
|
34058
34182
|
try {
|
|
34059
34183
|
return await withFileLock(
|
|
34060
|
-
envHealLockPath((0,
|
|
34184
|
+
envHealLockPath((0, import_node_os17.homedir)()),
|
|
34061
34185
|
{ staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
|
|
34062
34186
|
run
|
|
34063
34187
|
);
|
|
@@ -34154,7 +34278,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
34154
34278
|
const configRoot = surfaceConfigRoot(surface);
|
|
34155
34279
|
const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
|
|
34156
34280
|
const plan = buildPluginCachePlan(
|
|
34157
|
-
(0,
|
|
34281
|
+
(0, import_node_os17.homedir)(),
|
|
34158
34282
|
running,
|
|
34159
34283
|
pluginCacheFsDeps(configRoot, () => 0),
|
|
34160
34284
|
{ configRoot, includeStaging: surface !== "codex" }
|
|
@@ -34178,14 +34302,14 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
34178
34302
|
const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
|
|
34179
34303
|
const installed = installedActivePluginVersion(surface);
|
|
34180
34304
|
const plan = buildPluginCachePlan(
|
|
34181
|
-
(0,
|
|
34305
|
+
(0, import_node_os17.homedir)(),
|
|
34182
34306
|
running,
|
|
34183
34307
|
pluginCacheFsDeps(configRoot, () => 0),
|
|
34184
34308
|
{ configRoot, includeStaging: surface !== "codex", installedVersion: installed }
|
|
34185
34309
|
);
|
|
34186
34310
|
const result = applyPluginCachePlan(
|
|
34187
34311
|
plan,
|
|
34188
|
-
(p) => (0,
|
|
34312
|
+
(p) => (0, import_node_fs42.rmSync)(p, { recursive: true }),
|
|
34189
34313
|
stagingApplyFsGuard(configRoot)
|
|
34190
34314
|
);
|
|
34191
34315
|
return {
|
|
@@ -34213,12 +34337,12 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
34213
34337
|
piPluginState: () => {
|
|
34214
34338
|
const env = { ...process.env };
|
|
34215
34339
|
delete env.CLAUDE_PLUGIN_ROOT;
|
|
34216
|
-
return readPiPluginState((0,
|
|
34340
|
+
return readPiPluginState((0, import_node_os17.homedir)(), env);
|
|
34217
34341
|
},
|
|
34218
34342
|
healPiPlugin: () => {
|
|
34219
34343
|
const env = { ...process.env };
|
|
34220
34344
|
delete env.CLAUDE_PLUGIN_ROOT;
|
|
34221
|
-
return healPiPluginRegistration((0,
|
|
34345
|
+
return healPiPluginRegistration((0, import_node_os17.homedir)(), env);
|
|
34222
34346
|
},
|
|
34223
34347
|
// #3470: what the SessionStart hook LAST emitted, measured at emission by the session-start verb below.
|
|
34224
34348
|
// A local record read ? cheap enough for every lane, including the banner.
|
|
@@ -34228,17 +34352,17 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
34228
34352
|
marketplaceRows: () => {
|
|
34229
34353
|
try {
|
|
34230
34354
|
if (detectSurface(process.env) === "codex") return [];
|
|
34231
|
-
const home = (0,
|
|
34355
|
+
const home = (0, import_node_os17.homedir)();
|
|
34232
34356
|
const rows = marketplaceRows(
|
|
34233
34357
|
MMI_MARKETPLACE_NAME,
|
|
34234
|
-
readFileSyncSafe((0,
|
|
34235
|
-
readFileSyncSafe((0,
|
|
34358
|
+
readFileSyncSafe((0, import_node_path40.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs42.readFileSync),
|
|
34359
|
+
readFileSyncSafe((0, import_node_path40.join)(home, ".claude", "settings.json"), import_node_fs42.readFileSync),
|
|
34236
34360
|
// #3974: this CLI heals these rows, so report mode names the doctor run rather than the hand
|
|
34237
34361
|
// edit. Unconditional ? it is a fact about mmi-cli, not about the lane this run is on.
|
|
34238
34362
|
true
|
|
34239
34363
|
);
|
|
34240
34364
|
const pending = readMarketplacePinPending(
|
|
34241
|
-
(0,
|
|
34365
|
+
(0, import_node_path40.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"),
|
|
34242
34366
|
MMI_MARKETPLACE_NAME
|
|
34243
34367
|
);
|
|
34244
34368
|
if (!pending) return rows;
|
|
@@ -34262,11 +34386,11 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
34262
34386
|
healMarketplacePins: () => {
|
|
34263
34387
|
try {
|
|
34264
34388
|
if (detectSurface(process.env) === "codex") return void 0;
|
|
34265
|
-
const home = (0,
|
|
34389
|
+
const home = (0, import_node_os17.homedir)();
|
|
34266
34390
|
const names = [MMI_MARKETPLACE_NAME];
|
|
34267
|
-
const result = applyOrgMarketplacePins((0,
|
|
34391
|
+
const result = applyOrgMarketplacePins((0, import_node_path40.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), names);
|
|
34268
34392
|
if (result?.wrote) {
|
|
34269
|
-
writeMarketplacePinPending((0,
|
|
34393
|
+
writeMarketplacePinPending((0, import_node_path40.join)(home, ".claude", "plugins", ".mmi-marketplace-pin-pending.json"), names);
|
|
34270
34394
|
}
|
|
34271
34395
|
return result;
|
|
34272
34396
|
} catch {
|
|
@@ -34282,7 +34406,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
34282
34406
|
// adopted the generated routing index (MMG-Unlive: `docs/Archive/**` only, no index, no gate.yml) would
|
|
34283
34407
|
// get a permanent ? demanding an artifact it never asked for.
|
|
34284
34408
|
docsIndexState: (root) => {
|
|
34285
|
-
if (!(0,
|
|
34409
|
+
if (!(0, import_node_fs42.existsSync)((0, import_node_path40.join)(root, DOCS_INDEX_PATH))) return void 0;
|
|
34286
34410
|
const real = createDocsIndexDeps(root);
|
|
34287
34411
|
let docs2;
|
|
34288
34412
|
const listDocs = () => docs2 ??= real.listDocs();
|
|
@@ -34291,7 +34415,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
34291
34415
|
},
|
|
34292
34416
|
// #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
|
|
34293
34417
|
healDocsIndex: (root) => {
|
|
34294
|
-
if (!(0,
|
|
34418
|
+
if (!(0, import_node_fs42.existsSync)((0, import_node_path40.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
|
|
34295
34419
|
const real = createDocsIndexDeps(root);
|
|
34296
34420
|
let docs2;
|
|
34297
34421
|
const listDocs = () => docs2 ??= real.listDocs();
|
|
@@ -34626,19 +34750,19 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
34626
34750
|
});
|
|
34627
34751
|
var rules = program2.command("rules").description("org-managed .gitignore delivery");
|
|
34628
34752
|
rules.command("gitignore").option("--write", "upsert the managed block into .gitignore (default: check only, non-zero exit on drift)").option("--json", "machine-readable output").description("verify (or --write) this repo's org-managed .gitignore block matches the SSOT").action((opts) => {
|
|
34629
|
-
const path2 = (0,
|
|
34630
|
-
const current = (0,
|
|
34753
|
+
const path2 = (0, import_node_path40.join)(process.cwd(), ".gitignore");
|
|
34754
|
+
const current = (0, import_node_fs42.existsSync)(path2) ? (0, import_node_fs42.readFileSync)(path2, "utf8") : null;
|
|
34631
34755
|
const plan = planManagedGitignore(current);
|
|
34632
34756
|
const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
|
|
34633
34757
|
if (opts.json) {
|
|
34634
|
-
if (opts.write && plan.changed) (0,
|
|
34758
|
+
if (opts.write && plan.changed) (0, import_node_fs42.writeFileSync)(path2, plan.content, "utf8");
|
|
34635
34759
|
console.log(JSON.stringify(plan, null, 2));
|
|
34636
34760
|
if (!opts.write && plan.changed) process.exitCode = 1;
|
|
34637
34761
|
return;
|
|
34638
34762
|
}
|
|
34639
34763
|
if (opts.write) {
|
|
34640
34764
|
if (plan.changed) {
|
|
34641
|
-
(0,
|
|
34765
|
+
(0, import_node_fs42.writeFileSync)(path2, plan.content, "utf8");
|
|
34642
34766
|
console.log(`mmi-cli org rules gitignore: updated .gitignore (${drift})`);
|
|
34643
34767
|
} else {
|
|
34644
34768
|
console.log("mmi-cli org rules gitignore: up to date");
|
|
@@ -34796,8 +34920,8 @@ gcCmd.option("--dry-run", "show what would be deleted (default)").option("--appl
|
|
|
34796
34920
|
if (!Number.isFinite(limit) || limit < 1) return fail("worktree gc: --limit must be a positive integer");
|
|
34797
34921
|
let root;
|
|
34798
34922
|
if (o.root !== void 0) {
|
|
34799
|
-
root = (0,
|
|
34800
|
-
if (!(0,
|
|
34923
|
+
root = (0, import_node_path40.resolve)(o.root);
|
|
34924
|
+
if (!(0, import_node_fs42.existsSync)(root) || !(0, import_node_fs42.statSync)(root).isDirectory()) return fail(`worktree gc: --root ${o.root} is not a directory`);
|
|
34801
34925
|
const gcRepoRoot = (await execFileP2("git", ["rev-parse", "--show-toplevel"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout.trim() || process.cwd();
|
|
34802
34926
|
if (isPathUnderDirectory(gcRepoRoot, root)) {
|
|
34803
34927
|
return fail(`worktree gc: --root ${root} contains this checkout ? name a worktrees root, not the repo or an ancestor of it`);
|
|
@@ -34877,7 +35001,7 @@ async function currentWorktreeRemovalContext(command, force) {
|
|
|
34877
35001
|
};
|
|
34878
35002
|
}
|
|
34879
35003
|
async function unprovenWorktreeReason(wtPath, repoRoot2) {
|
|
34880
|
-
if (!(0,
|
|
35004
|
+
if (!(0, import_node_fs42.existsSync)(wtPath)) return `${wtPath} does not exist on disk`;
|
|
34881
35005
|
const porcelain = (await execFileP2("git", ["-C", repoRoot2, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).catch(() => ({ stdout: "" }))).stdout;
|
|
34882
35006
|
const registered = parseWorktreePorcelainEntries(porcelain);
|
|
34883
35007
|
if (!registered.length) {
|
|
@@ -34899,26 +35023,26 @@ function makeProvisionDeps(worktreeRoot, quiet, log) {
|
|
|
34899
35023
|
function acquireWorktreeSetupLock(worktreeRoot) {
|
|
34900
35024
|
const lockPath = repoRuntimeStatePath(worktreeRoot, "worktree-setup.lock");
|
|
34901
35025
|
const take = () => {
|
|
34902
|
-
const fd = (0,
|
|
35026
|
+
const fd = (0, import_node_fs42.openSync)(lockPath, "wx");
|
|
34903
35027
|
try {
|
|
34904
|
-
(0,
|
|
35028
|
+
(0, import_node_fs42.writeSync)(fd, String(Date.now()));
|
|
34905
35029
|
} finally {
|
|
34906
|
-
(0,
|
|
35030
|
+
(0, import_node_fs42.closeSync)(fd);
|
|
34907
35031
|
}
|
|
34908
35032
|
return () => {
|
|
34909
35033
|
try {
|
|
34910
|
-
(0,
|
|
35034
|
+
(0, import_node_fs42.rmSync)(lockPath, { force: true });
|
|
34911
35035
|
} catch {
|
|
34912
35036
|
}
|
|
34913
35037
|
};
|
|
34914
35038
|
};
|
|
34915
35039
|
try {
|
|
34916
|
-
(0,
|
|
35040
|
+
(0, import_node_fs42.mkdirSync)((0, import_node_path40.dirname)(lockPath), { recursive: true });
|
|
34917
35041
|
return take();
|
|
34918
35042
|
} catch {
|
|
34919
35043
|
try {
|
|
34920
|
-
if (Date.now() - (0,
|
|
34921
|
-
(0,
|
|
35044
|
+
if (Date.now() - (0, import_node_fs42.statSync)(lockPath).mtimeMs > WORKTREE_SETUP_LOCK_TTL_MS) {
|
|
35045
|
+
(0, import_node_fs42.rmSync)(lockPath, { force: true });
|
|
34922
35046
|
return take();
|
|
34923
35047
|
}
|
|
34924
35048
|
} catch {
|
|
@@ -34944,6 +35068,11 @@ withExamples(mutating(
|
|
|
34944
35068
|
const resolvedRepo = await resolveRepo();
|
|
34945
35069
|
if (!resolvedRepo) return fail("worktree create: could not resolve the repo for the issue ref (run from a repo checkout)");
|
|
34946
35070
|
selector = parseIssueSelector(target, resolvedRepo);
|
|
35071
|
+
if (selector.repo.toLowerCase() !== resolvedRepo.toLowerCase()) {
|
|
35072
|
+
return fail(
|
|
35073
|
+
`worktree create: issue ${selector.repo}#${selector.number} belongs to ${selector.repo}, but this checkout is ${resolvedRepo} \u2014 re-run from ${selector.repo}'s primary checkout. Refusing to attach a foreign issue branch here (MMI-Hub#4351).`
|
|
35074
|
+
);
|
|
35075
|
+
}
|
|
34947
35076
|
const slug = o.slug ?? await fetchIssueTitle(selector.repo, selector.number).then((t) => t ? slugifyIssueTitle(t) : "");
|
|
34948
35077
|
branch = buildNewBranchName(selector.number, slug ?? "");
|
|
34949
35078
|
if (PROTECTED_BRANCHES2.has(branch)) {
|
|
@@ -35057,7 +35186,7 @@ withExamples(mutating(
|
|
|
35057
35186
|
appendWorktreeEvent(repoRoot2, { action: "created", command: "worktree create", target: wtPath, branch, actor: owner.actor });
|
|
35058
35187
|
let lease;
|
|
35059
35188
|
try {
|
|
35060
|
-
await
|
|
35189
|
+
await execJervCli([
|
|
35061
35190
|
"lease",
|
|
35062
35191
|
"open",
|
|
35063
35192
|
"--kind",
|
|
@@ -35766,7 +35895,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
|
|
|
35766
35895
|
if (dupe) return fail(`org project set: KEY "${dupe}" was passed to both --var and --set; --set is an alias of --var, so pass each KEY once`);
|
|
35767
35896
|
if (o.secretsFile) {
|
|
35768
35897
|
try {
|
|
35769
|
-
vars.push(`secrets=${(0,
|
|
35898
|
+
vars.push(`secrets=${(0, import_node_fs42.readFileSync)(o.secretsFile, "utf8")}`);
|
|
35770
35899
|
} catch (e) {
|
|
35771
35900
|
return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
|
|
35772
35901
|
}
|
|
@@ -36520,11 +36649,11 @@ pr.command("view <number>").description("read a PR as structured JSON (merged st
|
|
|
36520
36649
|
}
|
|
36521
36650
|
});
|
|
36522
36651
|
async function listCiWorkflowPaths(cwd = process.cwd()) {
|
|
36523
|
-
const wfDir = (0,
|
|
36524
|
-
if (!(0,
|
|
36525
|
-
return (0,
|
|
36652
|
+
const wfDir = (0, import_node_path40.join)(cwd, ".github", "workflows");
|
|
36653
|
+
if (!(0, import_node_fs42.existsSync)(wfDir)) return [];
|
|
36654
|
+
return (0, import_node_fs42.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
|
|
36526
36655
|
try {
|
|
36527
|
-
return workflowReportsPrChecks((0,
|
|
36656
|
+
return workflowReportsPrChecks((0, import_node_fs42.readFileSync)((0, import_node_path40.join)(wfDir, name), "utf8"));
|
|
36528
36657
|
} catch {
|
|
36529
36658
|
return true;
|
|
36530
36659
|
}
|
|
@@ -36556,16 +36685,16 @@ function ciAuditDeps() {
|
|
|
36556
36685
|
// gate re-seed step is skipped gracefully rather than failing mid-run.
|
|
36557
36686
|
readSeedFile: (path2) => {
|
|
36558
36687
|
if (!root) return null;
|
|
36559
|
-
const fullPath = (0,
|
|
36560
|
-
return (0,
|
|
36688
|
+
const fullPath = (0, import_node_path40.join)(root, path2);
|
|
36689
|
+
return (0, import_node_fs42.existsSync)(fullPath) ? (0, import_node_fs42.readFileSync)(fullPath, "utf8") : null;
|
|
36561
36690
|
}
|
|
36562
36691
|
};
|
|
36563
36692
|
}
|
|
36564
36693
|
function hubRoot() {
|
|
36565
|
-
const fromPkg = (0,
|
|
36694
|
+
const fromPkg = (0, import_node_path40.join)(__dirname, "..", "..");
|
|
36566
36695
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
36567
|
-
if ((0,
|
|
36568
|
-
if ((0,
|
|
36696
|
+
if ((0, import_node_fs42.existsSync)((0, import_node_path40.join)(fromPkg, marker))) return fromPkg;
|
|
36697
|
+
if ((0, import_node_fs42.existsSync)((0, import_node_path40.join)(process.cwd(), marker))) return process.cwd();
|
|
36569
36698
|
return null;
|
|
36570
36699
|
}
|
|
36571
36700
|
pr.command("ci-policy").description("report merge CI policy: wait-for-checks vs no-ci (for grind/build agents)").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the current checkout)").action(async (o) => {
|
|
@@ -36877,7 +37006,7 @@ jsonParity(pr.command("merge <number>").description("merge a PR (squash by defau
|
|
|
36877
37006
|
localCleanup = await cleanupPrMergeLocalBranch(headRef, {
|
|
36878
37007
|
beforeWorktrees,
|
|
36879
37008
|
startingPath,
|
|
36880
|
-
pathExists: (p) => (0,
|
|
37009
|
+
pathExists: (p) => (0, import_node_fs42.existsSync)(p),
|
|
36881
37010
|
execGit: async (args) => (await execFileP2("git", args, { timeout: GIT_TIMEOUT_MS })).stdout,
|
|
36882
37011
|
teardownWorktreeStage,
|
|
36883
37012
|
deferredStore,
|
|
@@ -37373,12 +37502,12 @@ access.command("audit").description("audit collaborator roles + train-branch pus
|
|
|
37373
37502
|
targets = resolution.targets;
|
|
37374
37503
|
}
|
|
37375
37504
|
const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
|
|
37376
|
-
const fileMatrix = (0,
|
|
37505
|
+
const fileMatrix = (0, import_node_fs42.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs42.readFileSync)("access-matrix.json", "utf8")) : {};
|
|
37377
37506
|
const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
|
|
37378
37507
|
const derivedContracts = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
|
|
37379
|
-
const fileContracts = (0,
|
|
37508
|
+
const fileContracts = (0, import_node_fs42.existsSync)("data-access-contracts.json") ? loadDataAccessContracts((0, import_node_fs42.readFileSync)("data-access-contracts.json", "utf8")) : { consumers: {} };
|
|
37380
37509
|
const dataAccess = mergeDataAccessContracts(fileContracts, derivedContracts);
|
|
37381
|
-
const sanctioned = (0,
|
|
37510
|
+
const sanctioned = (0, import_node_fs42.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs42.readFileSync)("access-matrix.json", "utf8")) : {};
|
|
37382
37511
|
const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
|
|
37383
37512
|
console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
|
|
37384
37513
|
if (!report.ok) process.exitCode = 1;
|
|
@@ -37410,16 +37539,16 @@ function directoryBytes(path2) {
|
|
|
37410
37539
|
let total = 0;
|
|
37411
37540
|
let entries;
|
|
37412
37541
|
try {
|
|
37413
|
-
entries = (0,
|
|
37542
|
+
entries = (0, import_node_fs42.readdirSync)(path2, { withFileTypes: true });
|
|
37414
37543
|
} catch {
|
|
37415
37544
|
return 0;
|
|
37416
37545
|
}
|
|
37417
37546
|
for (const entry of entries) {
|
|
37418
|
-
const child2 = (0,
|
|
37547
|
+
const child2 = (0, import_node_path40.join)(path2, entry.name);
|
|
37419
37548
|
if (entry.isDirectory()) total += directoryBytes(child2);
|
|
37420
37549
|
else {
|
|
37421
37550
|
try {
|
|
37422
|
-
total += (0,
|
|
37551
|
+
total += (0, import_node_fs42.statSync)(child2).size;
|
|
37423
37552
|
} catch {
|
|
37424
37553
|
}
|
|
37425
37554
|
}
|
|
@@ -37427,25 +37556,25 @@ function directoryBytes(path2) {
|
|
|
37427
37556
|
return total;
|
|
37428
37557
|
}
|
|
37429
37558
|
function listDirEntries(dir) {
|
|
37430
|
-
return (0,
|
|
37559
|
+
return (0, import_node_fs42.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
|
|
37431
37560
|
}
|
|
37432
37561
|
function readInstalledPluginRefs(configRoot) {
|
|
37433
37562
|
const p = installedPluginsPathForConfig(configRoot);
|
|
37434
|
-
if (!(0,
|
|
37563
|
+
if (!(0, import_node_fs42.existsSync)(p)) return [];
|
|
37435
37564
|
try {
|
|
37436
|
-
return installedPluginPaths((0,
|
|
37565
|
+
return installedPluginPaths((0, import_node_fs42.readFileSync)(p, "utf8"));
|
|
37437
37566
|
} catch {
|
|
37438
37567
|
return null;
|
|
37439
37568
|
}
|
|
37440
37569
|
}
|
|
37441
37570
|
function pluginCacheFsDeps(configRoot, dirBytes) {
|
|
37442
37571
|
return {
|
|
37443
|
-
exists: (p) => (0,
|
|
37444
|
-
listVersionDirs: (root) => (0,
|
|
37572
|
+
exists: (p) => (0, import_node_fs42.existsSync)(p),
|
|
37573
|
+
listVersionDirs: (root) => (0, import_node_fs42.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
|
|
37445
37574
|
dirBytes,
|
|
37446
|
-
listStagingDirs: (root) => (0,
|
|
37575
|
+
listStagingDirs: (root) => (0, import_node_fs42.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
|
|
37447
37576
|
try {
|
|
37448
|
-
return { name: d.name, mtimeMs: newestMtimeMs((0,
|
|
37577
|
+
return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path40.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs42.statSync)(p).mtimeMs) };
|
|
37449
37578
|
} catch {
|
|
37450
37579
|
return { name: d.name, mtimeMs: Date.now() };
|
|
37451
37580
|
}
|
|
@@ -37459,10 +37588,10 @@ function stagingApplyFsGuard(configRoot) {
|
|
|
37459
37588
|
return {
|
|
37460
37589
|
referencedPaths: () => readInstalledPluginRefs(configRoot),
|
|
37461
37590
|
mtimeMs: (name) => {
|
|
37462
|
-
const p = (0,
|
|
37463
|
-
if (!(0,
|
|
37591
|
+
const p = (0, import_node_path40.join)(stagingRoot, name);
|
|
37592
|
+
if (!(0, import_node_fs42.existsSync)(p)) return null;
|
|
37464
37593
|
try {
|
|
37465
|
-
return newestMtimeMs(p, listDirEntries, (q) => (0,
|
|
37594
|
+
return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs42.statSync)(q).mtimeMs);
|
|
37466
37595
|
} catch {
|
|
37467
37596
|
return null;
|
|
37468
37597
|
}
|
|
@@ -37482,13 +37611,13 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
|
|
|
37482
37611
|
return;
|
|
37483
37612
|
}
|
|
37484
37613
|
const plan = buildPluginCachePlan(
|
|
37485
|
-
(0,
|
|
37614
|
+
(0, import_node_os17.homedir)(),
|
|
37486
37615
|
running,
|
|
37487
37616
|
pluginCacheFsDeps(configRoot, directoryBytes),
|
|
37488
37617
|
{ withBytes: true, configRoot, includeStaging: surface !== "codex" }
|
|
37489
37618
|
);
|
|
37490
37619
|
const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
|
|
37491
|
-
const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0,
|
|
37620
|
+
const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs42.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
|
|
37492
37621
|
const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
|
|
37493
37622
|
if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
|
|
37494
37623
|
else console.log(renderPluginCachePlan(plan, result));
|
|
@@ -37496,7 +37625,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
|
|
|
37496
37625
|
});
|
|
37497
37626
|
function readReleaseCatchupState(path2) {
|
|
37498
37627
|
try {
|
|
37499
|
-
const parsed = JSON.parse((0,
|
|
37628
|
+
const parsed = JSON.parse((0, import_node_fs42.readFileSync)(path2, "utf8"));
|
|
37500
37629
|
return typeof parsed?.checkedAt === "number" ? parsed : void 0;
|
|
37501
37630
|
} catch {
|
|
37502
37631
|
return void 0;
|
|
@@ -37504,8 +37633,8 @@ function readReleaseCatchupState(path2) {
|
|
|
37504
37633
|
}
|
|
37505
37634
|
function writeReleaseCatchupState(path2, state) {
|
|
37506
37635
|
try {
|
|
37507
|
-
(0,
|
|
37508
|
-
(0,
|
|
37636
|
+
(0, import_node_fs42.mkdirSync)((0, import_node_path40.dirname)(path2), { recursive: true });
|
|
37637
|
+
(0, import_node_fs42.writeFileSync)(path2, `${JSON.stringify(state)}
|
|
37509
37638
|
`);
|
|
37510
37639
|
} catch {
|
|
37511
37640
|
}
|
|
@@ -37513,7 +37642,7 @@ function writeReleaseCatchupState(path2, state) {
|
|
|
37513
37642
|
program2.command("plugin-release-catchup").description("install a newer released MMI plugin clone non-destructively and re-point the Pi registration (#4297); TTL-gated no-op when current").option("--force", "skip the 24h TTL (acceptance proof / manual run)").option("--quiet", "print only failures (the detached session-start lane)").option("--json", "machine-readable output").action(async (o) => {
|
|
37514
37643
|
const outcome = await withEnvHealLock(
|
|
37515
37644
|
"plugin release catch-up",
|
|
37516
|
-
() => runReleaseCatchup((0,
|
|
37645
|
+
() => runReleaseCatchup((0, import_node_os17.homedir)(), process.env, {
|
|
37517
37646
|
fetchReleased: fetchNpmReleasedVersion,
|
|
37518
37647
|
runClaude: (args, step) => runPluginCli("claude", args, (msg) => {
|
|
37519
37648
|
if (!o.quiet && !o.json) console.log(msg);
|
|
@@ -37529,7 +37658,7 @@ program2.command("plugin-release-catchup").description("install a newer released
|
|
|
37529
37658
|
},
|
|
37530
37659
|
readState: readReleaseCatchupState,
|
|
37531
37660
|
writeState: writeReleaseCatchupState,
|
|
37532
|
-
healRegistration: defaultRegistrationHeal((0,
|
|
37661
|
+
healRegistration: defaultRegistrationHeal((0, import_node_os17.homedir)(), process.env),
|
|
37533
37662
|
now: () => Date.now()
|
|
37534
37663
|
}, { force: o.force })
|
|
37535
37664
|
);
|
|
@@ -37597,7 +37726,7 @@ program2.command("session-start").description("run the SessionStart verbs (whoam
|
|
|
37597
37726
|
spawnDetachedSelf(["worktree", "setup", "--quiet"], { spawn: import_node_child_process19.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
|
|
37598
37727
|
bannerIo.log(worktreeBanner);
|
|
37599
37728
|
}
|
|
37600
|
-
if (shouldSpawnReleaseCatchup((0,
|
|
37729
|
+
if (shouldSpawnReleaseCatchup((0, import_node_os17.homedir)(), process.env, readReleaseCatchupState)) {
|
|
37601
37730
|
spawnDetachedSelf(["plugin", "release-catchup", "--quiet"], { spawn: import_node_child_process19.spawn, execPath: process.execPath, scriptPath: process.argv[1] });
|
|
37602
37731
|
}
|
|
37603
37732
|
if (isLinkedWorktree(process.cwd())) {
|
package/package.json
CHANGED