@mutmutco/cli 4.3.44 → 4.3.45
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/README.md +3 -4
- package/dist/main.cjs +338 -508
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -3416,7 +3416,7 @@ function useColor() {
|
|
|
3416
3416
|
var program = new Command();
|
|
3417
3417
|
|
|
3418
3418
|
// src/command-composition.ts
|
|
3419
|
-
var
|
|
3419
|
+
var import_node_fs48 = require("node:fs");
|
|
3420
3420
|
|
|
3421
3421
|
// src/clean-exit.ts
|
|
3422
3422
|
var UNDICI_GLOBAL_DISPATCHER_SYMBOL = Object.getOwnPropertySymbols(globalThis).find(
|
|
@@ -5252,16 +5252,14 @@ var GUIDES = /* @__PURE__ */ new Map([
|
|
|
5252
5252
|
did_you_mean: "oracle issue edit"
|
|
5253
5253
|
}
|
|
5254
5254
|
],
|
|
5255
|
-
//
|
|
5256
|
-
// envelope built `mmi-cli explain jervcode worktree-create --json` — an explain hop that itself
|
|
5257
|
-
// dead-ends on ERR_NOT_FOUND — so the guide carries the corrected command directly.
|
|
5255
|
+
// Worktree creation belongs to Git or the selected host, not an MMI command.
|
|
5258
5256
|
[
|
|
5259
5257
|
"worktree:create",
|
|
5260
5258
|
{
|
|
5261
|
-
hint: "no `worktree create` in mmi-cli \u2014
|
|
5262
|
-
expected: ["
|
|
5263
|
-
did_you_mean: "
|
|
5264
|
-
corrected_command: "
|
|
5259
|
+
hint: "no `worktree create` in mmi-cli \u2014 after claiming the issue, use Git or your host to create an isolated worktree",
|
|
5260
|
+
expected: ["git worktree add"],
|
|
5261
|
+
did_you_mean: "git worktree add",
|
|
5262
|
+
corrected_command: "git worktree -h"
|
|
5265
5263
|
}
|
|
5266
5264
|
]
|
|
5267
5265
|
]);
|
|
@@ -5304,8 +5302,8 @@ function resolveVerbAliasShim(argv) {
|
|
|
5304
5302
|
}
|
|
5305
5303
|
|
|
5306
5304
|
// src/command-composition.ts
|
|
5307
|
-
var
|
|
5308
|
-
var
|
|
5305
|
+
var import_node_os21 = require("node:os");
|
|
5306
|
+
var import_node_path46 = require("node:path");
|
|
5309
5307
|
|
|
5310
5308
|
// src/board-read.ts
|
|
5311
5309
|
var import_node_fs13 = require("node:fs");
|
|
@@ -7348,7 +7346,7 @@ var OWNER = "mutmutco";
|
|
|
7348
7346
|
var SSM_ROOT = "/mmi-future";
|
|
7349
7347
|
var PROJECT_TIER_SEGMENT = "dev";
|
|
7350
7348
|
var ORG_INFRA_SLUG = "_org";
|
|
7351
|
-
var
|
|
7349
|
+
var MMI_VAULT_GUIDANCE = 'Check MMI access with `mmi-cli oracle org access capabilities`; a master can locate credentials with `mmi-cli vault secrets find "<what it is for>"`.';
|
|
7352
7350
|
var KEY_MAX_PATH_SEGMENTS = 4;
|
|
7353
7351
|
var KEY_RE = new RegExp(`^(?:[a-z0-9][a-z0-9-]*/){0,${KEY_MAX_PATH_SEGMENTS}}[A-Za-z][A-Za-z0-9_]*$`);
|
|
7354
7352
|
function isValidSecretKey(key) {
|
|
@@ -7365,7 +7363,7 @@ function secretParamName(slug, key) {
|
|
|
7365
7363
|
return `${SSM_ROOT}/${slug}/${key}`;
|
|
7366
7364
|
}
|
|
7367
7365
|
function formatSecretList(items) {
|
|
7368
|
-
if (!items.length) return `no secrets \u2014 ${
|
|
7366
|
+
if (!items.length) return `no secrets \u2014 ${MMI_VAULT_GUIDANCE}`;
|
|
7369
7367
|
const width = Math.max(...items.map((i) => i.key.length));
|
|
7370
7368
|
return items.map((i) => {
|
|
7371
7369
|
const head = `${i.canManage ? "*" : " "} ${i.key.padEnd(width)} ${i.tier}`;
|
|
@@ -7558,7 +7556,7 @@ function formatCapabilities(r) {
|
|
|
7558
7556
|
const items = [...r.capabilities ?? []].sort((a, b) => a.scope.localeCompare(b.scope));
|
|
7559
7557
|
if (!items.length) return `${head}
|
|
7560
7558
|
|
|
7561
|
-
no vault credentials visible \u2014 ${
|
|
7559
|
+
no vault credentials visible \u2014 ${MMI_VAULT_GUIDANCE}`;
|
|
7562
7560
|
const width = Math.max(...items.map((i) => i.scope.length));
|
|
7563
7561
|
const lines2 = items.map(
|
|
7564
7562
|
(i) => `${i.accessible ? "+" : " "} ${i.scope.padEnd(width)} ${i.tier.padEnd(7)} ${i.grantScope ? `${i.reason} (${i.grantScope})` : i.reason}`
|
|
@@ -7682,7 +7680,7 @@ function resolveNotFoundGuidance(input) {
|
|
|
7682
7680
|
`Secret ${key} was not found at ${tried}, and no key named ${leaf} is visible to you.`,
|
|
7683
7681
|
`Locate it by intent first: \`mmi-cli vault secrets find "<what it is for>"\` \u2014 it returns the exact keyless-use command.`,
|
|
7684
7682
|
mnemonic,
|
|
7685
|
-
|
|
7683
|
+
MMI_VAULT_GUIDANCE
|
|
7686
7684
|
];
|
|
7687
7685
|
if (isMaster) {
|
|
7688
7686
|
lines2.push("You are master: if it truly does not exist yet, create it with `mmi-cli vault secrets set` rather than requesting a grant from yourself.");
|
|
@@ -8792,7 +8790,7 @@ async function secretsVerify(deps, key, opts) {
|
|
|
8792
8790
|
if (!value) {
|
|
8793
8791
|
deps.err(`${key}: ABSENT or unreachable at this coordinate \u2014 no value could be read`);
|
|
8794
8792
|
deps.err(`Locate a key across every vault you can reach: mmi-cli oracle org access capabilities${opts.repo ? ` --repo ${opts.repo}` : ""}`);
|
|
8795
|
-
deps.err(
|
|
8793
|
+
deps.err(MMI_VAULT_GUIDANCE);
|
|
8796
8794
|
return false;
|
|
8797
8795
|
}
|
|
8798
8796
|
deps.log(`${key}: PRESENT (${value.length} chars) \u2014 reachability only; no provider verifier is configured for ${secretLeafName(key)}, so the credential itself was not validated`);
|
|
@@ -9632,7 +9630,7 @@ async function loadConfigForBoardSelector(selector, repoOption) {
|
|
|
9632
9630
|
var SKILL_LESSON_LABEL = "skill-lesson";
|
|
9633
9631
|
var SKILL_LESSON_FILE_LABELS = [SKILL_LESSON_LABEL, LEARNING_LABEL2];
|
|
9634
9632
|
var SKILL_LESSON_LOOP_KIND = "lesson";
|
|
9635
|
-
var SKILL_NAMES = ["bootstrap", "epic", "hotfix", "rcand", "release", "secrets", "stage"];
|
|
9633
|
+
var SKILL_NAMES = ["board", "bootstrap", "epic", "hotfix", "rcand", "release", "secrets", "stage"];
|
|
9636
9634
|
function assertSkillName(name) {
|
|
9637
9635
|
const match = SKILL_NAMES.find((skill) => skill === name);
|
|
9638
9636
|
if (!match) throw new Error(`unknown skill "${name}" \u2014 expected one of: ${SKILL_NAMES.join(", ")}`);
|
|
@@ -9661,11 +9659,6 @@ ${buildSkillLessonBody(body, sourceRepo, pluginSha)}`;
|
|
|
9661
9659
|
function findDuplicateLesson(source, openLessons) {
|
|
9662
9660
|
return findDuplicateReport(source, openLessons);
|
|
9663
9661
|
}
|
|
9664
|
-
var SKILL_LESSON_DEPRECATION_NOTICE = "mmi-cli learning skill-lesson is deprecated \u2014 file the retro with the jerv_learning_note tool in-session (origin retro), or `jervcode learn --origin retro --surface skills` on a machine path. This verb still files.";
|
|
9665
|
-
function warnSkillLessonDeprecated(write = (line) => void process.stderr.write(line)) {
|
|
9666
|
-
write(`${SKILL_LESSON_DEPRECATION_NOTICE}
|
|
9667
|
-
`);
|
|
9668
|
-
}
|
|
9669
9662
|
|
|
9670
9663
|
// src/session-identity.ts
|
|
9671
9664
|
var import_node_crypto4 = require("node:crypto");
|
|
@@ -15710,10 +15703,10 @@ var rollout_plan_default = {
|
|
|
15710
15703
|
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)."
|
|
15711
15704
|
},
|
|
15712
15705
|
baseline: {
|
|
15713
|
-
version: "4.3.
|
|
15714
|
-
tag: "v4.3.
|
|
15715
|
-
commit: "
|
|
15716
|
-
npm: "@mutmutco/cli@4.3.
|
|
15706
|
+
version: "4.3.45",
|
|
15707
|
+
tag: "v4.3.45",
|
|
15708
|
+
commit: "519cee3af091",
|
|
15709
|
+
npm: "@mutmutco/cli@4.3.45"
|
|
15717
15710
|
},
|
|
15718
15711
|
exitCriterion: "fleet-n-of-n",
|
|
15719
15712
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15730,14 +15723,14 @@ var rollout_plan_default = {
|
|
|
15730
15723
|
repo: "mutmutco/mmi-hub",
|
|
15731
15724
|
role: "canary",
|
|
15732
15725
|
schedule: "train",
|
|
15733
|
-
v3Target: "v4.3.
|
|
15726
|
+
v3Target: "v4.3.45"
|
|
15734
15727
|
}
|
|
15735
15728
|
],
|
|
15736
15729
|
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.",
|
|
15737
15730
|
rollback: {
|
|
15738
15731
|
independent: true,
|
|
15739
|
-
mechanism: "npm dist-tag latest -> 4.3.
|
|
15740
|
-
v3Target: "v4.3.
|
|
15732
|
+
mechanism: "npm dist-tag latest -> 4.3.45 and redeploy the Hub Lambda from tag v4.3.45 (519cee3af091); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15733
|
+
v3Target: "v4.3.45 (@mutmutco/cli@4.3.45, tag commit 519cee3af091 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15741
15734
|
}
|
|
15742
15735
|
},
|
|
15743
15736
|
{
|
|
@@ -19126,7 +19119,7 @@ function renderTenantControl(r) {
|
|
|
19126
19119
|
}
|
|
19127
19120
|
|
|
19128
19121
|
// src/train-apply-phases.ts
|
|
19129
|
-
var
|
|
19122
|
+
var import_node_fs23 = require("node:fs");
|
|
19130
19123
|
var import_promises3 = require("node:fs/promises");
|
|
19131
19124
|
var import_node_path23 = require("node:path");
|
|
19132
19125
|
|
|
@@ -19381,7 +19374,7 @@ Resume it: ${resumeCommand}
|
|
|
19381
19374
|
|
|
19382
19375
|
// src/train-doctor.ts
|
|
19383
19376
|
var import_node_child_process9 = require("node:child_process");
|
|
19384
|
-
var
|
|
19377
|
+
var import_node_fs22 = require("node:fs");
|
|
19385
19378
|
var import_node_os13 = require("node:os");
|
|
19386
19379
|
var import_node_path22 = require("node:path");
|
|
19387
19380
|
|
|
@@ -19592,16 +19585,13 @@ function compatHolds(range, version) {
|
|
|
19592
19585
|
}
|
|
19593
19586
|
|
|
19594
19587
|
// src/claude-binary-doctor.ts
|
|
19595
|
-
var
|
|
19588
|
+
var import_node_fs20 = require("node:fs");
|
|
19596
19589
|
var import_node_os12 = require("node:os");
|
|
19597
19590
|
var import_node_path19 = require("node:path");
|
|
19598
19591
|
|
|
19599
19592
|
// src/jerv-cli-spawn.ts
|
|
19600
|
-
var import_node_fs20 = require("node:fs");
|
|
19601
19593
|
var import_node_os11 = require("node:os");
|
|
19602
19594
|
var import_node_path18 = require("node:path");
|
|
19603
|
-
var WIN_NAMES = ["jerv-cli.cmd", "jerv-cli.exe", "jerv-cli"];
|
|
19604
|
-
var POSIX_NAMES = ["jerv-cli"];
|
|
19605
19595
|
var JERV_CLI_ENTRY = (0, import_node_path18.join)("node_modules", "@jervaise", "jerv-cli", "dist", "index.cjs");
|
|
19606
19596
|
function pathEnvEntries(pathEnv, platform2 = process.platform) {
|
|
19607
19597
|
if (platform2 !== "win32") {
|
|
@@ -19645,67 +19635,6 @@ function jervCliCandidateDirs(env = process.env, home = (0, import_node_os11.hom
|
|
|
19645
19635
|
}
|
|
19646
19636
|
return out;
|
|
19647
19637
|
}
|
|
19648
|
-
function jervCliCandidatePaths(env = process.env, home = (0, import_node_os11.homedir)(), platform2 = process.platform) {
|
|
19649
|
-
const names = platform2 === "win32" ? WIN_NAMES : POSIX_NAMES;
|
|
19650
|
-
const out = [];
|
|
19651
|
-
for (const dir of jervCliCandidateDirs(env, home, platform2)) {
|
|
19652
|
-
for (const name of names) out.push((0, import_node_path18.join)(dir, name));
|
|
19653
|
-
}
|
|
19654
|
-
return out;
|
|
19655
|
-
}
|
|
19656
|
-
function resolveJervCliPath(env = process.env, home = (0, import_node_os11.homedir)(), platform2 = process.platform, exists = import_node_fs20.existsSync) {
|
|
19657
|
-
for (const candidate of jervCliCandidatePaths(env, home, platform2)) {
|
|
19658
|
-
if (exists(candidate)) return candidate;
|
|
19659
|
-
}
|
|
19660
|
-
return void 0;
|
|
19661
|
-
}
|
|
19662
|
-
function resolveJervCliNodeEntry(shimPath, exists = import_node_fs20.existsSync) {
|
|
19663
|
-
const entry = (0, import_node_path18.join)((0, import_node_path18.dirname)(shimPath), JERV_CLI_ENTRY);
|
|
19664
|
-
return exists(entry) ? entry : void 0;
|
|
19665
|
-
}
|
|
19666
|
-
function jervCliExecFileArgs(args, opts = {}) {
|
|
19667
|
-
const platform2 = opts.platform ?? process.platform;
|
|
19668
|
-
const exists = opts.exists ?? import_node_fs20.existsSync;
|
|
19669
|
-
const resolved = resolveJervCliPath(opts.env ?? process.env, opts.home ?? (0, import_node_os11.homedir)(), platform2, exists);
|
|
19670
|
-
if (resolved) {
|
|
19671
|
-
const entry = resolveJervCliNodeEntry(resolved, exists);
|
|
19672
|
-
if (entry) {
|
|
19673
|
-
return { file: opts.execPath ?? process.execPath, args: [entry, ...args], via: "node-entry" };
|
|
19674
|
-
}
|
|
19675
|
-
}
|
|
19676
|
-
const bin = resolved ?? "jerv-cli";
|
|
19677
|
-
if (platform2 === "win32") {
|
|
19678
|
-
return { file: "cmd.exe", args: ["/c", bin, ...args], via: resolved ? "cmd-shim" : "bare" };
|
|
19679
|
-
}
|
|
19680
|
-
return { file: bin, args: [...args], via: resolved ? "posix" : "bare" };
|
|
19681
|
-
}
|
|
19682
|
-
function formatJervCliSpawnFailure(err, plan, candidates) {
|
|
19683
|
-
const base = (err.stderr?.trim() || err.message.trim()).split("\n")[0] || "spawn failed";
|
|
19684
|
-
const code = err.code;
|
|
19685
|
-
if (code !== "ENOENT" && !/\bENOENT\b/i.test(base)) return base;
|
|
19686
|
-
const tried = candidates.length > 0 ? candidates.join(" | ") : "(no candidates)";
|
|
19687
|
-
return `${base} [via=${plan.via} file=${plan.file}; tried: ${tried}]`;
|
|
19688
|
-
}
|
|
19689
|
-
function isEnoent(err) {
|
|
19690
|
-
const code = err.code;
|
|
19691
|
-
if (code === "ENOENT") return true;
|
|
19692
|
-
return /\bENOENT\b/i.test(err.message ?? "");
|
|
19693
|
-
}
|
|
19694
|
-
function execJervCli(args, options = {}) {
|
|
19695
|
-
const env = options.env ?? process.env;
|
|
19696
|
-
const candidates = jervCliCandidatePaths(env);
|
|
19697
|
-
const plan = jervCliExecFileArgs(args, { env });
|
|
19698
|
-
return execFileP(plan.file, plan.args, options).catch((err) => {
|
|
19699
|
-
if (!isEnoent(err)) throw err;
|
|
19700
|
-
const wrapped = new Error(formatJervCliSpawnFailure(err, plan, candidates));
|
|
19701
|
-
Object.assign(wrapped, {
|
|
19702
|
-
code: "ENOENT",
|
|
19703
|
-
stderr: err.stderr,
|
|
19704
|
-
cause: err
|
|
19705
|
-
});
|
|
19706
|
-
throw wrapped;
|
|
19707
|
-
});
|
|
19708
|
-
}
|
|
19709
19638
|
|
|
19710
19639
|
// src/claude-binary-doctor.ts
|
|
19711
19640
|
var PACKAGE = "@anthropic-ai/claude-code";
|
|
@@ -19765,16 +19694,16 @@ function globalNodeModulesRoots(host) {
|
|
|
19765
19694
|
function readHead(path2) {
|
|
19766
19695
|
let fd;
|
|
19767
19696
|
try {
|
|
19768
|
-
fd = (0,
|
|
19697
|
+
fd = (0, import_node_fs20.openSync)(path2, "r");
|
|
19769
19698
|
const buffer = new Uint8Array(MAGIC_HEAD_BYTES);
|
|
19770
|
-
const read = (0,
|
|
19699
|
+
const read = (0, import_node_fs20.readSync)(fd, buffer, 0, MAGIC_HEAD_BYTES, 0);
|
|
19771
19700
|
return buffer.subarray(0, read);
|
|
19772
19701
|
} catch {
|
|
19773
19702
|
return void 0;
|
|
19774
19703
|
} finally {
|
|
19775
19704
|
if (fd !== void 0) {
|
|
19776
19705
|
try {
|
|
19777
|
-
(0,
|
|
19706
|
+
(0, import_node_fs20.closeSync)(fd);
|
|
19778
19707
|
} catch {
|
|
19779
19708
|
}
|
|
19780
19709
|
}
|
|
@@ -19782,7 +19711,7 @@ function readHead(path2) {
|
|
|
19782
19711
|
}
|
|
19783
19712
|
function fileBytes(path2) {
|
|
19784
19713
|
try {
|
|
19785
|
-
return (0,
|
|
19714
|
+
return (0, import_node_fs20.statSync)(path2).size;
|
|
19786
19715
|
} catch {
|
|
19787
19716
|
return void 0;
|
|
19788
19717
|
}
|
|
@@ -19796,13 +19725,13 @@ function readClaudeBinaryState(host = {}) {
|
|
|
19796
19725
|
const arch = host.arch ?? process.arch;
|
|
19797
19726
|
const magic = EXECUTABLE_MAGIC[platform2];
|
|
19798
19727
|
if (!magic) return void 0;
|
|
19799
|
-
const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path19.join)(root, ...PACKAGE.split("/"))).find((dir) => (0,
|
|
19728
|
+
const packageRoot = globalNodeModulesRoots(host).map((root) => (0, import_node_path19.join)(root, ...PACKAGE.split("/"))).find((dir) => (0, import_node_fs20.existsSync)((0, import_node_path19.join)(dir, "package.json")));
|
|
19800
19729
|
if (!packageRoot) return void 0;
|
|
19801
19730
|
const keys = platformPackageKeys(platform2, arch);
|
|
19802
19731
|
const fallbackPackage = `${PACKAGE}-${keys[0]}`;
|
|
19803
19732
|
let manifest;
|
|
19804
19733
|
try {
|
|
19805
|
-
manifest = JSON.parse((0,
|
|
19734
|
+
manifest = JSON.parse((0, import_node_fs20.readFileSync)((0, import_node_path19.join)(packageRoot, "package.json"), "utf8"));
|
|
19806
19735
|
} catch (e) {
|
|
19807
19736
|
return {
|
|
19808
19737
|
state: "unreadable",
|
|
@@ -19833,7 +19762,7 @@ function readClaudeBinaryState(host = {}) {
|
|
|
19833
19762
|
(0, import_node_path19.join)(packageRoot, "node_modules", ...name.split("/"), binName),
|
|
19834
19763
|
(0, import_node_path19.join)((0, import_node_path19.dirname)((0, import_node_path19.dirname)(packageRoot)), ...name.split("/"), binName)
|
|
19835
19764
|
];
|
|
19836
|
-
const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0,
|
|
19765
|
+
const found = published.map((name) => ({ name, path: binIn(name).find((file) => (0, import_node_fs20.existsSync)(file)) })).find((c) => c.path);
|
|
19837
19766
|
const platformPackage = found?.name ?? published[0];
|
|
19838
19767
|
let source;
|
|
19839
19768
|
let sourceProblem;
|
|
@@ -19844,7 +19773,7 @@ function readClaudeBinaryState(host = {}) {
|
|
|
19844
19773
|
} else {
|
|
19845
19774
|
source = { path: found.path, bytes: fileBytes(found.path) ?? 0 };
|
|
19846
19775
|
}
|
|
19847
|
-
if (!(0,
|
|
19776
|
+
if (!(0, import_node_fs20.existsSync)(binPath)) {
|
|
19848
19777
|
return { state: "missing", binPath, expectedMagic: magic.name, platformPackage, ...source ? { source } : {}, ...sourceProblem ? { sourceProblem } : {} };
|
|
19849
19778
|
}
|
|
19850
19779
|
const head = readHead(binPath);
|
|
@@ -19887,9 +19816,9 @@ function healClaudeBinary(host = {}, onStep) {
|
|
|
19887
19816
|
const platform2 = host.platform ?? process.platform;
|
|
19888
19817
|
const aside = `${probe.binPath}.stub-${Date.now()}`;
|
|
19889
19818
|
let renamed = false;
|
|
19890
|
-
if ((0,
|
|
19819
|
+
if ((0, import_node_fs20.existsSync)(probe.binPath)) {
|
|
19891
19820
|
try {
|
|
19892
|
-
(0,
|
|
19821
|
+
(0, import_node_fs20.renameSync)(probe.binPath, aside);
|
|
19893
19822
|
renamed = true;
|
|
19894
19823
|
onStep?.(`renamed the stub aside: ${aside}`);
|
|
19895
19824
|
} catch (e) {
|
|
@@ -19898,12 +19827,12 @@ function healClaudeBinary(host = {}, onStep) {
|
|
|
19898
19827
|
}
|
|
19899
19828
|
try {
|
|
19900
19829
|
onStep?.(`copying ${probe.source.path} \u2192 ${probe.binPath} (${(probe.source.bytes / 1e6).toFixed(0)} MB)`);
|
|
19901
|
-
(0,
|
|
19902
|
-
if (platform2 !== "win32") (0,
|
|
19830
|
+
(0, import_node_fs20.copyFileSync)(probe.source.path, probe.binPath);
|
|
19831
|
+
if (platform2 !== "win32") (0, import_node_fs20.chmodSync)(probe.binPath, 493);
|
|
19903
19832
|
} catch (e) {
|
|
19904
19833
|
if (renamed) {
|
|
19905
19834
|
try {
|
|
19906
|
-
(0,
|
|
19835
|
+
(0, import_node_fs20.renameSync)(aside, probe.binPath);
|
|
19907
19836
|
} catch {
|
|
19908
19837
|
return { ok: false, detail: `copy failed (${e.message}) and the stub could not be restored \u2014 the original is at ${aside}` };
|
|
19909
19838
|
}
|
|
@@ -19917,7 +19846,7 @@ function healClaudeBinary(host = {}, onStep) {
|
|
|
19917
19846
|
let kept = false;
|
|
19918
19847
|
if (renamed) {
|
|
19919
19848
|
try {
|
|
19920
|
-
(0,
|
|
19849
|
+
(0, import_node_fs20.rmSync)(aside);
|
|
19921
19850
|
} catch {
|
|
19922
19851
|
kept = true;
|
|
19923
19852
|
}
|
|
@@ -20276,7 +20205,7 @@ function checkLineEndings(probe) {
|
|
|
20276
20205
|
}
|
|
20277
20206
|
|
|
20278
20207
|
// src/release-ledger.ts
|
|
20279
|
-
var
|
|
20208
|
+
var import_node_fs21 = require("node:fs");
|
|
20280
20209
|
var import_node_path21 = require("node:path");
|
|
20281
20210
|
var import_node_crypto5 = require("node:crypto");
|
|
20282
20211
|
|
|
@@ -20533,7 +20462,7 @@ function resolvePrimaryGitDir(cwd) {
|
|
|
20533
20462
|
}
|
|
20534
20463
|
let common;
|
|
20535
20464
|
try {
|
|
20536
|
-
common = (0,
|
|
20465
|
+
common = (0, import_node_fs21.readFileSync)((0, import_node_path21.join)(gitDir, "commondir"), "utf8").trim();
|
|
20537
20466
|
} catch (e) {
|
|
20538
20467
|
if (e.code !== "ENOENT") {
|
|
20539
20468
|
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)`);
|
|
@@ -20542,7 +20471,7 @@ function resolvePrimaryGitDir(cwd) {
|
|
|
20542
20471
|
if (!common) return gitDir;
|
|
20543
20472
|
const commonDir = (0, import_node_path21.isAbsolute)(common) ? common : (0, import_node_path21.resolve)(gitDir, common);
|
|
20544
20473
|
try {
|
|
20545
|
-
(0,
|
|
20474
|
+
(0, import_node_fs21.readFileSync)((0, import_node_path21.join)(commonDir, "HEAD"), "utf8");
|
|
20546
20475
|
} catch (e) {
|
|
20547
20476
|
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`);
|
|
20548
20477
|
}
|
|
@@ -20552,18 +20481,18 @@ function releaseLedgerPath(cwd) {
|
|
|
20552
20481
|
return (0, import_node_path21.join)(resolvePrimaryGitDir(cwd), "mmi-runtime", "release", "phases.json");
|
|
20553
20482
|
}
|
|
20554
20483
|
function atomicWriteJson(path2, ledger) {
|
|
20555
|
-
(0,
|
|
20484
|
+
(0, import_node_fs21.mkdirSync)((0, import_node_path21.dirname)(path2), { recursive: true });
|
|
20556
20485
|
const tmp = `${path2}.tmp-${process.pid}-${(0, import_node_crypto5.randomBytes)(4).toString("hex")}`;
|
|
20557
|
-
(0,
|
|
20486
|
+
(0, import_node_fs21.writeFileSync)(tmp, `${JSON.stringify(ledger, null, 2)}
|
|
20558
20487
|
`, "utf8");
|
|
20559
|
-
(0,
|
|
20488
|
+
(0, import_node_fs21.renameSync)(tmp, path2);
|
|
20560
20489
|
}
|
|
20561
20490
|
async function withReleaseLedger(path2, expected, fn, opts = {}) {
|
|
20562
20491
|
return withFileLock(`${path2}.lock`, { label: "release ledger", maxWaitMs: opts.maxWaitMs ?? 5e3 }, async () => {
|
|
20563
20492
|
let current;
|
|
20564
20493
|
let raw;
|
|
20565
20494
|
try {
|
|
20566
|
-
raw = (0,
|
|
20495
|
+
raw = (0, import_node_fs21.readFileSync)(path2, "utf8");
|
|
20567
20496
|
} catch (e) {
|
|
20568
20497
|
if (e.code !== "ENOENT") {
|
|
20569
20498
|
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)`);
|
|
@@ -21197,7 +21126,7 @@ async function clearLedgerFile(path2, anchors, maxWaitMs) {
|
|
|
21197
21126
|
return withFileLock(`${path2}.lock`, { label: "release ledger", maxWaitMs }, async () => {
|
|
21198
21127
|
let raw;
|
|
21199
21128
|
try {
|
|
21200
|
-
raw = (0,
|
|
21129
|
+
raw = (0, import_node_fs21.readFileSync)(path2, "utf8");
|
|
21201
21130
|
} catch (e) {
|
|
21202
21131
|
if (e.code === "ENOENT") return { cleared: false };
|
|
21203
21132
|
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` };
|
|
@@ -21213,7 +21142,7 @@ async function clearLedgerFile(path2, anchors, maxWaitMs) {
|
|
|
21213
21142
|
} catch (e) {
|
|
21214
21143
|
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)})` };
|
|
21215
21144
|
}
|
|
21216
|
-
(0,
|
|
21145
|
+
(0, import_node_fs21.unlinkSync)(path2);
|
|
21217
21146
|
return { cleared: true, note: `cleared the release ledger at ${path2} for the live-proven aborted ${anchors.tag}` };
|
|
21218
21147
|
});
|
|
21219
21148
|
}
|
|
@@ -21316,7 +21245,7 @@ async function healStaleAlignmentLeg(deps, cwd, expected) {
|
|
|
21316
21245
|
return withFileLock(`${path2}.lock`, { label: "release ledger" }, async () => {
|
|
21317
21246
|
let prior;
|
|
21318
21247
|
try {
|
|
21319
|
-
prior = parseReleaseLedger((0,
|
|
21248
|
+
prior = parseReleaseLedger((0, import_node_fs21.readFileSync)(path2, "utf8"));
|
|
21320
21249
|
} catch {
|
|
21321
21250
|
return void 0;
|
|
21322
21251
|
}
|
|
@@ -21336,7 +21265,7 @@ async function healStaleAlignmentLeg(deps, cwd, expected) {
|
|
|
21336
21265
|
async function reverifyPriorRunLegs(deps, path2, targetTag) {
|
|
21337
21266
|
let prior;
|
|
21338
21267
|
try {
|
|
21339
|
-
prior = parseReleaseLedger((0,
|
|
21268
|
+
prior = parseReleaseLedger((0, import_node_fs21.readFileSync)(path2, "utf8"));
|
|
21340
21269
|
} catch {
|
|
21341
21270
|
return;
|
|
21342
21271
|
}
|
|
@@ -21356,7 +21285,7 @@ async function beginReleaseLedger(deps, cwd, targetTag) {
|
|
|
21356
21285
|
return withFileLock(`${path2}.lock`, { label: "release ledger" }, async () => {
|
|
21357
21286
|
let raw;
|
|
21358
21287
|
try {
|
|
21359
|
-
raw = (0,
|
|
21288
|
+
raw = (0, import_node_fs21.readFileSync)(path2, "utf8");
|
|
21360
21289
|
} catch (e) {
|
|
21361
21290
|
if (e.code === "ENOENT") return { ok: true };
|
|
21362
21291
|
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)` };
|
|
@@ -21395,13 +21324,13 @@ async function beginReleaseLedger(deps, cwd, targetTag) {
|
|
|
21395
21324
|
}
|
|
21396
21325
|
const archivePath = (0, import_node_path21.join)((0, import_node_path21.dirname)(path2), `phases.archive-${prior.tag}.json`);
|
|
21397
21326
|
try {
|
|
21398
|
-
(0,
|
|
21327
|
+
(0, import_node_fs21.unlinkSync)(archivePath);
|
|
21399
21328
|
} catch (e) {
|
|
21400
21329
|
if (e.code !== "ENOENT") {
|
|
21401
21330
|
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)` };
|
|
21402
21331
|
}
|
|
21403
21332
|
}
|
|
21404
|
-
(0,
|
|
21333
|
+
(0, import_node_fs21.renameSync)(path2, archivePath);
|
|
21405
21334
|
return { ok: true, note: `archived the completed release ledger ${prior.tag} to ${archivePath} (live-proven at ${prior.tagSha.slice(0, 12)})` };
|
|
21406
21335
|
});
|
|
21407
21336
|
}
|
|
@@ -21498,10 +21427,10 @@ function readOriginWorkflowsDefault(root, ref) {
|
|
|
21498
21427
|
}
|
|
21499
21428
|
var NPM_REGISTRY = "https://registry.npmjs.org";
|
|
21500
21429
|
async function probeRegistryWhoami(train) {
|
|
21501
|
-
const dir = (0,
|
|
21430
|
+
const dir = (0, import_node_fs22.mkdtempSync)((0, import_node_path22.join)((0, import_node_os13.tmpdir)(), "mmi-npmrc-"));
|
|
21502
21431
|
const rc = (0, import_node_path22.join)(dir, "npmrc");
|
|
21503
21432
|
try {
|
|
21504
|
-
(0,
|
|
21433
|
+
(0, import_node_fs22.writeFileSync)(rc, "//registry.npmjs.org/:_authToken=${NPM_TOKEN}\n");
|
|
21505
21434
|
await train.runSelf(["secrets", "use", "npm/NPM_TOKEN", "--slug", "_org", "--", "npm", "whoami", "--registry", NPM_REGISTRY, "--userconfig", rc]);
|
|
21506
21435
|
return { kind: "ok", detail: "the registry answered a login" };
|
|
21507
21436
|
} catch (e) {
|
|
@@ -21512,7 +21441,7 @@ async function probeRegistryWhoami(train) {
|
|
|
21512
21441
|
if (/\bE401\b|401 Unauthorized/.test(stderr)) return { kind: "rejected", detail: "npm whoami answered 401 Unauthorized" };
|
|
21513
21442
|
return { kind: "unverified", detail: first };
|
|
21514
21443
|
} finally {
|
|
21515
|
-
(0,
|
|
21444
|
+
(0, import_node_fs22.rmSync)(dir, { recursive: true, force: true });
|
|
21516
21445
|
}
|
|
21517
21446
|
}
|
|
21518
21447
|
var REGISTRY_TOKEN_ENV = /\b(NODE_AUTH_TOKEN|NPM_TOKEN)\b/;
|
|
@@ -21530,7 +21459,7 @@ var defaultDeps2 = {
|
|
|
21530
21459
|
ledgerPath: releaseLedgerPath,
|
|
21531
21460
|
readLedgerRaw: (path2) => {
|
|
21532
21461
|
try {
|
|
21533
|
-
return (0,
|
|
21462
|
+
return (0, import_node_fs22.readFileSync)(path2, "utf8");
|
|
21534
21463
|
} catch (e) {
|
|
21535
21464
|
if (e.code === "ENOENT") return void 0;
|
|
21536
21465
|
throw e;
|
|
@@ -21539,7 +21468,7 @@ var defaultDeps2 = {
|
|
|
21539
21468
|
healAlignmentLeg: healStaleAlignmentLeg,
|
|
21540
21469
|
readSurfacesRaw: (cwd) => {
|
|
21541
21470
|
try {
|
|
21542
|
-
return (0,
|
|
21471
|
+
return (0, import_node_fs22.readFileSync)((0, import_node_path22.join)(cwd, "surfaces.json"), "utf8");
|
|
21543
21472
|
} catch {
|
|
21544
21473
|
return void 0;
|
|
21545
21474
|
}
|
|
@@ -22029,14 +21958,14 @@ function readLocalGateWorkflows() {
|
|
|
22029
21958
|
const dir = (0, import_node_path23.join)(".github", "workflows");
|
|
22030
21959
|
let names;
|
|
22031
21960
|
try {
|
|
22032
|
-
names = (0,
|
|
21961
|
+
names = (0, import_node_fs23.readdirSync)(dir);
|
|
22033
21962
|
} catch {
|
|
22034
21963
|
return null;
|
|
22035
21964
|
}
|
|
22036
21965
|
const files = [];
|
|
22037
21966
|
for (const name of names.filter(isGateWorkflowPath)) {
|
|
22038
21967
|
try {
|
|
22039
|
-
files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0,
|
|
21968
|
+
files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs23.readFileSync)((0, import_node_path23.join)(dir, name), "utf8") });
|
|
22040
21969
|
} catch {
|
|
22041
21970
|
}
|
|
22042
21971
|
}
|
|
@@ -22046,14 +21975,14 @@ function readLocalWorkflows() {
|
|
|
22046
21975
|
const dir = (0, import_node_path23.join)(".github", "workflows");
|
|
22047
21976
|
let names;
|
|
22048
21977
|
try {
|
|
22049
|
-
names = (0,
|
|
21978
|
+
names = (0, import_node_fs23.readdirSync)(dir);
|
|
22050
21979
|
} catch {
|
|
22051
21980
|
return null;
|
|
22052
21981
|
}
|
|
22053
21982
|
const files = [];
|
|
22054
21983
|
for (const name of names.filter((n) => /\.ya?ml$/i.test(n))) {
|
|
22055
21984
|
try {
|
|
22056
|
-
files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0,
|
|
21985
|
+
files.push({ path: `${dir}/${name}`.replace(/\\/g, "/"), body: (0, import_node_fs23.readFileSync)((0, import_node_path23.join)(dir, name), "utf8") });
|
|
22057
21986
|
} catch {
|
|
22058
21987
|
}
|
|
22059
21988
|
}
|
|
@@ -22823,7 +22752,7 @@ async function activeRcandLedgerCandidate(deps, cwd) {
|
|
|
22823
22752
|
}
|
|
22824
22753
|
let prior;
|
|
22825
22754
|
try {
|
|
22826
|
-
prior = parseReleaseLedger((0,
|
|
22755
|
+
prior = parseReleaseLedger((0, import_node_fs23.readFileSync)(path2, "utf8"));
|
|
22827
22756
|
} catch {
|
|
22828
22757
|
return void 0;
|
|
22829
22758
|
}
|
|
@@ -25874,22 +25803,6 @@ async function loadConfigForBoardSelector2(selector, repoOption) {
|
|
|
25874
25803
|
return loadConfigForRepo(repoFromSelector(selector) ?? repoOption);
|
|
25875
25804
|
}
|
|
25876
25805
|
|
|
25877
|
-
// src/statusline-invalidate.ts
|
|
25878
|
-
var import_node_child_process10 = require("node:child_process");
|
|
25879
|
-
function invalidateStatuslineBoardCache() {
|
|
25880
|
-
try {
|
|
25881
|
-
const child2 = (0, import_node_child_process10.spawn)("jerv-cli", ["lane", "ops", "invalidate-board"], {
|
|
25882
|
-
detached: true,
|
|
25883
|
-
stdio: "ignore",
|
|
25884
|
-
windowsHide: true
|
|
25885
|
-
});
|
|
25886
|
-
child2.on("error", () => {
|
|
25887
|
-
});
|
|
25888
|
-
child2.unref();
|
|
25889
|
-
} catch {
|
|
25890
|
-
}
|
|
25891
|
-
}
|
|
25892
|
-
|
|
25893
25806
|
// src/board-commands.ts
|
|
25894
25807
|
function refuseRateLimited(e, json) {
|
|
25895
25808
|
if (!isRateLimitedError(e)) return false;
|
|
@@ -25990,7 +25903,6 @@ function registerBoardCommands(program3) {
|
|
|
25990
25903
|
check: o.check,
|
|
25991
25904
|
allowPartial: o.allowPartial
|
|
25992
25905
|
}, { snapshot: registryClientDeps(config) });
|
|
25993
|
-
if (!result.checked) invalidateStatuslineBoardCache();
|
|
25994
25906
|
if (o.json) return console.log(JSON.stringify(result));
|
|
25995
25907
|
console.log(claimVerdict(result.item.ref, result));
|
|
25996
25908
|
printClaimWarnings(result.warnings);
|
|
@@ -26012,7 +25924,6 @@ function registerBoardCommands(program3) {
|
|
|
26012
25924
|
check: o.check,
|
|
26013
25925
|
allowPartial: o.allowPartial
|
|
26014
25926
|
}, { snapshot: registryClientDeps(config) });
|
|
26015
|
-
if (bulk.results.some((r) => r.claimed && !r.checked)) invalidateStatuslineBoardCache();
|
|
26016
25927
|
if (o.json) {
|
|
26017
25928
|
console.log(JSON.stringify(bulk.results));
|
|
26018
25929
|
printClaimWarnings(bulk.warnings, true);
|
|
@@ -26068,7 +25979,6 @@ function registerBoardCommands(program3) {
|
|
|
26068
25979
|
repo: o.repo,
|
|
26069
25980
|
allowPartial: o.allowPartial
|
|
26070
25981
|
});
|
|
26071
|
-
if (bulk.results.some((r) => r.moved)) invalidateStatuslineBoardCache();
|
|
26072
25982
|
if (o.json) {
|
|
26073
25983
|
console.log(JSON.stringify(bulk.results));
|
|
26074
25984
|
} else {
|
|
@@ -26093,7 +26003,6 @@ function registerBoardCommands(program3) {
|
|
|
26093
26003
|
if (issueRefs.length === 1) {
|
|
26094
26004
|
try {
|
|
26095
26005
|
const result = await moveBoardItem({ config: await loadConfigForBoardSelector2(issueRefs[0], o.repo), selector: issueRefs[0], status: canonicalStatus, repo: o.repo, allowPartial: o.allowPartial });
|
|
26096
|
-
invalidateStatuslineBoardCache();
|
|
26097
26006
|
if (o.json) return console.log(JSON.stringify(result));
|
|
26098
26007
|
console.log(result.archived ? `Already terminal ${result.item.ref}: ${result.warning}` : result.partial ? `Partially moved ${result.item.ref}: ${result.warning}` : `Moved ${result.item.ref} -> ${result.status}`);
|
|
26099
26008
|
} catch (e) {
|
|
@@ -26145,7 +26054,6 @@ function registerBoardCommands(program3) {
|
|
|
26145
26054
|
force: o.force,
|
|
26146
26055
|
allowPartial: o.allowPartial
|
|
26147
26056
|
});
|
|
26148
|
-
invalidateStatuslineBoardCache();
|
|
26149
26057
|
if (o.json) return console.log(JSON.stringify(result));
|
|
26150
26058
|
console.log(result.partial ? `Partially unclaimed ${result.item.ref}: ${result.warning}` : `Unclaimed ${result.item.ref} -> ${result.status}`);
|
|
26151
26059
|
} catch (e) {
|
|
@@ -26159,7 +26067,6 @@ function registerBoardCommands(program3) {
|
|
|
26159
26067
|
repo: o.repo,
|
|
26160
26068
|
apply: o.apply
|
|
26161
26069
|
});
|
|
26162
|
-
if (result.archived.length) invalidateStatuslineBoardCache();
|
|
26163
26070
|
if (o.json) return console.log(JSON.stringify(result));
|
|
26164
26071
|
console.log(o.apply ? `board archive-done: archived ${result.archived.length}/${result.candidates.length}, failed ${result.failures.length}` : `board archive-done: would archive ${result.candidates.length} closed Done cards (scanned ${result.scanned}; pass --apply to write)`);
|
|
26165
26072
|
if (result.failures.length) process.exitCode = 1;
|
|
@@ -26195,7 +26102,7 @@ function registerBoardCommands(program3) {
|
|
|
26195
26102
|
}
|
|
26196
26103
|
|
|
26197
26104
|
// src/bootstrap-commands.ts
|
|
26198
|
-
var
|
|
26105
|
+
var import_node_fs25 = require("node:fs");
|
|
26199
26106
|
var import_node_os14 = require("node:os");
|
|
26200
26107
|
var import_node_path25 = require("node:path");
|
|
26201
26108
|
|
|
@@ -26362,7 +26269,7 @@ function renderSteps(title, steps) {
|
|
|
26362
26269
|
}
|
|
26363
26270
|
|
|
26364
26271
|
// src/port-registry.ts
|
|
26365
|
-
var
|
|
26272
|
+
var import_node_fs24 = require("node:fs");
|
|
26366
26273
|
var import_node_path24 = require("node:path");
|
|
26367
26274
|
|
|
26368
26275
|
// ../infra/port-geometry.mjs
|
|
@@ -26377,8 +26284,8 @@ function nextPortBlock(registry2) {
|
|
|
26377
26284
|
return [base, base + PORT_SPAN];
|
|
26378
26285
|
}
|
|
26379
26286
|
function loadPortRegistry(path2) {
|
|
26380
|
-
if (!(0,
|
|
26381
|
-
const raw = JSON.parse((0,
|
|
26287
|
+
if (!(0, import_node_fs24.existsSync)(path2)) return {};
|
|
26288
|
+
const raw = JSON.parse((0, import_node_fs24.readFileSync)(path2, "utf8"));
|
|
26382
26289
|
const out = {};
|
|
26383
26290
|
for (const [key, value] of Object.entries(raw)) {
|
|
26384
26291
|
if (Array.isArray(value) && value.length === 2 && value.every((n) => typeof n === "number")) {
|
|
@@ -26392,9 +26299,9 @@ function ensurePortRange(repo, path2) {
|
|
|
26392
26299
|
const existing = registry2[repo];
|
|
26393
26300
|
if (existing) return existing;
|
|
26394
26301
|
const range = nextPortBlock(registry2);
|
|
26395
|
-
const raw = (0,
|
|
26302
|
+
const raw = (0, import_node_fs24.existsSync)(path2) ? JSON.parse((0, import_node_fs24.readFileSync)(path2, "utf8")) : {};
|
|
26396
26303
|
raw[repo] = range;
|
|
26397
|
-
(0,
|
|
26304
|
+
(0, import_node_fs24.writeFileSync)(path2, JSON.stringify(raw, null, 2) + "\n", "utf8");
|
|
26398
26305
|
return range;
|
|
26399
26306
|
}
|
|
26400
26307
|
function portCursorSeed(registry2) {
|
|
@@ -26418,7 +26325,7 @@ function existingPortRange(repo, registry2) {
|
|
|
26418
26325
|
function portRangeInfraAt(root, source) {
|
|
26419
26326
|
const registryPath = (0, import_node_path24.join)(root, "infra", "port-ranges.json");
|
|
26420
26327
|
const ddbScriptPath = (0, import_node_path24.join)(root, "infra", "port-ddb.mjs");
|
|
26421
|
-
if (!(0,
|
|
26328
|
+
if (!(0, import_node_fs24.existsSync)(registryPath) || !(0, import_node_fs24.existsSync)(ddbScriptPath)) return null;
|
|
26422
26329
|
return { root, source, registryPath, ddbScriptPath };
|
|
26423
26330
|
}
|
|
26424
26331
|
function resolvePortRangeInfra(cwd, packageDir) {
|
|
@@ -27900,13 +27807,13 @@ function registerBootstrapCommands(program3) {
|
|
|
27900
27807
|
deployFactsRead: deployFacts !== null,
|
|
27901
27808
|
pushAllowlistOwners: verifyOwners,
|
|
27902
27809
|
pushAllowlistOwnersRead: verifyOwnersRead,
|
|
27903
|
-
readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0,
|
|
27810
|
+
readLocalFile: (path2) => path2 === "projects.json" && apiProjects != null ? apiProjects : (0, import_node_fs25.existsSync)(path2) ? (0, import_node_fs25.readFileSync)(path2, "utf8") : null,
|
|
27904
27811
|
// requiredGcpApis is stored as an array by a JSON write, but `org project set --var KEY=VALUE` stores a raw
|
|
27905
27812
|
// comma-string — accept either so the seeded value verifies regardless of how it was written.
|
|
27906
27813
|
// #3689: the same committed map the org access audit reads (#3664), so a sanctioned admin is not a
|
|
27907
27814
|
// permanent bootstrap failure on one surface and an intended state on the other. Absent file → no
|
|
27908
27815
|
// sanction, which is the pre-#3664 behaviour.
|
|
27909
|
-
sanctionedAdmins: (0,
|
|
27816
|
+
sanctionedAdmins: (0, import_node_fs25.existsSync)("access-matrix.json") ? entriesValueByCanonicalRepo(loadSanctionedAdmins((0, import_node_fs25.readFileSync)("access-matrix.json", "utf8")), repo) : void 0,
|
|
27910
27817
|
requiredGcpApis: (() => {
|
|
27911
27818
|
const v = meta?.requiredGcpApis;
|
|
27912
27819
|
if (Array.isArray(v)) return v;
|
|
@@ -27984,14 +27891,14 @@ function registerBootstrapCommands(program3) {
|
|
|
27984
27891
|
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 () => {
|
|
27985
27892
|
const o = { repo: rawValue("--repo", ""), json: rawFlag("--json") };
|
|
27986
27893
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
27987
|
-
if (!(0,
|
|
27894
|
+
if (!(0, import_node_fs25.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`);
|
|
27988
27895
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
27989
27896
|
if (!seedSource.ok) return fail(`bootstrap drift: ${seedSource.reason}`);
|
|
27990
|
-
const manifest = loadBootstrapSeeds((0,
|
|
27897
|
+
const manifest = loadBootstrapSeeds((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
|
|
27991
27898
|
const hubContents = /* @__PURE__ */ new Map();
|
|
27992
27899
|
for (const s of manifest.seeds) {
|
|
27993
27900
|
if (s.ownership !== "org" || s.source !== "self") continue;
|
|
27994
|
-
hubContents.set(s.target, (0,
|
|
27901
|
+
hubContents.set(s.target, (0, import_node_fs25.existsSync)(s.target) ? (0, import_node_fs25.readFileSync)(s.target, "utf8") : null);
|
|
27995
27902
|
}
|
|
27996
27903
|
let targets;
|
|
27997
27904
|
let classOf = (_repo) => "deployable";
|
|
@@ -28154,10 +28061,10 @@ function registerBootstrapCommands(program3) {
|
|
|
28154
28061
|
return;
|
|
28155
28062
|
}
|
|
28156
28063
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
28157
|
-
if (!(0,
|
|
28064
|
+
if (!(0, import_node_fs25.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`);
|
|
28158
28065
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
28159
28066
|
if (!seedSource.ok) return fail(`bootstrap apply: ${seedSource.reason}`);
|
|
28160
|
-
const manifest = loadBootstrapSeeds((0,
|
|
28067
|
+
const manifest = loadBootstrapSeeds((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
|
|
28161
28068
|
const baseBranch = o.class === "content" ? "main" : "development";
|
|
28162
28069
|
const slug = parsedRepo.slug;
|
|
28163
28070
|
const onlyTarget = o.only.trim();
|
|
@@ -28169,16 +28076,16 @@ function registerBootstrapCommands(program3) {
|
|
|
28169
28076
|
}
|
|
28170
28077
|
const onlyManagedBlock = onlyTarget ? seedsToApply[0]?.managedBlock != null : false;
|
|
28171
28078
|
const gh = async (args) => execFileP("gh", args, { timeout: 2e4 });
|
|
28172
|
-
const readFile9 = (p) => (0,
|
|
28079
|
+
const readFile9 = (p) => (0, import_node_fs25.existsSync)(p) ? (0, import_node_fs25.readFileSync)(p, "utf8") : null;
|
|
28173
28080
|
const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
|
|
28174
28081
|
const putSeed = async (target, content, ref, sha) => {
|
|
28175
28082
|
const tmp = (0, import_node_path25.join)((0, import_node_os14.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
|
|
28176
|
-
(0,
|
|
28083
|
+
(0, import_node_fs25.writeFileSync)(tmp, JSON.stringify(contentPutBody(target, content, ref, sha)), "utf8");
|
|
28177
28084
|
try {
|
|
28178
28085
|
await gh(contentPutInputArgs(repo, target, tmp));
|
|
28179
28086
|
} finally {
|
|
28180
28087
|
try {
|
|
28181
|
-
(0,
|
|
28088
|
+
(0, import_node_fs25.unlinkSync)(tmp);
|
|
28182
28089
|
} catch {
|
|
28183
28090
|
}
|
|
28184
28091
|
}
|
|
@@ -28627,10 +28534,10 @@ LIVE apply to ${repo}:
|
|
|
28627
28534
|
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 () => {
|
|
28628
28535
|
const o = { target: rawValue("--target", ""), execute: rawFlag("--execute"), json: rawFlag("--json") };
|
|
28629
28536
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
28630
|
-
if (!(0,
|
|
28537
|
+
if (!(0, import_node_fs25.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`);
|
|
28631
28538
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
28632
28539
|
if (!seedSource.ok) return fail(`bootstrap propagate: ${seedSource.reason}`);
|
|
28633
|
-
const manifest = loadBootstrapSeeds((0,
|
|
28540
|
+
const manifest = loadBootstrapSeeds((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
|
|
28634
28541
|
const propagatable = manifest.seeds.filter(isPropagatableSeed);
|
|
28635
28542
|
if (!o.target) {
|
|
28636
28543
|
return fail(`bootstrap propagate: --target <path> is required \u2014 one of:
|
|
@@ -28639,9 +28546,9 @@ LIVE apply to ${repo}:
|
|
|
28639
28546
|
const seed = propagatable.find((s) => s.target === o.target);
|
|
28640
28547
|
if (!seed) return fail(`bootstrap propagate: --target '${o.target}' names no centrally propagatable seed in ${manifestPath}. Propagatable targets:
|
|
28641
28548
|
${propagatable.map((s) => s.target).join("\n ")}`);
|
|
28642
|
-
if (!seed.managedBlock && !(0,
|
|
28643
|
-
const hubContent = seed.managedBlock ? null : (0,
|
|
28644
|
-
const readSeedFile2 = (path2) => (0,
|
|
28549
|
+
if (!seed.managedBlock && !(0, import_node_fs25.existsSync)(seed.target)) return fail(`bootstrap propagate: the Hub's own copy of '${seed.target}' is missing \u2014 nothing to propagate`);
|
|
28550
|
+
const hubContent = seed.managedBlock ? null : (0, import_node_fs25.readFileSync)(seed.target, "utf8");
|
|
28551
|
+
const readSeedFile2 = (path2) => (0, import_node_fs25.existsSync)(path2) ? (0, import_node_fs25.readFileSync)(path2, "utf8") : null;
|
|
28645
28552
|
const isWorkflowSeed = seed.target.startsWith(".github/workflows/");
|
|
28646
28553
|
const cfg = await loadConfig();
|
|
28647
28554
|
const projects = await fetchProjectsList(registryClientDeps(cfg));
|
|
@@ -28650,9 +28557,9 @@ LIVE apply to ${repo}:
|
|
|
28650
28557
|
}
|
|
28651
28558
|
const rosterRepos = collectRegistryRepos(projects).filter((r) => r.toLowerCase() !== "mutmutco/mmi-hub");
|
|
28652
28559
|
let independentCount = rosterRepos.length;
|
|
28653
|
-
if ((0,
|
|
28560
|
+
if ((0, import_node_fs25.existsSync)("projects.json")) {
|
|
28654
28561
|
try {
|
|
28655
|
-
const local = JSON.parse((0,
|
|
28562
|
+
const local = JSON.parse((0, import_node_fs25.readFileSync)("projects.json", "utf8"));
|
|
28656
28563
|
const localRepos = /* @__PURE__ */ new Set();
|
|
28657
28564
|
for (const p of local.projects ?? []) for (const r of p.repos ?? []) {
|
|
28658
28565
|
const full = (r.includes("/") ? r : `mutmutco/${r}`).toLowerCase();
|
|
@@ -28816,12 +28723,12 @@ LIVE apply to ${repo}:
|
|
|
28816
28723
|
const tmp = (0, import_node_path25.join)((0, import_node_os14.tmpdir)(), `mmi-propagate-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
|
|
28817
28724
|
const desiredContent = desiredByRepo.get(rec.repo);
|
|
28818
28725
|
if (desiredContent == null) return fail(`bootstrap propagate: no resolved content for ${rec.repo} ${seed.target} \u2014 refusing to write`);
|
|
28819
|
-
(0,
|
|
28726
|
+
(0, import_node_fs25.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, desiredContent, branch, existingSha)), "utf8");
|
|
28820
28727
|
try {
|
|
28821
28728
|
await gh(contentPutInputArgs(rec.repo, seed.target, tmp));
|
|
28822
28729
|
} finally {
|
|
28823
28730
|
try {
|
|
28824
|
-
(0,
|
|
28731
|
+
(0, import_node_fs25.unlinkSync)(tmp);
|
|
28825
28732
|
} catch {
|
|
28826
28733
|
}
|
|
28827
28734
|
}
|
|
@@ -28888,10 +28795,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
|
|
|
28888
28795
|
return fail(`bootstrap rollback: ${e.message}`);
|
|
28889
28796
|
}
|
|
28890
28797
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
28891
|
-
if (!(0,
|
|
28798
|
+
if (!(0, import_node_fs25.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)`);
|
|
28892
28799
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
28893
28800
|
if (!seedSource.ok) return fail(`bootstrap rollback: ${seedSource.reason}`);
|
|
28894
|
-
const manifest = loadBootstrapSeeds((0,
|
|
28801
|
+
const manifest = loadBootstrapSeeds((0, import_node_fs25.readFileSync)(manifestPath, "utf8"));
|
|
28895
28802
|
const propagatable = manifest.seeds.filter(isPropagatableSeed);
|
|
28896
28803
|
if (!o.target) {
|
|
28897
28804
|
return fail(`bootstrap rollback: --target <path> is required \u2014 one of:
|
|
@@ -28908,10 +28815,10 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
|
|
|
28908
28815
|
const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
|
|
28909
28816
|
let candidates;
|
|
28910
28817
|
if (o.record) {
|
|
28911
|
-
if (!(0,
|
|
28818
|
+
if (!(0, import_node_fs25.existsSync)(o.record)) return fail(`bootstrap rollback: --record '${o.record}' not found`);
|
|
28912
28819
|
let parsed;
|
|
28913
28820
|
try {
|
|
28914
|
-
parsed = JSON.parse((0,
|
|
28821
|
+
parsed = JSON.parse((0, import_node_fs25.readFileSync)(o.record, "utf8"));
|
|
28915
28822
|
} catch (e) {
|
|
28916
28823
|
return fail(`bootstrap rollback: --record '${o.record}' is not valid JSON: ${e.message}`);
|
|
28917
28824
|
}
|
|
@@ -28989,12 +28896,12 @@ Rollback: \`mmi-cli devops bootstrap rollback ${rec.repo} --target ${seed.target
|
|
|
28989
28896
|
existingSha = void 0;
|
|
28990
28897
|
}
|
|
28991
28898
|
const tmp = (0, import_node_path25.join)((0, import_node_os14.tmpdir)(), `mmi-rollback-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
|
|
28992
|
-
(0,
|
|
28899
|
+
(0, import_node_fs25.writeFileSync)(tmp, JSON.stringify(contentPutBody(seed.target, preSeedContent, plan.branch, existingSha)), "utf8");
|
|
28993
28900
|
try {
|
|
28994
28901
|
await gh(contentPutInputArgs(repo, seed.target, tmp));
|
|
28995
28902
|
} finally {
|
|
28996
28903
|
try {
|
|
28997
|
-
(0,
|
|
28904
|
+
(0, import_node_fs25.unlinkSync)(tmp);
|
|
28998
28905
|
} catch {
|
|
28999
28906
|
}
|
|
29000
28907
|
}
|
|
@@ -30008,7 +29915,7 @@ function renderDeployPortDoctor(report) {
|
|
|
30008
29915
|
}
|
|
30009
29916
|
|
|
30010
29917
|
// src/wave-status.ts
|
|
30011
|
-
var
|
|
29918
|
+
var import_node_fs28 = require("node:fs");
|
|
30012
29919
|
|
|
30013
29920
|
// src/git-worktree-observation.ts
|
|
30014
29921
|
function parseGitWorktreePorcelain(text) {
|
|
@@ -30038,8 +29945,8 @@ function deriveComposeProjectName(worktreePath) {
|
|
|
30038
29945
|
}
|
|
30039
29946
|
|
|
30040
29947
|
// src/stage-runner.ts
|
|
30041
|
-
var
|
|
30042
|
-
var
|
|
29948
|
+
var import_node_child_process10 = require("node:child_process");
|
|
29949
|
+
var import_node_fs27 = require("node:fs");
|
|
30043
29950
|
var import_node_path27 = require("node:path");
|
|
30044
29951
|
var import_node_net = require("node:net");
|
|
30045
29952
|
var import_node_util5 = require("node:util");
|
|
@@ -30050,7 +29957,7 @@ function normalizeEol2(s) {
|
|
|
30050
29957
|
}
|
|
30051
29958
|
|
|
30052
29959
|
// src/env-detection.ts
|
|
30053
|
-
var
|
|
29960
|
+
var import_node_fs26 = require("node:fs");
|
|
30054
29961
|
var import_node_path26 = require("node:path");
|
|
30055
29962
|
var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".jerv", ".pi", ".venv", "venv"]);
|
|
30056
29963
|
function isEnvBaseName(name) {
|
|
@@ -30061,7 +29968,7 @@ function findEnvFiles(root) {
|
|
|
30061
29968
|
const walk2 = (dir, rel) => {
|
|
30062
29969
|
let entries;
|
|
30063
29970
|
try {
|
|
30064
|
-
entries = (0,
|
|
29971
|
+
entries = (0, import_node_fs26.readdirSync)(dir, { withFileTypes: true });
|
|
30065
29972
|
} catch {
|
|
30066
29973
|
return;
|
|
30067
29974
|
}
|
|
@@ -30075,7 +29982,7 @@ function findEnvFiles(root) {
|
|
|
30075
29982
|
if (isEnvBaseName(entry.name)) {
|
|
30076
29983
|
let isDir = false;
|
|
30077
29984
|
try {
|
|
30078
|
-
isDir = (0,
|
|
29985
|
+
isDir = (0, import_node_fs26.lstatSync)((0, import_node_path26.join)(dir, entry.name)).isDirectory();
|
|
30079
29986
|
} catch {
|
|
30080
29987
|
}
|
|
30081
29988
|
if (!isDir) found.push(relPath);
|
|
@@ -30132,17 +30039,17 @@ function stageComposeFileEnv(files) {
|
|
|
30132
30039
|
}
|
|
30133
30040
|
|
|
30134
30041
|
// src/stage-runner.ts
|
|
30135
|
-
var execFileP3 = (0, import_node_util5.promisify)(
|
|
30042
|
+
var execFileP3 = (0, import_node_util5.promisify)(import_node_child_process10.execFile);
|
|
30136
30043
|
var DOCKER_TIMEOUT_MS = 15e3;
|
|
30137
30044
|
function stageBash() {
|
|
30138
30045
|
if (process.platform !== "win32") return "bash";
|
|
30139
30046
|
const configured = process.env.SHELL;
|
|
30140
|
-
if (configured && (0, import_node_path27.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0,
|
|
30047
|
+
if (configured && (0, import_node_path27.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs27.existsSync)(configured)) return configured;
|
|
30141
30048
|
const candidates = [
|
|
30142
30049
|
(0, import_node_path27.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
|
|
30143
30050
|
...process.env.LOCALAPPDATA ? [(0, import_node_path27.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
|
|
30144
30051
|
];
|
|
30145
|
-
const bash = candidates.find((path2) => (0,
|
|
30052
|
+
const bash = candidates.find((path2) => (0, import_node_fs27.existsSync)(path2));
|
|
30146
30053
|
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.");
|
|
30147
30054
|
return bash;
|
|
30148
30055
|
}
|
|
@@ -30491,7 +30398,7 @@ function stageProcessEnv(stagePort, extraEnv) {
|
|
|
30491
30398
|
function composeResolvesPort(cwd) {
|
|
30492
30399
|
if (process.env.PORT) return true;
|
|
30493
30400
|
const envFile = (0, import_node_path27.join)(cwd, ".env");
|
|
30494
|
-
return (0,
|
|
30401
|
+
return (0, import_node_fs27.existsSync)(envFile) && envFileKeys((0, import_node_fs27.readFileSync)(envFile, "utf8")).has("PORT");
|
|
30495
30402
|
}
|
|
30496
30403
|
function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
|
|
30497
30404
|
return {
|
|
@@ -30504,13 +30411,13 @@ function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
|
|
|
30504
30411
|
function stageComposeFiles(cwd) {
|
|
30505
30412
|
const files = ["docker-compose.yml"];
|
|
30506
30413
|
for (const conventional of ["docker-compose.override.yml", "docker-compose.override.yaml"]) {
|
|
30507
|
-
if ((0,
|
|
30414
|
+
if ((0, import_node_fs27.existsSync)((0, import_node_path27.join)(cwd, conventional))) files.push(conventional);
|
|
30508
30415
|
}
|
|
30509
30416
|
return [...files, RUNTIME_ENV_OVERRIDE_RELPATH];
|
|
30510
30417
|
}
|
|
30511
30418
|
async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
|
|
30512
30419
|
const keys = Object.keys(vaultEnvMerge ?? {});
|
|
30513
|
-
if (!keys.length || !(0,
|
|
30420
|
+
if (!keys.length || !(0, import_node_fs27.existsSync)((0, import_node_path27.join)(cwd, "docker-compose.yml"))) return {};
|
|
30514
30421
|
let configJson;
|
|
30515
30422
|
try {
|
|
30516
30423
|
const { stdout } = await execFileP3("docker", ["compose", "config", "--format", "json"], {
|
|
@@ -30527,20 +30434,20 @@ async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
|
|
|
30527
30434
|
const body = renderRuntimeEnvOverride(runtimeEnvMarkedServices(configJson), keys);
|
|
30528
30435
|
if (!body) return {};
|
|
30529
30436
|
const overridePath = (0, import_node_path27.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
|
|
30530
|
-
(0,
|
|
30531
|
-
(0,
|
|
30437
|
+
(0, import_node_fs27.mkdirSync)((0, import_node_path27.join)(cwd, "tmp", "stage"), { recursive: true });
|
|
30438
|
+
(0, import_node_fs27.writeFileSync)(overridePath, body, "utf8");
|
|
30532
30439
|
return stageComposeFileEnv(stageComposeFiles(cwd));
|
|
30533
30440
|
}
|
|
30534
30441
|
async function ensureStageRuntimeEnv(config, opts, cwd) {
|
|
30535
30442
|
if (!config.ensureEnv) return;
|
|
30536
30443
|
const target = (0, import_node_path27.join)(cwd, config.ensureEnv.target);
|
|
30537
30444
|
const example = (0, import_node_path27.join)(cwd, config.ensureEnv.example);
|
|
30538
|
-
if (!(0,
|
|
30539
|
-
(0,
|
|
30540
|
-
} else if ((0,
|
|
30541
|
-
const stale = detectStaleEnvFile((0,
|
|
30542
|
-
exampleMtimeMs: (0,
|
|
30543
|
-
targetMtimeMs: (0,
|
|
30445
|
+
if (!(0, import_node_fs27.existsSync)(target) && (0, import_node_fs27.existsSync)(example)) {
|
|
30446
|
+
(0, import_node_fs27.copyFileSync)(example, target);
|
|
30447
|
+
} else if ((0, import_node_fs27.existsSync)(target) && (0, import_node_fs27.existsSync)(example)) {
|
|
30448
|
+
const stale = detectStaleEnvFile((0, import_node_fs27.readFileSync)(example, "utf8"), (0, import_node_fs27.readFileSync)(target, "utf8"), {
|
|
30449
|
+
exampleMtimeMs: (0, import_node_fs27.statSync)(example).mtimeMs,
|
|
30450
|
+
targetMtimeMs: (0, import_node_fs27.statSync)(target).mtimeMs
|
|
30544
30451
|
});
|
|
30545
30452
|
if (stale) {
|
|
30546
30453
|
const msg = `stale ${config.ensureEnv.target} (${stale}) \u2014 delete it or refresh from ${config.ensureEnv.example} before re-running /stage`;
|
|
@@ -30548,8 +30455,8 @@ async function ensureStageRuntimeEnv(config, opts, cwd) {
|
|
|
30548
30455
|
console.error(`mmi-cli stage: ${msg} (allowed via --allow-stale-env)`);
|
|
30549
30456
|
}
|
|
30550
30457
|
}
|
|
30551
|
-
if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0,
|
|
30552
|
-
(0,
|
|
30458
|
+
if (opts.vaultEnvMerge && Object.keys(opts.vaultEnvMerge).length && (0, import_node_fs27.existsSync)(target)) {
|
|
30459
|
+
(0, import_node_fs27.writeFileSync)(target, mergeEnvSecretsIntoFile((0, import_node_fs27.readFileSync)(target, "utf8"), opts.vaultEnvMerge), "utf8");
|
|
30553
30460
|
}
|
|
30554
30461
|
}
|
|
30555
30462
|
async function gitText(cwd, args) {
|
|
@@ -30579,20 +30486,20 @@ async function resolveGlobalStatePath(cwd, explicit) {
|
|
|
30579
30486
|
return void 0;
|
|
30580
30487
|
}
|
|
30581
30488
|
function readState(path2) {
|
|
30582
|
-
if (!(0,
|
|
30489
|
+
if (!(0, import_node_fs27.existsSync)(path2)) return null;
|
|
30583
30490
|
try {
|
|
30584
|
-
return JSON.parse((0,
|
|
30491
|
+
return JSON.parse((0, import_node_fs27.readFileSync)(path2, "utf8"));
|
|
30585
30492
|
} catch {
|
|
30586
30493
|
return null;
|
|
30587
30494
|
}
|
|
30588
30495
|
}
|
|
30589
30496
|
function mkdirFor(path2) {
|
|
30590
30497
|
const dir = path2.slice(0, Math.max(path2.lastIndexOf("/"), path2.lastIndexOf("\\")));
|
|
30591
|
-
(0,
|
|
30498
|
+
(0, import_node_fs27.mkdirSync)(dir, { recursive: true });
|
|
30592
30499
|
}
|
|
30593
30500
|
function writeState(path2, state) {
|
|
30594
30501
|
mkdirFor(path2);
|
|
30595
|
-
(0,
|
|
30502
|
+
(0, import_node_fs27.writeFileSync)(path2, JSON.stringify(state, null, 2), "utf8");
|
|
30596
30503
|
}
|
|
30597
30504
|
function writeStagePortReservation(port, cwd, statePath, globalStatePath, now) {
|
|
30598
30505
|
const reservation = {
|
|
@@ -30621,7 +30528,7 @@ async function cleanupStageState(state, paths, timeoutMs, fallbackCwd, currentEn
|
|
|
30621
30528
|
);
|
|
30622
30529
|
}
|
|
30623
30530
|
for (const path2 of [...new Set(paths.filter((p) => Boolean(p)))]) {
|
|
30624
|
-
(0,
|
|
30531
|
+
(0, import_node_fs27.rmSync)(path2, { force: true });
|
|
30625
30532
|
}
|
|
30626
30533
|
}
|
|
30627
30534
|
async function killTree(pid) {
|
|
@@ -30715,7 +30622,7 @@ async function startStage(config = {}, opts = {}) {
|
|
|
30715
30622
|
let up = sub(config.up.trim());
|
|
30716
30623
|
if (opts.forceRecreate) up = appendForceRecreate(up);
|
|
30717
30624
|
const identity = await resolveStageIdentity(cwd);
|
|
30718
|
-
const child2 = (0,
|
|
30625
|
+
const child2 = (0, import_node_child_process10.spawn)(bash, ["-c", up], {
|
|
30719
30626
|
cwd,
|
|
30720
30627
|
// POSIX-only: the process group exists for the group-kill in stopStage. On win32 teardown is
|
|
30721
30628
|
// `taskkill /T /F` (no group needed), and detached+shell defeats windowsHide — every spawn would
|
|
@@ -30808,8 +30715,8 @@ async function runStage(config = {}, opts = {}) {
|
|
|
30808
30715
|
});
|
|
30809
30716
|
}
|
|
30810
30717
|
} catch (e) {
|
|
30811
|
-
(0,
|
|
30812
|
-
if (globalStatePath && globalStatePath !== statePath) (0,
|
|
30718
|
+
(0, import_node_fs27.rmSync)(statePath, { force: true });
|
|
30719
|
+
if (globalStatePath && globalStatePath !== statePath) (0, import_node_fs27.rmSync)(globalStatePath, { force: true });
|
|
30813
30720
|
throw e;
|
|
30814
30721
|
}
|
|
30815
30722
|
const started = await startStage(config, {
|
|
@@ -30826,9 +30733,9 @@ async function runStage(config = {}, opts = {}) {
|
|
|
30826
30733
|
// src/wave-status.ts
|
|
30827
30734
|
function readStageSummary(worktreePath) {
|
|
30828
30735
|
const statePath = stageStatePath(worktreePath);
|
|
30829
|
-
if (!(0,
|
|
30736
|
+
if (!(0, import_node_fs28.existsSync)(statePath)) return void 0;
|
|
30830
30737
|
try {
|
|
30831
|
-
const state = JSON.parse((0,
|
|
30738
|
+
const state = JSON.parse((0, import_node_fs28.readFileSync)(statePath, "utf8"));
|
|
30832
30739
|
const port = typeof state.port === "number" ? state.port : void 0;
|
|
30833
30740
|
if (port == null || !Number.isInteger(port) || port <= 0) return void 0;
|
|
30834
30741
|
return { port, url: typeof state.url === "string" ? state.url : void 0 };
|
|
@@ -30883,7 +30790,7 @@ async function collectWaveStatus(deps) {
|
|
|
30883
30790
|
}
|
|
30884
30791
|
|
|
30885
30792
|
// src/discovery-commands.ts
|
|
30886
|
-
var
|
|
30793
|
+
var import_node_fs29 = require("node:fs");
|
|
30887
30794
|
var import_node_os15 = require("node:os");
|
|
30888
30795
|
var import_node_path28 = require("node:path");
|
|
30889
30796
|
var GC_GH_TIMEOUT_MS = 2e4;
|
|
@@ -31075,8 +30982,8 @@ async function collectOnboardStatus(opts = {}) {
|
|
|
31075
30982
|
}
|
|
31076
30983
|
const home = (0, import_node_os15.homedir)();
|
|
31077
30984
|
const plugin = onboardPluginGate({
|
|
31078
|
-
readKnown: () => readFileSyncSafe((0, import_node_path28.join)(home, ...KNOWN_MARKETPLACES_RELATIVE),
|
|
31079
|
-
readSettings: () => readFileSyncSafe((0, import_node_path28.join)(home, ".claude", "settings.json"),
|
|
30985
|
+
readKnown: () => readFileSyncSafe((0, import_node_path28.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs29.readFileSync),
|
|
30986
|
+
readSettings: () => readFileSyncSafe((0, import_node_path28.join)(home, ".claude", "settings.json"), import_node_fs29.readFileSync)
|
|
31080
30987
|
});
|
|
31081
30988
|
return {
|
|
31082
30989
|
guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
|
|
@@ -33029,7 +32936,7 @@ function parseOriginRepo(remoteUrl) {
|
|
|
33029
32936
|
}
|
|
33030
32937
|
|
|
33031
32938
|
// src/issue-commands.ts
|
|
33032
|
-
var
|
|
32939
|
+
var import_node_fs30 = require("node:fs");
|
|
33033
32940
|
var import_node_crypto10 = require("node:crypto");
|
|
33034
32941
|
|
|
33035
32942
|
// src/issue-body.ts
|
|
@@ -33279,7 +33186,7 @@ async function editIssue(client, options, deps = {}) {
|
|
|
33279
33186
|
const url = `https://github.com/${repo}/issues/${parsed.number}`;
|
|
33280
33187
|
const patch = {};
|
|
33281
33188
|
let bodyChanged = false;
|
|
33282
|
-
const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0,
|
|
33189
|
+
const textDeps = () => deps.textDeps ?? { readFile: (p, e) => Promise.resolve((0, import_node_fs30.readFileSync)(p, e)), readStdin: () => Promise.resolve("") };
|
|
33283
33190
|
if (options.titleFile !== void 0) {
|
|
33284
33191
|
patch.title = await resolveIssueTitle({ title: options.title, titleFile: options.titleFile }, textDeps());
|
|
33285
33192
|
} else if (options.title !== void 0) {
|
|
@@ -33935,7 +33842,7 @@ function extendCreateCommand(issue, batchAttach) {
|
|
|
33935
33842
|
if (opts.batch) {
|
|
33936
33843
|
let specs;
|
|
33937
33844
|
try {
|
|
33938
|
-
const raw = (0,
|
|
33845
|
+
const raw = (0, import_node_fs30.readFileSync)(opts.batch, "utf8");
|
|
33939
33846
|
specs = JSON.parse(raw);
|
|
33940
33847
|
if (!Array.isArray(specs)) {
|
|
33941
33848
|
const top = specs === null ? "null" : typeof specs === "object" ? `an object with keys: ${Object.keys(specs).join(", ") || "(none)"}` : `a ${typeof specs}`;
|
|
@@ -33987,7 +33894,6 @@ ${lines2}`, {
|
|
|
33987
33894
|
surface: batchSurface,
|
|
33988
33895
|
noSurface: batchNoSurface
|
|
33989
33896
|
}, { attach: batchAttach });
|
|
33990
|
-
if (result.created.some((row) => !row.idempotent)) invalidateStatuslineBoardCache();
|
|
33991
33897
|
console.log(JSON.stringify(result));
|
|
33992
33898
|
if (result.failures.length) process.exitCode = 1;
|
|
33993
33899
|
} catch (e) {
|
|
@@ -35095,7 +35001,7 @@ function registerPrLifecycleCommands(program3) {
|
|
|
35095
35001
|
}
|
|
35096
35002
|
|
|
35097
35003
|
// src/project-info-sync.ts
|
|
35098
|
-
var
|
|
35004
|
+
var import_node_fs31 = require("node:fs");
|
|
35099
35005
|
var import_node_path29 = require("node:path");
|
|
35100
35006
|
var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
|
|
35101
35007
|
updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
|
|
@@ -35144,13 +35050,13 @@ function sharedName(entries, fallback) {
|
|
|
35144
35050
|
function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
|
|
35145
35051
|
if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
|
|
35146
35052
|
const readmePath = (0, import_node_path29.join)(repoRoot2, "README.md");
|
|
35147
|
-
if (!(0,
|
|
35053
|
+
if (!(0, import_node_fs31.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
|
|
35148
35054
|
const entries = entriesFor(project2, projects);
|
|
35149
35055
|
const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
|
|
35150
35056
|
const projectName = sharedName(entries, project2.name?.trim() || targetRepo2.split("/").pop() || targetRepo2);
|
|
35151
35057
|
if (!memberRepos.length) throw new Error(`org project sync-info: project ${projectName} has no registered member repos`);
|
|
35152
35058
|
const entryNames = entries.map((entry) => entry.name?.trim()).filter((name) => Boolean(name));
|
|
35153
|
-
const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0,
|
|
35059
|
+
const shortDescription = memberRepos.length === 1 ? shortDescriptionFromReadme((0, import_node_fs31.readFileSync)(readmePath, "utf8")) : `Shared work across ${new Intl.ListFormat("en", { type: "conjunction" }).format(entryNames)}.`;
|
|
35154
35060
|
const lines2 = [
|
|
35155
35061
|
`# ${projectName}`,
|
|
35156
35062
|
"",
|
|
@@ -35169,8 +35075,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
|
|
|
35169
35075
|
const targetBase = `https://github.com/${targetRepo2}`;
|
|
35170
35076
|
const targetBranch = branchFor(targetRepo2, projects);
|
|
35171
35077
|
const orgDocs = [
|
|
35172
|
-
(0,
|
|
35173
|
-
(0,
|
|
35078
|
+
(0, import_node_fs31.existsSync)((0, import_node_path29.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
|
|
35079
|
+
(0, import_node_fs31.existsSync)((0, import_node_path29.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
|
|
35174
35080
|
].filter(Boolean);
|
|
35175
35081
|
if (orgDocs.length) lines2.push("", "## Organisation docs", "", ...orgDocs);
|
|
35176
35082
|
return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines2.join("\n")}
|
|
@@ -35271,9 +35177,9 @@ function writeError(res) {
|
|
|
35271
35177
|
|
|
35272
35178
|
// src/schedules-commands.ts
|
|
35273
35179
|
var import_promises5 = require("node:fs/promises");
|
|
35274
|
-
var
|
|
35180
|
+
var import_node_child_process11 = require("node:child_process");
|
|
35275
35181
|
var import_node_util6 = require("node:util");
|
|
35276
|
-
var execFileP4 = (0, import_node_util6.promisify)(
|
|
35182
|
+
var execFileP4 = (0, import_node_util6.promisify)(import_node_child_process11.execFile);
|
|
35277
35183
|
var AWS_REGION = "eu-central-1";
|
|
35278
35184
|
var AWS_TIMEOUT_MS = 3e4;
|
|
35279
35185
|
var AWS_RETRY_DELAY_MS = 1500;
|
|
@@ -35588,7 +35494,7 @@ function registerSchedulesCommands(program3) {
|
|
|
35588
35494
|
}
|
|
35589
35495
|
|
|
35590
35496
|
// src/secrets-commands.ts
|
|
35591
|
-
var
|
|
35497
|
+
var import_node_fs32 = require("node:fs");
|
|
35592
35498
|
var import_node_path30 = require("node:path");
|
|
35593
35499
|
var import_node_os17 = require("node:os");
|
|
35594
35500
|
|
|
@@ -35702,8 +35608,8 @@ async function decryptRailsCredentials(input) {
|
|
|
35702
35608
|
MMI_RAILS_CREDENTIALS_FILE: credentialsPath,
|
|
35703
35609
|
MMI_RAILS_MASTER_KEY_FILE: masterKeyPath
|
|
35704
35610
|
};
|
|
35705
|
-
if ((0,
|
|
35706
|
-
env.RAILS_MASTER_KEY = (0,
|
|
35611
|
+
if ((0, import_node_fs32.existsSync)(masterKeyPath)) {
|
|
35612
|
+
env.RAILS_MASTER_KEY = (0, import_node_fs32.readFileSync)(masterKeyPath, "utf8").trim();
|
|
35707
35613
|
}
|
|
35708
35614
|
const script = [
|
|
35709
35615
|
'require "json"',
|
|
@@ -35713,9 +35619,9 @@ async function decryptRailsCredentials(input) {
|
|
|
35713
35619
|
'config = ActiveSupport::EncryptedConfiguration.new(config_path: config_path, key_path: key_path, env_key: "RAILS_MASTER_KEY", raise_if_missing_key: true)',
|
|
35714
35620
|
"puts JSON.generate(config.config)"
|
|
35715
35621
|
].join("\n");
|
|
35716
|
-
const scriptDir = (0,
|
|
35622
|
+
const scriptDir = (0, import_node_fs32.mkdtempSync)((0, import_node_path30.join)((0, import_node_os17.tmpdir)(), "mmi-rails-decrypt-"));
|
|
35717
35623
|
const scriptPath = (0, import_node_path30.join)(scriptDir, "decrypt.rb");
|
|
35718
|
-
(0,
|
|
35624
|
+
(0, import_node_fs32.writeFileSync)(scriptPath, script, "utf8");
|
|
35719
35625
|
try {
|
|
35720
35626
|
const args = ["exec", "ruby", scriptPath];
|
|
35721
35627
|
const cmd = process.platform === "win32" ? "cmd.exe" : "bundle";
|
|
@@ -35727,7 +35633,7 @@ async function decryptRailsCredentials(input) {
|
|
|
35727
35633
|
});
|
|
35728
35634
|
return JSON.parse(stdout);
|
|
35729
35635
|
} finally {
|
|
35730
|
-
(0,
|
|
35636
|
+
(0, import_node_fs32.rmSync)(scriptDir, { recursive: true, force: true });
|
|
35731
35637
|
}
|
|
35732
35638
|
}
|
|
35733
35639
|
async function readSecretStdin() {
|
|
@@ -35817,7 +35723,7 @@ function registerSecretsCommands(program3) {
|
|
|
35817
35723
|
let body;
|
|
35818
35724
|
if (o.file) {
|
|
35819
35725
|
try {
|
|
35820
|
-
body = (0,
|
|
35726
|
+
body = (0, import_node_fs32.readFileSync)((0, import_node_path30.resolve)(o.file), "utf8");
|
|
35821
35727
|
} catch (e) {
|
|
35822
35728
|
return fail(`secrets org-catalog: cannot read --file ${o.file}: ${e.message}`);
|
|
35823
35729
|
}
|
|
@@ -35925,7 +35831,7 @@ function registerSecretsCommands(program3) {
|
|
|
35925
35831
|
{
|
|
35926
35832
|
...d,
|
|
35927
35833
|
decryptRailsCredentials,
|
|
35928
|
-
removeFile: (path2) => (0,
|
|
35834
|
+
removeFile: (path2) => (0, import_node_fs32.unlinkSync)((0, import_node_path30.resolve)(o.appDir ?? process.cwd(), path2))
|
|
35929
35835
|
},
|
|
35930
35836
|
{
|
|
35931
35837
|
repo: o.repo,
|
|
@@ -36087,7 +35993,7 @@ function registerSessionReport(program3) {
|
|
|
36087
35993
|
}
|
|
36088
35994
|
|
|
36089
35995
|
// src/stage-commands.ts
|
|
36090
|
-
var
|
|
35996
|
+
var import_node_fs33 = require("node:fs");
|
|
36091
35997
|
var import_node_path31 = require("node:path");
|
|
36092
35998
|
|
|
36093
35999
|
// src/stage-default.ts
|
|
@@ -36372,8 +36278,8 @@ function registerStageCommands(program3) {
|
|
|
36372
36278
|
return {
|
|
36373
36279
|
resolution: decideStage({
|
|
36374
36280
|
registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
|
|
36375
|
-
hasCompose: (0,
|
|
36376
|
-
hasEnvExample: (0,
|
|
36281
|
+
hasCompose: (0, import_node_fs33.existsSync)((0, import_node_path31.join)(process.cwd(), "docker-compose.yml")),
|
|
36282
|
+
hasEnvExample: (0, import_node_fs33.existsSync)((0, import_node_path31.join)(process.cwd(), ".env.example")),
|
|
36377
36283
|
repo
|
|
36378
36284
|
}),
|
|
36379
36285
|
project: project2,
|
|
@@ -36634,14 +36540,14 @@ function registerStageCommands(program3) {
|
|
|
36634
36540
|
|
|
36635
36541
|
// src/tenant-artifact.ts
|
|
36636
36542
|
var import_node_crypto11 = require("node:crypto");
|
|
36637
|
-
var
|
|
36543
|
+
var import_node_fs34 = require("node:fs");
|
|
36638
36544
|
var import_promises6 = require("node:fs/promises");
|
|
36639
36545
|
var import_node_path32 = require("node:path");
|
|
36640
36546
|
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}$/;
|
|
36641
36547
|
var MAX_BYTES = 5 * 1024 * 1024 * 1024;
|
|
36642
36548
|
async function sha256File(path2) {
|
|
36643
36549
|
const hash = (0, import_node_crypto11.createHash)("sha256");
|
|
36644
|
-
for await (const chunk of (0,
|
|
36550
|
+
for await (const chunk of (0, import_node_fs34.createReadStream)(path2)) hash.update(chunk);
|
|
36645
36551
|
return hash.digest("hex");
|
|
36646
36552
|
}
|
|
36647
36553
|
async function putTenantArtifact(repo, stage, inputPath, deps) {
|
|
@@ -36664,7 +36570,7 @@ async function putTenantArtifact(repo, stage, inputPath, deps) {
|
|
|
36664
36570
|
return [key, value];
|
|
36665
36571
|
}));
|
|
36666
36572
|
headers["content-length"] = String(info.size);
|
|
36667
|
-
const stream = (0,
|
|
36573
|
+
const stream = (0, import_node_fs34.createReadStream)(path2);
|
|
36668
36574
|
let uploaded;
|
|
36669
36575
|
try {
|
|
36670
36576
|
uploaded = await fetch(body.uploadUrl, {
|
|
@@ -36803,8 +36709,8 @@ function renderVerifySecrets(body) {
|
|
|
36803
36709
|
}
|
|
36804
36710
|
|
|
36805
36711
|
// src/command-register-collaboration.ts
|
|
36806
|
-
var
|
|
36807
|
-
var
|
|
36712
|
+
var import_node_child_process16 = require("node:child_process");
|
|
36713
|
+
var import_node_fs41 = require("node:fs");
|
|
36808
36714
|
var import_promises7 = require("node:fs/promises");
|
|
36809
36715
|
|
|
36810
36716
|
// src/session-runtime.ts
|
|
@@ -36824,7 +36730,7 @@ function spawnDetachedSelf(args, deps, opts = {}) {
|
|
|
36824
36730
|
}
|
|
36825
36731
|
|
|
36826
36732
|
// src/command-register-collaboration.ts
|
|
36827
|
-
var
|
|
36733
|
+
var import_node_path39 = require("node:path");
|
|
36828
36734
|
|
|
36829
36735
|
// src/attach-to-project.ts
|
|
36830
36736
|
function boardAttachRateLimitedReceipt(resetEpochSeconds) {
|
|
@@ -37070,7 +36976,7 @@ async function runPrLand(prNumber, options, deps) {
|
|
|
37070
36976
|
}
|
|
37071
36977
|
|
|
37072
36978
|
// src/merge-cleanup.ts
|
|
37073
|
-
var
|
|
36979
|
+
var import_node_fs36 = require("node:fs");
|
|
37074
36980
|
var import_node_path34 = require("node:path");
|
|
37075
36981
|
var import_node_os18 = require("node:os");
|
|
37076
36982
|
|
|
@@ -37177,12 +37083,12 @@ function boardAdvanceFailureMessage(result) {
|
|
|
37177
37083
|
}
|
|
37178
37084
|
|
|
37179
37085
|
// src/test-policy-core.ts
|
|
37180
|
-
var
|
|
37181
|
-
var
|
|
37086
|
+
var import_node_child_process13 = require("node:child_process");
|
|
37087
|
+
var import_node_fs35 = require("node:fs");
|
|
37182
37088
|
var import_node_path33 = require("node:path");
|
|
37183
37089
|
|
|
37184
37090
|
// src/test-command-policy-shared.mjs
|
|
37185
|
-
var
|
|
37091
|
+
var import_node_child_process12 = require("node:child_process");
|
|
37186
37092
|
var TEST_COMMAND_CLASS = "test";
|
|
37187
37093
|
var TRAILER_KEY = "Test-Policy-Override";
|
|
37188
37094
|
var OVERRIDE_RE = /^Test-Policy-Override:\s*(.+)$/im;
|
|
@@ -37299,7 +37205,7 @@ function evaluateTestCommandPolicy({ paths, mandatory, regulated = true, overrid
|
|
|
37299
37205
|
};
|
|
37300
37206
|
}
|
|
37301
37207
|
function git(args, cwd) {
|
|
37302
|
-
return (0,
|
|
37208
|
+
return (0, import_node_child_process12.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
|
|
37303
37209
|
}
|
|
37304
37210
|
function parseScope(value) {
|
|
37305
37211
|
const scoped = /^\[([^\]]*)\]\s*([\s\S]*)$/.exec(value);
|
|
@@ -37732,7 +37638,7 @@ function loadPolicySource(root, explicitRef, diffBase) {
|
|
|
37732
37638
|
}
|
|
37733
37639
|
function readFileOrNull2(path2) {
|
|
37734
37640
|
try {
|
|
37735
|
-
return (0,
|
|
37641
|
+
return (0, import_node_fs35.readFileSync)(path2, "utf8");
|
|
37736
37642
|
} catch {
|
|
37737
37643
|
return null;
|
|
37738
37644
|
}
|
|
@@ -37760,10 +37666,10 @@ function classify(changed, policy, present = () => false) {
|
|
|
37760
37666
|
const removedProtected = [...removed].filter((p) => protectedBy.has(p)).map((p) => ({ path: p, why: protectedBy.get(p) ?? "" }));
|
|
37761
37667
|
return { mandatoryHits, untestedHits, testChanges, meaningfulTestChanges, addedTests, removedProtected };
|
|
37762
37668
|
}
|
|
37763
|
-
function unresolvedProtectedEntries(policy, root, exists = (path2) => (0,
|
|
37669
|
+
function unresolvedProtectedEntries(policy, root, exists = (path2) => (0, import_node_fs35.existsSync)(path2)) {
|
|
37764
37670
|
return (policy.protected ?? []).map((p) => p.path).filter((p) => !exists((0, import_node_path33.join)(root, p)));
|
|
37765
37671
|
}
|
|
37766
|
-
function unresolvedSatisfiers(policy, root, exists = (path2) => (0,
|
|
37672
|
+
function unresolvedSatisfiers(policy, root, exists = (path2) => (0, import_node_fs35.existsSync)(path2)) {
|
|
37767
37673
|
const declared = (policy.mandatory ?? []).flatMap((m) => m.satisfiedBy ?? []);
|
|
37768
37674
|
return [...new Set(declared)].filter((p) => !exists((0, import_node_path33.join)(root, p)));
|
|
37769
37675
|
}
|
|
@@ -37798,14 +37704,14 @@ function evaluate(changed, policy, present = () => false) {
|
|
|
37798
37704
|
return findings;
|
|
37799
37705
|
}
|
|
37800
37706
|
function git2(args, cwd) {
|
|
37801
|
-
return (0,
|
|
37707
|
+
return (0, import_node_child_process13.execFileSync)("git", args, { windowsHide: true, cwd, encoding: "utf8", maxBuffer: 32 * 1024 * 1024 });
|
|
37802
37708
|
}
|
|
37803
37709
|
var COAUTHOR_KEY = "Co-authored-by";
|
|
37804
37710
|
var GH_MESSAGE_SEPARATOR = /^-{5,}$/;
|
|
37805
37711
|
var LIFTED_KEYS = new RegExp(`^(?:${TRAILER_KEY}|${COAUTHOR_KEY}):`, "i");
|
|
37806
37712
|
function parseTrailers(message2, cwd) {
|
|
37807
37713
|
try {
|
|
37808
|
-
return (0,
|
|
37714
|
+
return (0, import_node_child_process13.execFileSync)("git", ["interpret-trailers", "--parse", "--unfold"], {
|
|
37809
37715
|
windowsHide: true,
|
|
37810
37716
|
cwd,
|
|
37811
37717
|
input: message2,
|
|
@@ -37904,7 +37810,7 @@ function runTestPolicy(root, deps = {}) {
|
|
|
37904
37810
|
}
|
|
37905
37811
|
const loaded = deps.policy ? { policy: deps.policy, source: { ref: null, sha: null, path: POLICY_FILE } } : loadPolicySource(root, deps.policyRef, deps.base);
|
|
37906
37812
|
const { policy, source: policySource } = loaded;
|
|
37907
|
-
const exists = deps.exists ?? ((path2) => (0,
|
|
37813
|
+
const exists = deps.exists ?? ((path2) => (0, import_node_fs35.existsSync)(path2));
|
|
37908
37814
|
const counts = { mandatoryCount: (policy.mandatory ?? []).length, protectedCount: (policy.protected ?? []).length };
|
|
37909
37815
|
const base = deps.changed ? "(injected)" : deps.policyRef ? resolveHotfixBase(root) : resolveBase(root, deps.base);
|
|
37910
37816
|
const refusal = deps.changed ? null : untrustworthyRange(root, base);
|
|
@@ -38140,13 +38046,13 @@ function resolveSquashMergeBodyText(commits, allowedClosing, cwd) {
|
|
|
38140
38046
|
return rewritten === base ? null : rewritten;
|
|
38141
38047
|
}
|
|
38142
38048
|
function writeSquashBodyFile(body) {
|
|
38143
|
-
const dir = (0,
|
|
38049
|
+
const dir = (0, import_node_fs36.mkdtempSync)((0, import_node_path34.join)((0, import_node_os18.tmpdir)(), "mmi-squash-body-"));
|
|
38144
38050
|
const path2 = (0, import_node_path34.join)(dir, "body.txt");
|
|
38145
|
-
(0,
|
|
38051
|
+
(0, import_node_fs36.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
|
|
38146
38052
|
`, "utf8");
|
|
38147
38053
|
return { path: path2, cleanup: () => {
|
|
38148
38054
|
try {
|
|
38149
|
-
(0,
|
|
38055
|
+
(0, import_node_fs36.rmSync)(dir, { recursive: true, force: true });
|
|
38150
38056
|
} catch {
|
|
38151
38057
|
}
|
|
38152
38058
|
} };
|
|
@@ -38353,7 +38259,7 @@ async function deleteMergedRemoteBranch(options) {
|
|
|
38353
38259
|
}
|
|
38354
38260
|
|
|
38355
38261
|
// src/post-merge-recon.ts
|
|
38356
|
-
var
|
|
38262
|
+
var import_node_fs37 = require("node:fs");
|
|
38357
38263
|
var import_node_path35 = require("node:path");
|
|
38358
38264
|
|
|
38359
38265
|
// src/cross-repo-filing-issue.ts
|
|
@@ -38520,16 +38426,16 @@ function buildPostMergeReconRecovery(input) {
|
|
|
38520
38426
|
}
|
|
38521
38427
|
function writePostMergeReconRecovery(cwd, recovery) {
|
|
38522
38428
|
const path2 = postMergeReconStatePath(cwd, recovery.repo, recovery.pr);
|
|
38523
|
-
(0,
|
|
38524
|
-
(0,
|
|
38429
|
+
(0, import_node_fs37.mkdirSync)((0, import_node_path35.dirname)(path2), { recursive: true });
|
|
38430
|
+
(0, import_node_fs37.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
|
|
38525
38431
|
`, "utf8");
|
|
38526
38432
|
return path2;
|
|
38527
38433
|
}
|
|
38528
38434
|
function clearPostMergeReconRecovery(cwd, repo, pr) {
|
|
38529
38435
|
const path2 = postMergeReconStatePath(cwd, repo, pr);
|
|
38530
|
-
if (!(0,
|
|
38436
|
+
if (!(0, import_node_fs37.existsSync)(path2)) return;
|
|
38531
38437
|
try {
|
|
38532
|
-
(0,
|
|
38438
|
+
(0, import_node_fs37.unlinkSync)(path2);
|
|
38533
38439
|
} catch {
|
|
38534
38440
|
}
|
|
38535
38441
|
}
|
|
@@ -38560,8 +38466,8 @@ function postMergeReconWarnings(input) {
|
|
|
38560
38466
|
}
|
|
38561
38467
|
|
|
38562
38468
|
// src/review-verdict.ts
|
|
38563
|
-
var
|
|
38564
|
-
var
|
|
38469
|
+
var import_node_child_process14 = require("node:child_process");
|
|
38470
|
+
var import_node_fs38 = require("node:fs");
|
|
38565
38471
|
var import_node_os19 = require("node:os");
|
|
38566
38472
|
var import_node_path36 = require("node:path");
|
|
38567
38473
|
var REVIEW_VERDICT_MARKER = "<!-- zeroci-review v1 -->";
|
|
@@ -38659,8 +38565,8 @@ async function checkPrReview(number, repo, head, deps = {
|
|
|
38659
38565
|
}
|
|
38660
38566
|
function computePrPatchId(number, repo) {
|
|
38661
38567
|
return new Promise((resolve7, reject) => {
|
|
38662
|
-
const gh = (0,
|
|
38663
|
-
const git3 = (0,
|
|
38568
|
+
const gh = (0, import_node_child_process14.spawn)("gh", ["pr", "diff", number, "--repo", repo], { windowsHide: true, stdio: ["ignore", "pipe", "pipe"] });
|
|
38569
|
+
const git3 = (0, import_node_child_process14.spawn)("git", ["patch-id", "--stable"], { windowsHide: true, stdio: ["pipe", "pipe", "pipe"] });
|
|
38664
38570
|
let out = "";
|
|
38665
38571
|
let ghErr = "";
|
|
38666
38572
|
let gitErr = "";
|
|
@@ -38727,29 +38633,29 @@ async function readPrIssueComments(number, repo) {
|
|
|
38727
38633
|
return comments;
|
|
38728
38634
|
}
|
|
38729
38635
|
async function postPrCommentFromFile(number, repo, body) {
|
|
38730
|
-
const dir = (0,
|
|
38636
|
+
const dir = (0, import_node_fs38.mkdtempSync)((0, import_node_path36.join)((0, import_node_os19.tmpdir)(), "mmi-review-verdict-"));
|
|
38731
38637
|
const path2 = (0, import_node_path36.join)(dir, "body.md");
|
|
38732
38638
|
try {
|
|
38733
|
-
(0,
|
|
38639
|
+
(0, import_node_fs38.writeFileSync)(path2, body, "utf8");
|
|
38734
38640
|
const { stdout } = await execFileP("gh", ["pr", "comment", number, "--repo", repo, "--body-file", path2], { timeout: GH_MUTATION_TIMEOUT_MS });
|
|
38735
38641
|
return stdout.trim();
|
|
38736
38642
|
} finally {
|
|
38737
38643
|
try {
|
|
38738
|
-
(0,
|
|
38644
|
+
(0, import_node_fs38.rmSync)(dir, { recursive: true, force: true });
|
|
38739
38645
|
} catch {
|
|
38740
38646
|
}
|
|
38741
38647
|
}
|
|
38742
38648
|
}
|
|
38743
38649
|
|
|
38744
38650
|
// src/pr-create-docs-check.ts
|
|
38745
|
-
var
|
|
38651
|
+
var import_node_child_process15 = require("node:child_process");
|
|
38746
38652
|
var GIT_TIMEOUT_MS2 = 15e3;
|
|
38747
38653
|
function catFileBatch(root, ref, paths) {
|
|
38748
38654
|
if (paths.length === 0) return Promise.resolve([]);
|
|
38749
38655
|
return new Promise((resolve7) => {
|
|
38750
38656
|
const chunks = [];
|
|
38751
38657
|
let settled = false;
|
|
38752
|
-
const child2 = (0,
|
|
38658
|
+
const child2 = (0, import_node_child_process15.spawn)("git", ["-C", root, "cat-file", "--batch", "--buffer"], { windowsHide: true });
|
|
38753
38659
|
const finish = () => {
|
|
38754
38660
|
if (settled) return;
|
|
38755
38661
|
settled = true;
|
|
@@ -38919,69 +38825,12 @@ async function prCreateClaimRefusal(body, repoOption, deps = {}) {
|
|
|
38919
38825
|
}
|
|
38920
38826
|
|
|
38921
38827
|
// src/worktree-merge-cleanup.ts
|
|
38922
|
-
var import_node_fs42 = require("node:fs");
|
|
38923
|
-
var import_node_path39 = require("node:path");
|
|
38924
|
-
|
|
38925
|
-
// src/jervcode-node-modules-cleanup.ts
|
|
38926
38828
|
var import_node_fs40 = require("node:fs");
|
|
38927
|
-
var
|
|
38928
|
-
var import_node_path37 = require("node:path");
|
|
38929
|
-
var JERVCODE_PACKAGE_ENTRY = (0, import_node_path37.join)("node_modules", "@jervaise", "jervcode", "dist", "launcher-entry.js");
|
|
38930
|
-
var WIN_NAMES2 = ["jervcode.cmd", "jervcode"];
|
|
38931
|
-
var POSIX_NAMES2 = ["jervcode"];
|
|
38932
|
-
var NODE_MODULES_CLEANUP_TIMEOUT_MS = 3e5;
|
|
38933
|
-
function jervcodeCandidatePaths(env = process.env, home = (0, import_node_os20.homedir)(), platform2 = process.platform) {
|
|
38934
|
-
const names = platform2 === "win32" ? WIN_NAMES2 : POSIX_NAMES2;
|
|
38935
|
-
const out = [];
|
|
38936
|
-
for (const dir of jervCliCandidateDirs(env, home, platform2)) {
|
|
38937
|
-
for (const name of names) out.push((0, import_node_path37.join)(dir, name));
|
|
38938
|
-
}
|
|
38939
|
-
return out;
|
|
38940
|
-
}
|
|
38941
|
-
function resolveJervcodePath(env = process.env, home = (0, import_node_os20.homedir)(), platform2 = process.platform, exists = import_node_fs40.existsSync) {
|
|
38942
|
-
for (const candidate of jervcodeCandidatePaths(env, home, platform2)) {
|
|
38943
|
-
if (exists(candidate)) return candidate;
|
|
38944
|
-
}
|
|
38945
|
-
return void 0;
|
|
38946
|
-
}
|
|
38947
|
-
function jervcodeExecFileArgs(args, opts = {}) {
|
|
38948
|
-
const platform2 = opts.platform ?? process.platform;
|
|
38949
|
-
const exists = opts.exists ?? import_node_fs40.existsSync;
|
|
38950
|
-
const resolved = resolveJervcodePath(opts.env ?? process.env, opts.home ?? (0, import_node_os20.homedir)(), platform2, exists);
|
|
38951
|
-
if (resolved) {
|
|
38952
|
-
const entry = (0, import_node_path37.join)((0, import_node_path37.join)(resolved, ".."), JERVCODE_PACKAGE_ENTRY);
|
|
38953
|
-
if (exists(entry)) {
|
|
38954
|
-
return { file: opts.execPath ?? process.execPath, args: [entry, ...args], via: "node-entry" };
|
|
38955
|
-
}
|
|
38956
|
-
}
|
|
38957
|
-
const bin = resolved ?? "jervcode";
|
|
38958
|
-
if (platform2 === "win32") {
|
|
38959
|
-
return { file: "cmd.exe", args: ["/c", bin, ...args], via: resolved ? "cmd-shim" : "bare" };
|
|
38960
|
-
}
|
|
38961
|
-
return { file: bin, args: [...args], via: resolved ? "posix" : "bare" };
|
|
38962
|
-
}
|
|
38963
|
-
async function removeWorktreeNodeModulesViaHelper(wtPath, opts = {}) {
|
|
38964
|
-
const { cwd, timeoutMs = NODE_MODULES_CLEANUP_TIMEOUT_MS } = opts;
|
|
38965
|
-
const env = opts.env ?? process.env;
|
|
38966
|
-
const exec = opts.exec ?? execFileP;
|
|
38967
|
-
const candidates = jervcodeCandidatePaths(env, opts.home, opts.platform ?? process.platform);
|
|
38968
|
-
const plan = jervcodeExecFileArgs(["worktree-node-modules-cleanup", "--worktree", wtPath], opts);
|
|
38969
|
-
const execOptions = { timeout: timeoutMs, ...cwd ? { cwd } : {} };
|
|
38970
|
-
try {
|
|
38971
|
-
await exec(plan.file, plan.args, execOptions);
|
|
38972
|
-
return { ok: true };
|
|
38973
|
-
} catch (e) {
|
|
38974
|
-
const err = e;
|
|
38975
|
-
const base = formatJervCliSpawnFailure(err, plan, candidates);
|
|
38976
|
-
const stderr = typeof err.stderr === "string" ? err.stderr.trim() : "";
|
|
38977
|
-
const detail = stderr.split("\n")[0] || base;
|
|
38978
|
-
return { ok: false, error: `jervcode worktree-node-modules-cleanup failed: ${detail}` };
|
|
38979
|
-
}
|
|
38980
|
-
}
|
|
38829
|
+
var import_node_path38 = require("node:path");
|
|
38981
38830
|
|
|
38982
38831
|
// src/worktree-evidence-archive.ts
|
|
38983
|
-
var
|
|
38984
|
-
var
|
|
38832
|
+
var import_node_fs39 = require("node:fs");
|
|
38833
|
+
var import_node_path37 = require("node:path");
|
|
38985
38834
|
var JERV_ARTIFACT_RUN_SCOPE_ENV_VARS = ["JERV_RUN_ID", ...SESSION_ID_ENV_VARS];
|
|
38986
38835
|
function sanitizeArchiveSegment(value, max = 80) {
|
|
38987
38836
|
const scrubbed = value.replace(/[^A-Za-z0-9._@+-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -38996,24 +38845,24 @@ function resolveArtifactRunScope(env = process.env) {
|
|
|
38996
38845
|
}
|
|
38997
38846
|
function defaultIsDirectory(path2) {
|
|
38998
38847
|
try {
|
|
38999
|
-
return (0,
|
|
38848
|
+
return (0, import_node_fs39.lstatSync)(path2).isDirectory();
|
|
39000
38849
|
} catch {
|
|
39001
38850
|
return false;
|
|
39002
38851
|
}
|
|
39003
38852
|
}
|
|
39004
38853
|
function archiveWorktreeJervArtifacts(args, deps = {}) {
|
|
39005
|
-
const exists = deps.exists ??
|
|
38854
|
+
const exists = deps.exists ?? import_node_fs39.existsSync;
|
|
39006
38855
|
const isDirectory = deps.isDirectory ?? defaultIsDirectory;
|
|
39007
|
-
const copyDir = deps.copyDir ?? ((from, to) => (0,
|
|
38856
|
+
const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs39.cpSync)(from, to, { recursive: true, force: true }));
|
|
39008
38857
|
const mkdirp = deps.mkdirp ?? ((path2) => {
|
|
39009
|
-
(0,
|
|
38858
|
+
(0, import_node_fs39.mkdirSync)(path2, { recursive: true });
|
|
39010
38859
|
});
|
|
39011
38860
|
const env = deps.env ?? process.env;
|
|
39012
38861
|
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
39013
38862
|
const resolveRoot = deps.resolveArchiveRoot ?? repoRuntimeStatePath;
|
|
39014
38863
|
if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
|
|
39015
38864
|
if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
|
|
39016
|
-
const source = (0,
|
|
38865
|
+
const source = (0, import_node_path37.join)(args.worktreePath, ".jerv");
|
|
39017
38866
|
if (!exists(source)) return { status: "absent" };
|
|
39018
38867
|
if (!isDirectory(source)) return { status: "skipped", reason: "jerv-not-a-directory" };
|
|
39019
38868
|
const runScope = resolveArtifactRunScope(env);
|
|
@@ -39021,7 +38870,7 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
|
|
|
39021
38870
|
const stamp = now().toISOString().replace(/[:.]/g, "-");
|
|
39022
38871
|
const dest = resolveRoot(args.primaryRoot, "jerv-artifacts", runScope, branchSlug, stamp, ".jerv");
|
|
39023
38872
|
try {
|
|
39024
|
-
mkdirp((0,
|
|
38873
|
+
mkdirp((0, import_node_path37.dirname)(dest));
|
|
39025
38874
|
copyDir(source, dest);
|
|
39026
38875
|
if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
|
|
39027
38876
|
return { status: "archived", path: dest, runScope };
|
|
@@ -39030,14 +38879,14 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
|
|
|
39030
38879
|
}
|
|
39031
38880
|
}
|
|
39032
38881
|
function defaultStat(path2) {
|
|
39033
|
-
const st = (0,
|
|
38882
|
+
const st = (0, import_node_fs39.statSync)(path2);
|
|
39034
38883
|
return { mtimeMs: st.mtimeMs, size: st.size, isDirectory: () => st.isDirectory() };
|
|
39035
38884
|
}
|
|
39036
38885
|
function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
|
|
39037
|
-
const exists = deps.exists ??
|
|
38886
|
+
const exists = deps.exists ?? import_node_fs39.existsSync;
|
|
39038
38887
|
const stat4 = deps.stat ?? defaultStat;
|
|
39039
|
-
const readdir2 = deps.readdir ??
|
|
39040
|
-
const tmpRoot = (0,
|
|
38888
|
+
const readdir2 = deps.readdir ?? import_node_fs39.readdirSync;
|
|
38889
|
+
const tmpRoot = (0, import_node_path37.join)(worktreePath, "tmp");
|
|
39041
38890
|
if (!exists(tmpRoot)) return [];
|
|
39042
38891
|
const entries = [];
|
|
39043
38892
|
const walk2 = (dir) => {
|
|
@@ -39048,14 +38897,14 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
|
|
|
39048
38897
|
return;
|
|
39049
38898
|
}
|
|
39050
38899
|
for (const name of names) {
|
|
39051
|
-
const full = (0,
|
|
38900
|
+
const full = (0, import_node_path37.join)(dir, name);
|
|
39052
38901
|
let st;
|
|
39053
38902
|
try {
|
|
39054
38903
|
st = stat4(full);
|
|
39055
38904
|
} catch {
|
|
39056
38905
|
continue;
|
|
39057
38906
|
}
|
|
39058
|
-
const relPath = (0,
|
|
38907
|
+
const relPath = (0, import_node_path37.relative)(worktreePath, full).replace(/\\/g, "/");
|
|
39059
38908
|
if (st.isDirectory()) {
|
|
39060
38909
|
if (st.mtimeMs > newerThanMs) entries.push({ relPath, bytes: 0, mtimeMs: st.mtimeMs });
|
|
39061
38910
|
walk2(full);
|
|
@@ -39069,10 +38918,10 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
|
|
|
39069
38918
|
return entries;
|
|
39070
38919
|
}
|
|
39071
38920
|
function archiveWorktreeTmpArtifacts(args, deps = {}) {
|
|
39072
|
-
const exists = deps.exists ??
|
|
39073
|
-
const copyDir = deps.copyDir ?? ((from, to) => (0,
|
|
38921
|
+
const exists = deps.exists ?? import_node_fs39.existsSync;
|
|
38922
|
+
const copyDir = deps.copyDir ?? ((from, to) => (0, import_node_fs39.cpSync)(from, to, { recursive: true, force: true }));
|
|
39074
38923
|
const mkdirp = deps.mkdirp ?? ((path2) => {
|
|
39075
|
-
(0,
|
|
38924
|
+
(0, import_node_fs39.mkdirSync)(path2, { recursive: true });
|
|
39076
38925
|
});
|
|
39077
38926
|
const env = deps.env ?? process.env;
|
|
39078
38927
|
const now = deps.now ?? (() => /* @__PURE__ */ new Date());
|
|
@@ -39080,7 +38929,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
|
|
|
39080
38929
|
if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
|
|
39081
38930
|
if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
|
|
39082
38931
|
const scanned = scanWorktreeTmpEvidence(args.worktreePath, args.newerThanMs, deps);
|
|
39083
|
-
const source = (0,
|
|
38932
|
+
const source = (0, import_node_path37.join)(args.worktreePath, "tmp");
|
|
39084
38933
|
if (!scanned.length) return { status: "absent" };
|
|
39085
38934
|
if (!exists(source)) return { status: "absent" };
|
|
39086
38935
|
const runScope = resolveArtifactRunScope(env);
|
|
@@ -39088,7 +38937,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
|
|
|
39088
38937
|
const stamp = now().toISOString().replace(/[:.]/g, "-");
|
|
39089
38938
|
const dest = resolveRoot(args.primaryRoot, "worktree-artifacts", runScope, branchSlug, stamp, "tmp");
|
|
39090
38939
|
try {
|
|
39091
|
-
mkdirp((0,
|
|
38940
|
+
mkdirp((0, import_node_path37.dirname)(dest));
|
|
39092
38941
|
copyDir(source, dest);
|
|
39093
38942
|
if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
|
|
39094
38943
|
const bytes = scanned.reduce((sum, e) => sum + e.bytes, 0);
|
|
@@ -39157,9 +39006,9 @@ function normPath2(p) {
|
|
|
39157
39006
|
return p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
39158
39007
|
}
|
|
39159
39008
|
function unlinkNodeModulesJunction(wtPath) {
|
|
39160
|
-
const nm = (0,
|
|
39009
|
+
const nm = (0, import_node_path38.join)(wtPath, "node_modules");
|
|
39161
39010
|
try {
|
|
39162
|
-
if ((0,
|
|
39011
|
+
if ((0, import_node_fs40.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs40.rmdirSync)(nm);
|
|
39163
39012
|
return { ok: true };
|
|
39164
39013
|
} catch (e) {
|
|
39165
39014
|
if (e.code === "ENOENT") return { ok: true };
|
|
@@ -39170,8 +39019,8 @@ function defaultSleep2(ms) {
|
|
|
39170
39019
|
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
39171
39020
|
}
|
|
39172
39021
|
async function removeResidueDirectory(wtPath, options = {}) {
|
|
39173
|
-
const { sleep: sleep2 = defaultSleep2, removeEmptyDir =
|
|
39174
|
-
const removeRecursive = options.removeRecursive ?? ((path2) => (0,
|
|
39022
|
+
const { sleep: sleep2 = defaultSleep2, removeEmptyDir = import_node_fs40.rmdirSync, exists = import_node_fs40.existsSync } = options;
|
|
39023
|
+
const removeRecursive = options.removeRecursive ?? ((path2) => (0, import_node_fs40.rmSync)(path2, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 }));
|
|
39175
39024
|
const junction = unlinkNodeModulesJunction(wtPath);
|
|
39176
39025
|
if (!junction.ok) return junction;
|
|
39177
39026
|
try {
|
|
@@ -39217,7 +39066,7 @@ function isWindowsCwdLockResidueError(error) {
|
|
|
39217
39066
|
}
|
|
39218
39067
|
function deferredCwdLockRemediation(wtPath) {
|
|
39219
39068
|
const quote = (path2) => path2.replace(/'/g, "''");
|
|
39220
|
-
return `After
|
|
39069
|
+
return `After leaving the directory and closing its handles, remove it only if empty: [System.IO.Directory]::Delete('${quote(wtPath)}', $false)`;
|
|
39221
39070
|
}
|
|
39222
39071
|
function primaryCheckoutBranchRemediation(primaryRoot, baseRef, branch) {
|
|
39223
39072
|
const quote = (value) => value.replace(/'/g, "''");
|
|
@@ -39294,31 +39143,40 @@ async function preCleanWorktreeForRemoval(wtPath, execGit) {
|
|
|
39294
39143
|
}
|
|
39295
39144
|
async function listNestedIgnoredNodeModules(wtPath, execGit) {
|
|
39296
39145
|
const out = await execGit(["-C", wtPath, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory"]).catch(() => "");
|
|
39297
|
-
return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0,
|
|
39146
|
+
return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path38.join)(wtPath, line.slice(0, -1)));
|
|
39298
39147
|
}
|
|
39299
39148
|
function safeRemoveTree(path2) {
|
|
39300
|
-
const stat4 = (0,
|
|
39149
|
+
const stat4 = (0, import_node_fs40.lstatSync)(path2);
|
|
39301
39150
|
if (stat4.isSymbolicLink()) {
|
|
39302
39151
|
try {
|
|
39303
|
-
(0,
|
|
39152
|
+
(0, import_node_fs40.rmdirSync)(path2);
|
|
39304
39153
|
} catch {
|
|
39305
|
-
(0,
|
|
39154
|
+
(0, import_node_fs40.unlinkSync)(path2);
|
|
39306
39155
|
}
|
|
39307
39156
|
return;
|
|
39308
39157
|
}
|
|
39309
39158
|
if (stat4.isDirectory()) {
|
|
39310
|
-
for (const entry of (0,
|
|
39311
|
-
(0,
|
|
39159
|
+
for (const entry of (0, import_node_fs40.readdirSync)(path2)) safeRemoveTree((0, import_node_path38.join)(path2, entry));
|
|
39160
|
+
(0, import_node_fs40.rmdirSync)(path2);
|
|
39312
39161
|
return;
|
|
39313
39162
|
}
|
|
39314
|
-
(0,
|
|
39163
|
+
(0, import_node_fs40.unlinkSync)(path2);
|
|
39164
|
+
}
|
|
39165
|
+
async function removeWorktreeNodeModules(wtPath) {
|
|
39166
|
+
try {
|
|
39167
|
+
safeRemoveTree((0, import_node_path38.join)(wtPath, "node_modules"));
|
|
39168
|
+
return { ok: true };
|
|
39169
|
+
} catch (e) {
|
|
39170
|
+
if (e.code === "ENOENT") return { ok: true };
|
|
39171
|
+
return { ok: false, error: errorMessage(e) };
|
|
39172
|
+
}
|
|
39315
39173
|
}
|
|
39316
39174
|
function errorMessage(e) {
|
|
39317
39175
|
return e instanceof Error ? e.message : String(e);
|
|
39318
39176
|
}
|
|
39319
39177
|
function resolvedOrRaw(path2) {
|
|
39320
39178
|
try {
|
|
39321
|
-
return normPath2((0,
|
|
39179
|
+
return normPath2((0, import_node_fs40.realpathSync)(path2));
|
|
39322
39180
|
} catch {
|
|
39323
39181
|
return normPath2(path2);
|
|
39324
39182
|
}
|
|
@@ -39326,10 +39184,10 @@ function resolvedOrRaw(path2) {
|
|
|
39326
39184
|
function unlinkEscapingReparsePoints(root, primaryRoot) {
|
|
39327
39185
|
let realRoot;
|
|
39328
39186
|
try {
|
|
39329
|
-
if ((0,
|
|
39187
|
+
if ((0, import_node_fs40.lstatSync)(root).isSymbolicLink()) {
|
|
39330
39188
|
return { ok: false, error: `delete root ${normPath2(root)} is a reparse point resolving to ${resolvedOrRaw(root)}` };
|
|
39331
39189
|
}
|
|
39332
|
-
realRoot = normPath2((0,
|
|
39190
|
+
realRoot = normPath2((0, import_node_fs40.realpathSync)(root));
|
|
39333
39191
|
} catch (e) {
|
|
39334
39192
|
if (e.code === "ENOENT") return { ok: true, unlinked: [] };
|
|
39335
39193
|
return { ok: false, error: `cannot resolve delete root ${normPath2(root)}: ${errorMessage(e)}` };
|
|
@@ -39345,16 +39203,16 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
|
|
|
39345
39203
|
const dir = stack.pop();
|
|
39346
39204
|
let entries;
|
|
39347
39205
|
try {
|
|
39348
|
-
entries = (0,
|
|
39206
|
+
entries = (0, import_node_fs40.readdirSync)(dir, { withFileTypes: true });
|
|
39349
39207
|
} catch (e) {
|
|
39350
39208
|
return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
|
|
39351
39209
|
}
|
|
39352
39210
|
for (const entry of entries) {
|
|
39353
|
-
const child2 = (0,
|
|
39211
|
+
const child2 = (0, import_node_path38.join)(dir, entry.name);
|
|
39354
39212
|
if (entry.isSymbolicLink()) {
|
|
39355
39213
|
let target = "";
|
|
39356
39214
|
try {
|
|
39357
|
-
target = normPath2((0,
|
|
39215
|
+
target = normPath2((0, import_node_fs40.realpathSync)(child2));
|
|
39358
39216
|
} catch {
|
|
39359
39217
|
target = "";
|
|
39360
39218
|
}
|
|
@@ -39383,8 +39241,7 @@ async function describePreCleanFailure(wtPath, execGit, error) {
|
|
|
39383
39241
|
const shown = remaining.slice(0, 10).join(", ");
|
|
39384
39242
|
const more = remaining.length > 10 ? ` (+${remaining.length - 10} more)` : "";
|
|
39385
39243
|
const quote = (path2) => path2.replace(/'/g, "''");
|
|
39386
|
-
const
|
|
39387
|
-
const remediation = remaining.includes("node_modules/") ? `jervcode worktree-node-modules-cleanup --worktree '${quote(wtPath)}'` : nested ? `Remove-Item -LiteralPath '${quote((0, import_node_path39.join)(wtPath, nested.slice(0, -1)))}' -Recurse -Force` : void 0;
|
|
39244
|
+
const remediation = remaining.some((path2) => path2.endsWith("node_modules/")) ? `Close handles to '${quote(wtPath)}' and retry MMI PR landing from the primary checkout` : void 0;
|
|
39388
39245
|
return { ok: false, error: `${error}; remaining ignored paths: ${shown}${more}`, ...remediation ? { remediation } : {} };
|
|
39389
39246
|
}
|
|
39390
39247
|
function formatWorktreeRemovalFailureDetail(options) {
|
|
@@ -39538,7 +39395,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
|
|
|
39538
39395
|
return report;
|
|
39539
39396
|
}
|
|
39540
39397
|
const execGit = options.execGit ?? (async (args) => (await execFileP("git", args, { timeout: GIT_TIMEOUT_MS })).stdout);
|
|
39541
|
-
const pathExists = options.pathExists ??
|
|
39398
|
+
const pathExists = options.pathExists ?? import_node_fs40.existsSync;
|
|
39542
39399
|
let afterWorktrees = [];
|
|
39543
39400
|
try {
|
|
39544
39401
|
afterWorktrees = parseGitWorktreePorcelain(await execGit(["worktree", "list", "--porcelain"]));
|
|
@@ -39678,8 +39535,8 @@ async function cleanupPrMergeLocalBranch(branch, options) {
|
|
|
39678
39535
|
const preHelperGuard = unlinkEscapingReparsePoints(wtPath, options.primaryRoot);
|
|
39679
39536
|
if (!preHelperGuard.ok) return refuseReparseEscape(preHelperGuard.error);
|
|
39680
39537
|
unlinkedReparsePoints.push(...preHelperGuard.unlinked);
|
|
39681
|
-
if (pathExists((0,
|
|
39682
|
-
const nmRemoved = await (options.removeRealNodeModules ??
|
|
39538
|
+
if (pathExists((0, import_node_path38.join)(wtPath, "node_modules"))) {
|
|
39539
|
+
const nmRemoved = await (options.removeRealNodeModules ?? removeWorktreeNodeModules)(wtPath);
|
|
39683
39540
|
if (!nmRemoved.ok) {
|
|
39684
39541
|
report.worktree = {
|
|
39685
39542
|
path: wtPath,
|
|
@@ -39690,7 +39547,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
|
|
|
39690
39547
|
stageTeardown,
|
|
39691
39548
|
tmpEvidenceCount: tmpEvidence.length,
|
|
39692
39549
|
...unlinkedReparsePoints.length ? { unlinkedReparsePoints } : {},
|
|
39693
|
-
remediation: `
|
|
39550
|
+
remediation: `Close handles to '${wtPath.replace(/'/g, "''")}' and retry MMI PR landing from the primary checkout`
|
|
39694
39551
|
};
|
|
39695
39552
|
report.localBranch = { name: branch, status: "not-attempted", reason: "worktree-pre-clean-failed" };
|
|
39696
39553
|
return report;
|
|
@@ -39845,10 +39702,10 @@ function argvWantsJson2() {
|
|
|
39845
39702
|
return process.argv.some((a) => a === "--json" || a.startsWith("--json="));
|
|
39846
39703
|
}
|
|
39847
39704
|
function hubRoot() {
|
|
39848
|
-
const fromPkg = (0,
|
|
39705
|
+
const fromPkg = (0, import_node_path39.join)(__dirname, "..", "..");
|
|
39849
39706
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
39850
|
-
if ((0,
|
|
39851
|
-
if ((0,
|
|
39707
|
+
if ((0, import_node_fs41.existsSync)((0, import_node_path39.join)(fromPkg, marker))) return fromPkg;
|
|
39708
|
+
if ((0, import_node_fs41.existsSync)((0, import_node_path39.join)(process.cwd(), marker))) return process.cwd();
|
|
39852
39709
|
return null;
|
|
39853
39710
|
}
|
|
39854
39711
|
function ciAuditDeps() {
|
|
@@ -39860,8 +39717,8 @@ function ciAuditDeps() {
|
|
|
39860
39717
|
getProjectMeta: async (slug) => fetchProjectBySlug(slug, registryClientDeps(await cfgPromise)),
|
|
39861
39718
|
readSeedFile: (path2) => {
|
|
39862
39719
|
if (!root) return null;
|
|
39863
|
-
const fullPath = (0,
|
|
39864
|
-
return (0,
|
|
39720
|
+
const fullPath = (0, import_node_path39.join)(root, path2);
|
|
39721
|
+
return (0, import_node_fs41.existsSync)(fullPath) ? (0, import_node_fs41.readFileSync)(fullPath, "utf8") : null;
|
|
39865
39722
|
}
|
|
39866
39723
|
};
|
|
39867
39724
|
}
|
|
@@ -39943,7 +39800,7 @@ function scheduleRelatedDiscovery(o) {
|
|
|
39943
39800
|
try {
|
|
39944
39801
|
const args = ["issue", "discover-related", "--number", String(o.number), "--title", o.title, "--body", o.body, "--fail-soft"];
|
|
39945
39802
|
if (o.repo) args.push("--repo", o.repo);
|
|
39946
|
-
spawnDetachedSelf(args, { spawn:
|
|
39803
|
+
spawnDetachedSelf(args, { spawn: import_node_child_process16.spawn, execPath: process.execPath, scriptPath: process.argv[1] }, { cwd: process.cwd() });
|
|
39947
39804
|
} catch {
|
|
39948
39805
|
}
|
|
39949
39806
|
}
|
|
@@ -40153,7 +40010,6 @@ function registerCollaborationCommands(program3) {
|
|
|
40153
40010
|
}
|
|
40154
40011
|
}
|
|
40155
40012
|
if (o.related !== false) scheduleRelatedDiscovery({ repo: o.repo, number: created.number, title, body });
|
|
40156
|
-
invalidateStatuslineBoardCache();
|
|
40157
40013
|
console.log(JSON.stringify({
|
|
40158
40014
|
...created,
|
|
40159
40015
|
label: issueType,
|
|
@@ -40396,7 +40252,6 @@ ${list}`);
|
|
|
40396
40252
|
}
|
|
40397
40253
|
}
|
|
40398
40254
|
program3.command("skill-lesson").description("file a skill-lesson on the Hub board (GitHub auth, dedups open lessons) and print {number,url} JSON").addOption(new Option("--skill <name>", `which skill misfired (${SKILL_NAMES.join(" | ")})`).makeOptionMandatory().choices([...SKILL_NAMES])).option("--title <title>", "one-line summary of what misfired").option("--title-file <path|->", "read the one-line summary from a UTF-8 file, or from stdin with -").option("--body <body>", "lesson body: what misfired, the evidence, and the proposed amendment (markdown)").option("--body-file <path|->", "read the lesson body from a UTF-8 file, or from stdin with -").option("--priority <priority>", "urgent | high | medium | low (defaults to medium; sets the board Priority field only, #416)").option("--repo <owner/repo>", `target repo (defaults to the org Hub: ${HUB_REPO})`).option("--force", "file a new issue even when an open lesson looks like a duplicate").option("--json", "machine-readable output (already the default \u2014 skill-lesson always prints JSON)").action(async (o) => {
|
|
40399
|
-
warnSkillLessonDeprecated();
|
|
40400
40255
|
const targetRepo2 = o.repo ?? HUB_REPO;
|
|
40401
40256
|
const sourceRepo = await resolveRepo(void 0);
|
|
40402
40257
|
const pluginSha = await resolvePluginSha();
|
|
@@ -40497,7 +40352,6 @@ ${list}`);
|
|
|
40497
40352
|
process.exitCode = 1;
|
|
40498
40353
|
return;
|
|
40499
40354
|
}
|
|
40500
|
-
invalidateStatuslineBoardCache();
|
|
40501
40355
|
console.log(JSON.stringify(created));
|
|
40502
40356
|
}), [
|
|
40503
40357
|
'mmi-cli devops pr create --title "Add the schema" --body "Closes #2680"',
|
|
@@ -40535,11 +40389,11 @@ ${list}`);
|
|
|
40535
40389
|
}
|
|
40536
40390
|
});
|
|
40537
40391
|
async function listCiWorkflowPaths(cwd = process.cwd()) {
|
|
40538
|
-
const wfDir = (0,
|
|
40539
|
-
if (!(0,
|
|
40540
|
-
return (0,
|
|
40392
|
+
const wfDir = (0, import_node_path39.join)(cwd, ".github", "workflows");
|
|
40393
|
+
if (!(0, import_node_fs41.existsSync)(wfDir)) return [];
|
|
40394
|
+
return (0, import_node_fs41.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
|
|
40541
40395
|
try {
|
|
40542
|
-
return workflowReportsPrChecks((0,
|
|
40396
|
+
return workflowReportsPrChecks((0, import_node_fs41.readFileSync)((0, import_node_path39.join)(wfDir, name), "utf8"));
|
|
40543
40397
|
} catch {
|
|
40544
40398
|
return true;
|
|
40545
40399
|
}
|
|
@@ -40735,7 +40589,7 @@ ${list}`);
|
|
|
40735
40589
|
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) => {
|
|
40736
40590
|
if (!isReviewVerdict(o.verdict)) return fail(`pr review-verdict: --verdict must be one of ${REVIEW_VERDICTS.join("|")} (got ${o.verdict})`);
|
|
40737
40591
|
const verdict = o.verdict;
|
|
40738
|
-
const findings = o.findingsFile ? (0,
|
|
40592
|
+
const findings = o.findingsFile ? (0, import_node_fs41.readFileSync)(o.findingsFile, "utf8") : void 0;
|
|
40739
40593
|
let patch;
|
|
40740
40594
|
let head;
|
|
40741
40595
|
try {
|
|
@@ -40929,7 +40783,6 @@ ${list}`);
|
|
|
40929
40783
|
...crossRepoFilingIssue.status !== "not-applicable" ? { crossRepoFilingIssue } : {},
|
|
40930
40784
|
...recovery ? { postMergeReconRecovery: recovery } : {}
|
|
40931
40785
|
});
|
|
40932
|
-
invalidateStatuslineBoardCache();
|
|
40933
40786
|
for (const line of postMergeReconWarnings({
|
|
40934
40787
|
context: "pr land",
|
|
40935
40788
|
boardAdvance,
|
|
@@ -40983,7 +40836,7 @@ ${list}`);
|
|
|
40983
40836
|
const mergeSquashBody = squashBodyTextForMerge(
|
|
40984
40837
|
closingGuardInput,
|
|
40985
40838
|
method === "--squash",
|
|
40986
|
-
o.squashBodyFile ? (0,
|
|
40839
|
+
o.squashBodyFile ? (0, import_node_fs41.readFileSync)(o.squashBodyFile, "utf8") : void 0
|
|
40987
40840
|
);
|
|
40988
40841
|
if (!o.squashBodyFile) warnSquashBodyClosingStrip("pr merge", closingGuardInput, mergeSquashBody);
|
|
40989
40842
|
const closingGuardVerdict = evaluateClosingGuard(closingGuardInput, {
|
|
@@ -41015,7 +40868,7 @@ ${list}`);
|
|
|
41015
40868
|
const remote = foreignCwd ? `https://github.com/${targetRepo2}.git` : "origin";
|
|
41016
40869
|
let foreignCheckout;
|
|
41017
40870
|
if (foreignCwd) {
|
|
41018
|
-
const sibling = (0,
|
|
40871
|
+
const sibling = (0, import_node_path39.join)((0, import_node_path39.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
|
|
41019
40872
|
const siblingRepo = repoFromRemoteUrl(await gitOut(["-C", sibling, "remote", "get-url", "origin"]).catch(() => ""));
|
|
41020
40873
|
if (siblingRepo?.toLowerCase() === targetRepo2.toLowerCase()) {
|
|
41021
40874
|
const siblingWorktrees = await execFileP("git", ["-C", sibling, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => parseGitWorktreePorcelain(r.stdout)).catch(() => void 0);
|
|
@@ -41113,7 +40966,7 @@ ${list}`);
|
|
|
41113
40966
|
}
|
|
41114
40967
|
if (!repoForPostCleanup) throw e;
|
|
41115
40968
|
console.warn(`pr merge: gh GraphQL rate-limited \u2014 merging PR #${number} via REST PUT instead (#4588).`);
|
|
41116
|
-
const commitMessage = bodyFile ? (0,
|
|
40969
|
+
const commitMessage = bodyFile ? (0, import_node_fs41.readFileSync)(bodyFile, "utf8") : void 0;
|
|
41117
40970
|
await defaultGitHubClient().rest("PUT", `repos/${repoForPostCleanup}/pulls/${number}/merge`, {
|
|
41118
40971
|
body: { merge_method: method.slice(2), ...commitMessage ? { commit_message: commitMessage } : {} },
|
|
41119
40972
|
timeoutMs: GH_MUTATION_TIMEOUT_MS
|
|
@@ -41233,7 +41086,7 @@ ${list}`);
|
|
|
41233
41086
|
preserveWorktree: o.preserveWorktree,
|
|
41234
41087
|
gcAcknowledged: o.gc,
|
|
41235
41088
|
expectedHeadOid: headRefOid,
|
|
41236
|
-
pathExists: (p) => (0,
|
|
41089
|
+
pathExists: (p) => (0, import_node_fs41.existsSync)(p),
|
|
41237
41090
|
// #5899: pin cleanup git calls to the main checkout — the task worktree this process may be
|
|
41238
41091
|
// standing in is removed mid-cleanup, so a cwd-relative invocation fails with
|
|
41239
41092
|
// 'fatal: not a git repository' and leaves a spurious partial-cleanup exit.
|
|
@@ -41298,7 +41151,6 @@ ${list}`);
|
|
|
41298
41151
|
} else if (repoForPostCleanup) {
|
|
41299
41152
|
clearPostMergeReconRecovery(process.cwd(), repoForPostCleanup, number);
|
|
41300
41153
|
}
|
|
41301
|
-
invalidateStatuslineBoardCache();
|
|
41302
41154
|
const devDeploy = devDeployPlan.applicable && devDeployDeps && remoteNotAttemptedReason !== "pr-already-merged" ? await dispatchDevDeploy(repoForPostCleanup, devDeployDeps) : void 0;
|
|
41303
41155
|
const devDeployManual = devDeployPlan.applicable ? devDeployPlan.manualPointer : void 0;
|
|
41304
41156
|
let observedMethod;
|
|
@@ -41355,7 +41207,7 @@ ${list}`);
|
|
|
41355
41207
|
}
|
|
41356
41208
|
|
|
41357
41209
|
// src/command-register-developer.ts
|
|
41358
|
-
var
|
|
41210
|
+
var import_node_fs46 = require("node:fs");
|
|
41359
41211
|
|
|
41360
41212
|
// src/whoami.ts
|
|
41361
41213
|
async function resolveWhoami(deps) {
|
|
@@ -41385,7 +41237,7 @@ async function resolveWhoami(deps) {
|
|
|
41385
41237
|
}
|
|
41386
41238
|
|
|
41387
41239
|
// src/command-register-developer.ts
|
|
41388
|
-
var
|
|
41240
|
+
var import_node_path44 = require("node:path");
|
|
41389
41241
|
|
|
41390
41242
|
// src/wave-land.ts
|
|
41391
41243
|
function planWaveLand(prs) {
|
|
@@ -41416,7 +41268,7 @@ async function executeWaveLand(plan, deps) {
|
|
|
41416
41268
|
}
|
|
41417
41269
|
|
|
41418
41270
|
// src/box-commands.ts
|
|
41419
|
-
var
|
|
41271
|
+
var import_node_fs42 = require("node:fs");
|
|
41420
41272
|
|
|
41421
41273
|
// src/box.ts
|
|
41422
41274
|
var BOX_KEYS = {
|
|
@@ -41618,7 +41470,7 @@ function registerBoxCommands(program3) {
|
|
|
41618
41470
|
return;
|
|
41619
41471
|
}
|
|
41620
41472
|
const wroteScript = o.ssh && o.script ? o.script : null;
|
|
41621
|
-
if (wroteScript) (0,
|
|
41473
|
+
if (wroteScript) (0, import_node_fs42.writeFileSync)(wroteScript, sshRecipeScript(found), "utf8");
|
|
41622
41474
|
if (o.json) {
|
|
41623
41475
|
console.log(JSON.stringify({
|
|
41624
41476
|
box: found,
|
|
@@ -41638,21 +41490,21 @@ ${SSH_RECIPE_AGENT_NOTE}`);
|
|
|
41638
41490
|
}
|
|
41639
41491
|
|
|
41640
41492
|
// src/dist-drift.ts
|
|
41641
|
-
var
|
|
41493
|
+
var import_node_child_process17 = require("node:child_process");
|
|
41642
41494
|
var import_node_crypto13 = require("node:crypto");
|
|
41643
|
-
var
|
|
41644
|
-
var
|
|
41645
|
-
var
|
|
41495
|
+
var import_node_fs44 = require("node:fs");
|
|
41496
|
+
var import_node_os20 = require("node:os");
|
|
41497
|
+
var import_node_path41 = require("node:path");
|
|
41646
41498
|
|
|
41647
41499
|
// ../scripts/distribution-digest.mjs
|
|
41648
41500
|
var import_node_crypto12 = require("node:crypto");
|
|
41649
|
-
var
|
|
41650
|
-
var
|
|
41501
|
+
var import_node_fs43 = require("node:fs");
|
|
41502
|
+
var import_node_path40 = require("node:path");
|
|
41651
41503
|
var slash = (value) => value.replaceAll("\\", "/");
|
|
41652
41504
|
function repoPath(root, declaredPath, label) {
|
|
41653
|
-
const absoluteRoot = (0,
|
|
41654
|
-
const target = (0,
|
|
41655
|
-
if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${
|
|
41505
|
+
const absoluteRoot = (0, import_node_path40.resolve)(root);
|
|
41506
|
+
const target = (0, import_node_path40.resolve)(root, declaredPath);
|
|
41507
|
+
if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path40.sep}`)) {
|
|
41656
41508
|
throw new Error(`${label} ${declaredPath} escapes the repository root`);
|
|
41657
41509
|
}
|
|
41658
41510
|
return target;
|
|
@@ -41660,7 +41512,7 @@ function repoPath(root, declaredPath, label) {
|
|
|
41660
41512
|
function digestFiles(files) {
|
|
41661
41513
|
const hash = (0, import_node_crypto12.createHash)("sha256");
|
|
41662
41514
|
for (const file of [...files].sort((a, b) => a.relative.localeCompare(b.relative))) {
|
|
41663
|
-
const content = file.stat.isSymbolicLink() ? Buffer.from((0,
|
|
41515
|
+
const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs43.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs43.readFileSync)(file.absolute);
|
|
41664
41516
|
hash.update(file.relative, "utf8");
|
|
41665
41517
|
hash.update("\0");
|
|
41666
41518
|
hash.update(file.stat.isSymbolicLink() ? "symlink" : "file", "utf8");
|
|
@@ -41675,8 +41527,8 @@ function digestFiles(files) {
|
|
|
41675
41527
|
function digestPackedFiles(packageRoot, packedFiles) {
|
|
41676
41528
|
return digestFiles(packedFiles.map((path2) => {
|
|
41677
41529
|
const absolute = repoPath(packageRoot, path2, "packed artifact identity path");
|
|
41678
|
-
if (!(0,
|
|
41679
|
-
return { absolute, relative: slash(path2), stat: (0,
|
|
41530
|
+
if (!(0, import_node_fs43.existsSync)(absolute)) throw new Error(`packed artifact identity path ${path2} does not exist`);
|
|
41531
|
+
return { absolute, relative: slash(path2), stat: (0, import_node_fs43.lstatSync)(absolute) };
|
|
41680
41532
|
}));
|
|
41681
41533
|
}
|
|
41682
41534
|
|
|
@@ -41760,13 +41612,13 @@ function renderDistDriftReceipt(receipt) {
|
|
|
41760
41612
|
return lines2;
|
|
41761
41613
|
}
|
|
41762
41614
|
function readOrNull(path2) {
|
|
41763
|
-
return (0,
|
|
41615
|
+
return (0, import_node_fs44.existsSync)(path2) ? (0, import_node_fs44.readFileSync)(path2) : null;
|
|
41764
41616
|
}
|
|
41765
41617
|
function walkFiles(root) {
|
|
41766
41618
|
const files = [];
|
|
41767
41619
|
const walk2 = (directory) => {
|
|
41768
|
-
for (const entry of (0,
|
|
41769
|
-
const child2 = (0,
|
|
41620
|
+
for (const entry of (0, import_node_fs44.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
41621
|
+
const child2 = (0, import_node_path41.join)(directory, entry.name);
|
|
41770
41622
|
if (entry.isDirectory()) walk2(child2);
|
|
41771
41623
|
else files.push(child2);
|
|
41772
41624
|
}
|
|
@@ -41776,14 +41628,14 @@ function walkFiles(root) {
|
|
|
41776
41628
|
}
|
|
41777
41629
|
function bomPathFor(root) {
|
|
41778
41630
|
try {
|
|
41779
|
-
const registry2 = JSON.parse((0,
|
|
41780
|
-
return (0,
|
|
41631
|
+
const registry2 = JSON.parse((0, import_node_fs44.readFileSync)((0, import_node_path41.join)(root, "surfaces.json"), "utf8"));
|
|
41632
|
+
return (0, import_node_path41.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
|
|
41781
41633
|
} catch {
|
|
41782
|
-
return (0,
|
|
41634
|
+
return (0, import_node_path41.join)(root, "distribution-bom.json");
|
|
41783
41635
|
}
|
|
41784
41636
|
}
|
|
41785
41637
|
function rebuildTo(packageRoot, outDir) {
|
|
41786
|
-
(0,
|
|
41638
|
+
(0, import_node_child_process17.execFileSync)(process.execPath, ["build.mjs"], {
|
|
41787
41639
|
cwd: packageRoot,
|
|
41788
41640
|
env: { ...process.env, MMI_DIST_OUTDIR: outDir },
|
|
41789
41641
|
windowsHide: true,
|
|
@@ -41792,35 +41644,35 @@ function rebuildTo(packageRoot, outDir) {
|
|
|
41792
41644
|
});
|
|
41793
41645
|
}
|
|
41794
41646
|
function runDistStatus(root) {
|
|
41795
|
-
const stage = (0,
|
|
41647
|
+
const stage = (0, import_node_fs44.mkdtempSync)((0, import_node_path41.join)((0, import_node_os20.tmpdir)(), "mmi-dist-drift-"));
|
|
41796
41648
|
let overlayCount = 0;
|
|
41797
41649
|
try {
|
|
41798
|
-
const cliOut = (0,
|
|
41799
|
-
const hubOut = (0,
|
|
41800
|
-
rebuildTo((0,
|
|
41801
|
-
rebuildTo((0,
|
|
41650
|
+
const cliOut = (0, import_node_path41.join)(stage, "cli-dist");
|
|
41651
|
+
const hubOut = (0, import_node_path41.join)(stage, "hub-dist");
|
|
41652
|
+
rebuildTo((0, import_node_path41.join)(root, "cli"), cliOut);
|
|
41653
|
+
rebuildTo((0, import_node_path41.join)(root, "updater"), hubOut);
|
|
41802
41654
|
const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
|
|
41803
41655
|
const rebuilt = (path2) => {
|
|
41804
41656
|
const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
|
|
41805
|
-
return spec ? readOrNull((0,
|
|
41657
|
+
return spec ? readOrNull((0, import_node_path41.join)(outDirFor(spec.packageDir), spec.output)) : null;
|
|
41806
41658
|
};
|
|
41807
|
-
const committed = (path2) => readOrNull((0,
|
|
41808
|
-
const tree = (path2) => readOrNull((0,
|
|
41809
|
-
const distRoot = (0,
|
|
41810
|
-
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0,
|
|
41811
|
-
const bom = JSON.parse((0,
|
|
41659
|
+
const committed = (path2) => readOrNull((0, import_node_path41.join)(root, path2));
|
|
41660
|
+
const tree = (path2) => readOrNull((0, import_node_path41.join)(root, path2));
|
|
41661
|
+
const distRoot = (0, import_node_path41.join)(root, "cli", "dist");
|
|
41662
|
+
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path41.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
|
|
41663
|
+
const bom = JSON.parse((0, import_node_fs44.readFileSync)(bomPathFor(root), "utf8"));
|
|
41812
41664
|
const digest = (entries) => {
|
|
41813
|
-
const overlay = (0,
|
|
41665
|
+
const overlay = (0, import_node_path41.join)(stage, `overlay-${overlayCount++}`);
|
|
41814
41666
|
for (const entry of entries) {
|
|
41815
|
-
const target = (0,
|
|
41816
|
-
(0,
|
|
41817
|
-
(0,
|
|
41667
|
+
const target = (0, import_node_path41.join)(overlay, entry.path);
|
|
41668
|
+
(0, import_node_fs44.mkdirSync)((0, import_node_path41.dirname)(target), { recursive: true });
|
|
41669
|
+
(0, import_node_fs44.writeFileSync)(target, entry.bytes);
|
|
41818
41670
|
}
|
|
41819
41671
|
return digestPackedFiles(overlay, entries.map((entry) => entry.path));
|
|
41820
41672
|
};
|
|
41821
41673
|
return computeDistDriftReceipt({ committed, tree, rebuilt, distTree, bom, digest });
|
|
41822
41674
|
} finally {
|
|
41823
|
-
(0,
|
|
41675
|
+
(0, import_node_fs44.rmSync)(stage, { recursive: true, force: true });
|
|
41824
41676
|
}
|
|
41825
41677
|
}
|
|
41826
41678
|
|
|
@@ -41892,7 +41744,7 @@ function registerEdgeCommands(program3) {
|
|
|
41892
41744
|
|
|
41893
41745
|
// src/schedules-lift-command.ts
|
|
41894
41746
|
var import_promises8 = require("node:fs/promises");
|
|
41895
|
-
var
|
|
41747
|
+
var import_node_path42 = require("node:path");
|
|
41896
41748
|
var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
|
|
41897
41749
|
var SCHEDULE_REPO_RE = /^[A-Za-z0-9_.-]+$/;
|
|
41898
41750
|
var SchedulesLiftUsageError = class extends Error {
|
|
@@ -41919,7 +41771,7 @@ async function readWorkflowFiles(dir) {
|
|
|
41919
41771
|
const files = [];
|
|
41920
41772
|
for (const name of names.sort()) {
|
|
41921
41773
|
if (!/\.ya?ml$/.test(name)) continue;
|
|
41922
|
-
files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises8.readFile)((0,
|
|
41774
|
+
files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises8.readFile)((0, import_node_path42.join)(dir, name), "utf8") });
|
|
41923
41775
|
}
|
|
41924
41776
|
return files;
|
|
41925
41777
|
}
|
|
@@ -42001,9 +41853,9 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
|
|
|
42001
41853
|
}
|
|
42002
41854
|
|
|
42003
41855
|
// src/spawn-policy-core.ts
|
|
42004
|
-
var
|
|
42005
|
-
var
|
|
42006
|
-
var
|
|
41856
|
+
var import_node_child_process18 = require("node:child_process");
|
|
41857
|
+
var import_node_fs45 = require("node:fs");
|
|
41858
|
+
var import_node_path43 = require("node:path");
|
|
42007
41859
|
var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
|
|
42008
41860
|
var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
|
|
42009
41861
|
var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
|
|
@@ -42072,7 +41924,7 @@ function findViolationsInSource(raw) {
|
|
|
42072
41924
|
return found;
|
|
42073
41925
|
}
|
|
42074
41926
|
function policedFiles(root) {
|
|
42075
|
-
const r = (0,
|
|
41927
|
+
const r = (0, import_node_child_process18.spawnSync)("git", ["ls-files", "-z", "--cached", "--others", "--exclude-standard"], {
|
|
42076
41928
|
cwd: root,
|
|
42077
41929
|
encoding: "utf8",
|
|
42078
41930
|
windowsHide: true,
|
|
@@ -42089,7 +41941,7 @@ function runSpawnPolicy(root) {
|
|
|
42089
41941
|
for (const file of files) {
|
|
42090
41942
|
let raw;
|
|
42091
41943
|
try {
|
|
42092
|
-
raw = (0,
|
|
41944
|
+
raw = (0, import_node_fs45.readFileSync)((0, import_node_path43.join)(root, file), "utf8");
|
|
42093
41945
|
} catch {
|
|
42094
41946
|
continue;
|
|
42095
41947
|
}
|
|
@@ -42109,19 +41961,19 @@ function runSpawnPolicy(root) {
|
|
|
42109
41961
|
function registerDeveloperCommands(program3) {
|
|
42110
41962
|
const rules = program3.command("rules").description("org-managed .gitignore delivery");
|
|
42111
41963
|
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) => {
|
|
42112
|
-
const path2 = (0,
|
|
42113
|
-
const current = (0,
|
|
41964
|
+
const path2 = (0, import_node_path44.join)(process.cwd(), ".gitignore");
|
|
41965
|
+
const current = (0, import_node_fs46.existsSync)(path2) ? (0, import_node_fs46.readFileSync)(path2, "utf8") : null;
|
|
42114
41966
|
const plan = planManagedGitignore(current);
|
|
42115
41967
|
const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
|
|
42116
41968
|
if (opts.json) {
|
|
42117
|
-
if (opts.write && plan.changed) (0,
|
|
41969
|
+
if (opts.write && plan.changed) (0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
|
|
42118
41970
|
console.log(JSON.stringify(plan, null, 2));
|
|
42119
41971
|
if (!opts.write && plan.changed) process.exitCode = 1;
|
|
42120
41972
|
return;
|
|
42121
41973
|
}
|
|
42122
41974
|
if (opts.write) {
|
|
42123
41975
|
if (plan.changed) {
|
|
42124
|
-
(0,
|
|
41976
|
+
(0, import_node_fs46.writeFileSync)(path2, plan.content, "utf8");
|
|
42125
41977
|
console.log(`mmi-cli devops org rules gitignore: updated .gitignore (${drift})`);
|
|
42126
41978
|
} else {
|
|
42127
41979
|
console.log("mmi-cli devops org rules gitignore: up to date");
|
|
@@ -43674,12 +43526,12 @@ async function findInFlightHotfixVersion(deps, ctx, latestMainTag, workflows = H
|
|
|
43674
43526
|
}
|
|
43675
43527
|
|
|
43676
43528
|
// src/hotfix-coverage.ts
|
|
43677
|
-
var
|
|
43529
|
+
var import_node_child_process19 = require("node:child_process");
|
|
43678
43530
|
var CHERRY_TRAILER = /\(cherry picked from commit ([0-9a-f]{7,40})\)/g;
|
|
43679
43531
|
function checkHotfixCoverage(options = {}) {
|
|
43680
43532
|
const { cwd = process.cwd(), mainRef = "origin/main", rcRef = "origin/rc", manifestPaths = [] } = options;
|
|
43681
43533
|
const ack = (options.ack ?? []).filter(Boolean);
|
|
43682
|
-
const git3 = options.git ?? ((args, opts) => (0,
|
|
43534
|
+
const git3 = options.git ?? ((args, opts) => (0, import_node_child_process19.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
|
|
43683
43535
|
const revList = (range) => {
|
|
43684
43536
|
const out = git3(["rev-list", "--no-merges", range]).trim();
|
|
43685
43537
|
return out ? out.split("\n") : [];
|
|
@@ -43747,7 +43599,7 @@ function checkHotfixCoverage(options = {}) {
|
|
|
43747
43599
|
}
|
|
43748
43600
|
function checkHotfixCarries(options) {
|
|
43749
43601
|
const { cwd = process.cwd(), branch, baseRef, targets } = options;
|
|
43750
|
-
const git3 = options.git ?? ((args, opts) => (0,
|
|
43602
|
+
const git3 = options.git ?? ((args, opts) => (0, import_node_child_process19.execFileSync)("git", args, { cwd, encoding: "utf8", input: opts?.input, stdio: ["pipe", "pipe", "pipe"] }));
|
|
43751
43603
|
const isAncestor = (sha, ref) => {
|
|
43752
43604
|
try {
|
|
43753
43605
|
git3(["merge-base", "--is-ancestor", sha, ref]);
|
|
@@ -43779,8 +43631,8 @@ function checkHotfixCarries(options) {
|
|
|
43779
43631
|
}
|
|
43780
43632
|
|
|
43781
43633
|
// src/train-commands.ts
|
|
43782
|
-
var
|
|
43783
|
-
var
|
|
43634
|
+
var import_node_fs47 = require("node:fs");
|
|
43635
|
+
var import_node_path45 = require("node:path");
|
|
43784
43636
|
var INVOKED_ARGV = process.argv.slice(2);
|
|
43785
43637
|
var RELEASE_BUMP_INTENTS = ["major", "minor", "patch"];
|
|
43786
43638
|
function resolveReleaseBumpIntent(raw) {
|
|
@@ -43792,7 +43644,7 @@ function resolveReleaseBumpIntent(raw) {
|
|
|
43792
43644
|
}
|
|
43793
43645
|
function readRepoVersion() {
|
|
43794
43646
|
try {
|
|
43795
|
-
return JSON.parse((0,
|
|
43647
|
+
return JSON.parse((0, import_node_fs47.readFileSync)((0, import_node_path45.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
|
|
43796
43648
|
} catch {
|
|
43797
43649
|
return void 0;
|
|
43798
43650
|
}
|
|
@@ -44127,21 +43979,6 @@ function hotfixFollowUpLegs(runs, foldPort, alignment, foldNote, deployNote) {
|
|
|
44127
43979
|
}
|
|
44128
43980
|
return legs;
|
|
44129
43981
|
}
|
|
44130
|
-
var JERV_POWERTOOLS_REPO = "mutmutco/Jerv-PowerTools";
|
|
44131
|
-
async function runPostReleaseJervDoctor(repo) {
|
|
44132
|
-
if (repo.toLowerCase() !== JERV_POWERTOOLS_REPO.toLowerCase()) return void 0;
|
|
44133
|
-
try {
|
|
44134
|
-
await execJervCli(["doctor"], { timeout: 10 * 6e4 });
|
|
44135
|
-
return { status: "completed", note: "jerv-cli doctor completed on this owner machine" };
|
|
44136
|
-
} catch (e) {
|
|
44137
|
-
const err = e;
|
|
44138
|
-
const detail = (err.stderr?.trim() || err.message || "unknown doctor failure").split(/\r?\n/)[0];
|
|
44139
|
-
return {
|
|
44140
|
-
status: "reported-issues",
|
|
44141
|
-
note: `jerv-cli doctor ran but reported issues (${detail})`
|
|
44142
|
-
};
|
|
44143
|
-
}
|
|
44144
|
-
}
|
|
44145
43982
|
async function runProjectInfoSyncLeg(cb, repo, sleep2 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms))) {
|
|
44146
43983
|
for (let attempt = 0; ; attempt++) {
|
|
44147
43984
|
try {
|
|
@@ -44206,9 +44043,6 @@ function renderTrainApply(commandName, r) {
|
|
|
44206
44043
|
if (r.projectInfoSync) {
|
|
44207
44044
|
base = `${base}; project info: ${r.projectInfoSync.note}`;
|
|
44208
44045
|
}
|
|
44209
|
-
if (r.postReleaseJervDoctor) {
|
|
44210
|
-
base = `${base}; Jerv convergence: ${r.postReleaseJervDoctor.note}`;
|
|
44211
|
-
}
|
|
44212
44046
|
if (r.announceNote) base = `${base}; announce: ${r.announceNote}`;
|
|
44213
44047
|
if (r.releaseVerdict) {
|
|
44214
44048
|
const v = r.releaseVerdict;
|
|
@@ -44410,7 +44244,6 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
|
|
|
44410
44244
|
const raw = await runTrainApply(commandName, trainApplyDeps(), { watch: o.watch, announceSummaryFile: o.announceSummaryFile, ack, dev: o.dev });
|
|
44411
44245
|
const result = raw.workflowRuns ? { ...raw, workflowRuns: raw.workflowRuns.map(workflowRunWithEvidence) } : raw;
|
|
44412
44246
|
let projectInfoSync;
|
|
44413
|
-
const postReleaseJervDoctor = commandName === "release" ? await runPostReleaseJervDoctor(result.repo) : void 0;
|
|
44414
44247
|
if (commandName === "release") {
|
|
44415
44248
|
projectInfoSync = await runProjectInfoSyncLeg(runProjectInfoSyncCallback, result.repo);
|
|
44416
44249
|
}
|
|
@@ -44418,7 +44251,6 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
|
|
|
44418
44251
|
const reported = {
|
|
44419
44252
|
...result,
|
|
44420
44253
|
...projectInfoSync ? { projectInfoSync } : {},
|
|
44421
|
-
...postReleaseJervDoctor ? { postReleaseJervDoctor } : {},
|
|
44422
44254
|
...releaseVerdict ? { releaseVerdict } : {}
|
|
44423
44255
|
};
|
|
44424
44256
|
const output = o.json ? JSON.stringify(reported, null, 2) : renderTrainApply(commandName, reported);
|
|
@@ -44491,7 +44323,6 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
|
|
|
44491
44323
|
...r.checkout ? [` - checkout: ${r.checkout.note}`] : [],
|
|
44492
44324
|
...r.localSync && localTrainSyncBannerLine(r.localSync) ? [` - local sync: ${localTrainSyncBannerLine(r.localSync)}`] : [],
|
|
44493
44325
|
...r.projectInfoSync ? [` - project info: ${r.projectInfoSync.note}`] : [],
|
|
44494
|
-
...r.postReleaseJervDoctor ? [` - Jerv convergence: ${r.postReleaseJervDoctor.note}`] : [],
|
|
44495
44326
|
` - next: mmi-cli devops hotfix status ${r.tag} (no back-merge of the FIX \u2014 development already has it; the version fold above is ported for you, #4410)`,
|
|
44496
44327
|
...r.ledger ? formatReleaseLedgerReport(r.ledger).map((line) => ` ${line}`) : []
|
|
44497
44328
|
].join("\n");
|
|
@@ -44552,9 +44383,8 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
|
|
|
44552
44383
|
hotfixCmd.command("start").description("cherry-pick one or more merged development PRs (or SHAs) onto hotfix/vX.Y.Z from origin/main, bump the distribution, open the main-base PR").requiredOption("--from <pr#|sha[,pr#|sha...]>", "merged development PR number(s) or commit SHA(s) to cherry-pick, in pick order \u2014 one hotfix cycle carries as many fixes as you name (#4411)").option("--json", "machine-readable output").option("--out <path>", "write the result to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5983/#6068)").action(async (o) => runHotfixSub("start", () => runHotfixStart(trainApplyDeps(), { from: o.from }), o, renderHotfixStart));
|
|
44553
44384
|
hotfixCmd.command("release <version>").description("after the hotfix PR is merged + checks green: tag, GitHub Release, watch deploy/publish, verify distribution (idempotent)").option("--json", "machine-readable output").option("--announce-summary-file <path>", "agent-curated 3-6 line release Slack summary; required for a NEW MMI-Hub hotfix Release (#883/#3901/#6068), optional for a product repo announcing to its project release channel (#6517)").option("--carries <pr#|sha[,pr#|sha...]>", "declared fix target(s) this hotfix must carry; each must be proven present before tagging (#3056)").option("--out <path>", "write the result to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5983/#6068)").action(async (version, o) => runHotfixSub("release", async () => {
|
|
44554
44385
|
const result = await runHotfixRelease(trainApplyDeps(), version, { announceSummaryFile: o.announceSummaryFile, carries: o.carries ? [o.carries] : [] });
|
|
44555
|
-
const postReleaseJervDoctor = await runPostReleaseJervDoctor(result.repo);
|
|
44556
44386
|
const projectInfoSync = await runProjectInfoSyncLeg(runProjectInfoSyncCallback, result.repo);
|
|
44557
|
-
return { ...result, projectInfoSync
|
|
44387
|
+
return { ...result, projectInfoSync };
|
|
44558
44388
|
}, o, renderHotfixRelease));
|
|
44559
44389
|
function hotfixStatusDeps() {
|
|
44560
44390
|
const STATUS_GH_MS = 8e3;
|
|
@@ -44592,12 +44422,12 @@ ${r.stderr ?? ""}`).catch(() => "");
|
|
|
44592
44422
|
var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
|
|
44593
44423
|
var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
|
|
44594
44424
|
function envHealLockPath(home) {
|
|
44595
|
-
return (0,
|
|
44425
|
+
return (0, import_node_path46.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
|
|
44596
44426
|
}
|
|
44597
44427
|
async function withEnvHealLock(what, run) {
|
|
44598
44428
|
try {
|
|
44599
44429
|
return await withFileLock(
|
|
44600
|
-
envHealLockPath((0,
|
|
44430
|
+
envHealLockPath((0, import_node_os21.homedir)()),
|
|
44601
44431
|
{ staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
|
|
44602
44432
|
run
|
|
44603
44433
|
);
|
|
@@ -44693,7 +44523,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
44693
44523
|
const configRoot = surfaceConfigRoot(surface);
|
|
44694
44524
|
const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
|
|
44695
44525
|
const plan = buildPluginCachePlan(
|
|
44696
|
-
(0,
|
|
44526
|
+
(0, import_node_os21.homedir)(),
|
|
44697
44527
|
running,
|
|
44698
44528
|
pluginCacheFsDeps(configRoot, () => 0),
|
|
44699
44529
|
{ configRoot, includeStaging: surface !== "codex" }
|
|
@@ -44721,14 +44551,14 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
44721
44551
|
const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
|
|
44722
44552
|
const installed = installedActivePluginVersion(surface);
|
|
44723
44553
|
const plan = buildPluginCachePlan(
|
|
44724
|
-
(0,
|
|
44554
|
+
(0, import_node_os21.homedir)(),
|
|
44725
44555
|
running,
|
|
44726
44556
|
pluginCacheFsDeps(configRoot, () => 0),
|
|
44727
44557
|
{ configRoot, includeStaging: surface !== "codex", installedVersion: installed }
|
|
44728
44558
|
);
|
|
44729
44559
|
const result = applyPluginCachePlan(
|
|
44730
44560
|
plan,
|
|
44731
|
-
(p) => (0,
|
|
44561
|
+
(p) => (0, import_node_fs48.rmSync)(p, { recursive: true }),
|
|
44732
44562
|
stagingApplyFsGuard(configRoot)
|
|
44733
44563
|
);
|
|
44734
44564
|
return {
|
|
@@ -44763,7 +44593,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
44763
44593
|
// has no generated routing index would
|
|
44764
44594
|
// get a permanent — demanding an artifact it never asked for.
|
|
44765
44595
|
docsIndexState: (root) => {
|
|
44766
|
-
if (!(0,
|
|
44596
|
+
if (!(0, import_node_fs48.existsSync)((0, import_node_path46.join)(root, DOCS_INDEX_PATH))) return void 0;
|
|
44767
44597
|
const real = createDocsIndexDeps(root);
|
|
44768
44598
|
let docs;
|
|
44769
44599
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -44772,7 +44602,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
44772
44602
|
},
|
|
44773
44603
|
// #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
|
|
44774
44604
|
healDocsIndex: (root) => {
|
|
44775
|
-
if (!(0,
|
|
44605
|
+
if (!(0, import_node_fs48.existsSync)((0, import_node_path46.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
|
|
44776
44606
|
const real = createDocsIndexDeps(root);
|
|
44777
44607
|
let docs;
|
|
44778
44608
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -45398,7 +45228,7 @@ project.command("set [owner/repo]").description("upsert project META (idempotent
|
|
|
45398
45228
|
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`);
|
|
45399
45229
|
if (o.secretsFile) {
|
|
45400
45230
|
try {
|
|
45401
|
-
vars.push(`secrets=${(0,
|
|
45231
|
+
vars.push(`secrets=${(0, import_node_fs48.readFileSync)(o.secretsFile, "utf8")}`);
|
|
45402
45232
|
} catch (e) {
|
|
45403
45233
|
return fail(`org project set: cannot read --secrets-file ${o.secretsFile}: ${e.message}`);
|
|
45404
45234
|
}
|
|
@@ -45720,16 +45550,16 @@ function ciAuditDeps2() {
|
|
|
45720
45550
|
// gate re-seed step is skipped gracefully rather than failing mid-run.
|
|
45721
45551
|
readSeedFile: (path2) => {
|
|
45722
45552
|
if (!root) return null;
|
|
45723
|
-
const fullPath = (0,
|
|
45724
|
-
return (0,
|
|
45553
|
+
const fullPath = (0, import_node_path46.join)(root, path2);
|
|
45554
|
+
return (0, import_node_fs48.existsSync)(fullPath) ? (0, import_node_fs48.readFileSync)(fullPath, "utf8") : null;
|
|
45725
45555
|
}
|
|
45726
45556
|
};
|
|
45727
45557
|
}
|
|
45728
45558
|
function hubRoot2() {
|
|
45729
|
-
const fromPkg = (0,
|
|
45559
|
+
const fromPkg = (0, import_node_path46.join)(__dirname, "..", "..");
|
|
45730
45560
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
45731
|
-
if ((0,
|
|
45732
|
-
if ((0,
|
|
45561
|
+
if ((0, import_node_fs48.existsSync)((0, import_node_path46.join)(fromPkg, marker))) return fromPkg;
|
|
45562
|
+
if ((0, import_node_fs48.existsSync)((0, import_node_path46.join)(process.cwd(), marker))) return process.cwd();
|
|
45733
45563
|
return null;
|
|
45734
45564
|
}
|
|
45735
45565
|
registerQueryCommands(program2);
|
|
@@ -45829,10 +45659,10 @@ access.command("audit").description("audit collaborator roles + train-branch pus
|
|
|
45829
45659
|
targets = resolution.targets;
|
|
45830
45660
|
}
|
|
45831
45661
|
const derivedMatrix = registryProjects ? accessMatrixFromProjects(registryProjects) : {};
|
|
45832
|
-
const fileMatrix = (0,
|
|
45662
|
+
const fileMatrix = (0, import_node_fs48.existsSync)("access-matrix.json") ? loadAccessMatrix((0, import_node_fs48.readFileSync)("access-matrix.json", "utf8")) : {};
|
|
45833
45663
|
const matrix = mergeAccessMatrix(fileMatrix, derivedMatrix);
|
|
45834
45664
|
const dataAccess = registryProjects ? dataAccessContractsFromProjects(registryProjects) : { consumers: {} };
|
|
45835
|
-
const sanctioned = (0,
|
|
45665
|
+
const sanctioned = (0, import_node_fs48.existsSync)("access-matrix.json") ? loadSanctionedAdmins((0, import_node_fs48.readFileSync)("access-matrix.json", "utf8")) : {};
|
|
45836
45666
|
const report = await auditOrgAccess(targets, deps, matrix, dataAccess, sanctioned);
|
|
45837
45667
|
console.log(o.json ? JSON.stringify(report, null, 2) : renderAccessReport(report));
|
|
45838
45668
|
if (!report.ok) process.exitCode = 1;
|
|
@@ -45863,16 +45693,16 @@ function directoryBytes(path2) {
|
|
|
45863
45693
|
let total = 0;
|
|
45864
45694
|
let entries;
|
|
45865
45695
|
try {
|
|
45866
|
-
entries = (0,
|
|
45696
|
+
entries = (0, import_node_fs48.readdirSync)(path2, { withFileTypes: true });
|
|
45867
45697
|
} catch {
|
|
45868
45698
|
return 0;
|
|
45869
45699
|
}
|
|
45870
45700
|
for (const entry of entries) {
|
|
45871
|
-
const child2 = (0,
|
|
45701
|
+
const child2 = (0, import_node_path46.join)(path2, entry.name);
|
|
45872
45702
|
if (entry.isDirectory()) total += directoryBytes(child2);
|
|
45873
45703
|
else {
|
|
45874
45704
|
try {
|
|
45875
|
-
total += (0,
|
|
45705
|
+
total += (0, import_node_fs48.statSync)(child2).size;
|
|
45876
45706
|
} catch {
|
|
45877
45707
|
}
|
|
45878
45708
|
}
|
|
@@ -45880,25 +45710,25 @@ function directoryBytes(path2) {
|
|
|
45880
45710
|
return total;
|
|
45881
45711
|
}
|
|
45882
45712
|
function listDirEntries(dir) {
|
|
45883
|
-
return (0,
|
|
45713
|
+
return (0, import_node_fs48.readdirSync)(dir, { withFileTypes: true }).map((d) => ({ name: d.name, isDirectory: d.isDirectory() }));
|
|
45884
45714
|
}
|
|
45885
45715
|
function readInstalledPluginRefs(configRoot) {
|
|
45886
45716
|
const p = installedPluginsPathForConfig(configRoot);
|
|
45887
|
-
if (!(0,
|
|
45717
|
+
if (!(0, import_node_fs48.existsSync)(p)) return [];
|
|
45888
45718
|
try {
|
|
45889
|
-
return installedPluginPaths((0,
|
|
45719
|
+
return installedPluginPaths((0, import_node_fs48.readFileSync)(p, "utf8"));
|
|
45890
45720
|
} catch {
|
|
45891
45721
|
return null;
|
|
45892
45722
|
}
|
|
45893
45723
|
}
|
|
45894
45724
|
function pluginCacheFsDeps(configRoot, dirBytes) {
|
|
45895
45725
|
return {
|
|
45896
|
-
exists: (p) => (0,
|
|
45897
|
-
listVersionDirs: (root) => (0,
|
|
45726
|
+
exists: (p) => (0, import_node_fs48.existsSync)(p),
|
|
45727
|
+
listVersionDirs: (root) => (0, import_node_fs48.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name),
|
|
45898
45728
|
dirBytes,
|
|
45899
|
-
listStagingDirs: (root) => (0,
|
|
45729
|
+
listStagingDirs: (root) => (0, import_node_fs48.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
|
|
45900
45730
|
try {
|
|
45901
|
-
return { name: d.name, mtimeMs: newestMtimeMs((0,
|
|
45731
|
+
return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path46.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs48.statSync)(p).mtimeMs) };
|
|
45902
45732
|
} catch {
|
|
45903
45733
|
return { name: d.name, mtimeMs: Date.now() };
|
|
45904
45734
|
}
|
|
@@ -45912,10 +45742,10 @@ function stagingApplyFsGuard(configRoot) {
|
|
|
45912
45742
|
return {
|
|
45913
45743
|
referencedPaths: () => readInstalledPluginRefs(configRoot),
|
|
45914
45744
|
mtimeMs: (name) => {
|
|
45915
|
-
const p = (0,
|
|
45916
|
-
if (!(0,
|
|
45745
|
+
const p = (0, import_node_path46.join)(stagingRoot, name);
|
|
45746
|
+
if (!(0, import_node_fs48.existsSync)(p)) return null;
|
|
45917
45747
|
try {
|
|
45918
|
-
return newestMtimeMs(p, listDirEntries, (q) => (0,
|
|
45748
|
+
return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs48.statSync)(q).mtimeMs);
|
|
45919
45749
|
} catch {
|
|
45920
45750
|
return null;
|
|
45921
45751
|
}
|
|
@@ -45935,13 +45765,13 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
|
|
|
45935
45765
|
return;
|
|
45936
45766
|
}
|
|
45937
45767
|
const plan = buildPluginCachePlan(
|
|
45938
|
-
(0,
|
|
45768
|
+
(0, import_node_os21.homedir)(),
|
|
45939
45769
|
running,
|
|
45940
45770
|
pluginCacheFsDeps(configRoot, directoryBytes),
|
|
45941
45771
|
{ withBytes: true, configRoot, includeStaging: surface !== "codex" }
|
|
45942
45772
|
);
|
|
45943
45773
|
const anythingToDelete = plan.prune.length > 0 || plan.staging.length > 0;
|
|
45944
|
-
const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0,
|
|
45774
|
+
const result = o.apply && anythingToDelete ? applyPluginCachePlan(plan, (p) => (0, import_node_fs48.rmSync)(p, { recursive: true, force: true }), stagingApplyFsGuard(configRoot)) : void 0;
|
|
45945
45775
|
const warnings = plan.prune.length > 0 ? [CONCURRENT_SESSION_WARNING] : [];
|
|
45946
45776
|
if (o.json) console.log(JSON.stringify({ ...plan, warnings, applied: result ?? null }));
|
|
45947
45777
|
else console.log(renderPluginCachePlan(plan, result));
|