@mutmutco/claude-plugin 4.5.228 → 4.5.229
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/.claude-plugin/plugin.json +1 -1
- package/cli/dist/main.cjs +392 -309
- package/cli/package.json +1 -1
- package/package.json +1 -1
- package/skills/bootstrap/SKILL.md +1 -1
- package/skills/hotfix/SKILL.md +1 -1
- package/skills/mmi-help/SKILL.md +3 -2
- package/skills/rcand/SKILL.md +1 -1
- package/skills/release/SKILL.md +1 -1
- package/skills/secrets/SKILL.md +1 -1
package/cli/dist/main.cjs
CHANGED
|
@@ -13472,7 +13472,7 @@ function useColor() {
|
|
|
13472
13472
|
var program = new Command();
|
|
13473
13473
|
|
|
13474
13474
|
// src/command-composition.ts
|
|
13475
|
-
var
|
|
13475
|
+
var import_node_fs61 = require("node:fs");
|
|
13476
13476
|
init_clean_exit();
|
|
13477
13477
|
init_cli_shared();
|
|
13478
13478
|
|
|
@@ -27210,10 +27210,10 @@ var rollout_plan_default = {
|
|
|
27210
27210
|
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)."
|
|
27211
27211
|
},
|
|
27212
27212
|
baseline: {
|
|
27213
|
-
version: "4.5.
|
|
27214
|
-
tag: "v4.5.
|
|
27215
|
-
commit: "
|
|
27216
|
-
npm: "@mutmutco/cli@4.5.
|
|
27213
|
+
version: "4.5.229",
|
|
27214
|
+
tag: "v4.5.229",
|
|
27215
|
+
commit: "15792605c6d9",
|
|
27216
|
+
npm: "@mutmutco/cli@4.5.229"
|
|
27217
27217
|
},
|
|
27218
27218
|
exitCriterion: "fleet-n-of-n",
|
|
27219
27219
|
hubOnlyShortcut: "forbidden",
|
|
@@ -27230,14 +27230,14 @@ var rollout_plan_default = {
|
|
|
27230
27230
|
repo: "mutmutco/mmi-hub",
|
|
27231
27231
|
role: "canary",
|
|
27232
27232
|
schedule: "train",
|
|
27233
|
-
v3Target: "v4.5.
|
|
27233
|
+
v3Target: "v4.5.229"
|
|
27234
27234
|
}
|
|
27235
27235
|
],
|
|
27236
27236
|
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.",
|
|
27237
27237
|
rollback: {
|
|
27238
27238
|
independent: true,
|
|
27239
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
27240
|
-
v3Target: "v4.5.
|
|
27239
|
+
mechanism: "npm dist-tag latest -> 4.5.229 and redeploy the Hub Lambda from tag v4.5.229 (15792605c6d9); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
27240
|
+
v3Target: "v4.5.229 (@mutmutco/cli@4.5.229, tag commit 15792605c6d9 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
27241
27241
|
}
|
|
27242
27242
|
},
|
|
27243
27243
|
{
|
|
@@ -31784,7 +31784,7 @@ function renderTenantControl(r) {
|
|
|
31784
31784
|
}
|
|
31785
31785
|
|
|
31786
31786
|
// src/train-apply-phases.ts
|
|
31787
|
-
var
|
|
31787
|
+
var import_node_fs31 = require("node:fs");
|
|
31788
31788
|
var import_promises4 = require("node:fs/promises");
|
|
31789
31789
|
var import_node_path28 = require("node:path");
|
|
31790
31790
|
|
|
@@ -32092,6 +32092,71 @@ Resume it: ${resumeCommand}
|
|
|
32092
32092
|
);
|
|
32093
32093
|
}
|
|
32094
32094
|
|
|
32095
|
+
// src/train-apply-pretag-hook.ts
|
|
32096
|
+
var import_node_fs25 = require("node:fs");
|
|
32097
|
+
var PRETAG_SCRIPT = "release:pretag";
|
|
32098
|
+
var PRETAG_TAIL_LINES = 40;
|
|
32099
|
+
function declaredScripts() {
|
|
32100
|
+
try {
|
|
32101
|
+
const parsed = JSON.parse((0, import_node_fs25.readFileSync)("package.json", "utf8"));
|
|
32102
|
+
return parsed.scripts ?? {};
|
|
32103
|
+
} catch {
|
|
32104
|
+
return null;
|
|
32105
|
+
}
|
|
32106
|
+
}
|
|
32107
|
+
function outputTail(error) {
|
|
32108
|
+
const e = error;
|
|
32109
|
+
const streams = [e?.stdout, e?.stderr].filter((s) => typeof s === "string" && s.trim() !== "");
|
|
32110
|
+
const text = streams.length > 0 ? streams.join("\n") : error instanceof Error ? error.message : String(error);
|
|
32111
|
+
const lines2 = text.replace(/\r\n/g, "\n").trimEnd().split("\n");
|
|
32112
|
+
return lines2.slice(-PRETAG_TAIL_LINES).join("\n");
|
|
32113
|
+
}
|
|
32114
|
+
function porcelainPaths(output) {
|
|
32115
|
+
return output.split("\n").map((line) => line.trimEnd()).filter(Boolean).map((line) => line.slice(3).trim().replace(/^"|"$/g, "").replaceAll("\\", "/"));
|
|
32116
|
+
}
|
|
32117
|
+
async function runPreTagHook(deps, input) {
|
|
32118
|
+
const command = `npm run ${PRETAG_SCRIPT}`;
|
|
32119
|
+
const shortSha = input.releaseSha.slice(0, 12);
|
|
32120
|
+
const scripts = declaredScripts();
|
|
32121
|
+
if (!scripts || !String(scripts[PRETAG_SCRIPT] ?? "").trim()) {
|
|
32122
|
+
const note = `no \`${PRETAG_SCRIPT}\` script in the repo's package.json: this release's refusable checks run only in CI, AFTER the tag is pushed \u2014 a late failure then leaves a public tag (and Release) on a version that never shipped (#9189). Declare "${PRETAG_SCRIPT}": "<the checks your publish/Release has refused before>" so the train can refuse before anything reaches origin.`;
|
|
32123
|
+
deps.warn?.(`Release: ${note}`);
|
|
32124
|
+
return { status: "missing", command, note };
|
|
32125
|
+
}
|
|
32126
|
+
const headBefore = clean2(await deps.run("git", ["rev-parse", "HEAD"]));
|
|
32127
|
+
if (headBefore !== input.releaseSha) {
|
|
32128
|
+
throw new Error(
|
|
32129
|
+
`pre-tag checks refused: the checkout is on ${headBefore.slice(0, 12)}, not the folded release commit ${shortSha} \u2014 \`${command}\` must prove the exact commit the tag would make immutable (#9189). Nothing was tagged, main was not pushed and no GitHub Release exists.`
|
|
32130
|
+
);
|
|
32131
|
+
}
|
|
32132
|
+
deps.warn?.(`Release: Running the repo's pre-tag checks (${command})`);
|
|
32133
|
+
try {
|
|
32134
|
+
await deps.run("npm", ["run", PRETAG_SCRIPT]);
|
|
32135
|
+
} catch (e) {
|
|
32136
|
+
throw new Error(
|
|
32137
|
+
`pre-tag checks refused: \`${command}\` failed on the folded release commit ${shortSha} \u2014 nothing was tagged, main was not pushed and no GitHub Release exists (#9189).
|
|
32138
|
+
|
|
32139
|
+
--- ${command} output (tail) ---
|
|
32140
|
+
${outputTail(e)}
|
|
32141
|
+
--- end of ${command} output ---
|
|
32142
|
+
Remedy: fix the failing check in the release fold (or in the repo) and rerun the release. Never tag around it \u2014 the same check runs again on the v* tag, after the tag is public and un-removable without deleting a release.`
|
|
32143
|
+
);
|
|
32144
|
+
}
|
|
32145
|
+
const headAfter = clean2(await deps.run("git", ["rev-parse", "HEAD"]));
|
|
32146
|
+
if (headAfter !== input.releaseSha) {
|
|
32147
|
+
throw new Error(
|
|
32148
|
+
`pre-tag checks refused: \`${command}\` moved the checkout to ${headAfter.slice(0, 12)} (the release commit is ${shortSha}) \u2014 the hook must VERIFY the committed release bytes, never commit or check out. Anything it changed would ship unverified (#9189). Nothing was tagged, main was not pushed and no GitHub Release exists.`
|
|
32149
|
+
);
|
|
32150
|
+
}
|
|
32151
|
+
const dirty = porcelainPaths(await deps.run("git", ["status", "--porcelain=v1", "--untracked-files=no"]));
|
|
32152
|
+
if (dirty.length > 0) {
|
|
32153
|
+
throw new Error(
|
|
32154
|
+
`pre-tag checks refused: \`${command}\` modified tracked file(s) in the release checkout \u2014 ${dirty.join(", ")}. The train tags the COMMITTED fold commit, so an uncommitted regeneration would never ship and the check that produced it proves nothing (#9189). Commit the regenerated file into the fold (or make the hook read-only) and rerun: nothing was tagged, main was not pushed and no GitHub Release exists.`
|
|
32155
|
+
);
|
|
32156
|
+
}
|
|
32157
|
+
return { status: "passed", command, note: `\`${command}\` passed on ${shortSha} before the tag` };
|
|
32158
|
+
}
|
|
32159
|
+
|
|
32095
32160
|
// src/pre-one-zero.ts
|
|
32096
32161
|
function preOneZeroInForce(meta) {
|
|
32097
32162
|
return !!meta?.suite && meta.preOneZero !== false;
|
|
@@ -32114,12 +32179,12 @@ function assertPreOneZero(repo, meta, tag) {
|
|
|
32114
32179
|
|
|
32115
32180
|
// src/train-doctor.ts
|
|
32116
32181
|
var import_node_child_process9 = require("node:child_process");
|
|
32117
|
-
var
|
|
32182
|
+
var import_node_fs29 = require("node:fs");
|
|
32118
32183
|
var import_node_os16 = require("node:os");
|
|
32119
32184
|
var import_node_path27 = require("node:path");
|
|
32120
32185
|
|
|
32121
32186
|
// src/doctor-io.ts
|
|
32122
|
-
var
|
|
32187
|
+
var import_node_fs26 = require("node:fs");
|
|
32123
32188
|
var import_node_os13 = require("node:os");
|
|
32124
32189
|
var import_node_path22 = require("node:path");
|
|
32125
32190
|
var import_node_child_process7 = require("node:child_process");
|
|
@@ -32134,8 +32199,8 @@ function nodeDiscardSinkPath(platform2 = process.platform) {
|
|
|
32134
32199
|
var execFileP2 = (0, import_node_util4.promisify)(import_node_child_process7.execFile);
|
|
32135
32200
|
function execFileCapture(file, args, opts = {}) {
|
|
32136
32201
|
const sink = nodeDiscardSinkPath();
|
|
32137
|
-
const inFd = (0,
|
|
32138
|
-
const errFd = (0,
|
|
32202
|
+
const inFd = (0, import_node_fs26.openSync)(sink, "r");
|
|
32203
|
+
const errFd = (0, import_node_fs26.openSync)(sink, "w");
|
|
32139
32204
|
try {
|
|
32140
32205
|
return (0, import_node_child_process7.execFileSync)(file, args, {
|
|
32141
32206
|
...opts,
|
|
@@ -32143,17 +32208,17 @@ function execFileCapture(file, args, opts = {}) {
|
|
|
32143
32208
|
stdio: [inFd, "pipe", errFd]
|
|
32144
32209
|
});
|
|
32145
32210
|
} finally {
|
|
32146
|
-
(0,
|
|
32147
|
-
(0,
|
|
32211
|
+
(0, import_node_fs26.closeSync)(inFd);
|
|
32212
|
+
(0, import_node_fs26.closeSync)(errFd);
|
|
32148
32213
|
}
|
|
32149
32214
|
}
|
|
32150
32215
|
var MMI_PLUGIN_ID2 = "mmi@mutmutco";
|
|
32151
32216
|
function stagedClaudePluginVersion() {
|
|
32152
32217
|
try {
|
|
32153
32218
|
const stagingRoot = (0, import_node_path22.join)((0, import_node_os13.homedir)(), ".claude", "plugins", "staging");
|
|
32154
|
-
const record2 = JSON.parse((0,
|
|
32219
|
+
const record2 = JSON.parse((0, import_node_fs26.readFileSync)((0, import_node_path22.join)(stagingRoot, "launch-target.json"), "utf8"));
|
|
32155
32220
|
if (typeof record2.target !== "string" || typeof record2.incoming !== "string") return void 0;
|
|
32156
|
-
const manifest = JSON.parse((0,
|
|
32221
|
+
const manifest = JSON.parse((0, import_node_fs26.readFileSync)((0, import_node_path22.join)(record2.incoming, ".claude-plugin", "plugin.json"), "utf8"));
|
|
32157
32222
|
if (typeof manifest.version !== "string") return void 0;
|
|
32158
32223
|
return manifest.version === record2.target ? record2.target : void 0;
|
|
32159
32224
|
} catch {
|
|
@@ -32163,7 +32228,7 @@ function stagedClaudePluginVersion() {
|
|
|
32163
32228
|
function installedClaudePluginVersion() {
|
|
32164
32229
|
try {
|
|
32165
32230
|
const file = JSON.parse(
|
|
32166
|
-
(0,
|
|
32231
|
+
(0, import_node_fs26.readFileSync)((0, import_node_path22.join)((0, import_node_os13.homedir)(), ".claude", "plugins", "installed_plugins.json"), "utf8")
|
|
32167
32232
|
);
|
|
32168
32233
|
const versions = (file.plugins?.[MMI_PLUGIN_ID2] ?? []).map((r) => r.version).filter((v) => Boolean(v));
|
|
32169
32234
|
if (versions.length === 0) return void 0;
|
|
@@ -32231,7 +32296,7 @@ function readGitignore() {
|
|
|
32231
32296
|
const path2 = gitignorePath();
|
|
32232
32297
|
if (path2 === null) return null;
|
|
32233
32298
|
try {
|
|
32234
|
-
return (0,
|
|
32299
|
+
return (0, import_node_fs26.readFileSync)(path2, "utf8");
|
|
32235
32300
|
} catch {
|
|
32236
32301
|
return null;
|
|
32237
32302
|
}
|
|
@@ -32240,14 +32305,14 @@ function writeGitignore(content) {
|
|
|
32240
32305
|
const path2 = gitignorePath();
|
|
32241
32306
|
if (path2 === null) return false;
|
|
32242
32307
|
try {
|
|
32243
|
-
(0,
|
|
32308
|
+
(0, import_node_fs26.writeFileSync)(path2, content, "utf8");
|
|
32244
32309
|
return true;
|
|
32245
32310
|
} catch {
|
|
32246
32311
|
return false;
|
|
32247
32312
|
}
|
|
32248
32313
|
}
|
|
32249
32314
|
function lineEndingState(root) {
|
|
32250
|
-
const attributesPresent = (0,
|
|
32315
|
+
const attributesPresent = (0, import_node_fs26.existsSync)((0, import_node_path22.join)(root, ".gitattributes"));
|
|
32251
32316
|
try {
|
|
32252
32317
|
const output = execFileCapture("git", ["-C", root, "ls-files", "--eol", "--", ":(glob)**/*.sh"], {
|
|
32253
32318
|
windowsHide: true
|
|
@@ -32290,7 +32355,7 @@ function compatHolds(range, version) {
|
|
|
32290
32355
|
}
|
|
32291
32356
|
|
|
32292
32357
|
// src/claude-binary-doctor.ts
|
|
32293
|
-
var
|
|
32358
|
+
var import_node_fs27 = require("node:fs");
|
|
32294
32359
|
var import_node_os15 = require("node:os");
|
|
32295
32360
|
var import_node_path24 = require("node:path");
|
|
32296
32361
|
|
|
@@ -32398,16 +32463,16 @@ function globalNodeModulesRoots(host) {
|
|
|
32398
32463
|
function readHead(path2) {
|
|
32399
32464
|
let fd;
|
|
32400
32465
|
try {
|
|
32401
|
-
fd = (0,
|
|
32466
|
+
fd = (0, import_node_fs27.openSync)(path2, "r");
|
|
32402
32467
|
const buffer = new Uint8Array(MAGIC_HEAD_BYTES);
|
|
32403
|
-
const read = (0,
|
|
32468
|
+
const read = (0, import_node_fs27.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
|
|
32404
32469
|
return buffer.subarray(0, read);
|
|
32405
32470
|
} catch {
|
|
32406
32471
|
return void 0;
|
|
32407
32472
|
} finally {
|
|
32408
32473
|
if (fd !== void 0) {
|
|
32409
32474
|
try {
|
|
32410
|
-
(0,
|
|
32475
|
+
(0, import_node_fs27.closeSync)(fd);
|
|
32411
32476
|
} catch {
|
|
32412
32477
|
}
|
|
32413
32478
|
}
|
|
@@ -32415,7 +32480,7 @@ function readHead(path2) {
|
|
|
32415
32480
|
}
|
|
32416
32481
|
function fileBytes(path2) {
|
|
32417
32482
|
try {
|
|
32418
|
-
return (0,
|
|
32483
|
+
return (0, import_node_fs27.statSync)(path2).size;
|
|
32419
32484
|
} catch {
|
|
32420
32485
|
return void 0;
|
|
32421
32486
|
}
|
|
@@ -32429,13 +32494,13 @@ function readClaudeBinaryState(host = {}) {
|
|
|
32429
32494
|
const arch = host.arch ?? process.arch;
|
|
32430
32495
|
const magic = EXECUTABLE_MAGIC[platform2];
|
|
32431
32496
|
if (!magic) return void 0;
|
|
32432
|
-
const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path24.join)(root, ...PACKAGE.split("/"))).find((dir) => (0,
|
|
32497
|
+
const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path24.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs27.existsSync)((0, import_node_path24.join)(dir, "package.json")));
|
|
32433
32498
|
if (!packageRoot) return void 0;
|
|
32434
32499
|
const keys = platformPackageKeys(platform2, arch);
|
|
32435
32500
|
const fallbackPackage = `${PACKAGE}-${keys[0]}`;
|
|
32436
32501
|
let manifest;
|
|
32437
32502
|
try {
|
|
32438
|
-
manifest = JSON.parse((0,
|
|
32503
|
+
manifest = JSON.parse((0, import_node_fs27.readFileSync)((0, import_node_path24.join)(packageRoot, "package.json"), "utf8"));
|
|
32439
32504
|
} catch (e) {
|
|
32440
32505
|
return {
|
|
32441
32506
|
state: "unreadable",
|
|
@@ -32466,7 +32531,7 @@ function readClaudeBinaryState(host = {}) {
|
|
|
32466
32531
|
(0, import_node_path24.join)(packageRoot, "node_modules", ...name.split("/"), binName),
|
|
32467
32532
|
(0, import_node_path24.join)((0, import_node_path24.dirname)((0, import_node_path24.dirname)(packageRoot)), ...name.split("/"), binName)
|
|
32468
32533
|
];
|
|
32469
|
-
const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0,
|
|
32534
|
+
const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs27.existsSync)(file)) })).find((c) => c.path);
|
|
32470
32535
|
const platformPackage = found?.name ?? published[0];
|
|
32471
32536
|
let source;
|
|
32472
32537
|
let sourceProblem;
|
|
@@ -32477,7 +32542,7 @@ function readClaudeBinaryState(host = {}) {
|
|
|
32477
32542
|
} else {
|
|
32478
32543
|
source = { path: found.path, bytes: fileBytes(found.path) ?? 0 };
|
|
32479
32544
|
}
|
|
32480
|
-
if (!(0,
|
|
32545
|
+
if (!(0, import_node_fs27.existsSync)(binPath)) {
|
|
32481
32546
|
return { state: "missing", binPath, expectedMagic: magic.name, platformPackage, ...source ? { source } : {}, ...sourceProblem ? { sourceProblem } : {} };
|
|
32482
32547
|
}
|
|
32483
32548
|
const head = readHead(binPath);
|
|
@@ -32520,9 +32585,9 @@ function healClaudeBinary(host = {}, onStep) {
|
|
|
32520
32585
|
const platform2 = host.platform ?? process.platform;
|
|
32521
32586
|
const aside = `${probe.binPath}.stub-${Date.now()}`;
|
|
32522
32587
|
let renamed = false;
|
|
32523
|
-
if ((0,
|
|
32588
|
+
if ((0, import_node_fs27.existsSync)(probe.binPath)) {
|
|
32524
32589
|
try {
|
|
32525
|
-
(0,
|
|
32590
|
+
(0, import_node_fs27.renameSync)(probe.binPath, aside);
|
|
32526
32591
|
renamed = true;
|
|
32527
32592
|
onStep?.(`renamed the stub aside: ${aside}`);
|
|
32528
32593
|
} catch (e) {
|
|
@@ -32531,12 +32596,12 @@ function healClaudeBinary(host = {}, onStep) {
|
|
|
32531
32596
|
}
|
|
32532
32597
|
try {
|
|
32533
32598
|
onStep?.(`copying ${probe.source.path} \u2192 ${probe.binPath} (${(probe.source.bytes / 1e6).toFixed(0)} MB)`);
|
|
32534
|
-
(0,
|
|
32535
|
-
if (platform2 !== "win32") (0,
|
|
32599
|
+
(0, import_node_fs27.copyFileSync)(probe.source.path, probe.binPath);
|
|
32600
|
+
if (platform2 !== "win32") (0, import_node_fs27.chmodSync)(probe.binPath, 493);
|
|
32536
32601
|
} catch (e) {
|
|
32537
32602
|
if (renamed) {
|
|
32538
32603
|
try {
|
|
32539
|
-
(0,
|
|
32604
|
+
(0, import_node_fs27.renameSync)(aside, probe.binPath);
|
|
32540
32605
|
} catch {
|
|
32541
32606
|
return { ok: false, detail: `copy failed (${e.message}) and the stub could not be restored \u2014 the original is at ${aside}` };
|
|
32542
32607
|
}
|
|
@@ -32550,7 +32615,7 @@ function healClaudeBinary(host = {}, onStep) {
|
|
|
32550
32615
|
let kept = false;
|
|
32551
32616
|
if (renamed) {
|
|
32552
32617
|
try {
|
|
32553
|
-
(0,
|
|
32618
|
+
(0, import_node_fs27.rmSync)(aside);
|
|
32554
32619
|
} catch {
|
|
32555
32620
|
kept = true;
|
|
32556
32621
|
}
|
|
@@ -32909,7 +32974,7 @@ function checkLineEndings(probe) {
|
|
|
32909
32974
|
}
|
|
32910
32975
|
|
|
32911
32976
|
// src/release-ledger.ts
|
|
32912
|
-
var
|
|
32977
|
+
var import_node_fs28 = require("node:fs");
|
|
32913
32978
|
var import_node_path26 = require("node:path");
|
|
32914
32979
|
var import_node_crypto9 = require("node:crypto");
|
|
32915
32980
|
|
|
@@ -33084,8 +33149,8 @@ function attachOutputNote(note, suffix) {
|
|
|
33084
33149
|
}
|
|
33085
33150
|
function writeFailingLegOutput(artifactPath, output) {
|
|
33086
33151
|
const fileLines = lastNonEmptyLines(output, LEDGER_OUTPUT_FILE_LINES);
|
|
33087
|
-
(0,
|
|
33088
|
-
(0,
|
|
33152
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path26.dirname)(artifactPath), { recursive: true });
|
|
33153
|
+
(0, import_node_fs28.writeFileSync)(artifactPath, `${fileLines.join("\n")}
|
|
33089
33154
|
`, "utf8");
|
|
33090
33155
|
const tail = fileLines.slice(-LEDGER_OUTPUT_NOTE_LINES).join("\n");
|
|
33091
33156
|
const noteSuffix = truncate(`failing-leg output: ${artifactPath}
|
|
@@ -33253,7 +33318,7 @@ function resolvePrimaryGitDir(cwd) {
|
|
|
33253
33318
|
}
|
|
33254
33319
|
let common;
|
|
33255
33320
|
try {
|
|
33256
|
-
common = (0,
|
|
33321
|
+
common = (0, import_node_fs28.readFileSync)((0, import_node_path26.join)(gitDir, "commondir"), "utf8").trim();
|
|
33257
33322
|
} catch (e) {
|
|
33258
33323
|
if (e.code !== "ENOENT") {
|
|
33259
33324
|
throw new ReleaseLedgerError("unreadable", `release ledger: the worktree gitdir's commondir pointer could not be READ (${e instanceof Error ? e.message : String(e)}) \u2014 a failed read is unverified, not primary (#5987/#4713)`);
|
|
@@ -33262,7 +33327,7 @@ function resolvePrimaryGitDir(cwd) {
|
|
|
33262
33327
|
if (!common) return gitDir;
|
|
33263
33328
|
const commonDir = (0, import_node_path26.isAbsolute)(common) ? common : (0, import_node_path26.resolve)(gitDir, common);
|
|
33264
33329
|
try {
|
|
33265
|
-
(0,
|
|
33330
|
+
(0, import_node_fs28.readFileSync)((0, import_node_path26.join)(commonDir, "HEAD"), "utf8");
|
|
33266
33331
|
} catch (e) {
|
|
33267
33332
|
throw new ReleaseLedgerError("no-checkout", `release ledger: the worktree's commondir pointer names ${commonDir}, which has no readable HEAD (${e instanceof Error ? e.message : String(e)}) \u2014 the primary checkout may have been removed; refusing to write the ledger into a doomed location`);
|
|
33268
33333
|
}
|
|
@@ -33272,11 +33337,11 @@ function releaseLedgerPath(cwd) {
|
|
|
33272
33337
|
return (0, import_node_path26.join)(resolvePrimaryGitDir(cwd), "mmi-runtime", "release", "phases.json");
|
|
33273
33338
|
}
|
|
33274
33339
|
function atomicWriteJson(path2, ledger) {
|
|
33275
|
-
(0,
|
|
33340
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path26.dirname)(path2), { recursive: true });
|
|
33276
33341
|
const tmp = `${path2}.tmp-${process.pid}-${(0, import_node_crypto9.randomBytes)(4).toString("hex")}`;
|
|
33277
|
-
(0,
|
|
33342
|
+
(0, import_node_fs28.writeFileSync)(tmp, `${JSON.stringify(ledger, null, 2)}
|
|
33278
33343
|
`, "utf8");
|
|
33279
|
-
(0,
|
|
33344
|
+
(0, import_node_fs28.renameSync)(tmp, path2);
|
|
33280
33345
|
}
|
|
33281
33346
|
var LEDGER_LOCK_OPTS = { label: "release ledger", staleMs: 18e4, deadHolderSteal: true };
|
|
33282
33347
|
async function withLedgerLock(path2, fn, opts = {}) {
|
|
@@ -33323,7 +33388,7 @@ function describeTrainWriterToken(token) {
|
|
|
33323
33388
|
function liveTrainWriterHolder(cwd) {
|
|
33324
33389
|
let token;
|
|
33325
33390
|
try {
|
|
33326
|
-
token = (0,
|
|
33391
|
+
token = (0, import_node_fs28.readFileSync)(trainWriterLockPath(cwd), "utf8");
|
|
33327
33392
|
} catch {
|
|
33328
33393
|
return void 0;
|
|
33329
33394
|
}
|
|
@@ -33345,7 +33410,7 @@ async function acquireTrainWriterLock(cwd, verb) {
|
|
|
33345
33410
|
if (heldTrainWriter) heldTrainWriter.depth -= 1;
|
|
33346
33411
|
};
|
|
33347
33412
|
}
|
|
33348
|
-
(0,
|
|
33413
|
+
(0, import_node_fs28.mkdirSync)((0, import_node_path26.dirname)(lockPath), { recursive: true });
|
|
33349
33414
|
const opts = resolveFileLockOpts({ label: "train writer", staleMs: TRAIN_WRITER_STALE_MS, deadHolderSteal: true, maxWaitMs: 0, holder: verb });
|
|
33350
33415
|
let guard;
|
|
33351
33416
|
try {
|
|
@@ -33354,7 +33419,7 @@ async function acquireTrainWriterLock(cwd, verb) {
|
|
|
33354
33419
|
if (!(e instanceof FileLockBusyError)) throw e;
|
|
33355
33420
|
let token = "";
|
|
33356
33421
|
try {
|
|
33357
|
-
token = (0,
|
|
33422
|
+
token = (0, import_node_fs28.readFileSync)(lockPath, "utf8");
|
|
33358
33423
|
} catch {
|
|
33359
33424
|
token = "";
|
|
33360
33425
|
}
|
|
@@ -33389,7 +33454,7 @@ async function withReleaseLedger(path2, expected, fn, opts = {}) {
|
|
|
33389
33454
|
let current;
|
|
33390
33455
|
let raw;
|
|
33391
33456
|
try {
|
|
33392
|
-
raw = (0,
|
|
33457
|
+
raw = (0, import_node_fs28.readFileSync)(path2, "utf8");
|
|
33393
33458
|
} catch (e) {
|
|
33394
33459
|
if (e.code !== "ENOENT") {
|
|
33395
33460
|
throw new ReleaseLedgerError("unreadable", `release ledger at ${path2} could not be READ (${e instanceof Error ? e.message : String(e)}) \u2014 a failed read is unverified, not absent (#5987)`);
|
|
@@ -34056,7 +34121,7 @@ async function clearLedgerFile(path2, anchors, maxWaitMs) {
|
|
|
34056
34121
|
return withLedgerLock(path2, async (fence) => {
|
|
34057
34122
|
let raw;
|
|
34058
34123
|
try {
|
|
34059
|
-
raw = (0,
|
|
34124
|
+
raw = (0, import_node_fs28.readFileSync)(path2, "utf8");
|
|
34060
34125
|
} catch (e) {
|
|
34061
34126
|
if (e.code === "ENOENT") return { cleared: false };
|
|
34062
34127
|
return { cleared: false, note: `release ledger at ${path2} could not be read for clearing (${e instanceof Error ? e.message : String(e)}) \u2014 left in place` };
|
|
@@ -34072,7 +34137,7 @@ async function clearLedgerFile(path2, anchors, maxWaitMs) {
|
|
|
34072
34137
|
} catch (e) {
|
|
34073
34138
|
return { cleared: false, note: `release ledger at ${path2} belongs to ${ledger.tag} @ ${ledger.tagSha.slice(0, 12)} \u2014 not this release; left in place (${e instanceof Error ? e.message : String(e)})` };
|
|
34074
34139
|
}
|
|
34075
|
-
await fence(() => (0,
|
|
34140
|
+
await fence(() => (0, import_node_fs28.unlinkSync)(path2));
|
|
34076
34141
|
return { cleared: true, note: `cleared the release ledger at ${path2} for the live-proven aborted ${anchors.tag}` };
|
|
34077
34142
|
}, { maxWaitMs });
|
|
34078
34143
|
}
|
|
@@ -34232,7 +34297,7 @@ async function healStaleAlignmentLeg(deps, cwd, expected) {
|
|
|
34232
34297
|
return withLedgerLock(path2, async (fence) => {
|
|
34233
34298
|
let prior;
|
|
34234
34299
|
try {
|
|
34235
|
-
prior = parseReleaseLedger((0,
|
|
34300
|
+
prior = parseReleaseLedger((0, import_node_fs28.readFileSync)(path2, "utf8"));
|
|
34236
34301
|
} catch {
|
|
34237
34302
|
return void 0;
|
|
34238
34303
|
}
|
|
@@ -34257,7 +34322,7 @@ async function healUnfoldedRunLegs(deps, cwd, model) {
|
|
|
34257
34322
|
const path2 = releaseLedgerPath(cwd);
|
|
34258
34323
|
let prior;
|
|
34259
34324
|
try {
|
|
34260
|
-
prior = parseReleaseLedger((0,
|
|
34325
|
+
prior = parseReleaseLedger((0, import_node_fs28.readFileSync)(path2, "utf8"));
|
|
34261
34326
|
} catch {
|
|
34262
34327
|
return void 0;
|
|
34263
34328
|
}
|
|
@@ -34326,7 +34391,7 @@ async function supersedeContentCausedDeployLeg(deps, cwd) {
|
|
|
34326
34391
|
return withLedgerLock(path2, async (fence) => {
|
|
34327
34392
|
let prior;
|
|
34328
34393
|
try {
|
|
34329
|
-
prior = parseReleaseLedger((0,
|
|
34394
|
+
prior = parseReleaseLedger((0, import_node_fs28.readFileSync)(path2, "utf8"));
|
|
34330
34395
|
} catch (e) {
|
|
34331
34396
|
throw new ReleaseLedgerError(
|
|
34332
34397
|
"unreadable",
|
|
@@ -34440,10 +34505,10 @@ async function proveOriginPromotionOrArchived(deps, prior, path2, label, ref, fe
|
|
|
34440
34505
|
throw new Error(`${label}: origin no longer has ${prior.tag} but its GitHub Release still exists \u2014 resolve the mixed external state before closing the ledger; nothing was written (${ref})`);
|
|
34441
34506
|
}
|
|
34442
34507
|
const archivePath = (0, import_node_path26.join)((0, import_node_path26.dirname)(path2), `phases.archive-${prior.tag}.json`);
|
|
34443
|
-
if ((0,
|
|
34508
|
+
if ((0, import_node_fs28.existsSync)(archivePath)) {
|
|
34444
34509
|
throw new Error(`${label}: archive already exists at ${archivePath} \u2014 preserving both ledger records; resolve the collision by hand; nothing was written (${ref})`);
|
|
34445
34510
|
}
|
|
34446
|
-
await fence(() => (0,
|
|
34511
|
+
await fence(() => (0, import_node_fs28.renameSync)(path2, archivePath));
|
|
34447
34512
|
return "deleted";
|
|
34448
34513
|
}
|
|
34449
34514
|
async function supersedeContentCausedPublishLeg(deps, cwd) {
|
|
@@ -34451,7 +34516,7 @@ async function supersedeContentCausedPublishLeg(deps, cwd) {
|
|
|
34451
34516
|
return withLedgerLock(path2, async (fence) => {
|
|
34452
34517
|
let prior;
|
|
34453
34518
|
try {
|
|
34454
|
-
prior = parseReleaseLedger((0,
|
|
34519
|
+
prior = parseReleaseLedger((0, import_node_fs28.readFileSync)(path2, "utf8"));
|
|
34455
34520
|
} catch (e) {
|
|
34456
34521
|
throw new ReleaseLedgerError(
|
|
34457
34522
|
"unreadable",
|
|
@@ -34539,7 +34604,7 @@ async function supersedeContentCausedDeployAndPublishLegs(deps, cwd) {
|
|
|
34539
34604
|
return withLedgerLock(path2, async (fence) => {
|
|
34540
34605
|
let prior;
|
|
34541
34606
|
try {
|
|
34542
|
-
prior = parseReleaseLedger((0,
|
|
34607
|
+
prior = parseReleaseLedger((0, import_node_fs28.readFileSync)(path2, "utf8"));
|
|
34543
34608
|
} catch (e) {
|
|
34544
34609
|
throw new ReleaseLedgerError(
|
|
34545
34610
|
"unreadable",
|
|
@@ -34648,7 +34713,7 @@ async function supersedeContentCausedDeployAndPublishLegs(deps, cwd) {
|
|
|
34648
34713
|
async function reverifyPriorRunLegs(deps, path2, targetTag) {
|
|
34649
34714
|
let prior;
|
|
34650
34715
|
try {
|
|
34651
|
-
prior = parseReleaseLedger((0,
|
|
34716
|
+
prior = parseReleaseLedger((0, import_node_fs28.readFileSync)(path2, "utf8"));
|
|
34652
34717
|
} catch {
|
|
34653
34718
|
return;
|
|
34654
34719
|
}
|
|
@@ -34668,7 +34733,7 @@ async function beginReleaseLedger(deps, cwd, targetTag) {
|
|
|
34668
34733
|
return withLedgerLock(path2, async (fence) => {
|
|
34669
34734
|
let raw;
|
|
34670
34735
|
try {
|
|
34671
|
-
raw = (0,
|
|
34736
|
+
raw = (0, import_node_fs28.readFileSync)(path2, "utf8");
|
|
34672
34737
|
} catch (e) {
|
|
34673
34738
|
if (e.code === "ENOENT") return { ok: true };
|
|
34674
34739
|
return { ok: false, error: `the release ledger at ${path2} could not be READ (${e instanceof Error ? e.message : String(e)}) \u2014 a failed read is unverified, not absent (#5987/#4713)` };
|
|
@@ -34708,13 +34773,13 @@ async function beginReleaseLedger(deps, cwd, targetTag) {
|
|
|
34708
34773
|
}
|
|
34709
34774
|
const archivePath = (0, import_node_path26.join)((0, import_node_path26.dirname)(path2), `phases.archive-${prior.tag}.json`);
|
|
34710
34775
|
try {
|
|
34711
|
-
await fence(() => (0,
|
|
34776
|
+
await fence(() => (0, import_node_fs28.unlinkSync)(archivePath));
|
|
34712
34777
|
} catch (e) {
|
|
34713
34778
|
if (e.code !== "ENOENT") {
|
|
34714
34779
|
return { ok: false, error: `could not clear the stale archive at ${archivePath} (${e instanceof Error ? e.message : String(e)}) \u2014 the ledger for ${prior.tag} stays active (#5987)` };
|
|
34715
34780
|
}
|
|
34716
34781
|
}
|
|
34717
|
-
await fence(() => (0,
|
|
34782
|
+
await fence(() => (0, import_node_fs28.renameSync)(path2, archivePath));
|
|
34718
34783
|
return { ok: true, note: `archived the completed release ledger ${prior.tag} to ${archivePath} (live-proven at ${prior.tagSha.slice(0, 12)})` };
|
|
34719
34784
|
});
|
|
34720
34785
|
}
|
|
@@ -34742,7 +34807,7 @@ async function retryHotfixDeployLegs(deps, cwd, opts = {}) {
|
|
|
34742
34807
|
return withLedgerLock(path2, async (fence) => {
|
|
34743
34808
|
let prior;
|
|
34744
34809
|
try {
|
|
34745
|
-
prior = parseReleaseLedger((0,
|
|
34810
|
+
prior = parseReleaseLedger((0, import_node_fs28.readFileSync)(path2, "utf8"));
|
|
34746
34811
|
} catch (e) {
|
|
34747
34812
|
throw new ReleaseLedgerError(
|
|
34748
34813
|
"unreadable",
|
|
@@ -34984,10 +35049,10 @@ function readOriginWorkflowsDefault(root, ref) {
|
|
|
34984
35049
|
}
|
|
34985
35050
|
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
34986
35051
|
async function probeRegistryWhoami(train) {
|
|
34987
|
-
const dir = (0,
|
|
35052
|
+
const dir = (0, import_node_fs29.mkdtempSync)((0, import_node_path27.join)((0, import_node_os16.tmpdir)(), "mmi-npmrc-"));
|
|
34988
35053
|
const rc = (0, import_node_path27.join)(dir, "npmrc");
|
|
34989
35054
|
try {
|
|
34990
|
-
(0,
|
|
35055
|
+
(0, import_node_fs29.writeFileSync)(rc, "//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n");
|
|
34991
35056
|
await train.runSelf(["secrets", "use", "npm/NPM_TOKEN", "--slug", "_org", "--", "npm", "whoami", "--registry", NPM_REGISTRY, "--userconfig", rc]);
|
|
34992
35057
|
return { kind: "ok", detail: "the registry answered a login" };
|
|
34993
35058
|
} catch (e) {
|
|
@@ -34998,7 +35063,7 @@ async function probeRegistryWhoami(train) {
|
|
|
34998
35063
|
if (/\bE401\b|401 Unauthorized/.test(stderr)) return { kind: "rejected", detail: "npm whoami answered 401 Unauthorized" };
|
|
34999
35064
|
return { kind: "unverified", detail: first };
|
|
35000
35065
|
} finally {
|
|
35001
|
-
(0,
|
|
35066
|
+
(0, import_node_fs29.rmSync)(dir, { recursive: true, force: true });
|
|
35002
35067
|
}
|
|
35003
35068
|
}
|
|
35004
35069
|
var REGISTRY_TOKEN_ENV = /\b(NODE_AUTH_TOKEN|NPM_TOKEN)\b/;
|
|
@@ -35016,7 +35081,7 @@ var defaultDeps2 = {
|
|
|
35016
35081
|
ledgerPath: releaseLedgerPath,
|
|
35017
35082
|
readLedgerRaw: (path2) => {
|
|
35018
35083
|
try {
|
|
35019
|
-
return (0,
|
|
35084
|
+
return (0, import_node_fs29.readFileSync)(path2, "utf8");
|
|
35020
35085
|
} catch (e) {
|
|
35021
35086
|
if (e.code === "ENOENT") return void 0;
|
|
35022
35087
|
throw e;
|
|
@@ -35027,7 +35092,7 @@ var defaultDeps2 = {
|
|
|
35027
35092
|
trainWriterHolder: liveTrainWriterHolder,
|
|
35028
35093
|
readSurfacesRaw: (cwd) => {
|
|
35029
35094
|
try {
|
|
35030
|
-
return (0,
|
|
35095
|
+
return (0, import_node_fs29.readFileSync)((0, import_node_path27.join)(cwd, "surfaces.json"), "utf8");
|
|
35031
35096
|
} catch {
|
|
35032
35097
|
return void 0;
|
|
35033
35098
|
}
|
|
@@ -35677,7 +35742,7 @@ function formatTrainDoctor(v) {
|
|
|
35677
35742
|
|
|
35678
35743
|
// src/release-plain-words.ts
|
|
35679
35744
|
var import_promises3 = require("node:fs/promises");
|
|
35680
|
-
var
|
|
35745
|
+
var import_node_fs30 = require("node:fs");
|
|
35681
35746
|
function releaseCutByNotes(cutBy) {
|
|
35682
35747
|
return `## Internal
|
|
35683
35748
|
Cut by ${formatSessionIdentity(cutBy)}
|
|
@@ -35783,7 +35848,7 @@ function validateSuiteReleaseSummary(path2, pathTr) {
|
|
|
35783
35848
|
for (const [lang, file] of files) {
|
|
35784
35849
|
let content;
|
|
35785
35850
|
try {
|
|
35786
|
-
content = (0,
|
|
35851
|
+
content = (0, import_node_fs30.readFileSync)(file, "utf8");
|
|
35787
35852
|
} catch (e) {
|
|
35788
35853
|
throw new Error(`could not read summary file ${file}: ${e.message} \u2014 see ${SUMMARY_GUIDE}`);
|
|
35789
35854
|
}
|
|
@@ -35998,14 +36063,14 @@ function readLocalGateWorkflows() {
|
|
|
35998
36063
|
const dir = (0, import_node_path28.join)(".github", "workflows");
|
|
35999
36064
|
let names;
|
|
36000
36065
|
try {
|
|
36001
|
-
names = (0,
|
|
36066
|
+
names = (0, import_node_fs31.readdirSync)(dir);
|
|
36002
36067
|
} catch {
|
|
36003
36068
|
return null;
|
|
36004
36069
|
}
|
|
36005
36070
|
const files = [];
|
|
36006
36071
|
for (const name of names.filter(isGateWorkflowPath)) {
|
|
36007
36072
|
try {
|
|
36008
|
-
files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0,
|
|
36073
|
+
files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs31.readFileSync)((0, import_node_path28.join)(dir, name), "utf8") });
|
|
36009
36074
|
} catch {
|
|
36010
36075
|
}
|
|
36011
36076
|
}
|
|
@@ -36015,14 +36080,14 @@ function readLocalWorkflows() {
|
|
|
36015
36080
|
const dir = (0, import_node_path28.join)(".github", "workflows");
|
|
36016
36081
|
let names;
|
|
36017
36082
|
try {
|
|
36018
|
-
names = (0,
|
|
36083
|
+
names = (0, import_node_fs31.readdirSync)(dir);
|
|
36019
36084
|
} catch {
|
|
36020
36085
|
return null;
|
|
36021
36086
|
}
|
|
36022
36087
|
const files = [];
|
|
36023
36088
|
for (const name of names.filter((n) => /\.ya?ml$/i.test(n))) {
|
|
36024
36089
|
try {
|
|
36025
|
-
files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0,
|
|
36090
|
+
files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs31.readFileSync)((0, import_node_path28.join)(dir, name), "utf8") });
|
|
36026
36091
|
} catch {
|
|
36027
36092
|
}
|
|
36028
36093
|
}
|
|
@@ -36694,6 +36759,12 @@ async function pushAfterVercelVersionEnv(deps, meta, stage, tag, pushArgs) {
|
|
|
36694
36759
|
}
|
|
36695
36760
|
async function completeMainRelease(deps, ctx, meta, deployModel, watch, options, tag, releaseSha, startBranch, preFold, tagProbe, branchHints, ledger, alignEarly) {
|
|
36696
36761
|
const resumeCommand = options.dev ? "mmi-cli devops release --dev --apply" : "mmi-cli devops release --apply";
|
|
36762
|
+
let pretag;
|
|
36763
|
+
try {
|
|
36764
|
+
pretag = await runPreTagHook(deps, { releaseSha });
|
|
36765
|
+
} catch (e) {
|
|
36766
|
+
throw await recoverFailedFold(deps, e, startBranch, preFold.mainSha, resumeCommand);
|
|
36767
|
+
}
|
|
36697
36768
|
const ledgerAnchors = { repo: ctx.repo, tag, tagSha: releaseSha };
|
|
36698
36769
|
try {
|
|
36699
36770
|
deps.warn?.("Release: Checking the package before publishing");
|
|
@@ -36869,7 +36940,7 @@ ${recovery.note}`), recoveryInput);
|
|
|
36869
36940
|
});
|
|
36870
36941
|
alignment = await aligning;
|
|
36871
36942
|
const announceNote = annotateVersionEnvAnnounce(await announcing, versionEnv);
|
|
36872
|
-
return { checks, releaseUrl, announceNote, localInstall, dispatch, ledgerAnchors, ...alignment ? { alignment } : {} };
|
|
36943
|
+
return { checks, releaseUrl, announceNote, localInstall, dispatch, ledgerAnchors, pretag, ...alignment ? { alignment } : {} };
|
|
36873
36944
|
}
|
|
36874
36945
|
function resumeStateOf(status) {
|
|
36875
36946
|
return status === "complete" ? "aligned" : status;
|
|
@@ -36911,7 +36982,7 @@ async function activeRcandLedgerCandidate(deps, cwd) {
|
|
|
36911
36982
|
}
|
|
36912
36983
|
let prior;
|
|
36913
36984
|
try {
|
|
36914
|
-
prior = parseReleaseLedger((0,
|
|
36985
|
+
prior = parseReleaseLedger((0, import_node_fs31.readFileSync)(path2, "utf8"));
|
|
36915
36986
|
} catch {
|
|
36916
36987
|
return void 0;
|
|
36917
36988
|
}
|
|
@@ -37848,7 +37919,7 @@ ${spent.note}`), rcandRecovery(tag2));
|
|
|
37848
37919
|
const releaseSha3 = requireValue(clean2(await deps.run("git", ["rev-parse", "main"])), "release sha");
|
|
37849
37920
|
return { versionFold: versionFold3, releaseSha: releaseSha3 };
|
|
37850
37921
|
});
|
|
37851
|
-
const { checks: checks2, releaseUrl: releaseUrl2, announceNote: announceNote2, localInstall: localInstall2, dispatch: d2, ledgerAnchors: ledgerAnchors2, alignment: alignment2 } = await completeMainRelease(
|
|
37922
|
+
const { checks: checks2, releaseUrl: releaseUrl2, announceNote: announceNote2, localInstall: localInstall2, dispatch: d2, ledgerAnchors: ledgerAnchors2, pretag: pretag2, alignment: alignment2 } = await completeMainRelease(
|
|
37852
37923
|
deps,
|
|
37853
37924
|
ctx,
|
|
37854
37925
|
meta,
|
|
@@ -37880,6 +37951,7 @@ ${spent.note}`), rcandRecovery(tag2));
|
|
|
37880
37951
|
promoted: true,
|
|
37881
37952
|
checks: checks2,
|
|
37882
37953
|
versionFold: versionFold2,
|
|
37954
|
+
pretag: pretag2,
|
|
37883
37955
|
dispatch: d2.note,
|
|
37884
37956
|
runId: d2.runId,
|
|
37885
37957
|
runUrl: d2.runUrl,
|
|
@@ -37910,6 +37982,7 @@ ${spent.note}`), rcandRecovery(tag2));
|
|
|
37910
37982
|
promoted: true,
|
|
37911
37983
|
checks: checks2,
|
|
37912
37984
|
versionFold: versionFold2,
|
|
37985
|
+
pretag: pretag2,
|
|
37913
37986
|
dispatch: d2.note,
|
|
37914
37987
|
runId: d2.runId,
|
|
37915
37988
|
runUrl: d2.runUrl,
|
|
@@ -37959,7 +38032,7 @@ ${spent.note}`), rcandRecovery(tag2));
|
|
|
37959
38032
|
const releaseSha2 = requireValue(clean2(await deps.run("git", ["rev-parse", "main"])), "release sha");
|
|
37960
38033
|
return { versionFold: versionFold2, releaseSha: releaseSha2 };
|
|
37961
38034
|
});
|
|
37962
|
-
const { checks, releaseUrl, announceNote, localInstall, dispatch: d, ledgerAnchors, alignment } = await completeMainRelease(
|
|
38035
|
+
const { checks, releaseUrl, announceNote, localInstall, dispatch: d, ledgerAnchors, pretag, alignment } = await completeMainRelease(
|
|
37963
38036
|
deps,
|
|
37964
38037
|
ctx,
|
|
37965
38038
|
meta,
|
|
@@ -37993,6 +38066,7 @@ ${spent.note}`), rcandRecovery(tag2));
|
|
|
37993
38066
|
promoted: true,
|
|
37994
38067
|
checks,
|
|
37995
38068
|
versionFold,
|
|
38069
|
+
pretag,
|
|
37996
38070
|
dispatch: d.note,
|
|
37997
38071
|
runId: d.runId,
|
|
37998
38072
|
runUrl: d.runUrl,
|
|
@@ -41164,7 +41238,7 @@ function registerBoardCommands(program3) {
|
|
|
41164
41238
|
}
|
|
41165
41239
|
|
|
41166
41240
|
// src/bootstrap-commands.ts
|
|
41167
|
-
var
|
|
41241
|
+
var import_node_fs35 = require("node:fs");
|
|
41168
41242
|
var import_node_os19 = require("node:os");
|
|
41169
41243
|
var import_node_path32 = require("node:path");
|
|
41170
41244
|
init_cli_shared();
|
|
@@ -41351,7 +41425,7 @@ init_github_client();
|
|
|
41351
41425
|
init_cli_shared();
|
|
41352
41426
|
|
|
41353
41427
|
// src/port-registry.ts
|
|
41354
|
-
var
|
|
41428
|
+
var import_node_fs32 = require("node:fs");
|
|
41355
41429
|
var import_node_path29 = require("node:path");
|
|
41356
41430
|
|
|
41357
41431
|
// ../infra/port-geometry.mjs
|
|
@@ -41366,8 +41440,8 @@ function nextPortBlock(registry2) {
|
|
|
41366
41440
|
return [base, base + PORT_SPAN];
|
|
41367
41441
|
}
|
|
41368
41442
|
function loadPortRegistry(path2) {
|
|
41369
|
-
if (!(0,
|
|
41370
|
-
const raw = JSON.parse((0,
|
|
41443
|
+
if (!(0, import_node_fs32.existsSync)(path2)) return {};
|
|
41444
|
+
const raw = JSON.parse((0, import_node_fs32.readFileSync)(path2, "utf8"));
|
|
41371
41445
|
const out = {};
|
|
41372
41446
|
for (const [key, value] of Object.entries(raw)) {
|
|
41373
41447
|
if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
|
|
@@ -41397,7 +41471,7 @@ function existingPortRange(repo, registry2) {
|
|
|
41397
41471
|
function portRangeInfraAt(root, source) {
|
|
41398
41472
|
const registryPath = (0, import_node_path29.join)(root, "infra", "port-ranges.json");
|
|
41399
41473
|
const ddbScriptPath = (0, import_node_path29.join)(root, "infra", "port-ddb.mjs");
|
|
41400
|
-
if (!(0,
|
|
41474
|
+
if (!(0, import_node_fs32.existsSync)(registryPath) || !(0, import_node_fs32.existsSync)(ddbScriptPath)) return null;
|
|
41401
41475
|
return { root, source, registryPath, ddbScriptPath };
|
|
41402
41476
|
}
|
|
41403
41477
|
function resolvePortRangeInfra(cwd, packageDir) {
|
|
@@ -41479,7 +41553,7 @@ async function assignPersistedPortRange(repo, slug, reg, opts) {
|
|
|
41479
41553
|
}
|
|
41480
41554
|
|
|
41481
41555
|
// src/box-commands.ts
|
|
41482
|
-
var
|
|
41556
|
+
var import_node_fs34 = require("node:fs");
|
|
41483
41557
|
var import_node_child_process10 = require("node:child_process");
|
|
41484
41558
|
var import_node_os18 = require("node:os");
|
|
41485
41559
|
var import_node_path31 = require("node:path");
|
|
@@ -41652,7 +41726,7 @@ init_clean_exit();
|
|
|
41652
41726
|
init_cli_shared();
|
|
41653
41727
|
|
|
41654
41728
|
// src/secrets-commands.ts
|
|
41655
|
-
var
|
|
41729
|
+
var import_node_fs33 = require("node:fs");
|
|
41656
41730
|
var import_node_path30 = require("node:path");
|
|
41657
41731
|
var import_node_os17 = require("node:os");
|
|
41658
41732
|
init_cli_shared();
|
|
@@ -42860,8 +42934,8 @@ async function decryptRailsCredentials(input) {
|
|
|
42860
42934
|
MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
|
|
42861
42935
|
MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
|
|
42862
42936
|
};
|
|
42863
|
-
if ((0,
|
|
42864
|
-
env.RAILS_MASTER_KEY = (0,
|
|
42937
|
+
if ((0, import_node_fs33.existsSync)(masterKeyPath)) {
|
|
42938
|
+
env.RAILS_MASTER_KEY = (0, import_node_fs33.readFileSync)(masterKeyPath, "utf8").trim();
|
|
42865
42939
|
}
|
|
42866
42940
|
const script = [
|
|
42867
42941
|
'require "json"',
|
|
@@ -42871,9 +42945,9 @@ async function decryptRailsCredentials(input) {
|
|
|
42871
42945
|
'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
|
|
42872
42946
|
"puts JSON.generate(config.config)"
|
|
42873
42947
|
].join("\n");
|
|
42874
|
-
const scriptDir = (0,
|
|
42948
|
+
const scriptDir = (0, import_node_fs33.mkdtempSync)((0, import_node_path30.join)((0, import_node_os17.tmpdir)(), "mmi-rails-decrypt-"));
|
|
42875
42949
|
const scriptPath = (0, import_node_path30.join)(scriptDir, "decrypt.rb");
|
|
42876
|
-
(0,
|
|
42950
|
+
(0, import_node_fs33.writeFileSync)(scriptPath, script, "utf8");
|
|
42877
42951
|
try {
|
|
42878
42952
|
const args = ["exec", "ruby", scriptPath];
|
|
42879
42953
|
const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
|
|
@@ -42885,7 +42959,7 @@ async function decryptRailsCredentials(input) {
|
|
|
42885
42959
|
});
|
|
42886
42960
|
return JSON.parse(stdout);
|
|
42887
42961
|
} finally {
|
|
42888
|
-
(0,
|
|
42962
|
+
(0, import_node_fs33.rmSync)(scriptDir, { recursive: true, force: true });
|
|
42889
42963
|
}
|
|
42890
42964
|
}
|
|
42891
42965
|
async function readSecretStdin() {
|
|
@@ -42975,7 +43049,7 @@ function registerSecretsCommands(program3) {
|
|
|
42975
43049
|
let body;
|
|
42976
43050
|
if (o.file) {
|
|
42977
43051
|
try {
|
|
42978
|
-
body = (0,
|
|
43052
|
+
body = (0, import_node_fs33.readFileSync)((0, import_node_path30.resolve)(o.file), "utf8");
|
|
42979
43053
|
} catch (e) {
|
|
42980
43054
|
return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
|
|
42981
43055
|
}
|
|
@@ -43111,7 +43185,7 @@ function registerSecretsCommands(program3) {
|
|
|
43111
43185
|
{
|
|
43112
43186
|
...d,
|
|
43113
43187
|
decryptRailsCredentials,
|
|
43114
|
-
removeFile: (path2) => (0,
|
|
43188
|
+
removeFile: (path2) => (0, import_node_fs33.unlinkSync)((0, import_node_path30.resolve)(o.appDir ?? process.cwd(), path2))
|
|
43115
43189
|
},
|
|
43116
43190
|
{
|
|
43117
43191
|
repo: o.repo,
|
|
@@ -43367,7 +43441,7 @@ function registerBoxCommands(program3) {
|
|
|
43367
43441
|
}
|
|
43368
43442
|
const remote = command && command.length ? command.join(" ") : void 0;
|
|
43369
43443
|
const wroteScript = o.ssh && o.script ? o.script : null;
|
|
43370
|
-
if (wroteScript) (0,
|
|
43444
|
+
if (wroteScript) (0, import_node_fs34.writeFileSync)(wroteScript, sshRecipeScript(found, remote), "utf8");
|
|
43371
43445
|
if (o.json) {
|
|
43372
43446
|
console.log(JSON.stringify({
|
|
43373
43447
|
box: found,
|
|
@@ -43491,17 +43565,17 @@ function hubGitShow(ref) {
|
|
|
43491
43565
|
return (path2) => git3(["show", `${ref}:${path2}`]);
|
|
43492
43566
|
}
|
|
43493
43567
|
function runOnBox(found, script) {
|
|
43494
|
-
const dir = (0,
|
|
43568
|
+
const dir = (0, import_node_fs34.mkdtempSync)((0, import_node_path31.join)((0, import_node_os18.tmpdir)(), "mmi-box-control-"));
|
|
43495
43569
|
try {
|
|
43496
43570
|
const recipe = (0, import_node_path31.join)(dir, "recipe.sh");
|
|
43497
|
-
(0,
|
|
43571
|
+
(0, import_node_fs34.writeFileSync)(recipe, sshRecipeScript(found, "sh -s"), "utf8");
|
|
43498
43572
|
const r = (0, import_node_child_process10.spawnSync)("bash", [recipe], { input: script, encoding: "utf8", maxBuffer: 16 * 1024 * 1024, timeout: 18e4, windowsHide: true });
|
|
43499
43573
|
if (r.status !== 0) {
|
|
43500
43574
|
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(" | ")}`);
|
|
43501
43575
|
}
|
|
43502
43576
|
return r.stdout;
|
|
43503
43577
|
} finally {
|
|
43504
|
-
(0,
|
|
43578
|
+
(0, import_node_fs34.rmSync)(dir, { recursive: true, force: true });
|
|
43505
43579
|
}
|
|
43506
43580
|
}
|
|
43507
43581
|
function formatControl(mode, box, rows) {
|
|
@@ -45144,12 +45218,12 @@ async function verifyTargetedSeedPr(repo, number, plan, target, expected, client
|
|
|
45144
45218
|
// src/bootstrap-commands.ts
|
|
45145
45219
|
var execGitForSeedSource = async (args) => (await execFileP("git", args, { timeout: GIT_TIMEOUT_MS })).stdout;
|
|
45146
45220
|
async function gateRenderDiff(current, rendered) {
|
|
45147
|
-
const dir = (0,
|
|
45221
|
+
const dir = (0, import_node_fs35.mkdtempSync)((0, import_node_path32.join)((0, import_node_os19.tmpdir)(), "mmi-gate-diff-"));
|
|
45148
45222
|
const before = (0, import_node_path32.join)(dir, "committed-gate.yml");
|
|
45149
45223
|
const after = (0, import_node_path32.join)(dir, "registry-render.yml");
|
|
45150
45224
|
try {
|
|
45151
|
-
(0,
|
|
45152
|
-
(0,
|
|
45225
|
+
(0, import_node_fs35.writeFileSync)(before, current);
|
|
45226
|
+
(0, import_node_fs35.writeFileSync)(after, rendered);
|
|
45153
45227
|
try {
|
|
45154
45228
|
return (await execFileP("git", ["diff", "--no-index", "--", before, after], { timeout: GIT_TIMEOUT_MS })).stdout;
|
|
45155
45229
|
} catch (e) {
|
|
@@ -45158,7 +45232,7 @@ async function gateRenderDiff(current, rendered) {
|
|
|
45158
45232
|
throw e;
|
|
45159
45233
|
}
|
|
45160
45234
|
} finally {
|
|
45161
|
-
(0,
|
|
45235
|
+
(0, import_node_fs35.rmSync)(dir, { recursive: true, force: true });
|
|
45162
45236
|
}
|
|
45163
45237
|
}
|
|
45164
45238
|
function bootstrapTrainDoctorDeps() {
|
|
@@ -45218,13 +45292,13 @@ function registerBootstrapCommands(program3) {
|
|
|
45218
45292
|
})),
|
|
45219
45293
|
pushAllowlistOwners: verifyOwners,
|
|
45220
45294
|
pushAllowlistOwnersRead: verifyOwnersRead,
|
|
45221
|
-
readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0,
|
|
45295
|
+
readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs35.existsSync)(path2) ? (0, import_node_fs35.readFileSync)(path2, "utf8") : null,
|
|
45222
45296
|
// requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
|
|
45223
45297
|
// comma-string — accept either so the seeded value verifies regardless of how it was written.
|
|
45224
45298
|
// #3689: the same committed map the org access audit reads (#3664), so a sanctioned admin is not a
|
|
45225
45299
|
// permanent bootstrap failure on one surface and an intended state on the other. Absent file → no
|
|
45226
45300
|
// sanction, which is the pre-#3664 behaviour.
|
|
45227
|
-
sanctionedAdmins: (0,
|
|
45301
|
+
sanctionedAdmins: (0, import_node_fs35.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs35.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
|
|
45228
45302
|
requiredGcpApis: (() => {
|
|
45229
45303
|
const v = meta?.requiredGcpApis;
|
|
45230
45304
|
if (Array.isArray(v)) return v;
|
|
@@ -45302,14 +45376,14 @@ function registerBootstrapCommands(program3) {
|
|
|
45302
45376
|
bootstrap.command("drift").description("#3818: compare every org-owned whole-file seed against MMI-Hub's copy across the registry roster; read-only").option("--repo <owner/repo>", "audit one repo instead of the roster (never a fleet verdict)").option("--json", "machine-readable output").action(async () => {
|
|
45303
45377
|
const o = { repo: rawValue("--repo", ""), json: rawFlag("--json") };
|
|
45304
45378
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
45305
|
-
if (!(0,
|
|
45379
|
+
if (!(0, import_node_fs35.existsSync)(manifestPath)) return fail(`bootstrap drift: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the reference this compares against`);
|
|
45306
45380
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
45307
45381
|
if (!seedSource.ok) return fail(`bootstrap drift: ${seedSource.reason}`);
|
|
45308
|
-
const manifest = loadBootstrapSeeds((0,
|
|
45382
|
+
const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
|
|
45309
45383
|
const hubContents = /* @__PURE__ */ new Map();
|
|
45310
45384
|
for (const s of manifest.seeds) {
|
|
45311
45385
|
if (s.ownership !== "org" || s.source !== "self") continue;
|
|
45312
|
-
hubContents.set(s.target, (0,
|
|
45386
|
+
hubContents.set(s.target, (0, import_node_fs35.existsSync)(s.target) ? (0, import_node_fs35.readFileSync)(s.target, "utf8") : null);
|
|
45313
45387
|
}
|
|
45314
45388
|
let targets;
|
|
45315
45389
|
let classOf = (_repo) => "deployable";
|
|
@@ -45517,24 +45591,24 @@ function registerBootstrapCommands(program3) {
|
|
|
45517
45591
|
return;
|
|
45518
45592
|
}
|
|
45519
45593
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
45520
|
-
if (!(0,
|
|
45594
|
+
if (!(0, import_node_fs35.existsSync)(manifestPath)) return fail(`bootstrap apply: ${manifestPath} not found; bootstrap runs from the MMI-Hub repo root by design \u2014 it stamps org-level resources (Project, Ruleset, secrets, access) through the GitHub App, which is only authorized from the Hub checkout`);
|
|
45521
45595
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
45522
45596
|
if (!seedSource.ok) return fail(`bootstrap apply: ${seedSource.reason}`);
|
|
45523
|
-
const manifest = loadBootstrapSeeds((0,
|
|
45597
|
+
const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
|
|
45524
45598
|
const baseBranch = o.class === "content" ? "main" : "development";
|
|
45525
45599
|
const slug = parsedRepo.slug;
|
|
45526
45600
|
const onlyTarget = o.fromConfig && o.only.trim() === "gate.yml" ? ".github/workflows/gate.yml" : o.only.trim();
|
|
45527
45601
|
const gh2 = async (args) => execFileP("gh", args, { timeout: 2e4 });
|
|
45528
|
-
const readFile10 = (p) => (0,
|
|
45602
|
+
const readFile10 = (p) => (0, import_node_fs35.existsSync)(p) ? (0, import_node_fs35.readFileSync)(p, "utf8") : null;
|
|
45529
45603
|
const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
|
|
45530
45604
|
const putSeed = async (target, content, ref, sha) => {
|
|
45531
45605
|
const tmp = (0, import_node_path32.join)((0, import_node_os19.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
|
|
45532
|
-
(0,
|
|
45606
|
+
(0, import_node_fs35.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
|
|
45533
45607
|
try {
|
|
45534
45608
|
await gh2(contentPutInputArgs(repo, target, tmp));
|
|
45535
45609
|
} finally {
|
|
45536
45610
|
try {
|
|
45537
|
-
(0,
|
|
45611
|
+
(0, import_node_fs35.unlinkSync)(tmp);
|
|
45538
45612
|
} catch {
|
|
45539
45613
|
}
|
|
45540
45614
|
}
|
|
@@ -46170,10 +46244,10 @@ LIVE apply to ${repo}:
|
|
|
46170
46244
|
bootstrap.command("propagate").description("#4238: re-entrant canary\u2192wave tick \u2014 plan (or, with --execute, open) per-repo PRs fanning an org-owned seed out to the fleet").option("--target <path>", "the manifest target to propagate (an org-owned whole file or declared Hub-managed block)").option("--execute", "LIVE tick via gh (master-gated) \u2014 opens/reuses per-repo seed-propagate PRs; dry-run prints the plan only").option("--json", "machine-readable output").action(async () => {
|
|
46171
46245
|
const o = { target: rawValue("--target", ""), execute: rawFlag("--execute"), json: rawFlag("--json") };
|
|
46172
46246
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
46173
|
-
if (!(0,
|
|
46247
|
+
if (!(0, import_node_fs35.existsSync)(manifestPath)) return fail(`bootstrap propagate: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the desired state this tick propagates`);
|
|
46174
46248
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
46175
46249
|
if (!seedSource.ok) return fail(`bootstrap propagate: ${seedSource.reason}`);
|
|
46176
|
-
const manifest = loadBootstrapSeeds((0,
|
|
46250
|
+
const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
|
|
46177
46251
|
const propagatable = manifest.seeds.filter(isPropagatableSeed);
|
|
46178
46252
|
if (!o.target) {
|
|
46179
46253
|
return fail(`bootstrap propagate: --target <path> is required \u2014 one of:
|
|
@@ -46182,9 +46256,9 @@ LIVE apply to ${repo}:
|
|
|
46182
46256
|
const seed = propagatable.find((s) => s.target === o.target);
|
|
46183
46257
|
if (!seed) return fail(`bootstrap propagate: --target '${o.target}' names no centrally propagatable seed in ${manifestPath}. Propagatable targets:
|
|
46184
46258
|
${propagatable.map((s) => s.target).join("\n ")}`);
|
|
46185
|
-
if (!seed.managedBlock && !(0,
|
|
46186
|
-
const hubContent = seed.managedBlock ? null : (0,
|
|
46187
|
-
const readSeedFile2 = (path2) => (0,
|
|
46259
|
+
if (!seed.managedBlock && !(0, import_node_fs35.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
|
|
46260
|
+
const hubContent = seed.managedBlock ? null : (0, import_node_fs35.readFileSync)(seed.target, "utf8");
|
|
46261
|
+
const readSeedFile2 = (path2) => (0, import_node_fs35.existsSync)(path2) ? (0, import_node_fs35.readFileSync)(path2, "utf8") : null;
|
|
46188
46262
|
const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
|
|
46189
46263
|
const cfg = await loadConfig();
|
|
46190
46264
|
const projects = await fetchProjectsList(registryClientDeps(cfg));
|
|
@@ -46193,9 +46267,9 @@ LIVE apply to ${repo}:
|
|
|
46193
46267
|
}
|
|
46194
46268
|
const rosterRepos = collectRegistryRepos(projects).filter((r) => r.toLowerCase() !== "mutmutco/mmi-hub");
|
|
46195
46269
|
let independentCount = rosterRepos.length;
|
|
46196
|
-
if ((0,
|
|
46270
|
+
if ((0, import_node_fs35.existsSync)("projects.json")) {
|
|
46197
46271
|
try {
|
|
46198
|
-
const local = JSON.parse((0,
|
|
46272
|
+
const local = JSON.parse((0, import_node_fs35.readFileSync)("projects.json", "utf8"));
|
|
46199
46273
|
const localRepos = /* @__PURE__ */ new Set();
|
|
46200
46274
|
for (const p of local.projects ?? []) for (const r of p.repos ?? []) {
|
|
46201
46275
|
const full = (r.includes("/") ? r : `mutmutco/${r}`).toLowerCase();
|
|
@@ -46351,7 +46425,7 @@ LIVE apply to ${repo}:
|
|
|
46351
46425
|
if (plan.refusedNoCanary) return fail("bootstrap propagate --execute: no canary declared for this target \u2014 refusing to write (set seedCanary:true on exactly one registry repo)");
|
|
46352
46426
|
const headSha = seedSource.sha;
|
|
46353
46427
|
const sourceBlob = (await execGitForSeedSource(["rev-parse", `${headSha}:${seedSourcePath(seed)}`])).trim();
|
|
46354
|
-
const runbookUnaffected = (0,
|
|
46428
|
+
const runbookUnaffected = (0, import_node_fs35.existsSync)(RUNBOOK_UNAFFECTED_PATH) ? runbookUnaffectedReason(JSON.parse((0, import_node_fs35.readFileSync)(RUNBOOK_UNAFFECTED_PATH, "utf8")), seed.target, sourceBlob) : void 0;
|
|
46355
46429
|
for (const rec of plan.records) {
|
|
46356
46430
|
if (rec.action !== "open-pr") continue;
|
|
46357
46431
|
const baseBranch = classOf(rec.repo) === "content" ? "main" : "development";
|
|
@@ -46376,12 +46450,12 @@ LIVE apply to ${repo}:
|
|
|
46376
46450
|
const tmp = (0, import_node_path32.join)((0, import_node_os19.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
|
|
46377
46451
|
const desiredContent = desiredByRepo.get(rec.repo);
|
|
46378
46452
|
if (desiredContent == null) return fail(`bootstrap propagate: no resolved content for ${rec.repo} ${seed.target} \u2014 refusing to write`);
|
|
46379
|
-
(0,
|
|
46453
|
+
(0, import_node_fs35.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, desiredContent, branch, existingSha, runbookUnaffected)), "utf8");
|
|
46380
46454
|
try {
|
|
46381
46455
|
await gh2(contentPutInputArgs(rec.repo, seed.target, tmp));
|
|
46382
46456
|
} finally {
|
|
46383
46457
|
try {
|
|
46384
|
-
(0,
|
|
46458
|
+
(0, import_node_fs35.unlinkSync)(tmp);
|
|
46385
46459
|
} catch {
|
|
46386
46460
|
}
|
|
46387
46461
|
}
|
|
@@ -46450,10 +46524,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
|
|
|
46450
46524
|
return fail(`bootstrap rollback: ${e.message}`);
|
|
46451
46525
|
}
|
|
46452
46526
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
46453
|
-
if (!(0,
|
|
46527
|
+
if (!(0, import_node_fs35.existsSync)(manifestPath)) return fail(`bootstrap rollback: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the manifest names which targets are org-owned and therefore propagated (and rollback-able)`);
|
|
46454
46528
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
46455
46529
|
if (!seedSource.ok) return fail(`bootstrap rollback: ${seedSource.reason}`);
|
|
46456
|
-
const manifest = loadBootstrapSeeds((0,
|
|
46530
|
+
const manifest = loadBootstrapSeeds((0, import_node_fs35.readFileSync)(manifestPath, "utf8"));
|
|
46457
46531
|
const propagatable = manifest.seeds.filter(isPropagatableSeed);
|
|
46458
46532
|
if (!o.target) {
|
|
46459
46533
|
return fail(`bootstrap rollback: --target <path> is required \u2014 one of:
|
|
@@ -46470,10 +46544,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
|
|
|
46470
46544
|
const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
|
|
46471
46545
|
let candidates;
|
|
46472
46546
|
if (o.record) {
|
|
46473
|
-
if (!(0,
|
|
46547
|
+
if (!(0, import_node_fs35.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
|
|
46474
46548
|
let parsed;
|
|
46475
46549
|
try {
|
|
46476
|
-
parsed = JSON.parse((0,
|
|
46550
|
+
parsed = JSON.parse((0, import_node_fs35.readFileSync)(o.record, "utf8"));
|
|
46477
46551
|
} catch (e) {
|
|
46478
46552
|
return fail(`bootstrap rollback: --record '${o.record}' is not valid JSON: ${e.message}`);
|
|
46479
46553
|
}
|
|
@@ -46551,12 +46625,12 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
|
|
|
46551
46625
|
existingSha = void 0;
|
|
46552
46626
|
}
|
|
46553
46627
|
const tmp = (0, import_node_path32.join)((0, import_node_os19.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
|
|
46554
|
-
(0,
|
|
46628
|
+
(0, import_node_fs35.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
|
|
46555
46629
|
try {
|
|
46556
46630
|
await gh2(contentPutInputArgs(repo, seed.target, tmp));
|
|
46557
46631
|
} finally {
|
|
46558
46632
|
try {
|
|
46559
|
-
(0,
|
|
46633
|
+
(0, import_node_fs35.unlinkSync)(tmp);
|
|
46560
46634
|
} catch {
|
|
46561
46635
|
}
|
|
46562
46636
|
}
|
|
@@ -47028,7 +47102,7 @@ async function waitSuiteDev(deps, opts) {
|
|
|
47028
47102
|
}
|
|
47029
47103
|
|
|
47030
47104
|
// src/suite-train.ts
|
|
47031
|
-
var
|
|
47105
|
+
var import_node_fs36 = require("node:fs");
|
|
47032
47106
|
var import_node_path33 = require("node:path");
|
|
47033
47107
|
var import_node_crypto15 = require("node:crypto");
|
|
47034
47108
|
|
|
@@ -47115,7 +47189,7 @@ function suiteReleaseTag(rc) {
|
|
|
47115
47189
|
function readSuiteCut(path2) {
|
|
47116
47190
|
let raw;
|
|
47117
47191
|
try {
|
|
47118
|
-
raw = (0,
|
|
47192
|
+
raw = (0, import_node_fs36.readFileSync)(path2, "utf8");
|
|
47119
47193
|
} catch (e) {
|
|
47120
47194
|
if (e.code === "ENOENT") return void 0;
|
|
47121
47195
|
throw e;
|
|
@@ -47131,11 +47205,11 @@ function readSuiteCut(path2) {
|
|
|
47131
47205
|
return record2;
|
|
47132
47206
|
}
|
|
47133
47207
|
function writeSuiteCut(path2, record2) {
|
|
47134
|
-
(0,
|
|
47208
|
+
(0, import_node_fs36.mkdirSync)((0, import_node_path33.dirname)(path2), { recursive: true });
|
|
47135
47209
|
const temp = `${path2}.${(0, import_node_crypto15.randomBytes)(8).toString("hex")}.tmp`;
|
|
47136
47210
|
try {
|
|
47137
|
-
(0,
|
|
47138
|
-
(0,
|
|
47211
|
+
(0, import_node_fs36.writeFileSync)(temp, JSON.stringify(record2, null, 2), { flag: "wx" });
|
|
47212
|
+
(0, import_node_fs36.renameSync)(temp, path2);
|
|
47139
47213
|
} catch (e) {
|
|
47140
47214
|
throw new Error(`suite cut record write failed at ${path2}: ${e.message}; stop, verify the file before retrying`);
|
|
47141
47215
|
}
|
|
@@ -47184,25 +47258,25 @@ async function suiteMarkAbandoned(deps, ownerGo = false) {
|
|
|
47184
47258
|
return tags.map((t) => `${t.repo}@${t.tag}`);
|
|
47185
47259
|
}
|
|
47186
47260
|
async function retireFailedLeadRcLedger(deps, ownerGo) {
|
|
47187
|
-
if (!(0,
|
|
47261
|
+
if (!(0, import_node_fs36.existsSync)(deps.ledgerPath)) return void 0;
|
|
47188
47262
|
return withLedgerLock(deps.ledgerPath, async (fence) => {
|
|
47189
|
-
const ledger = parseReleaseLedger((0,
|
|
47263
|
+
const ledger = parseReleaseLedger((0, import_node_fs36.readFileSync)(deps.ledgerPath, "utf8"));
|
|
47190
47264
|
const states = Object.values(ledger.phases).map((p) => p.state);
|
|
47191
47265
|
if (ledger.repo !== SUITE_REPO || ledger.lane !== "rcand" || ledger.phases.promotion.state === "complete" || !states.includes("failed")) return void 0;
|
|
47192
47266
|
if (!ownerGo) throw new Error(`the lead's failed rcand ledger for ${ledger.tag} blocks every train; retire it with suite abandon --owner-go`);
|
|
47193
47267
|
if ((await deps.rcHead())?.toLowerCase() === ledger.tagSha.toLowerCase()) throw new Error(`origin rc already points at ${ledger.tag}; it was promoted, so its ledger is not retired`);
|
|
47194
47268
|
const archive = (0, import_node_path33.join)((0, import_node_path33.dirname)(deps.ledgerPath), `phases.archive-${ledger.tag}.json`);
|
|
47195
|
-
if ((0,
|
|
47269
|
+
if ((0, import_node_fs36.existsSync)(archive)) throw new Error(`ledger archive already exists at ${archive}; inspect before retiring again`);
|
|
47196
47270
|
await deps.markAbandoned(SUITE_REPO, ledger.tag, ledger.tagSha);
|
|
47197
|
-
await fence(() => (0,
|
|
47271
|
+
await fence(() => (0, import_node_fs36.renameSync)(deps.ledgerPath, archive));
|
|
47198
47272
|
return `${ledger.tag} (ledger archived to ${archive})`;
|
|
47199
47273
|
});
|
|
47200
47274
|
}
|
|
47201
47275
|
function suiteAbandon(recordPath, ownerGo = false, now = /* @__PURE__ */ new Date()) {
|
|
47202
47276
|
const record2 = abandonableCut(recordPath, ownerGo);
|
|
47203
47277
|
const archive = `${recordPath}.abandoned-${record2.leadDevelopment.slice(0, 12)}-${now.toISOString().replace(/[:.]/g, "")}.json`;
|
|
47204
|
-
if ((0,
|
|
47205
|
-
(0,
|
|
47278
|
+
if ((0, import_node_fs36.existsSync)(archive)) throw new Error(`abandoned-cut archive already exists at ${archive}; inspect before abandoning again`);
|
|
47279
|
+
(0, import_node_fs36.renameSync)(recordPath, archive);
|
|
47206
47280
|
return { archive, orphanTags: record2.members.filter((m) => m.tag).map((m) => `${m.repo}@${m.tag}`) };
|
|
47207
47281
|
}
|
|
47208
47282
|
async function suiteRestoreMainPins(deps) {
|
|
@@ -47289,12 +47363,12 @@ async function suiteRcandRun(deps, opts) {
|
|
|
47289
47363
|
}
|
|
47290
47364
|
if ((record2?.announcement === "sent" || record2?.announcement === "skipped") && record2.leadReleased) {
|
|
47291
47365
|
const archive = `${deps.recordPath}.${record2.leadRcTag}.json`;
|
|
47292
|
-
if ((0,
|
|
47293
|
-
(0,
|
|
47366
|
+
if ((0, import_node_fs36.existsSync)(archive)) throw new Error(`suite cut archive already exists at ${archive}; inspect before a new cut`);
|
|
47367
|
+
(0, import_node_fs36.renameSync)(deps.recordPath, archive);
|
|
47294
47368
|
record2 = void 0;
|
|
47295
47369
|
}
|
|
47296
47370
|
if (record2 && !record2.pinPr && !record2.leadRcTag && record2.members.every((m) => !m.tag)) {
|
|
47297
|
-
(0,
|
|
47371
|
+
(0, import_node_fs36.rmSync)(deps.recordPath, { force: true });
|
|
47298
47372
|
record2 = void 0;
|
|
47299
47373
|
}
|
|
47300
47374
|
if (!record2) {
|
|
@@ -47348,7 +47422,7 @@ async function suiteRcandRun(deps, opts) {
|
|
|
47348
47422
|
quiet.push(member);
|
|
47349
47423
|
}
|
|
47350
47424
|
if (record2.members.every((m) => m.carried || quiet.includes(m)) && await deps.contains(SUITE_REPO, record2.leadDevelopment, record2.leadPreviousRc)) {
|
|
47351
|
-
(0,
|
|
47425
|
+
(0, import_node_fs36.rmSync)(deps.recordPath, { force: true });
|
|
47352
47426
|
throw new Error("nothing to promote: neither MM-Work nor any module has new development commits since its rc; no suite cut started");
|
|
47353
47427
|
}
|
|
47354
47428
|
for (const member of quiet) {
|
|
@@ -47366,7 +47440,7 @@ async function suiteRcandRun(deps, opts) {
|
|
|
47366
47440
|
}
|
|
47367
47441
|
if (refusals.length) {
|
|
47368
47442
|
const untouched = record2.members.every((m) => !m.tag) && !record2.pinPr;
|
|
47369
|
-
if (untouched) (0,
|
|
47443
|
+
if (untouched) (0, import_node_fs36.rmSync)(deps.recordPath, { force: true });
|
|
47370
47444
|
throw new Error(`module rc serving is not ready; ${untouched ? "no suite cut started" : "no new tag was cut"}:
|
|
47371
47445
|
${refusals.join("\n")}
|
|
47372
47446
|
Each module must ship a live release that bind-mounts <deployPath>/data read-only and serves <data>/rc/module.js at /rc/module.js (docs/Guides/suite-trains.md).`);
|
|
@@ -47562,7 +47636,7 @@ var hotfixRecordPath = (deps) => (0, import_node_path33.join)((0, import_node_pa
|
|
|
47562
47636
|
function readSuiteHotfix(path2) {
|
|
47563
47637
|
let raw;
|
|
47564
47638
|
try {
|
|
47565
|
-
raw = (0,
|
|
47639
|
+
raw = (0, import_node_fs36.readFileSync)(path2, "utf8");
|
|
47566
47640
|
} catch (e) {
|
|
47567
47641
|
if (e.code === "ENOENT") return void 0;
|
|
47568
47642
|
throw e;
|
|
@@ -47605,7 +47679,7 @@ async function suiteHotfix(deps, opts) {
|
|
|
47605
47679
|
if (completed) record2 = void 0;
|
|
47606
47680
|
if (record2 && record2.repo !== found.repo) throw new Error(`an unfinished suite hotfix for ${record2.repo} is recorded; finish it (rerun with that member) first`);
|
|
47607
47681
|
if (!record2?.tag) await deps.validateHotfixSummary();
|
|
47608
|
-
if (completed) (0,
|
|
47682
|
+
if (completed) (0, import_node_fs36.renameSync)(path2, `${path2}.${completed.leadTag}.json`);
|
|
47609
47683
|
const rec = record2 ?? { schema: "mmi-suite-hotfix/v1", member: found.id, repo: found.repo, from: opts.from, ...opts.ack?.length ? { ack: opts.ack } : {} };
|
|
47610
47684
|
const save = () => writeSuiteHotfix(path2, rec);
|
|
47611
47685
|
save();
|
|
@@ -47874,7 +47948,7 @@ async function runRcDataSwitch(deps, opts) {
|
|
|
47874
47948
|
// src/suite-train-io.ts
|
|
47875
47949
|
var import_node_child_process18 = require("node:child_process");
|
|
47876
47950
|
var import_node_path46 = require("node:path");
|
|
47877
|
-
var
|
|
47951
|
+
var import_node_fs49 = require("node:fs");
|
|
47878
47952
|
var import_node_path47 = require("node:path");
|
|
47879
47953
|
init_cli_shared();
|
|
47880
47954
|
|
|
@@ -48960,6 +49034,15 @@ async function runHotfixReleaseLocked(deps, versionInput, options, doctor) {
|
|
|
48960
49034
|
const invented = announceSummaryFidelity(lines2, rangeLog);
|
|
48961
49035
|
if (invented) throw new Error(invented);
|
|
48962
49036
|
}
|
|
49037
|
+
try {
|
|
49038
|
+
await runPreTagHook(deps, { releaseSha: mergedSha });
|
|
49039
|
+
} catch (e) {
|
|
49040
|
+
throw new Error(
|
|
49041
|
+
`${e instanceof Error ? e.message : String(e)}
|
|
49042
|
+
|
|
49043
|
+
hotfix: origin/main already carries ${mergedSha.slice(0, 12)} (the hotfix PR merged), but nothing was tagged, no Release was created and nothing was published \u2014 fix the check above and rerun \`mmi-cli devops hotfix release ${tag}\`.`
|
|
49044
|
+
);
|
|
49045
|
+
}
|
|
48963
49046
|
const anchors = { repo: ctx.repo, tag, tagSha: mergedSha };
|
|
48964
49047
|
const start = await startReleaseLedger(ledger, anchors, { lane: "hotfix" });
|
|
48965
49048
|
if (!start.ok) {
|
|
@@ -49558,7 +49641,7 @@ function checkHotfixCarries(options) {
|
|
|
49558
49641
|
}
|
|
49559
49642
|
|
|
49560
49643
|
// src/merge-cleanup.ts
|
|
49561
|
-
var
|
|
49644
|
+
var import_node_fs38 = require("node:fs");
|
|
49562
49645
|
var import_node_path35 = require("node:path");
|
|
49563
49646
|
var import_node_os20 = require("node:os");
|
|
49564
49647
|
init_cli_shared();
|
|
@@ -50047,7 +50130,7 @@ function renderPrLandTable(entries) {
|
|
|
50047
50130
|
|
|
50048
50131
|
// src/test-policy-core.ts
|
|
50049
50132
|
var import_node_child_process13 = require("node:child_process");
|
|
50050
|
-
var
|
|
50133
|
+
var import_node_fs37 = require("node:fs");
|
|
50051
50134
|
var import_node_path34 = require("node:path");
|
|
50052
50135
|
|
|
50053
50136
|
// src/test-command-policy-shared.mjs
|
|
@@ -50617,7 +50700,7 @@ function loadPolicySource(root, explicitRef, diffBase) {
|
|
|
50617
50700
|
}
|
|
50618
50701
|
function readFileOrNull2(path2) {
|
|
50619
50702
|
try {
|
|
50620
|
-
return (0,
|
|
50703
|
+
return (0, import_node_fs37.readFileSync)(path2, "utf8");
|
|
50621
50704
|
} catch {
|
|
50622
50705
|
return null;
|
|
50623
50706
|
}
|
|
@@ -50645,10 +50728,10 @@ function classify(changed, policy, present = () => false) {
|
|
|
50645
50728
|
const removedProtected = [...removed].filter((p) => protectedBy.has(p)).map((p) => ({ path: p, why: protectedBy.get(p) ?? "" }));
|
|
50646
50729
|
return { mandatoryHits, untestedHits, testChanges, meaningfulTestChanges, addedTests, removedProtected };
|
|
50647
50730
|
}
|
|
50648
|
-
function unresolvedProtectedEntries(policy, root, exists = (path2) => (0,
|
|
50731
|
+
function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs37.existsSync)(path2)) {
|
|
50649
50732
|
return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path34.join)(root, p)));
|
|
50650
50733
|
}
|
|
50651
|
-
function unresolvedSatisfiers(policy, root, exists = (path2) => (0,
|
|
50734
|
+
function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs37.existsSync)(path2)) {
|
|
50652
50735
|
const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
|
|
50653
50736
|
return [...new Set(declared)].filter((p) => !exists((0, import_node_path34.join)(root, p)));
|
|
50654
50737
|
}
|
|
@@ -50789,7 +50872,7 @@ function runTestPolicy(root, deps = {}) {
|
|
|
50789
50872
|
}
|
|
50790
50873
|
const loaded = deps.policy ? { policy: deps.policy, source: { ref: null, sha: null, path: POLICY_FILE } } : loadPolicySource(root, deps.policyRef, deps.base);
|
|
50791
50874
|
const { policy, source: policySource } = loaded;
|
|
50792
|
-
const exists = deps.exists ?? ((path2) => (0,
|
|
50875
|
+
const exists = deps.exists ?? ((path2) => (0, import_node_fs37.existsSync)(path2));
|
|
50793
50876
|
const counts = { mandatoryCount: (policy.mandatory ?? []).length, protectedCount: (policy.protected ?? []).length };
|
|
50794
50877
|
const base = deps.changed ? "(injected)" : deps.policyRef ? resolveHotfixBase(root) : resolveBase(root, deps.base);
|
|
50795
50878
|
const refusal = deps.changed ? null : untrustworthyRange(root, base);
|
|
@@ -51086,13 +51169,13 @@ function resolveSquashMergeBodyText(commits, allowedClosing, cwd) {
|
|
|
51086
51169
|
return rewritten === base ? null : rewritten;
|
|
51087
51170
|
}
|
|
51088
51171
|
function writeSquashBodyFile(body) {
|
|
51089
|
-
const dir = (0,
|
|
51172
|
+
const dir = (0, import_node_fs38.mkdtempSync)((0, import_node_path35.join)((0, import_node_os20.tmpdir)(), "mmi-squash-body-"));
|
|
51090
51173
|
const path2 = (0, import_node_path35.join)(dir, "body.txt");
|
|
51091
|
-
(0,
|
|
51174
|
+
(0, import_node_fs38.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
|
|
51092
51175
|
`, "utf8");
|
|
51093
51176
|
return { path: path2, cleanup: () => {
|
|
51094
51177
|
try {
|
|
51095
|
-
(0,
|
|
51178
|
+
(0, import_node_fs38.rmSync)(dir, { recursive: true, force: true });
|
|
51096
51179
|
} catch {
|
|
51097
51180
|
}
|
|
51098
51181
|
} };
|
|
@@ -51434,7 +51517,7 @@ function pinnedGitHubGetJson(token, fetchImpl = fetch) {
|
|
|
51434
51517
|
var HUB_RELEASE_CI_ANNOUNCE_DEFERRED = "announcement deferred: the Hub cannot authorize a release-workflow session to post yet (#9138); the curated summary is in this run's step summary";
|
|
51435
51518
|
|
|
51436
51519
|
// src/project-info-sync.ts
|
|
51437
|
-
var
|
|
51520
|
+
var import_node_fs39 = require("node:fs");
|
|
51438
51521
|
var import_node_path36 = require("node:path");
|
|
51439
51522
|
var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
|
|
51440
51523
|
updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
|
|
@@ -51483,13 +51566,13 @@ function sharedName(entries, fallback) {
|
|
|
51483
51566
|
function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
|
|
51484
51567
|
if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
|
|
51485
51568
|
const readmePath = (0, import_node_path36.join)(repoRoot2, "README.md");
|
|
51486
|
-
if (!(0,
|
|
51569
|
+
if (!(0, import_node_fs39.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
|
|
51487
51570
|
const entries = entriesFor(project2, projects);
|
|
51488
51571
|
const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
|
|
51489
51572
|
const projectName = sharedName(entries, project2.name?.trim() || targetRepo2.split("/").pop() || targetRepo2);
|
|
51490
51573
|
if (!memberRepos.length) throw new Error(`org project sync-info: project ${projectName} has no registered member repos`);
|
|
51491
51574
|
const entryNames = entries.map((entry) => entry.name?.trim()).filter((name) => Boolean(name));
|
|
51492
|
-
const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0,
|
|
51575
|
+
const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs39.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
|
|
51493
51576
|
const lines2 = [
|
|
51494
51577
|
`# ${projectName}`,
|
|
51495
51578
|
"",
|
|
@@ -51508,8 +51591,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
|
|
|
51508
51591
|
const targetBase = `https://github.com/${targetRepo2}`;
|
|
51509
51592
|
const targetBranch = branchFor(targetRepo2, projects);
|
|
51510
51593
|
const orgDocs = [
|
|
51511
|
-
(0,
|
|
51512
|
-
(0,
|
|
51594
|
+
(0, import_node_fs39.existsSync)((0, import_node_path36.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
|
|
51595
|
+
(0, import_node_fs39.existsSync)((0, import_node_path36.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
|
|
51513
51596
|
].filter(Boolean);
|
|
51514
51597
|
if (orgDocs.length) lines2.push("", "## Organisation docs", "", ...orgDocs);
|
|
51515
51598
|
return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines2.join("\n")}
|
|
@@ -51531,7 +51614,7 @@ async function syncProjectInfo(plan, client, apply) {
|
|
|
51531
51614
|
}
|
|
51532
51615
|
|
|
51533
51616
|
// src/train-commands.ts
|
|
51534
|
-
var
|
|
51617
|
+
var import_node_fs40 = require("node:fs");
|
|
51535
51618
|
var import_node_path37 = require("node:path");
|
|
51536
51619
|
init_cli_shared();
|
|
51537
51620
|
init_clean_exit();
|
|
@@ -51547,7 +51630,7 @@ function resolveReleaseBumpIntent(raw) {
|
|
|
51547
51630
|
}
|
|
51548
51631
|
function readRepoVersion() {
|
|
51549
51632
|
try {
|
|
51550
|
-
return JSON.parse((0,
|
|
51633
|
+
return JSON.parse((0, import_node_fs40.readFileSync)((0, import_node_path37.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
|
|
51551
51634
|
} catch {
|
|
51552
51635
|
return void 0;
|
|
51553
51636
|
}
|
|
@@ -51921,7 +52004,7 @@ function prTitleRefusal(title) {
|
|
|
51921
52004
|
|
|
51922
52005
|
// src/command-register-collaboration.ts
|
|
51923
52006
|
var import_node_child_process17 = require("node:child_process");
|
|
51924
|
-
var
|
|
52007
|
+
var import_node_fs48 = require("node:fs");
|
|
51925
52008
|
var import_promises8 = require("node:fs/promises");
|
|
51926
52009
|
init_clean_exit();
|
|
51927
52010
|
init_cli_shared();
|
|
@@ -52062,7 +52145,7 @@ init_github_client();
|
|
|
52062
52145
|
init_github_quota();
|
|
52063
52146
|
|
|
52064
52147
|
// src/issue-commands.ts
|
|
52065
|
-
var
|
|
52148
|
+
var import_node_fs41 = require("node:fs");
|
|
52066
52149
|
var import_node_crypto16 = require("node:crypto");
|
|
52067
52150
|
init_cli_shared();
|
|
52068
52151
|
init_clean_exit();
|
|
@@ -52255,7 +52338,7 @@ async function editIssue(client, options, deps = {}) {
|
|
|
52255
52338
|
const url = `https://github.com/${repo}/issues/${parsed.number}`;
|
|
52256
52339
|
const patch = {};
|
|
52257
52340
|
let bodyChanged = false;
|
|
52258
|
-
const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0,
|
|
52341
|
+
const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs41.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
|
|
52259
52342
|
if (options.titleFile !== void 0) {
|
|
52260
52343
|
patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
|
|
52261
52344
|
} else if (options.title !== void 0) {
|
|
@@ -52918,7 +53001,7 @@ function extendCreateCommand(issue, batchAttach) {
|
|
|
52918
53001
|
if (opts.batch) {
|
|
52919
53002
|
let specs;
|
|
52920
53003
|
try {
|
|
52921
|
-
const raw = (0,
|
|
53004
|
+
const raw = (0, import_node_fs41.readFileSync)(opts.batch, "utf8");
|
|
52922
53005
|
specs = JSON.parse(raw);
|
|
52923
53006
|
if (!Array.isArray(specs)) {
|
|
52924
53007
|
const top = specs === null ? "null" : typeof specs === "object" ? `an object with keys: ${Object.keys(specs).join(", ") || "(none)"}` : `a ${typeof specs}`;
|
|
@@ -52995,7 +53078,7 @@ ${lines2}`, {
|
|
|
52995
53078
|
}
|
|
52996
53079
|
|
|
52997
53080
|
// src/post-merge-recon.ts
|
|
52998
|
-
var
|
|
53081
|
+
var import_node_fs42 = require("node:fs");
|
|
52999
53082
|
var import_node_path39 = require("node:path");
|
|
53000
53083
|
|
|
53001
53084
|
// src/cross-repo-filing-issue.ts
|
|
@@ -53165,16 +53248,16 @@ function buildPostMergeReconRecovery(input) {
|
|
|
53165
53248
|
}
|
|
53166
53249
|
function writePostMergeReconRecovery(cwd, recovery) {
|
|
53167
53250
|
const path2 = postMergeReconStatePath(cwd, recovery.repo, recovery.pr);
|
|
53168
|
-
(0,
|
|
53169
|
-
(0,
|
|
53251
|
+
(0, import_node_fs42.mkdirSync)((0, import_node_path39.dirname)(path2), { recursive: true });
|
|
53252
|
+
(0, import_node_fs42.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
|
|
53170
53253
|
`, "utf8");
|
|
53171
53254
|
return path2;
|
|
53172
53255
|
}
|
|
53173
53256
|
function clearPostMergeReconRecovery(cwd, repo, pr) {
|
|
53174
53257
|
const path2 = postMergeReconStatePath(cwd, repo, pr);
|
|
53175
|
-
if (!(0,
|
|
53258
|
+
if (!(0, import_node_fs42.existsSync)(path2)) return;
|
|
53176
53259
|
try {
|
|
53177
|
-
(0,
|
|
53260
|
+
(0, import_node_fs42.unlinkSync)(path2);
|
|
53178
53261
|
} catch {
|
|
53179
53262
|
}
|
|
53180
53263
|
}
|
|
@@ -53650,7 +53733,7 @@ function registerPrLifecycleCommands(program3) {
|
|
|
53650
53733
|
|
|
53651
53734
|
// src/review-verdict.ts
|
|
53652
53735
|
var import_node_child_process14 = require("node:child_process");
|
|
53653
|
-
var
|
|
53736
|
+
var import_node_fs43 = require("node:fs");
|
|
53654
53737
|
var import_node_os22 = require("node:os");
|
|
53655
53738
|
var import_node_path40 = require("node:path");
|
|
53656
53739
|
init_cli_shared();
|
|
@@ -53817,15 +53900,15 @@ async function readPrIssueComments(number, repo) {
|
|
|
53817
53900
|
return comments;
|
|
53818
53901
|
}
|
|
53819
53902
|
async function postPrCommentFromFile(number, repo, body) {
|
|
53820
|
-
const dir = (0,
|
|
53903
|
+
const dir = (0, import_node_fs43.mkdtempSync)((0, import_node_path40.join)((0, import_node_os22.tmpdir)(), "mmi-review-verdict-"));
|
|
53821
53904
|
const path2 = (0, import_node_path40.join)(dir, "body.md");
|
|
53822
53905
|
try {
|
|
53823
|
-
(0,
|
|
53906
|
+
(0, import_node_fs43.writeFileSync)(path2, body, "utf8");
|
|
53824
53907
|
const { stdout } = await execFileP("gh", ["pr", "comment", number, "--repo", repo, "--body-file", path2], { timeout: GH_MUTATION_TIMEOUT_MS });
|
|
53825
53908
|
return stdout.trim();
|
|
53826
53909
|
} finally {
|
|
53827
53910
|
try {
|
|
53828
|
-
(0,
|
|
53911
|
+
(0, import_node_fs43.rmSync)(dir, { recursive: true, force: true });
|
|
53829
53912
|
} catch {
|
|
53830
53913
|
}
|
|
53831
53914
|
}
|
|
@@ -54063,17 +54146,17 @@ async function prCreateClaimRefusal(body, repoOption, deps = {}) {
|
|
|
54063
54146
|
}
|
|
54064
54147
|
|
|
54065
54148
|
// src/worktree-residue-sweep.ts
|
|
54066
|
-
var
|
|
54149
|
+
var import_node_fs47 = require("node:fs");
|
|
54067
54150
|
var import_node_path44 = require("node:path");
|
|
54068
54151
|
|
|
54069
54152
|
// src/worktree-merge-cleanup.ts
|
|
54070
|
-
var
|
|
54153
|
+
var import_node_fs46 = require("node:fs");
|
|
54071
54154
|
var import_node_path43 = require("node:path");
|
|
54072
54155
|
init_cli_shared();
|
|
54073
54156
|
|
|
54074
54157
|
// src/stage-runner.ts
|
|
54075
54158
|
var import_node_child_process16 = require("node:child_process");
|
|
54076
|
-
var
|
|
54159
|
+
var import_node_fs45 = require("node:fs");
|
|
54077
54160
|
var import_node_path42 = require("node:path");
|
|
54078
54161
|
var import_node_net = require("node:net");
|
|
54079
54162
|
var import_node_util5 = require("node:util");
|
|
@@ -54084,7 +54167,7 @@ function normalizeEol2(s) {
|
|
|
54084
54167
|
}
|
|
54085
54168
|
|
|
54086
54169
|
// src/env-detection.ts
|
|
54087
|
-
var
|
|
54170
|
+
var import_node_fs44 = require("node:fs");
|
|
54088
54171
|
var import_node_path41 = require("node:path");
|
|
54089
54172
|
var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".jerv", ".pi", ".venv", "venv"]);
|
|
54090
54173
|
function isEnvBaseName(name) {
|
|
@@ -54095,7 +54178,7 @@ function findEnvFiles(root) {
|
|
|
54095
54178
|
const walk2 = (dir, rel) => {
|
|
54096
54179
|
let entries;
|
|
54097
54180
|
try {
|
|
54098
|
-
entries = (0,
|
|
54181
|
+
entries = (0, import_node_fs44.readdirSync)(dir, { withFileTypes: true });
|
|
54099
54182
|
} catch {
|
|
54100
54183
|
return;
|
|
54101
54184
|
}
|
|
@@ -54109,7 +54192,7 @@ function findEnvFiles(root) {
|
|
|
54109
54192
|
if (isEnvBaseName(entry.name)) {
|
|
54110
54193
|
let isDir = false;
|
|
54111
54194
|
try {
|
|
54112
|
-
isDir = (0,
|
|
54195
|
+
isDir = (0, import_node_fs44.lstatSync)((0, import_node_path41.join)(dir, entry.name)).isDirectory();
|
|
54113
54196
|
} catch {
|
|
54114
54197
|
}
|
|
54115
54198
|
if (!isDir) found.push(relPath);
|
|
@@ -54248,12 +54331,12 @@ var DOCKER_TIMEOUT_MS = 15e3;
|
|
|
54248
54331
|
function stageBash() {
|
|
54249
54332
|
if (process.platform !== "win32") return "bash";
|
|
54250
54333
|
const configured = process.env.SHELL;
|
|
54251
|
-
if (configured && (0, import_node_path42.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0,
|
|
54334
|
+
if (configured && (0, import_node_path42.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs45.existsSync)(configured)) return configured;
|
|
54252
54335
|
const candidates = [
|
|
54253
54336
|
(0, import_node_path42.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
|
|
54254
54337
|
...process.env.LOCALAPPDATA ? [(0, import_node_path42.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
|
|
54255
54338
|
];
|
|
54256
|
-
const bash = candidates.find((path2) => (0,
|
|
54339
|
+
const bash = candidates.find((path2) => (0, import_node_fs45.existsSync)(path2));
|
|
54257
54340
|
if (!bash) throw new Error("Local stages require Git Bash on Windows. Install Git for Windows or set SHELL to its absolute bash.exe path.");
|
|
54258
54341
|
return bash;
|
|
54259
54342
|
}
|
|
@@ -54609,7 +54692,7 @@ function stageProcessEnv(stagePort, extraEnv) {
|
|
|
54609
54692
|
function composeResolvesPort(cwd) {
|
|
54610
54693
|
if (process.env.PORT) return true;
|
|
54611
54694
|
const envFile = (0, import_node_path42.join)(cwd, ".env");
|
|
54612
|
-
return (0,
|
|
54695
|
+
return (0, import_node_fs45.existsSync)(envFile) && envFileKeys((0, import_node_fs45.readFileSync)(envFile, "utf8")).has("PORT");
|
|
54613
54696
|
}
|
|
54614
54697
|
function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
|
|
54615
54698
|
const composeProject = config.env?.COMPOSE_PROJECT_NAME ?? vaultEnvMerge?.COMPOSE_PROJECT_NAME ?? stageComposeProjectName(cwd);
|
|
@@ -54624,13 +54707,13 @@ function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
|
|
|
54624
54707
|
function stageComposeFiles(cwd) {
|
|
54625
54708
|
const files = ["docker-compose.yml"];
|
|
54626
54709
|
for (const conventional of ["docker-compose.override.yml", "docker-compose.override.yaml"]) {
|
|
54627
|
-
if ((0,
|
|
54710
|
+
if ((0, import_node_fs45.existsSync)((0, import_node_path42.join)(cwd, conventional))) files.push(conventional);
|
|
54628
54711
|
}
|
|
54629
54712
|
return [...files, RUNTIME_ENV_OVERRIDE_RELPATH];
|
|
54630
54713
|
}
|
|
54631
54714
|
async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
|
|
54632
54715
|
const keys = Object.keys(vaultEnvMerge ?? {});
|
|
54633
|
-
if (!keys.length || !(0,
|
|
54716
|
+
if (!keys.length || !(0, import_node_fs45.existsSync)((0, import_node_path42.join)(cwd, "docker-compose.yml"))) return {};
|
|
54634
54717
|
let configJson;
|
|
54635
54718
|
try {
|
|
54636
54719
|
const { stdout } = await execFileP3("docker", ["compose", "config", "--format", "json"], {
|
|
@@ -54647,20 +54730,20 @@ async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
|
|
|
54647
54730
|
const body = renderRuntimeEnvOverride(runtimeEnvMarkedServices(configJson), keys, runtimeEnvExcludes(configJson), runtimeEnvSelects(configJson));
|
|
54648
54731
|
if (!body) return {};
|
|
54649
54732
|
const overridePath = (0, import_node_path42.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
|
|
54650
|
-
(0,
|
|
54651
|
-
(0,
|
|
54733
|
+
(0, import_node_fs45.mkdirSync)((0, import_node_path42.join)(cwd, "tmp", "stage"), { recursive: true });
|
|
54734
|
+
(0, import_node_fs45.writeFileSync)(overridePath, body, "utf8");
|
|
54652
54735
|
return stageComposeFileEnv(stageComposeFiles(cwd));
|
|
54653
54736
|
}
|
|
54654
54737
|
async function ensureStageRuntimeEnv(config, opts, cwd) {
|
|
54655
54738
|
if (!config.ensureEnv) return;
|
|
54656
54739
|
const target = (0, import_node_path42.join)(cwd, config.ensureEnv.target);
|
|
54657
54740
|
const example = (0, import_node_path42.join)(cwd, config.ensureEnv.example);
|
|
54658
|
-
if (!(0,
|
|
54659
|
-
(0,
|
|
54660
|
-
} else if ((0,
|
|
54661
|
-
const stale = detectStaleEnvFile((0,
|
|
54662
|
-
exampleMtimeMs: (0,
|
|
54663
|
-
targetMtimeMs: (0,
|
|
54741
|
+
if (!(0, import_node_fs45.existsSync)(target) && (0, import_node_fs45.existsSync)(example)) {
|
|
54742
|
+
(0, import_node_fs45.copyFileSync)(example, target);
|
|
54743
|
+
} else if ((0, import_node_fs45.existsSync)(target) && (0, import_node_fs45.existsSync)(example)) {
|
|
54744
|
+
const stale = detectStaleEnvFile((0, import_node_fs45.readFileSync)(example, "utf8"), (0, import_node_fs45.readFileSync)(target, "utf8"), {
|
|
54745
|
+
exampleMtimeMs: (0, import_node_fs45.statSync)(example).mtimeMs,
|
|
54746
|
+
targetMtimeMs: (0, import_node_fs45.statSync)(target).mtimeMs
|
|
54664
54747
|
});
|
|
54665
54748
|
if (stale) {
|
|
54666
54749
|
const msg = `stale ${config.ensureEnv.target} (${stale}) \u2014 delete it or refresh from ${config.ensureEnv.example} before re-running mmi-cli stage`;
|
|
@@ -54668,8 +54751,8 @@ async function ensureStageRuntimeEnv(config, opts, cwd) {
|
|
|
54668
54751
|
console.error(`mmi-cli stage: ${msg} (allowed via --allow-stale-env)`);
|
|
54669
54752
|
}
|
|
54670
54753
|
}
|
|
54671
|
-
if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0,
|
|
54672
|
-
(0,
|
|
54754
|
+
if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs45.existsSync)(target)) {
|
|
54755
|
+
(0, import_node_fs45.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs45.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
|
|
54673
54756
|
}
|
|
54674
54757
|
}
|
|
54675
54758
|
async function gitText(cwd, args) {
|
|
@@ -54699,20 +54782,20 @@ async function resolveGlobalStatePath(cwd, explicit) {
|
|
|
54699
54782
|
return void 0;
|
|
54700
54783
|
}
|
|
54701
54784
|
function readState(path2) {
|
|
54702
|
-
if (!(0,
|
|
54785
|
+
if (!(0, import_node_fs45.existsSync)(path2)) return null;
|
|
54703
54786
|
try {
|
|
54704
|
-
return JSON.parse((0,
|
|
54787
|
+
return JSON.parse((0, import_node_fs45.readFileSync)(path2, "utf8"));
|
|
54705
54788
|
} catch {
|
|
54706
54789
|
return null;
|
|
54707
54790
|
}
|
|
54708
54791
|
}
|
|
54709
54792
|
function mkdirFor(path2) {
|
|
54710
54793
|
const dir = path2.slice(0, Math.max(path2.lastIndexOf("/"), path2.lastIndexOf("\\")));
|
|
54711
|
-
(0,
|
|
54794
|
+
(0, import_node_fs45.mkdirSync)(dir, { recursive: true });
|
|
54712
54795
|
}
|
|
54713
54796
|
function writeState(path2, state) {
|
|
54714
54797
|
mkdirFor(path2);
|
|
54715
|
-
(0,
|
|
54798
|
+
(0, import_node_fs45.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
|
|
54716
54799
|
}
|
|
54717
54800
|
function writeStagePortReservation(port, cwd, statePath, globalStatePath, now) {
|
|
54718
54801
|
const reservation = {
|
|
@@ -54741,7 +54824,7 @@ async function cleanupStageState(state, paths, timeoutMs, fallbackCwd, currentEn
|
|
|
54741
54824
|
);
|
|
54742
54825
|
}
|
|
54743
54826
|
for (const path2 of [...new Set(paths.filter((p) => Boolean(p)))]) {
|
|
54744
|
-
(0,
|
|
54827
|
+
(0, import_node_fs45.rmSync)(path2, { force: true });
|
|
54745
54828
|
}
|
|
54746
54829
|
}
|
|
54747
54830
|
async function killTree(pid) {
|
|
@@ -54988,8 +55071,8 @@ async function runStage(config = {}, opts = {}) {
|
|
|
54988
55071
|
});
|
|
54989
55072
|
}
|
|
54990
55073
|
} catch (e) {
|
|
54991
|
-
(0,
|
|
54992
|
-
if (globalStatePath && globalStatePath !== statePath) (0,
|
|
55074
|
+
(0, import_node_fs45.rmSync)(statePath, { force: true });
|
|
55075
|
+
if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs45.rmSync)(globalStatePath, { force: true });
|
|
54993
55076
|
throw e;
|
|
54994
55077
|
}
|
|
54995
55078
|
const started = await startStage(config, {
|
|
@@ -55010,7 +55093,7 @@ function normPath2(p) {
|
|
|
55010
55093
|
function unlinkNodeModulesJunction(wtPath) {
|
|
55011
55094
|
const nm = (0, import_node_path43.join)(wtPath, "node_modules");
|
|
55012
55095
|
try {
|
|
55013
|
-
if ((0,
|
|
55096
|
+
if ((0, import_node_fs46.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs46.rmdirSync)(nm);
|
|
55014
55097
|
return { ok: true };
|
|
55015
55098
|
} catch (e) {
|
|
55016
55099
|
if (e.code === "ENOENT") return { ok: true };
|
|
@@ -55021,8 +55104,8 @@ function defaultSleep2(ms) {
|
|
|
55021
55104
|
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
55022
55105
|
}
|
|
55023
55106
|
async function removeResidueDirectory(wtPath, options = {}) {
|
|
55024
|
-
const { sleep: sleep2 = defaultSleep2, removeEmptyDir =
|
|
55025
|
-
const removeRecursive = options.removeRecursive ?? ((path2) => (0,
|
|
55107
|
+
const { sleep: sleep2 = defaultSleep2, removeEmptyDir = import_node_fs46.rmdirSync, exists = import_node_fs46.existsSync } = options;
|
|
55108
|
+
const removeRecursive = options.removeRecursive ?? ((path2) => (0, import_node_fs46.rmSync)(path2, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }));
|
|
55026
55109
|
const junction = unlinkNodeModulesJunction(wtPath);
|
|
55027
55110
|
if (!junction.ok) return junction;
|
|
55028
55111
|
try {
|
|
@@ -55148,21 +55231,21 @@ async function listNestedIgnoredNodeModules(wtPath, execGit) {
|
|
|
55148
55231
|
return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path43.join)(wtPath, line.slice(0, -1)));
|
|
55149
55232
|
}
|
|
55150
55233
|
function safeRemoveTree(path2) {
|
|
55151
|
-
const stat4 = (0,
|
|
55234
|
+
const stat4 = (0, import_node_fs46.lstatSync)(path2);
|
|
55152
55235
|
if (stat4.isSymbolicLink()) {
|
|
55153
55236
|
try {
|
|
55154
|
-
(0,
|
|
55237
|
+
(0, import_node_fs46.rmdirSync)(path2);
|
|
55155
55238
|
} catch {
|
|
55156
|
-
(0,
|
|
55239
|
+
(0, import_node_fs46.unlinkSync)(path2);
|
|
55157
55240
|
}
|
|
55158
55241
|
return;
|
|
55159
55242
|
}
|
|
55160
55243
|
if (stat4.isDirectory()) {
|
|
55161
|
-
for (const entry of (0,
|
|
55162
|
-
(0,
|
|
55244
|
+
for (const entry of (0, import_node_fs46.readdirSync)(path2)) safeRemoveTree((0, import_node_path43.join)(path2, entry));
|
|
55245
|
+
(0, import_node_fs46.rmdirSync)(path2);
|
|
55163
55246
|
return;
|
|
55164
55247
|
}
|
|
55165
|
-
(0,
|
|
55248
|
+
(0, import_node_fs46.unlinkSync)(path2);
|
|
55166
55249
|
}
|
|
55167
55250
|
async function removeWorktreeNodeModules(wtPath) {
|
|
55168
55251
|
try {
|
|
@@ -55178,7 +55261,7 @@ function errorMessage(e) {
|
|
|
55178
55261
|
}
|
|
55179
55262
|
function resolvedOrRaw(path2) {
|
|
55180
55263
|
try {
|
|
55181
|
-
return normPath2((0,
|
|
55264
|
+
return normPath2((0, import_node_fs46.realpathSync)(path2));
|
|
55182
55265
|
} catch {
|
|
55183
55266
|
return normPath2(path2);
|
|
55184
55267
|
}
|
|
@@ -55186,10 +55269,10 @@ function resolvedOrRaw(path2) {
|
|
|
55186
55269
|
function unlinkEscapingReparsePoints(root, primaryRoot) {
|
|
55187
55270
|
let realRoot;
|
|
55188
55271
|
try {
|
|
55189
|
-
if ((0,
|
|
55272
|
+
if ((0, import_node_fs46.lstatSync)(root).isSymbolicLink()) {
|
|
55190
55273
|
return { ok: false, error: `delete root ${normPath2(root)} is a reparse point resolving to ${resolvedOrRaw(root)}` };
|
|
55191
55274
|
}
|
|
55192
|
-
realRoot = normPath2((0,
|
|
55275
|
+
realRoot = normPath2((0, import_node_fs46.realpathSync)(root));
|
|
55193
55276
|
} catch (e) {
|
|
55194
55277
|
if (e.code === "ENOENT") return { ok: true, unlinked: [] };
|
|
55195
55278
|
return { ok: false, error: `cannot resolve delete root ${normPath2(root)}: ${errorMessage(e)}` };
|
|
@@ -55205,7 +55288,7 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
|
|
|
55205
55288
|
const dir = stack.pop();
|
|
55206
55289
|
let entries;
|
|
55207
55290
|
try {
|
|
55208
|
-
entries = (0,
|
|
55291
|
+
entries = (0, import_node_fs46.readdirSync)(dir, { withFileTypes: true });
|
|
55209
55292
|
} catch (e) {
|
|
55210
55293
|
if (e.code === "ENOENT") continue;
|
|
55211
55294
|
return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
|
|
@@ -55215,7 +55298,7 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
|
|
|
55215
55298
|
if (entry.isSymbolicLink()) {
|
|
55216
55299
|
let target = "";
|
|
55217
55300
|
try {
|
|
55218
|
-
target = normPath2((0,
|
|
55301
|
+
target = normPath2((0, import_node_fs46.realpathSync)(child2));
|
|
55219
55302
|
} catch {
|
|
55220
55303
|
target = "";
|
|
55221
55304
|
}
|
|
@@ -55398,7 +55481,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
|
|
|
55398
55481
|
return report;
|
|
55399
55482
|
}
|
|
55400
55483
|
const execGit = options.execGit ?? (async (args) => (await execFileP("git", args, { timeout: GIT_TIMEOUT_MS })).stdout);
|
|
55401
|
-
const pathExists = options.pathExists ??
|
|
55484
|
+
const pathExists = options.pathExists ?? import_node_fs46.existsSync;
|
|
55402
55485
|
let afterWorktrees = [];
|
|
55403
55486
|
try {
|
|
55404
55487
|
afterWorktrees = parseGitWorktreePorcelain(await execGit(["worktree", "list", "--porcelain"]));
|
|
@@ -55685,7 +55768,7 @@ function residueLedgerPath(gitCommonDir) {
|
|
|
55685
55768
|
}
|
|
55686
55769
|
function readPaths(file, deps) {
|
|
55687
55770
|
try {
|
|
55688
|
-
const parsed = JSON.parse((deps.readLedger ?? ((f) => (0,
|
|
55771
|
+
const parsed = JSON.parse((deps.readLedger ?? ((f) => (0, import_node_fs47.readFileSync)(f, "utf8")))(file));
|
|
55689
55772
|
return Array.isArray(parsed) ? parsed.filter((p) => typeof p === "string") : [];
|
|
55690
55773
|
} catch {
|
|
55691
55774
|
return [];
|
|
@@ -55694,8 +55777,8 @@ function readPaths(file, deps) {
|
|
|
55694
55777
|
function writePaths(file, paths, deps) {
|
|
55695
55778
|
try {
|
|
55696
55779
|
const write = deps.writeLedger ?? ((f, t) => {
|
|
55697
|
-
(0,
|
|
55698
|
-
(0,
|
|
55780
|
+
(0, import_node_fs47.mkdirSync)((0, import_node_path44.dirname)(f), { recursive: true });
|
|
55781
|
+
(0, import_node_fs47.writeFileSync)(f, t, "utf8");
|
|
55699
55782
|
});
|
|
55700
55783
|
write(file, `${JSON.stringify([...new Set(paths)], null, 1)}
|
|
55701
55784
|
`);
|
|
@@ -55709,17 +55792,17 @@ function recordResidue(gitCommonDir, path2, deps = {}) {
|
|
|
55709
55792
|
writePaths(file, paths, deps);
|
|
55710
55793
|
}
|
|
55711
55794
|
async function sweepWorktreeResidue(gitCommonDir, registered, deps = {}) {
|
|
55712
|
-
const exists = deps.exists ??
|
|
55713
|
-
const readDir = deps.readDir ?? ((p) => (0,
|
|
55795
|
+
const exists = deps.exists ?? import_node_fs47.existsSync;
|
|
55796
|
+
const readDir = deps.readDir ?? ((p) => (0, import_node_fs47.readdirSync)(p));
|
|
55714
55797
|
const isDir = deps.isDir ?? ((p) => {
|
|
55715
55798
|
try {
|
|
55716
|
-
return (0,
|
|
55799
|
+
return (0, import_node_fs47.statSync)(p).isDirectory();
|
|
55717
55800
|
} catch {
|
|
55718
55801
|
return false;
|
|
55719
55802
|
}
|
|
55720
55803
|
});
|
|
55721
55804
|
const removeRecorded = deps.removeRecorded ?? ((p) => removeResidueDirectory(p));
|
|
55722
|
-
const removeEmpty = deps.removeEmpty ?? ((p) => (0,
|
|
55805
|
+
const removeEmpty = deps.removeEmpty ?? ((p) => (0, import_node_fs47.rmdirSync)(p));
|
|
55723
55806
|
const report = { swept: [], kept: [], dropped: [], emptyRemoved: [], unrecorded: [] };
|
|
55724
55807
|
const live = new Set(registered.map(norm));
|
|
55725
55808
|
const primary = registered[0] ? norm(registered[0]) : void 0;
|
|
@@ -55799,8 +55882,8 @@ function argvWantsJson2() {
|
|
|
55799
55882
|
function hubRoot() {
|
|
55800
55883
|
const fromPkg = (0, import_node_path45.join)(__dirname, "..", "..");
|
|
55801
55884
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
55802
|
-
if ((0,
|
|
55803
|
-
if ((0,
|
|
55885
|
+
if ((0, import_node_fs48.existsSync)((0, import_node_path45.join)(fromPkg, marker))) return fromPkg;
|
|
55886
|
+
if ((0, import_node_fs48.existsSync)((0, import_node_path45.join)(process.cwd(), marker))) return process.cwd();
|
|
55804
55887
|
return null;
|
|
55805
55888
|
}
|
|
55806
55889
|
function ciAuditDeps() {
|
|
@@ -55813,7 +55896,7 @@ function ciAuditDeps() {
|
|
|
55813
55896
|
readSeedFile: (path2) => {
|
|
55814
55897
|
if (!root) return null;
|
|
55815
55898
|
const fullPath = (0, import_node_path45.join)(root, path2);
|
|
55816
|
-
return (0,
|
|
55899
|
+
return (0, import_node_fs48.existsSync)(fullPath) ? (0, import_node_fs48.readFileSync)(fullPath, "utf8") : null;
|
|
55817
55900
|
}
|
|
55818
55901
|
};
|
|
55819
55902
|
}
|
|
@@ -56627,10 +56710,10 @@ ${list}`);
|
|
|
56627
56710
|
});
|
|
56628
56711
|
async function listCiWorkflowPaths(cwd = process.cwd()) {
|
|
56629
56712
|
const wfDir = (0, import_node_path45.join)(cwd, ".github", "workflows");
|
|
56630
|
-
if (!(0,
|
|
56631
|
-
return (0,
|
|
56713
|
+
if (!(0, import_node_fs48.existsSync)(wfDir)) return [];
|
|
56714
|
+
return (0, import_node_fs48.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
|
|
56632
56715
|
try {
|
|
56633
|
-
return workflowReportsPrChecks((0,
|
|
56716
|
+
return workflowReportsPrChecks((0, import_node_fs48.readFileSync)((0, import_node_path45.join)(wfDir, name), "utf8"));
|
|
56634
56717
|
} catch {
|
|
56635
56718
|
return true;
|
|
56636
56719
|
}
|
|
@@ -56835,7 +56918,7 @@ ${list}`);
|
|
|
56835
56918
|
jsonParity(pr.command("review-verdict <number>").description("post an explicit review verdict comment: computes the PR diff patch-id and head sha, renders the v1 contract body, and posts it as a PR comment").requiredOption("--repo <owner/repo>", "target repo").requiredOption("--verdict <verdict>", `one of ${REVIEW_VERDICTS.join("|")}`).requiredOption("--scope <text>", "one line: what was reviewed").requiredOption("--risk <text>", "one line: the residual risk").option("--unverified <text>", "a claim the reviewer could not verify (repeatable)", (v, acc) => [...acc, v], []).requiredOption("--reviewer <id>", "reviewer seat or model id").option("--findings-file <path>", "Markdown findings appended after the JSON block")).action(async (number, o) => {
|
|
56836
56919
|
if (!isReviewVerdict(o.verdict)) return fail(`pr review-verdict: --verdict must be one of ${REVIEW_VERDICTS.join("|")} (got ${o.verdict})`);
|
|
56837
56920
|
const verdict = o.verdict;
|
|
56838
|
-
const findings = o.findingsFile ? (0,
|
|
56921
|
+
const findings = o.findingsFile ? (0, import_node_fs48.readFileSync)(o.findingsFile, "utf8") : void 0;
|
|
56839
56922
|
let patch;
|
|
56840
56923
|
let head;
|
|
56841
56924
|
try {
|
|
@@ -57110,7 +57193,7 @@ ${list}`);
|
|
|
57110
57193
|
const cleanupMerged = async (r) => {
|
|
57111
57194
|
if (opts.preserveWorktree) return "cleanup skipped (--preserve-worktree)";
|
|
57112
57195
|
const ran = await execFileP(process.execPath, [process.argv[1], ...canonicalArgvFor(["pr", "merge", r.pr, "--repo", r.repo])], {
|
|
57113
|
-
cwd: (0,
|
|
57196
|
+
cwd: (0, import_node_fs48.existsSync)(cwd0) ? cwd0 : primaryRoot0,
|
|
57114
57197
|
timeout: GH_MUTATION_TIMEOUT_MS * 3
|
|
57115
57198
|
}).then((x) => ({ stdout: x.stdout, stderr: x.stderr }), (e) => ({ stdout: e.stdout ?? "", stderr: e.stderr ?? "" }));
|
|
57116
57199
|
const json = ran.stdout.split("\n").reverse().find((l) => l.startsWith("{"));
|
|
@@ -57180,7 +57263,7 @@ ${list}`);
|
|
|
57180
57263
|
const mergeSquashBody = squashBodyTextForMerge(
|
|
57181
57264
|
closingGuardInput,
|
|
57182
57265
|
method === "--squash",
|
|
57183
|
-
o.squashBodyFile ? (0,
|
|
57266
|
+
o.squashBodyFile ? (0, import_node_fs48.readFileSync)(o.squashBodyFile, "utf8") : void 0
|
|
57184
57267
|
);
|
|
57185
57268
|
if (!o.squashBodyFile) warnSquashBodyClosingStrip("pr merge", closingGuardInput, mergeSquashBody);
|
|
57186
57269
|
const closingGuardVerdict = evaluateClosingGuard(closingGuardInput, {
|
|
@@ -57331,7 +57414,7 @@ ${list}`);
|
|
|
57331
57414
|
}
|
|
57332
57415
|
if (!repoForPostCleanup) throw e;
|
|
57333
57416
|
console.warn(`pr merge: gh GraphQL rate-limited \u2014 merging PR #${number} via REST PUT instead (#4588).`);
|
|
57334
|
-
const commitMessage = bodyFile ? (0,
|
|
57417
|
+
const commitMessage = bodyFile ? (0, import_node_fs48.readFileSync)(bodyFile, "utf8") : void 0;
|
|
57335
57418
|
await defaultGitHubClient().rest("PUT", `repos/${repoForPostCleanup}/pulls/${number}/merge`, {
|
|
57336
57419
|
body: { merge_method: method.slice(2), ...commitMessage ? { commit_message: commitMessage } : {} },
|
|
57337
57420
|
timeoutMs: GH_MUTATION_TIMEOUT_MS
|
|
@@ -57464,7 +57547,7 @@ ${list}`);
|
|
|
57464
57547
|
preserveWorktree: o.preserveWorktree,
|
|
57465
57548
|
gcAcknowledged: o.gc,
|
|
57466
57549
|
expectedHeadOid: headRefOid,
|
|
57467
|
-
pathExists: (p) => (0,
|
|
57550
|
+
pathExists: (p) => (0, import_node_fs48.existsSync)(p),
|
|
57468
57551
|
// #5899: pin cleanup git calls to the main checkout — the task worktree this process may be
|
|
57469
57552
|
// standing in is removed mid-cleanup, so a cwd-relative invocation fails with
|
|
57470
57553
|
// 'fatal: not a git repository' and leaves a spurious partial-cleanup exit.
|
|
@@ -58779,11 +58862,11 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
|
|
|
58779
58862
|
const checkout = async (repo) => {
|
|
58780
58863
|
if (repo === SUITE_REPO) return root;
|
|
58781
58864
|
const target = (0, import_node_path47.join)(base, repo.split("/")[1]);
|
|
58782
|
-
if (!(0,
|
|
58783
|
-
(0,
|
|
58865
|
+
if (!(0, import_node_fs49.existsSync)(target)) {
|
|
58866
|
+
(0, import_node_fs49.mkdirSync)(base, { recursive: true });
|
|
58784
58867
|
await exec("git", ["clone", "--quiet", "--branch", "development", `https://github.com/${repo}.git`, target], root, WATCH_TIMEOUT);
|
|
58785
58868
|
}
|
|
58786
|
-
if (!(0,
|
|
58869
|
+
if (!(0, import_node_fs49.existsSync)((0, import_node_path47.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
|
|
58787
58870
|
const origin = await exec("git", ["remote", "get-url", "origin"], target);
|
|
58788
58871
|
if (!origin.toLowerCase().endsWith(`/${repo.toLowerCase()}.git`) && !origin.toLowerCase().endsWith(`/${repo.toLowerCase()}`))
|
|
58789
58872
|
throw new Error(`${repo}: suite checkout origin mismatch at ${target}; stop`);
|
|
@@ -59090,9 +59173,9 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
|
|
|
59090
59173
|
const body = await gh(["release", "view", leadTag, "--repo", SUITE_REPO, "--json", "body", "--jq", ".body"]);
|
|
59091
59174
|
if (parseSuiteMapping(body)) return;
|
|
59092
59175
|
const dir = suiteStateDir(root);
|
|
59093
|
-
(0,
|
|
59176
|
+
(0, import_node_fs49.mkdirSync)(dir, { recursive: true });
|
|
59094
59177
|
const file = (0, import_node_path47.join)(dir, `notes-${leadTag}.md`);
|
|
59095
|
-
(0,
|
|
59178
|
+
(0, import_node_fs49.writeFileSync)(file, `${body}
|
|
59096
59179
|
|
|
59097
59180
|
${suiteMappingBlock(leadTag, mapping)}`);
|
|
59098
59181
|
await gh(["release", "edit", leadTag, "--repo", SUITE_REPO, "--notes-file", file]);
|
|
@@ -59133,7 +59216,7 @@ ${suiteMappingBlock(leadTag, mapping)}`);
|
|
|
59133
59216
|
|
|
59134
59217
|
// src/suite-commands.ts
|
|
59135
59218
|
init_cli_shared();
|
|
59136
|
-
var
|
|
59219
|
+
var import_node_fs50 = require("node:fs");
|
|
59137
59220
|
function parseMemberSummaryFiles(entries) {
|
|
59138
59221
|
const memberSummaryFiles = {};
|
|
59139
59222
|
for (const entry of entries) {
|
|
@@ -59227,7 +59310,7 @@ function registerSuiteCommands(program3) {
|
|
|
59227
59310
|
try {
|
|
59228
59311
|
const io = suiteTrainIo(root);
|
|
59229
59312
|
retired = await retireFailedLeadRcLedger({ ledgerPath: releaseLedgerPath(root), rcHead: () => io.head(SUITE_REPO, "rc").then((h) => h ?? void 0), markAbandoned: io.markAbandoned }, o.ownerGo === true);
|
|
59230
|
-
if (retired && !(0,
|
|
59313
|
+
if (retired && !(0, import_node_fs50.existsSync)(io.recordPath)) {
|
|
59231
59314
|
console.log(o.json ? JSON.stringify({ retiredLeadRc: retired }, null, 2) : `suite abandon: retired the lead's failed, never-promoted rc candidate ${retired}; marked abandoned on origin (#7854)`);
|
|
59232
59315
|
return;
|
|
59233
59316
|
}
|
|
@@ -59421,7 +59504,7 @@ function suiteStatusDeps(github, registry2) {
|
|
|
59421
59504
|
|
|
59422
59505
|
// src/packages-adopt-export.ts
|
|
59423
59506
|
var import_node_child_process19 = require("node:child_process");
|
|
59424
|
-
var
|
|
59507
|
+
var import_node_fs51 = require("node:fs");
|
|
59425
59508
|
var import_node_os23 = require("node:os");
|
|
59426
59509
|
var import_node_path48 = require("node:path");
|
|
59427
59510
|
var import_node_util6 = require("node:util");
|
|
@@ -60045,36 +60128,36 @@ async function adoptExport(opts, deps) {
|
|
|
60045
60128
|
if (!/^sha256:[0-9a-f]{64}$/.test(opts.digest)) throw new Error("--digest must be sha256:<64 hex>, from the export run summary");
|
|
60046
60129
|
const packagePath = (0, import_node_path48.join)(opts.dir, "package.json");
|
|
60047
60130
|
const lockPath = (0, import_node_path48.join)(opts.dir, "package-lock.json");
|
|
60048
|
-
const packageText = (0,
|
|
60049
|
-
const lockText = (0,
|
|
60050
|
-
const work = (0,
|
|
60131
|
+
const packageText = (0, import_node_fs51.readFileSync)(packagePath, "utf8");
|
|
60132
|
+
const lockText = (0, import_node_fs51.readFileSync)(lockPath, "utf8");
|
|
60133
|
+
const work = (0, import_node_fs51.mkdtempSync)((0, import_node_path48.join)((0, import_node_os23.tmpdir)(), "mmi-adopt-export-"));
|
|
60051
60134
|
try {
|
|
60052
60135
|
const run = JSON.parse((await deps.ghApi(`repos/${EXPORT_REPO}/actions/runs/${opts.run}`)).toString("utf8"));
|
|
60053
|
-
(0,
|
|
60054
|
-
(0,
|
|
60055
|
-
(0,
|
|
60136
|
+
(0, import_node_fs51.writeFileSync)((0, import_node_path48.join)(work, "expected.json"), JSON.stringify(expectedFromRun(run, opts)));
|
|
60137
|
+
(0, import_node_fs51.writeFileSync)((0, import_node_path48.join)(work, "provider.json"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}`));
|
|
60138
|
+
(0, import_node_fs51.writeFileSync)((0, import_node_path48.join)(work, "artifact.zip"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}/zip`));
|
|
60056
60139
|
const script = (0, import_node_path48.join)(work, "package_export.py");
|
|
60057
|
-
(0,
|
|
60140
|
+
(0, import_node_fs51.writeFileSync)(script, package_export_default);
|
|
60058
60141
|
await deps.python(script, ["verify", work, opts.ds, opts.screens]);
|
|
60059
60142
|
const verified = (0, import_node_path48.join)(work, "verified");
|
|
60060
|
-
const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0,
|
|
60143
|
+
const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs51.readFileSync)((0, import_node_path48.join)(verified, `${short3}.metadata.json`), "utf8"))]));
|
|
60061
60144
|
const plan = planAdoption(packageText, lockText, metadata);
|
|
60062
60145
|
for (const { name } of plan.result.adopted) {
|
|
60063
60146
|
const short3 = PACKAGES.find((p) => p.name === name).short;
|
|
60064
60147
|
await deps.npm(["cache", "add", (0, import_node_path48.join)(verified, `${short3}.tgz`)], opts.dir);
|
|
60065
60148
|
}
|
|
60066
|
-
(0,
|
|
60067
|
-
(0,
|
|
60149
|
+
(0, import_node_fs51.writeFileSync)(packagePath, plan.packageText);
|
|
60150
|
+
(0, import_node_fs51.writeFileSync)(lockPath, plan.lockText);
|
|
60068
60151
|
try {
|
|
60069
60152
|
await deps.npm(["ci", "--offline", "--ignore-scripts", "--no-audit", "--no-fund"], opts.dir);
|
|
60070
60153
|
} catch (error) {
|
|
60071
|
-
(0,
|
|
60072
|
-
(0,
|
|
60154
|
+
(0, import_node_fs51.writeFileSync)(packagePath, packageText);
|
|
60155
|
+
(0, import_node_fs51.writeFileSync)(lockPath, lockText);
|
|
60073
60156
|
throw new Error(`npm ci --offline failed, package.json and package-lock.json restored: ${error.message}`);
|
|
60074
60157
|
}
|
|
60075
60158
|
return plan.result;
|
|
60076
60159
|
} finally {
|
|
60077
|
-
(0,
|
|
60160
|
+
(0, import_node_fs51.rmSync)(work, { recursive: true, force: true });
|
|
60078
60161
|
}
|
|
60079
60162
|
}
|
|
60080
60163
|
var execFileBuffer = (0, import_node_util6.promisify)(import_node_child_process19.execFile);
|
|
@@ -60139,12 +60222,12 @@ function registerPackagesCommands(program3) {
|
|
|
60139
60222
|
init_cli_shared();
|
|
60140
60223
|
|
|
60141
60224
|
// src/wave-status.ts
|
|
60142
|
-
var
|
|
60225
|
+
var import_node_fs52 = require("node:fs");
|
|
60143
60226
|
function readStageSummary(worktreePath) {
|
|
60144
60227
|
const statePath = stageStatePath(worktreePath);
|
|
60145
|
-
if (!(0,
|
|
60228
|
+
if (!(0, import_node_fs52.existsSync)(statePath)) return void 0;
|
|
60146
60229
|
try {
|
|
60147
|
-
const state = JSON.parse((0,
|
|
60230
|
+
const state = JSON.parse((0, import_node_fs52.readFileSync)(statePath, "utf8"));
|
|
60148
60231
|
const port = typeof state.port === "number" ? state.port : void 0;
|
|
60149
60232
|
if (port == null || !Number.isInteger(port) || port <= 0) return void 0;
|
|
60150
60233
|
return { port, url: typeof state.url === "string" ? state.url : void 0 };
|
|
@@ -60201,7 +60284,7 @@ async function collectWaveStatus(deps) {
|
|
|
60201
60284
|
// src/discovery-commands.ts
|
|
60202
60285
|
init_github_client();
|
|
60203
60286
|
init_cli_shared();
|
|
60204
|
-
var
|
|
60287
|
+
var import_node_fs53 = require("node:fs");
|
|
60205
60288
|
var import_node_os24 = require("node:os");
|
|
60206
60289
|
var import_node_path49 = require("node:path");
|
|
60207
60290
|
var GC_GH_TIMEOUT_MS3 = 2e4;
|
|
@@ -60394,8 +60477,8 @@ async function collectOnboardStatus(opts = {}) {
|
|
|
60394
60477
|
}
|
|
60395
60478
|
const home = (0, import_node_os24.homedir)();
|
|
60396
60479
|
const plugin = onboardPluginGate({
|
|
60397
|
-
readKnown: () => readFileSyncSafe((0, import_node_path49.join)(home, ...KNOWN_MARKETPLACES_RELATIVE),
|
|
60398
|
-
readSettings: () => readFileSyncSafe((0, import_node_path49.join)(home, ".claude", "settings.json"),
|
|
60480
|
+
readKnown: () => readFileSyncSafe((0, import_node_path49.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs53.readFileSync),
|
|
60481
|
+
readSettings: () => readFileSyncSafe((0, import_node_path49.join)(home, ".claude", "settings.json"), import_node_fs53.readFileSync)
|
|
60399
60482
|
});
|
|
60400
60483
|
return {
|
|
60401
60484
|
guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
|
|
@@ -62585,7 +62668,7 @@ function registerOrgHealthQuery(program3, deps = defaultOrgHealthQueryDeps()) {
|
|
|
62585
62668
|
}
|
|
62586
62669
|
|
|
62587
62670
|
// src/api-read.ts
|
|
62588
|
-
var
|
|
62671
|
+
var import_node_fs54 = require("node:fs");
|
|
62589
62672
|
|
|
62590
62673
|
// src/run-log-read.ts
|
|
62591
62674
|
init_cli_shared();
|
|
@@ -63365,7 +63448,7 @@ function registerApiReadCommands(program3, overrides) {
|
|
|
63365
63448
|
o.accept
|
|
63366
63449
|
);
|
|
63367
63450
|
if (zip) {
|
|
63368
|
-
(0,
|
|
63451
|
+
(0, import_node_fs54.writeFileSync)(o.out, body, "latin1");
|
|
63369
63452
|
return;
|
|
63370
63453
|
}
|
|
63371
63454
|
} catch (e) {
|
|
@@ -64259,7 +64342,7 @@ function registerSessionReport(program3) {
|
|
|
64259
64342
|
}
|
|
64260
64343
|
|
|
64261
64344
|
// src/stage-commands.ts
|
|
64262
|
-
var
|
|
64345
|
+
var import_node_fs55 = require("node:fs");
|
|
64263
64346
|
var import_node_path50 = require("node:path");
|
|
64264
64347
|
init_cli_shared();
|
|
64265
64348
|
init_clean_exit();
|
|
@@ -64508,8 +64591,8 @@ function registerStageCommands(program3) {
|
|
|
64508
64591
|
const repo = Array.isArray(project2?.repos) && typeof project2.repos[0] === "string" ? project2.repos[0] : slug;
|
|
64509
64592
|
const resolution = decideStage({
|
|
64510
64593
|
registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
|
|
64511
|
-
hasCompose: (0,
|
|
64512
|
-
hasEnvExample: (0,
|
|
64594
|
+
hasCompose: (0, import_node_fs55.existsSync)((0, import_node_path50.join)(process.cwd(), "docker-compose.yml")),
|
|
64595
|
+
hasEnvExample: (0, import_node_fs55.existsSync)((0, import_node_path50.join)(process.cwd(), ".env.example")),
|
|
64513
64596
|
repo
|
|
64514
64597
|
});
|
|
64515
64598
|
if (resolution.source === "derived" && resolution.derived) {
|
|
@@ -64802,14 +64885,14 @@ vercel preview (${preview.branch}): ${d.state}${d.url ? ` \u2014 ${d.url}` : ""}
|
|
|
64802
64885
|
|
|
64803
64886
|
// src/tenant-artifact.ts
|
|
64804
64887
|
var import_node_crypto17 = require("node:crypto");
|
|
64805
|
-
var
|
|
64888
|
+
var import_node_fs56 = require("node:fs");
|
|
64806
64889
|
var import_promises11 = require("node:fs/promises");
|
|
64807
64890
|
var import_node_path51 = require("node:path");
|
|
64808
64891
|
var ARTIFACT_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
64809
64892
|
var MAX_BYTES2 = 5 * 1024 * 1024 * 1024;
|
|
64810
64893
|
async function sha256File(path2) {
|
|
64811
64894
|
const hash = (0, import_node_crypto17.createHash)("sha256");
|
|
64812
|
-
for await (const chunk of (0,
|
|
64895
|
+
for await (const chunk of (0, import_node_fs56.createReadStream)(path2)) hash.update(chunk);
|
|
64813
64896
|
return hash.digest("hex");
|
|
64814
64897
|
}
|
|
64815
64898
|
async function putTenantArtifact(repo, stage, inputPath, deps) {
|
|
@@ -64832,7 +64915,7 @@ async function putTenantArtifact(repo, stage, inputPath, deps) {
|
|
|
64832
64915
|
return [key, value];
|
|
64833
64916
|
}));
|
|
64834
64917
|
headers["content-length"] = String(info.size);
|
|
64835
|
-
const stream = (0,
|
|
64918
|
+
const stream = (0, import_node_fs56.createReadStream)(path2);
|
|
64836
64919
|
let uploaded;
|
|
64837
64920
|
try {
|
|
64838
64921
|
uploaded = await fetch(body.uploadUrl, {
|
|
@@ -64973,7 +65056,7 @@ function renderVerifySecrets(body) {
|
|
|
64973
65056
|
}
|
|
64974
65057
|
|
|
64975
65058
|
// src/command-register-developer.ts
|
|
64976
|
-
var
|
|
65059
|
+
var import_node_fs60 = require("node:fs");
|
|
64977
65060
|
init_clean_exit();
|
|
64978
65061
|
init_cli_shared();
|
|
64979
65062
|
init_error_codes();
|
|
@@ -65041,13 +65124,13 @@ async function executeWaveLand(plan, deps) {
|
|
|
65041
65124
|
// src/dist-drift.ts
|
|
65042
65125
|
var import_node_child_process21 = require("node:child_process");
|
|
65043
65126
|
var import_node_crypto19 = require("node:crypto");
|
|
65044
|
-
var
|
|
65127
|
+
var import_node_fs58 = require("node:fs");
|
|
65045
65128
|
var import_node_os25 = require("node:os");
|
|
65046
65129
|
var import_node_path53 = require("node:path");
|
|
65047
65130
|
|
|
65048
65131
|
// ../scripts/distribution-digest.mjs
|
|
65049
65132
|
var import_node_crypto18 = require("node:crypto");
|
|
65050
|
-
var
|
|
65133
|
+
var import_node_fs57 = require("node:fs");
|
|
65051
65134
|
var import_node_path52 = require("node:path");
|
|
65052
65135
|
var slash = (value) => value.replaceAll("\\", "/");
|
|
65053
65136
|
function repoPath(root, declaredPath, label) {
|
|
@@ -65061,7 +65144,7 @@ function repoPath(root, declaredPath, label) {
|
|
|
65061
65144
|
function digestFiles(files) {
|
|
65062
65145
|
const hash = (0, import_node_crypto18.createHash)("sha256");
|
|
65063
65146
|
for (const file of [...files].sort((a, b) => a.relative.localeCompare(b.relative))) {
|
|
65064
|
-
const content = file.stat.isSymbolicLink() ? Buffer.from((0,
|
|
65147
|
+
const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs57.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs57.readFileSync)(file.absolute);
|
|
65065
65148
|
hash.update(file.relative, "utf8");
|
|
65066
65149
|
hash.update("\0");
|
|
65067
65150
|
hash.update(file.stat.isSymbolicLink() ? "symlink" : "file", "utf8");
|
|
@@ -65076,8 +65159,8 @@ function digestFiles(files) {
|
|
|
65076
65159
|
function digestPackedFiles(packageRoot, packedFiles) {
|
|
65077
65160
|
return digestFiles(packedFiles.map((path2) => {
|
|
65078
65161
|
const absolute = repoPath(packageRoot, path2, "packed artifact identity path");
|
|
65079
|
-
if (!(0,
|
|
65080
|
-
return { absolute, relative: slash(path2), stat: (0,
|
|
65162
|
+
if (!(0, import_node_fs57.existsSync)(absolute)) throw new Error(`packed artifact identity path ${path2} does not exist`);
|
|
65163
|
+
return { absolute, relative: slash(path2), stat: (0, import_node_fs57.lstatSync)(absolute) };
|
|
65081
65164
|
}));
|
|
65082
65165
|
}
|
|
65083
65166
|
|
|
@@ -65162,12 +65245,12 @@ function renderDistDriftReceipt(receipt) {
|
|
|
65162
65245
|
return lines2;
|
|
65163
65246
|
}
|
|
65164
65247
|
function readOrNull(path2) {
|
|
65165
|
-
return (0,
|
|
65248
|
+
return (0, import_node_fs58.existsSync)(path2) ? (0, import_node_fs58.readFileSync)(path2) : null;
|
|
65166
65249
|
}
|
|
65167
65250
|
function walkFiles(root) {
|
|
65168
65251
|
const files = [];
|
|
65169
65252
|
const walk2 = (directory) => {
|
|
65170
|
-
for (const entry of (0,
|
|
65253
|
+
for (const entry of (0, import_node_fs58.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
65171
65254
|
const child2 = (0, import_node_path53.join)(directory, entry.name);
|
|
65172
65255
|
if (entry.isDirectory()) walk2(child2);
|
|
65173
65256
|
else files.push(child2);
|
|
@@ -65178,7 +65261,7 @@ function walkFiles(root) {
|
|
|
65178
65261
|
}
|
|
65179
65262
|
function bomPathFor(root) {
|
|
65180
65263
|
try {
|
|
65181
|
-
const registry2 = JSON.parse((0,
|
|
65264
|
+
const registry2 = JSON.parse((0, import_node_fs58.readFileSync)((0, import_node_path53.join)(root, "surfaces.json"), "utf8"));
|
|
65182
65265
|
return (0, import_node_path53.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
|
|
65183
65266
|
} catch {
|
|
65184
65267
|
return (0, import_node_path53.join)(root, "distribution-bom.json");
|
|
@@ -65194,7 +65277,7 @@ function rebuildTo(packageRoot, outDir) {
|
|
|
65194
65277
|
});
|
|
65195
65278
|
}
|
|
65196
65279
|
function runDistStatus(root) {
|
|
65197
|
-
const stage = (0,
|
|
65280
|
+
const stage = (0, import_node_fs58.mkdtempSync)((0, import_node_path53.join)((0, import_node_os25.tmpdir)(), "mmi-dist-drift-"));
|
|
65198
65281
|
let overlayCount = 0;
|
|
65199
65282
|
try {
|
|
65200
65283
|
const cliOut = (0, import_node_path53.join)(stage, "cli-dist");
|
|
@@ -65210,19 +65293,19 @@ function runDistStatus(root) {
|
|
|
65210
65293
|
const tree = (path2) => readOrNull((0, import_node_path53.join)(root, path2));
|
|
65211
65294
|
const distRoot = (0, import_node_path53.join)(root, "cli", "dist");
|
|
65212
65295
|
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path53.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
|
|
65213
|
-
const bom = JSON.parse((0,
|
|
65296
|
+
const bom = JSON.parse((0, import_node_fs58.readFileSync)(bomPathFor(root), "utf8"));
|
|
65214
65297
|
const digest = (entries) => {
|
|
65215
65298
|
const overlay = (0, import_node_path53.join)(stage, `overlay-${overlayCount++}`);
|
|
65216
65299
|
for (const entry of entries) {
|
|
65217
65300
|
const target = (0, import_node_path53.join)(overlay, entry.path);
|
|
65218
|
-
(0,
|
|
65219
|
-
(0,
|
|
65301
|
+
(0, import_node_fs58.mkdirSync)((0, import_node_path53.dirname)(target), { recursive: true });
|
|
65302
|
+
(0, import_node_fs58.writeFileSync)(target, entry.bytes);
|
|
65220
65303
|
}
|
|
65221
65304
|
return digestPackedFiles(overlay, entries.map((entry) => entry.path));
|
|
65222
65305
|
};
|
|
65223
65306
|
return computeDistDriftReceipt({ committed, tree, rebuilt, distTree, bom, digest });
|
|
65224
65307
|
} finally {
|
|
65225
|
-
(0,
|
|
65308
|
+
(0, import_node_fs58.rmSync)(stage, { recursive: true, force: true });
|
|
65226
65309
|
}
|
|
65227
65310
|
}
|
|
65228
65311
|
|
|
@@ -65554,7 +65637,7 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
|
|
|
65554
65637
|
|
|
65555
65638
|
// src/spawn-policy-core.ts
|
|
65556
65639
|
var import_node_child_process23 = require("node:child_process");
|
|
65557
|
-
var
|
|
65640
|
+
var import_node_fs59 = require("node:fs");
|
|
65558
65641
|
var import_node_path56 = require("node:path");
|
|
65559
65642
|
var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
|
|
65560
65643
|
var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
|
|
@@ -65641,7 +65724,7 @@ function runSpawnPolicy(root) {
|
|
|
65641
65724
|
for (const file of files) {
|
|
65642
65725
|
let raw;
|
|
65643
65726
|
try {
|
|
65644
|
-
raw = (0,
|
|
65727
|
+
raw = (0, import_node_fs59.readFileSync)((0, import_node_path56.join)(root, file), "utf8");
|
|
65645
65728
|
} catch {
|
|
65646
65729
|
continue;
|
|
65647
65730
|
}
|
|
@@ -65662,18 +65745,18 @@ function registerDeveloperCommands(program3) {
|
|
|
65662
65745
|
const rules = program3.command("rules").description("org-managed .gitignore delivery");
|
|
65663
65746
|
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) => {
|
|
65664
65747
|
const path2 = (0, import_node_path57.join)(process.cwd(), ".gitignore");
|
|
65665
|
-
const current = (0,
|
|
65748
|
+
const current = (0, import_node_fs60.existsSync)(path2) ? (0, import_node_fs60.readFileSync)(path2, "utf8") : null;
|
|
65666
65749
|
const plan = planManagedGitignore(current);
|
|
65667
65750
|
const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
|
|
65668
65751
|
if (opts.json) {
|
|
65669
|
-
if (opts.write && plan.changed) (0,
|
|
65752
|
+
if (opts.write && plan.changed) (0, import_node_fs60.writeFileSync)(path2, plan.content, "utf8");
|
|
65670
65753
|
console.log(JSON.stringify(plan, null, 2));
|
|
65671
65754
|
if (!opts.write && plan.changed) process.exitCode = 1;
|
|
65672
65755
|
return;
|
|
65673
65756
|
}
|
|
65674
65757
|
if (opts.write) {
|
|
65675
65758
|
if (plan.changed) {
|
|
65676
|
-
(0,
|
|
65759
|
+
(0, import_node_fs60.writeFileSync)(path2, plan.content, "utf8");
|
|
65677
65760
|
console.log(`mmi-cli devops org rules gitignore: updated .gitignore (${drift})`);
|
|
65678
65761
|
} else {
|
|
65679
65762
|
console.log("mmi-cli devops org rules gitignore: up to date");
|
|
@@ -66092,7 +66175,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
66092
66175
|
);
|
|
66093
66176
|
const result = applyPluginCachePlan(
|
|
66094
66177
|
plan,
|
|
66095
|
-
(p) => (0,
|
|
66178
|
+
(p) => (0, import_node_fs61.rmSync)(p, { recursive: true }),
|
|
66096
66179
|
stagingApplyFsGuard(configRoot)
|
|
66097
66180
|
);
|
|
66098
66181
|
return {
|
|
@@ -66127,7 +66210,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
66127
66210
|
// has no generated routing index would
|
|
66128
66211
|
// get a permanent — demanding an artifact it never asked for.
|
|
66129
66212
|
docsIndexState: (root) => {
|
|
66130
|
-
if (!(0,
|
|
66213
|
+
if (!(0, import_node_fs61.existsSync)((0, import_node_path58.join)(root, DOCS_INDEX_PATH))) return void 0;
|
|
66131
66214
|
const real = createDocsIndexDeps(root);
|
|
66132
66215
|
let docs;
|
|
66133
66216
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -66136,7 +66219,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
66136
66219
|
},
|
|
66137
66220
|
// #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
|
|
66138
66221
|
healDocsIndex: (root) => {
|
|
66139
|
-
if (!(0,
|
|
66222
|
+
if (!(0, import_node_fs61.existsSync)((0, import_node_path58.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
|
|
66140
66223
|
const real = createDocsIndexDeps(root);
|
|
66141
66224
|
let docs;
|
|
66142
66225
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -66891,7 +66974,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
|
|
|
66891
66974
|
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`);
|
|
66892
66975
|
if (o.secretsFile) {
|
|
66893
66976
|
try {
|
|
66894
|
-
vars.push(`secrets=${(0,
|
|
66977
|
+
vars.push(`secrets=${(0, import_node_fs61.readFileSync)(o.secretsFile, "utf8")}`);
|
|
66895
66978
|
} catch (e) {
|
|
66896
66979
|
return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
|
|
66897
66980
|
}
|
|
@@ -67284,15 +67367,15 @@ function ciAuditDeps2() {
|
|
|
67284
67367
|
readSeedFile: (path2) => {
|
|
67285
67368
|
if (!root) return null;
|
|
67286
67369
|
const fullPath = (0, import_node_path58.join)(root, path2);
|
|
67287
|
-
return (0,
|
|
67370
|
+
return (0, import_node_fs61.existsSync)(fullPath) ? (0, import_node_fs61.readFileSync)(fullPath, "utf8") : null;
|
|
67288
67371
|
}
|
|
67289
67372
|
};
|
|
67290
67373
|
}
|
|
67291
67374
|
function hubRoot2() {
|
|
67292
67375
|
const fromPkg = (0, import_node_path58.join)(__dirname, "..", "..");
|
|
67293
67376
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
67294
|
-
if ((0,
|
|
67295
|
-
if ((0,
|
|
67377
|
+
if ((0, import_node_fs61.existsSync)((0, import_node_path58.join)(fromPkg, marker))) return fromPkg;
|
|
67378
|
+
if ((0, import_node_fs61.existsSync)((0, import_node_path58.join)(process.cwd(), marker))) return process.cwd();
|
|
67296
67379
|
return null;
|
|
67297
67380
|
}
|
|
67298
67381
|
registerQueryCommands(program2);
|
|
@@ -67423,10 +67506,10 @@ access.command("audit").description("audit collaborator roles + train-branch pus
|
|
|
67423
67506
|
targets = resolution.targets;
|
|
67424
67507
|
}
|
|
67425
67508
|
const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
|
|
67426
|
-
const fileMatrix = (0,
|
|
67509
|
+
const fileMatrix = (0, import_node_fs61.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs61.readFileSync)("access-matrix.json", "utf8")) : {};
|
|
67427
67510
|
const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
|
|
67428
67511
|
const dataAccess = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
|
|
67429
|
-
const sanctioned = (0,
|
|
67512
|
+
const sanctioned = (0, import_node_fs61.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs61.readFileSync)("access-matrix.json", "utf8")) : {};
|
|
67430
67513
|
const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
|
|
67431
67514
|
console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
|
|
67432
67515
|
if (!report.ok) process.exitCode = 1;
|
|
@@ -67457,7 +67540,7 @@ function directoryBytes(path2) {
|
|
|
67457
67540
|
let total = 0;
|
|
67458
67541
|
let entries;
|
|
67459
67542
|
try {
|
|
67460
|
-
entries = (0,
|
|
67543
|
+
entries = (0, import_node_fs61.readdirSync)(path2, { withFileTypes: true });
|
|
67461
67544
|
} catch {
|
|
67462
67545
|
return 0;
|
|
67463
67546
|
}
|
|
@@ -67466,7 +67549,7 @@ function directoryBytes(path2) {
|
|
|
67466
67549
|
if (entry.isDirectory()) total += directoryBytes(child2);
|
|
67467
67550
|
else {
|
|
67468
67551
|
try {
|
|
67469
|
-
total += (0,
|
|
67552
|
+
total += (0, import_node_fs61.statSync)(child2).size;
|
|
67470
67553
|
} catch {
|
|
67471
67554
|
}
|
|
67472
67555
|
}
|
|
@@ -67474,25 +67557,25 @@ function directoryBytes(path2) {
|
|
|
67474
67557
|
return total;
|
|
67475
67558
|
}
|
|
67476
67559
|
function listDirEntries(dir) {
|
|
67477
|
-
return (0,
|
|
67560
|
+
return (0, import_node_fs61.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
|
|
67478
67561
|
}
|
|
67479
67562
|
function readInstalledPluginRefs(configRoot) {
|
|
67480
67563
|
const p = installedPluginsPathForConfig(configRoot);
|
|
67481
|
-
if (!(0,
|
|
67564
|
+
if (!(0, import_node_fs61.existsSync)(p)) return [];
|
|
67482
67565
|
try {
|
|
67483
|
-
return installedPluginPaths((0,
|
|
67566
|
+
return installedPluginPaths((0, import_node_fs61.readFileSync)(p, "utf8"));
|
|
67484
67567
|
} catch {
|
|
67485
67568
|
return null;
|
|
67486
67569
|
}
|
|
67487
67570
|
}
|
|
67488
67571
|
function pluginCacheFsDeps(configRoot, dirBytes) {
|
|
67489
67572
|
return {
|
|
67490
|
-
exists: (p) => (0,
|
|
67491
|
-
listVersionDirs: (root) => (0,
|
|
67573
|
+
exists: (p) => (0, import_node_fs61.existsSync)(p),
|
|
67574
|
+
listVersionDirs: (root) => (0, import_node_fs61.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
|
|
67492
67575
|
dirBytes,
|
|
67493
|
-
listStagingDirs: (root) => (0,
|
|
67576
|
+
listStagingDirs: (root) => (0, import_node_fs61.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
|
|
67494
67577
|
try {
|
|
67495
|
-
return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path58.join)(root, d.name), listDirEntries, (p) => (0,
|
|
67578
|
+
return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path58.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs61.statSync)(p).mtimeMs) };
|
|
67496
67579
|
} catch {
|
|
67497
67580
|
return { name: d.name, mtimeMs: Date.now() };
|
|
67498
67581
|
}
|
|
@@ -67507,9 +67590,9 @@ function stagingApplyFsGuard(configRoot) {
|
|
|
67507
67590
|
referencedPaths: () => readInstalledPluginRefs(configRoot),
|
|
67508
67591
|
mtimeMs: (name) => {
|
|
67509
67592
|
const p = (0, import_node_path58.join)(stagingRoot, name);
|
|
67510
|
-
if (!(0,
|
|
67593
|
+
if (!(0, import_node_fs61.existsSync)(p)) return null;
|
|
67511
67594
|
try {
|
|
67512
|
-
return newestMtimeMs(p, listDirEntries, (q) => (0,
|
|
67595
|
+
return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs61.statSync)(q).mtimeMs);
|
|
67513
67596
|
} catch {
|
|
67514
67597
|
return null;
|
|
67515
67598
|
}
|
|
@@ -67535,7 +67618,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
|
|
|
67535
67618
|
{ withBytes: true, configRoot, includeStaging: surface !== "codex" }
|
|
67536
67619
|
);
|
|
67537
67620
|
const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
|
|
67538
|
-
const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0,
|
|
67621
|
+
const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs61.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
|
|
67539
67622
|
const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
|
|
67540
67623
|
if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
|
|
67541
67624
|
else console.log(renderPluginCachePlan(plan, result));
|