@mutmutco/codex-plugin 4.6.36 → 4.6.37
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/.codex-plugin/plugin.json +1 -1
- package/cli/dist/main.cjs +574 -314
- package/cli/package.json +1 -1
- package/package.json +1 -1
- package/skills/intercom-guest/SKILL.md +22 -12
package/cli/dist/main.cjs
CHANGED
|
@@ -1229,8 +1229,6 @@ var init_house_map = __esm({
|
|
|
1229
1229
|
// --- harbour — declared lanes -------------------------------------------------------------------
|
|
1230
1230
|
"org schedules": "harbour",
|
|
1231
1231
|
// register/run/park schedule rows under the one lane contract
|
|
1232
|
-
intercom: "harbour",
|
|
1233
|
-
// #9184: the guest coordination lane to the MM Coordinator — a bounded lane, not a claim on org truth
|
|
1234
1232
|
// --- devops — shipping --------------------------------------------------------------------------
|
|
1235
1233
|
pr: "devops",
|
|
1236
1234
|
read: "devops",
|
|
@@ -1279,6 +1277,11 @@ var init_house_map = __esm({
|
|
|
1279
1277
|
pickup: "learning",
|
|
1280
1278
|
// cloud-agent adoption gate (#5708)
|
|
1281
1279
|
// --- core — the front door itself ---------------------------------------------------------------
|
|
1280
|
+
// #9993: `intercom` is the guest's own coordination door, not a declared org lane — it reads and
|
|
1281
|
+
// writes nothing of this org's truth (no schedules, no registry, no board), it talks to the Jerv
|
|
1282
|
+
// Gateway as this caller's own GitHub identity. So it is core: `mmi-cli intercom guest …`, unprefixed.
|
|
1283
|
+
// The old `harbour intercom guest …` spelling still runs through HOUSE_ALIASES below.
|
|
1284
|
+
intercom: "core",
|
|
1282
1285
|
commands: "core",
|
|
1283
1286
|
whoami: "core",
|
|
1284
1287
|
spawn: "core",
|
|
@@ -1303,7 +1306,9 @@ var init_house_map = __esm({
|
|
|
1303
1306
|
HOUSE_ALIASES = {
|
|
1304
1307
|
issue: ["devops"],
|
|
1305
1308
|
// filing/managing issues is oracle, but reads as shipping work
|
|
1306
|
-
"issue create": ["devops"]
|
|
1309
|
+
"issue create": ["devops"],
|
|
1310
|
+
intercom: ["harbour"]
|
|
1311
|
+
// #9993: `intercom` moved out of harbour to core; the old spelling still routes
|
|
1307
1312
|
};
|
|
1308
1313
|
}
|
|
1309
1314
|
});
|
|
@@ -13690,7 +13695,7 @@ function isAgentScratchPath(path2) {
|
|
|
13690
13695
|
return /^tmp_[^/]+$/.test(normalized);
|
|
13691
13696
|
}
|
|
13692
13697
|
var PUSH_WALL_AGENT_CONFIG_DIRS = [".cursor/rules/", ".codex/", ".agents/"];
|
|
13693
|
-
var LIVE_SESSION_DIRS = [".jerv/", ".pi/"];
|
|
13698
|
+
var LIVE_SESSION_DIRS = [".jerv/", ".pi/", "review-state/"];
|
|
13694
13699
|
function pathUnderDirPrefix(path2, dir) {
|
|
13695
13700
|
return path2 === dir || path2 === dir.slice(0, -1) || path2.startsWith(dir) || path2.includes(`/${dir}`);
|
|
13696
13701
|
}
|
|
@@ -14549,7 +14554,7 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
|
|
|
14549
14554
|
function archiveWorktreeTmpArtifacts(args, deps = {}) {
|
|
14550
14555
|
const copyFile = deps.copyFile ?? import_node_fs12.copyFileSync;
|
|
14551
14556
|
const fileSize = deps.fileSize ?? ((path2) => (0, import_node_fs12.statSync)(path2).size);
|
|
14552
|
-
const
|
|
14557
|
+
const writeFile5 = deps.writeFile ?? ((path2, text) => (0, import_node_fs12.writeFileSync)(path2, text));
|
|
14553
14558
|
const mkdirp = deps.mkdirp ?? ((path2) => {
|
|
14554
14559
|
(0, import_node_fs12.mkdirSync)(path2, { recursive: true });
|
|
14555
14560
|
});
|
|
@@ -14576,7 +14581,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
|
|
|
14576
14581
|
bytes += copied;
|
|
14577
14582
|
}
|
|
14578
14583
|
const manifest = (0, import_node_path9.join)((0, import_node_path9.dirname)(dest), "tmp-manifest.json");
|
|
14579
|
-
|
|
14584
|
+
writeFile5(manifest, `${JSON.stringify({ files: scan.entries.map(({ relPath, bytes: b }) => ({ relPath, bytes: b })), bytes, excluded: scan.excluded, skippedLinks: scan.links }, null, 2)}
|
|
14580
14585
|
`);
|
|
14581
14586
|
return { status: "archived", path: dest, runScope, entries: scan.entries.length, bytes, manifest, excluded: scan.excluded, skippedLinks: scan.links };
|
|
14582
14587
|
} catch (e) {
|
|
@@ -15261,8 +15266,8 @@ function resolveVerbAliasShim(argv) {
|
|
|
15261
15266
|
}
|
|
15262
15267
|
|
|
15263
15268
|
// src/command-composition.ts
|
|
15264
|
-
var
|
|
15265
|
-
var
|
|
15269
|
+
var import_node_os29 = require("node:os");
|
|
15270
|
+
var import_node_path65 = require("node:path");
|
|
15266
15271
|
|
|
15267
15272
|
// src/board-read.ts
|
|
15268
15273
|
var import_node_fs18 = require("node:fs");
|
|
@@ -25302,6 +25307,8 @@ var MANAGED_GITIGNORE_LINES = [
|
|
|
25302
25307
|
// (measured on the v3.120.0 Hub train), with no legal resolution: committing another host's runtime
|
|
25303
25308
|
// state is not an option, so the operator's only move was to park the directory outside the repo.
|
|
25304
25309
|
".pi/",
|
|
25310
|
+
// #10003: reviewer worktrees — never committable, regenerate during review (same runtime class as `.pi/`).
|
|
25311
|
+
"/review-state/",
|
|
25305
25312
|
".aws-sam/",
|
|
25306
25313
|
// jerv-cli lease markers are ephemeral runtime state and never tracked. Hub#2586.
|
|
25307
25314
|
".jerv-lease.json",
|
|
@@ -25427,7 +25434,7 @@ function extractForwardRefs(markdown) {
|
|
|
25427
25434
|
});
|
|
25428
25435
|
return refs;
|
|
25429
25436
|
}
|
|
25430
|
-
function checkPins(root,
|
|
25437
|
+
function checkPins(root, readFile11, docs) {
|
|
25431
25438
|
const findings = [];
|
|
25432
25439
|
for (const [doc, markdown] of Object.entries(docs)) {
|
|
25433
25440
|
for (const pin of extractPins(markdown)) {
|
|
@@ -25435,7 +25442,7 @@ function checkPins(root, readFile10, docs) {
|
|
|
25435
25442
|
findings.push({ kind: "malformed-pin", doc, line: pin.line, detail: pin.text });
|
|
25436
25443
|
continue;
|
|
25437
25444
|
}
|
|
25438
|
-
const source =
|
|
25445
|
+
const source = readFile11((0, import_node_path16.join)(root, pin.file));
|
|
25439
25446
|
if (source == null) {
|
|
25440
25447
|
findings.push({ kind: "missing-test", doc, line: pin.line, detail: pin.file });
|
|
25441
25448
|
continue;
|
|
@@ -25731,15 +25738,15 @@ function checkRunbookCoverage(docs, base, git3) {
|
|
|
25731
25738
|
}
|
|
25732
25739
|
return findings;
|
|
25733
25740
|
}
|
|
25734
|
-
function checkSeedRunbookReview(root, base,
|
|
25735
|
-
const manifestJson =
|
|
25741
|
+
function checkSeedRunbookReview(root, base, readFile11, git3) {
|
|
25742
|
+
const manifestJson = readFile11((0, import_node_path16.join)(root, "skills/bootstrap/seeds/manifest.json"));
|
|
25736
25743
|
if (!manifestJson) return [];
|
|
25737
25744
|
const changed = new Set(git3(["diff", "--name-only", `${base}...HEAD`]).split(/\r?\n/).filter(Boolean));
|
|
25738
25745
|
const touched = loadBootstrapSeeds(manifestJson).seeds.filter((seed) => isPropagatableSeed(seed) && changed.has(seedSourcePath(seed)));
|
|
25739
25746
|
if (!touched.length) return [];
|
|
25740
25747
|
let declarations = null;
|
|
25741
25748
|
try {
|
|
25742
|
-
declarations = JSON.parse(
|
|
25749
|
+
declarations = JSON.parse(readFile11((0, import_node_path16.join)(root, RUNBOOK_UNAFFECTED_PATH)) ?? "null");
|
|
25743
25750
|
} catch {
|
|
25744
25751
|
declarations = null;
|
|
25745
25752
|
}
|
|
@@ -25826,12 +25833,12 @@ function defaultTrackedFiles(root, firstSegments, exec3 = import_node_child_proc
|
|
|
25826
25833
|
throw error;
|
|
25827
25834
|
}
|
|
25828
25835
|
}
|
|
25829
|
-
function mergeGroupRunbookMessages(root, deps,
|
|
25836
|
+
function mergeGroupRunbookMessages(root, deps, readFile11, warnings) {
|
|
25830
25837
|
const env = deps.env ?? process.env;
|
|
25831
25838
|
if (env.GITHUB_EVENT_NAME !== "merge_group") return "";
|
|
25832
25839
|
let source = "merge_group event payload";
|
|
25833
25840
|
try {
|
|
25834
|
-
const event = JSON.parse(
|
|
25841
|
+
const event = JSON.parse(readFile11(env.GITHUB_EVENT_PATH ?? "") ?? "");
|
|
25835
25842
|
const match = /^refs\/heads\/gh-readonly-queue\/.+\/pr-([1-9]\d*)-[a-f0-9]+$/.exec(event.merge_group?.head_ref ?? "");
|
|
25836
25843
|
const repo = env.GITHUB_REPOSITORY;
|
|
25837
25844
|
if (!match || !repo || !/^[\w.-]+\/[\w.-]+$/.test(repo)) throw new Error("invalid queue source");
|
|
@@ -25854,7 +25861,7 @@ function mergeGroupRunbookMessages(root, deps, readFile10, warnings) {
|
|
|
25854
25861
|
}
|
|
25855
25862
|
}
|
|
25856
25863
|
function runDocRefs(root, deps = {}) {
|
|
25857
|
-
const
|
|
25864
|
+
const readFile11 = deps.readFile ?? readFileOrNull;
|
|
25858
25865
|
const exists = deps.exists ?? import_node_fs19.existsSync;
|
|
25859
25866
|
const listDocs = deps.listDocs ?? defaultListDocs;
|
|
25860
25867
|
const isIgnored = deps.isIgnored ?? ((paths) => defaultIsIgnored(root, paths));
|
|
@@ -25868,11 +25875,11 @@ function runDocRefs(root, deps = {}) {
|
|
|
25868
25875
|
const walked = listDocs(root);
|
|
25869
25876
|
const ignoredDocs = walked.length ? isIgnored(walked) : /* @__PURE__ */ new Set();
|
|
25870
25877
|
const docs = Object.fromEntries(
|
|
25871
|
-
walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel,
|
|
25878
|
+
walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel, readFile11((0, import_node_path16.join)(root, rel))]).filter(([rel, body]) => body != null && (!deps.runbooksOnly || isRunbook(rel, body)))
|
|
25872
25879
|
);
|
|
25873
25880
|
const refResult = checkRefs(root, { exists, isIgnored, trackedFirstSegments }, docs);
|
|
25874
25881
|
const findings = [
|
|
25875
|
-
...checkPins(root,
|
|
25882
|
+
...checkPins(root, readFile11, docs).findings,
|
|
25876
25883
|
...refResult.findings
|
|
25877
25884
|
];
|
|
25878
25885
|
if (commandPaths == null) {
|
|
@@ -25886,7 +25893,7 @@ function runDocRefs(root, deps = {}) {
|
|
|
25886
25893
|
findings.push(...checkCommands(docs, commandPaths).findings);
|
|
25887
25894
|
}
|
|
25888
25895
|
const runbooks = Object.fromEntries(Object.entries(docs).filter(([doc, body]) => isRunbook(doc, body)));
|
|
25889
|
-
findings.push(...checkRunbookClaims(root, runbooks, { readFile:
|
|
25896
|
+
findings.push(...checkRunbookClaims(root, runbooks, { readFile: readFile11, exists, isIgnored, trackedFirstSegments, commandPaths, commandOptions: deps.commandOptions, commandSource: deps.commandSource }));
|
|
25890
25897
|
const warnings = [...refResult.warnings];
|
|
25891
25898
|
if (deps.runbooksOnly && !Object.keys(runbooks).length) {
|
|
25892
25899
|
warnings.push({ kind: "runbook-missing", doc: "docs/Guides/operator.md", line: 0, detail: "no operator runbook or <!-- runbook --> document exists" });
|
|
@@ -25894,9 +25901,9 @@ function runDocRefs(root, deps = {}) {
|
|
|
25894
25901
|
if (deps.base) {
|
|
25895
25902
|
const git3 = deps.git ?? ((args) => (0, import_node_child_process6.execFileSync)("git", args, { cwd: root, encoding: "utf8", maxBuffer: CHECK_IGNORE_MAX_BUFFER, windowsHide: true }));
|
|
25896
25903
|
const stale = checkRunbookCoverage(runbooks, deps.base, git3);
|
|
25897
|
-
const seedStale = checkSeedRunbookReview(root, deps.base,
|
|
25904
|
+
const seedStale = checkSeedRunbookReview(root, deps.base, readFile11, git3);
|
|
25898
25905
|
const messages = git3(["log", "--format=%B", `${deps.base}..HEAD`]);
|
|
25899
|
-
const sourceMessages = stale.length || seedStale.length ? mergeGroupRunbookMessages(root, deps,
|
|
25906
|
+
const sourceMessages = stale.length || seedStale.length ? mergeGroupRunbookMessages(root, deps, readFile11, warnings) : "";
|
|
25900
25907
|
const allMessages = `${messages}
|
|
25901
25908
|
${sourceMessages}`;
|
|
25902
25909
|
const override = /^Runbook-Unaffected:[ \t]*\S.*$/m.test(allMessages);
|
|
@@ -26855,22 +26862,22 @@ function renderBootstrapAncillaryPlan(labels, environments, exceptions = []) {
|
|
|
26855
26862
|
...exceptions.map(({ name, detail }) => ` OK environment ${name} (${detail})`)
|
|
26856
26863
|
].join("\n");
|
|
26857
26864
|
}
|
|
26858
|
-
function resolveSeedContent(seed, vars,
|
|
26859
|
-
if (seed.source === "self") return
|
|
26865
|
+
function resolveSeedContent(seed, vars, readFile11) {
|
|
26866
|
+
if (seed.source === "self") return readFile11(seed.target);
|
|
26860
26867
|
if (seed.source.startsWith("seed:")) {
|
|
26861
|
-
const tmpl =
|
|
26868
|
+
const tmpl = readFile11(`skills/bootstrap/seeds/${seed.source.slice("seed:".length)}`);
|
|
26862
26869
|
return tmpl == null ? null : renderSeed(tmpl, vars);
|
|
26863
26870
|
}
|
|
26864
26871
|
return null;
|
|
26865
26872
|
}
|
|
26866
|
-
function resolveSeedWriteContent(seed, vars,
|
|
26873
|
+
function resolveSeedWriteContent(seed, vars, readFile11, remoteContent) {
|
|
26867
26874
|
if (!seed.managedBlock) {
|
|
26868
|
-
return { ok: true, content: resolveSeedContent(seed, vars,
|
|
26875
|
+
return { ok: true, content: resolveSeedContent(seed, vars, readFile11), managed: seed.source === "managed-block" };
|
|
26869
26876
|
}
|
|
26870
|
-
const base = remoteContent ?? resolveSeedContent(seed, vars,
|
|
26877
|
+
const base = remoteContent ?? resolveSeedContent(seed, vars, readFile11);
|
|
26871
26878
|
if (base == null) return { ok: true, content: null, managed: true };
|
|
26872
26879
|
const blockSeed = { ...seed, source: seed.managedBlock.source, managedBlock: void 0 };
|
|
26873
|
-
const desired = resolveSeedContent(blockSeed, vars,
|
|
26880
|
+
const desired = resolveSeedContent(blockSeed, vars, readFile11);
|
|
26874
26881
|
if (desired == null) return { ok: true, content: null, managed: true };
|
|
26875
26882
|
const result = upsertManagedSeedBlock(base, desired, seed.managedBlock.begin, seed.managedBlock.end);
|
|
26876
26883
|
return result.ok ? { ok: true, content: result.content, managed: true } : { ok: false, reason: result.reason, managed: true };
|
|
@@ -28385,10 +28392,10 @@ var rollout_plan_default = {
|
|
|
28385
28392
|
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)."
|
|
28386
28393
|
},
|
|
28387
28394
|
baseline: {
|
|
28388
|
-
version: "4.6.
|
|
28389
|
-
tag: "v4.6.
|
|
28390
|
-
commit: "
|
|
28391
|
-
npm: "@mutmutco/cli@4.6.
|
|
28395
|
+
version: "4.6.37",
|
|
28396
|
+
tag: "v4.6.37",
|
|
28397
|
+
commit: "94211a24e48a",
|
|
28398
|
+
npm: "@mutmutco/cli@4.6.37"
|
|
28392
28399
|
},
|
|
28393
28400
|
exitCriterion: "fleet-n-of-n",
|
|
28394
28401
|
hubOnlyShortcut: "forbidden",
|
|
@@ -28405,14 +28412,14 @@ var rollout_plan_default = {
|
|
|
28405
28412
|
repo: "mutmutco/mmi-hub",
|
|
28406
28413
|
role: "canary",
|
|
28407
28414
|
schedule: "train",
|
|
28408
|
-
v3Target: "v4.6.
|
|
28415
|
+
v3Target: "v4.6.37"
|
|
28409
28416
|
}
|
|
28410
28417
|
],
|
|
28411
28418
|
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.",
|
|
28412
28419
|
rollback: {
|
|
28413
28420
|
independent: true,
|
|
28414
|
-
mechanism: "npm dist-tag latest -> 4.6.
|
|
28415
|
-
v3Target: "v4.6.
|
|
28421
|
+
mechanism: "npm dist-tag latest -> 4.6.37 and redeploy the Hub Lambda from tag v4.6.37 (94211a24e48a); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
28422
|
+
v3Target: "v4.6.37 (@mutmutco/cli@4.6.37, tag commit 94211a24e48a \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
28416
28423
|
}
|
|
28417
28424
|
},
|
|
28418
28425
|
{
|
|
@@ -43435,8 +43442,8 @@ function annotateChangeMeaning(changed, policy, read) {
|
|
|
43435
43442
|
function isMeaningfulRow(file) {
|
|
43436
43443
|
return file.meaningful !== false;
|
|
43437
43444
|
}
|
|
43438
|
-
function loadPolicy(root,
|
|
43439
|
-
const raw =
|
|
43445
|
+
function loadPolicy(root, readFile11 = readFileOrNull2) {
|
|
43446
|
+
const raw = readFile11((0, import_node_path30.join)(root, POLICY_FILE));
|
|
43440
43447
|
if (raw == null) return { mandatory: [], declared: false };
|
|
43441
43448
|
return parsePolicy(raw, POLICY_FILE);
|
|
43442
43449
|
}
|
|
@@ -44173,12 +44180,16 @@ async function submitQueueAdmission(pr, repo, head, read, write, options, resume
|
|
|
44173
44180
|
receipt = { ...receipt, state: "pending", uuid: details.uuid };
|
|
44174
44181
|
}
|
|
44175
44182
|
const sleep2 = options.sleep ?? ((ms) => new Promise((resolve8) => setTimeout(resolve8, ms)));
|
|
44176
|
-
|
|
44177
|
-
|
|
44183
|
+
const confirmDelays = [0, 1e3, 2e3, 4e3, 8e3, 15e3, 15e3, 15e3];
|
|
44184
|
+
let readFailure;
|
|
44185
|
+
for (const delay of confirmDelays) {
|
|
44186
|
+
if (delay) await sleep2(delay);
|
|
44187
|
+
readFailure = void 0;
|
|
44178
44188
|
try {
|
|
44179
44189
|
response = admissionResponse(await read([`repos/${repo}/pulls/${pr}/merge-async/${receipt.uuid}`, "--include", ...ASYNC_HEADERS]));
|
|
44180
44190
|
} catch {
|
|
44181
|
-
|
|
44191
|
+
readFailure = "the saved operation cannot be read (including expired results)";
|
|
44192
|
+
continue;
|
|
44182
44193
|
}
|
|
44183
44194
|
if (response.code !== 200) return reconcile(`the saved operation returned HTTP ${response.code}`);
|
|
44184
44195
|
const { status, details } = response.body;
|
|
@@ -44220,6 +44231,7 @@ async function submitQueueAdmission(pr, repo, head, read, write, options, resume
|
|
|
44220
44231
|
if (receipt.head !== head) return reconcile("the previous head completed admission; inspect current head and membership before continuing");
|
|
44221
44232
|
return reconcile(`operation ${receipt.uuid} reported ${status}, but matching-head membership or merged state is unconfirmed`, status === "enqueued");
|
|
44222
44233
|
}
|
|
44234
|
+
if (readFailure) return reconcile(readFailure);
|
|
44223
44235
|
return markReenqueued({
|
|
44224
44236
|
mergeStatus: "queue-admission-pending",
|
|
44225
44237
|
retryable: false,
|
|
@@ -44442,8 +44454,8 @@ async function abandonQueueAdmission(pr, repo, options = {}) {
|
|
|
44442
44454
|
}
|
|
44443
44455
|
const receipt = journal.receipt;
|
|
44444
44456
|
if (!receipt) return refuse("no queue-admission receipt exists for this PR; nothing to abandon");
|
|
44445
|
-
if (!["pending", "enqueued"].includes(receipt.state)) {
|
|
44446
|
-
return refuse(`the saved admission is '${receipt.state}', not a stuck non-terminal 'pending'/'enqueued' receipt; nothing to abandon`);
|
|
44457
|
+
if (!["pending", "enqueued"].includes(receipt.state) && !(receipt.state === "dispatching" && !receipt.uuid)) {
|
|
44458
|
+
return refuse(`the saved admission is '${receipt.state}'${receipt.uuid ? ` with operation ${receipt.uuid}` : ""}, not a stuck non-terminal 'pending'/'enqueued' receipt; nothing to abandon`);
|
|
44447
44459
|
}
|
|
44448
44460
|
let snapshot;
|
|
44449
44461
|
try {
|
|
@@ -45777,20 +45789,20 @@ function buildPrLifecycle(state, manifest, joins) {
|
|
|
45777
45789
|
if (member.pr !== state.number) continue;
|
|
45778
45790
|
if (!member.admission_event_id) continue;
|
|
45779
45791
|
const ep = episodes.find((x) => x.episode_id === member.admission_event_id);
|
|
45780
|
-
const
|
|
45781
|
-
if (!
|
|
45792
|
+
const join55 = joins.find((j) => j.run_id === run.run_id && j.run_attempt === run.run_attempt && j.pr === member.pr && j.admission_event_id === member.admission_event_id);
|
|
45793
|
+
if (!join55) continue;
|
|
45782
45794
|
if (!ep) {
|
|
45783
45795
|
if (state.status === "complete") {
|
|
45784
|
-
|
|
45785
|
-
|
|
45796
|
+
join55.status = "unresolved";
|
|
45797
|
+
join55.reason = "admission-event-not-in-history";
|
|
45786
45798
|
} else {
|
|
45787
|
-
|
|
45788
|
-
|
|
45799
|
+
join55.status = "unresolved";
|
|
45800
|
+
join55.reason = "history-incomplete";
|
|
45789
45801
|
}
|
|
45790
45802
|
continue;
|
|
45791
45803
|
}
|
|
45792
|
-
|
|
45793
|
-
delete
|
|
45804
|
+
join55.status = "joined";
|
|
45805
|
+
delete join55.reason;
|
|
45794
45806
|
ep.runs.push({ run_id: run.run_id, run_attempt: run.run_attempt, head_sha: run.head_sha });
|
|
45795
45807
|
}
|
|
45796
45808
|
}
|
|
@@ -51654,7 +51666,7 @@ function registerBootstrapCommands(program3) {
|
|
|
51654
51666
|
const slug = parsedRepo.slug;
|
|
51655
51667
|
const onlyTarget = o.fromConfig && o.only.trim() === "gate.yml" ? ".github/workflows/gate.yml" : o.only.trim();
|
|
51656
51668
|
const gh2 = async (args) => execFileP("gh", args, { timeout: 2e4 });
|
|
51657
|
-
const
|
|
51669
|
+
const readFile11 = (p) => (0, import_node_fs40.existsSync)(p) ? (0, import_node_fs40.readFileSync)(p, "utf8") : null;
|
|
51658
51670
|
const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
|
|
51659
51671
|
const putSeed = async (target, content, ref, sha) => {
|
|
51660
51672
|
const tmp = (0, import_node_path37.join)((0, import_node_os21.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
|
|
@@ -51826,7 +51838,7 @@ function registerBootstrapCommands(program3) {
|
|
|
51826
51838
|
registryMeta?.requiredCheckBranches,
|
|
51827
51839
|
registryMeta?.requiredChecks
|
|
51828
51840
|
);
|
|
51829
|
-
const rendered = resolveSeedContent(gateSeed, gateVars,
|
|
51841
|
+
const rendered = resolveSeedContent(gateSeed, gateVars, readFile11);
|
|
51830
51842
|
if (rendered === null || missingPlaceholders(rendered).length) return failGraceful("bootstrap apply: registry gate template is unreadable or has unfilled placeholders");
|
|
51831
51843
|
const base = (await readTargetedSeedFiles(repo, scopedPlan, onlyTarget, scopedPlan.baseSha, controlClient)).base?.content ?? null;
|
|
51832
51844
|
configGateAction = planGateFromConfig(base, rendered);
|
|
@@ -51930,7 +51942,7 @@ function registerBootstrapCommands(program3) {
|
|
|
51930
51942
|
...vars,
|
|
51931
51943
|
...registryMeta?.requiredChecks?.length ? { GATE_RULESET_CONTEXTS_JSON: rulesetVars.GATE_RULESET_CONTEXTS_JSON } : {},
|
|
51932
51944
|
...registryMeta?.requiredCheckBranches?.length ? { GATE_RULESET_BRANCH_REFS_JSON: rulesetVars.GATE_RULESET_BRANCH_REFS_JSON } : {}
|
|
51933
|
-
} : vars,
|
|
51945
|
+
} : vars, readFile11, preservedContent);
|
|
51934
51946
|
if (!writeContent.ok) {
|
|
51935
51947
|
return fail(`bootstrap apply: ${resolved.target}: ${writeContent.reason} \u2014 refusing to overwrite repo-owned content`);
|
|
51936
51948
|
}
|
|
@@ -52076,7 +52088,7 @@ ${onlyManagedBlock ? `Only the marker-bounded Hub-managed block inside repo-owne
|
|
|
52076
52088
|
}
|
|
52077
52089
|
const rulesetSeed = repo.toLowerCase() === "mutmutco/mmi-hub" ? void 0 : manifest.seeds.find((s) => s.target === ".github/rulesets/mmi-product-required-checks.json");
|
|
52078
52090
|
if (rulesetSeed) {
|
|
52079
|
-
const rulesetContent = resolveSeedContent({ ...rulesetSeed, target: rulesetSeed.target.replace("{{REPO_SLUG}}", slug) }, vars,
|
|
52091
|
+
const rulesetContent = resolveSeedContent({ ...rulesetSeed, target: rulesetSeed.target.replace("{{REPO_SLUG}}", slug) }, vars, readFile11);
|
|
52080
52092
|
if (rulesetContent) {
|
|
52081
52093
|
try {
|
|
52082
52094
|
const client = controlClient;
|
|
@@ -52868,32 +52880,183 @@ function registerDeployCommands(program3) {
|
|
|
52868
52880
|
}
|
|
52869
52881
|
|
|
52870
52882
|
// src/intercom-guest.ts
|
|
52883
|
+
var import_node_crypto19 = require("node:crypto");
|
|
52884
|
+
var import_promises5 = require("node:fs/promises");
|
|
52885
|
+
var import_node_os22 = require("node:os");
|
|
52886
|
+
var import_node_path38 = require("node:path");
|
|
52887
|
+
init_cli_shared();
|
|
52871
52888
|
init_github_client();
|
|
52872
|
-
var CANONICAL_COMMAND = "mmi-cli
|
|
52889
|
+
var CANONICAL_COMMAND = "mmi-cli intercom guest";
|
|
52873
52890
|
var INTERCOM_GUEST_VERBS = ["register", "read", "send", "join", "leave"];
|
|
52891
|
+
var DELIVERIES_LIMIT_MAX = 100;
|
|
52892
|
+
var DELIVERIES_LIMIT_DEFAULT = 20;
|
|
52893
|
+
function deliveriesLimit(limit) {
|
|
52894
|
+
if (limit === void 0 || !Number.isFinite(limit) || limit < 1) return DELIVERIES_LIMIT_DEFAULT;
|
|
52895
|
+
return Math.min(Math.floor(limit), DELIVERIES_LIMIT_MAX);
|
|
52896
|
+
}
|
|
52874
52897
|
var INTERCOM_GUEST_CONTRACT = {
|
|
52875
|
-
source: "mutmutco/Jerv-Hub#
|
|
52898
|
+
source: "mutmutco/Jerv-Hub#2727 published guest wire contract (gateway/v1: contract/operations.js, contract/authorization.json, src/http/handler.js)",
|
|
52899
|
+
contractVersion: "gateway/v1",
|
|
52900
|
+
baseUrl: "https://jerv-central.tail4ce549.ts.net",
|
|
52876
52901
|
baseUrlEnv: "MMI_INTERCOM_GATEWAY_URL",
|
|
52877
|
-
|
|
52902
|
+
discovery: {
|
|
52903
|
+
operation: "intercom.directory",
|
|
52904
|
+
method: "POST",
|
|
52905
|
+
path: "/v1/intercom/directory",
|
|
52906
|
+
mutation: false,
|
|
52907
|
+
credential: "required",
|
|
52908
|
+
// Idle endpoints are included on purpose: the Coordinator is reachable while it is idle, and the
|
|
52909
|
+
// contract says to match its display name and take the id from the row, never to remember one.
|
|
52910
|
+
body: () => ({ limit: 200, includeIdle: true })
|
|
52911
|
+
},
|
|
52912
|
+
operations: {
|
|
52913
|
+
// #9993 — the guest's first contact. `displayName` is the gh login; the Gateway appends 8 hex of the
|
|
52914
|
+
// endpoint id only when the name collides. HostKind/project are optional and omitted (the Gateway
|
|
52915
|
+
// stores `remote`). With a stored credential this same call rotates and resumes the endpoint.
|
|
52916
|
+
register: {
|
|
52917
|
+
operation: "intercom.register",
|
|
52918
|
+
method: "POST",
|
|
52919
|
+
path: "/v1/intercom/register",
|
|
52920
|
+
mutation: true,
|
|
52921
|
+
credential: "optional",
|
|
52922
|
+
needsLogin: true,
|
|
52923
|
+
body: (_request, context) => ({ displayName: context.login ?? "" })
|
|
52924
|
+
},
|
|
52925
|
+
// #9993 — `read` is the inbox: pending deliveries. Accepting them (intercom.accept) or acking them
|
|
52926
|
+
// (intercom.ack) is a separate, explicit call the contract documents under `cliVerbs.read.then`.
|
|
52927
|
+
read: {
|
|
52928
|
+
operation: "intercom.deliveries",
|
|
52929
|
+
method: "POST",
|
|
52930
|
+
path: "/v1/intercom/deliveries",
|
|
52931
|
+
mutation: false,
|
|
52932
|
+
credential: "required",
|
|
52933
|
+
body: (request) => ({ state: "pending", limit: deliveriesLimit(request.limit) })
|
|
52934
|
+
},
|
|
52935
|
+
// #9993 — the wire field is `text`. A body field named `message` is `unknown_field` at the Gateway.
|
|
52936
|
+
send: {
|
|
52937
|
+
operation: "intercom.send",
|
|
52938
|
+
method: "POST",
|
|
52939
|
+
path: "/v1/intercom/send",
|
|
52940
|
+
mutation: true,
|
|
52941
|
+
credential: "required",
|
|
52942
|
+
body: (request) => ({ to: request.to, text: request.message })
|
|
52943
|
+
},
|
|
52944
|
+
// #9993 — no Gateway operation admits a guest to a suite (Jerv-Hub#2524): a join is an ordinary
|
|
52945
|
+
// `send` to the Coordinator carrying the suite message convention. The suite name travels inside the
|
|
52946
|
+
// text because the convention carries no suite field.
|
|
52947
|
+
join: {
|
|
52948
|
+
operation: "intercom.send",
|
|
52949
|
+
method: "POST",
|
|
52950
|
+
path: "/v1/intercom/send",
|
|
52951
|
+
mutation: true,
|
|
52952
|
+
credential: "required",
|
|
52953
|
+
needsCoordinator: true,
|
|
52954
|
+
body: (request, context) => ({
|
|
52955
|
+
to: context.coordinator,
|
|
52956
|
+
text: `Suite join: ${context.endpointId ?? ""}, ${context.displayName ?? context.login ?? ""} guest, repo ${context.repo}, host ${context.host}, suite ${request.suite ?? ""}`
|
|
52957
|
+
})
|
|
52958
|
+
},
|
|
52959
|
+
// #9993 — leaving is the same shape, and the Coordinator marks the seat left.
|
|
52960
|
+
leave: {
|
|
52961
|
+
operation: "intercom.send",
|
|
52962
|
+
method: "POST",
|
|
52963
|
+
path: "/v1/intercom/send",
|
|
52964
|
+
mutation: true,
|
|
52965
|
+
credential: "required",
|
|
52966
|
+
needsCoordinator: true,
|
|
52967
|
+
body: (_request, context) => ({
|
|
52968
|
+
to: context.coordinator,
|
|
52969
|
+
text: `Suite leave: ${context.endpointId ?? ""}`
|
|
52970
|
+
})
|
|
52971
|
+
}
|
|
52972
|
+
}
|
|
52878
52973
|
};
|
|
52879
52974
|
var INTERCOM_GUEST_CONTRACT_MISSING = "intercom-guest-contract-missing";
|
|
52880
52975
|
var INTERCOM_GUEST_BASE_URL_MISSING = "intercom-guest-base-url-missing";
|
|
52881
52976
|
var INTERCOM_GUEST_NO_IDENTITY = "intercom-guest-no-identity";
|
|
52977
|
+
var INTERCOM_GUEST_INPUT_MISSING = "intercom-guest-input-missing";
|
|
52978
|
+
var INTERCOM_GUEST_NO_CREDENTIAL = "intercom-guest-no-credential";
|
|
52979
|
+
var INTERCOM_GUEST_COORDINATOR_MISSING = "intercom-guest-coordinator-missing";
|
|
52980
|
+
function intercomGuestStorePath(env = process.env) {
|
|
52981
|
+
const home = env.MMI_INTERCOM_HOME?.trim();
|
|
52982
|
+
return (0, import_node_path38.join)(home && home.length > 0 ? home : (0, import_node_path38.join)((0, import_node_os22.homedir)(), ".mmi", "intercom"), "guest.json");
|
|
52983
|
+
}
|
|
52882
52984
|
function scrubToken(text, token) {
|
|
52883
52985
|
if (!token) return text;
|
|
52884
52986
|
return text.split(token).join("***");
|
|
52885
52987
|
}
|
|
52988
|
+
function scrubSecrets(text, secrets) {
|
|
52989
|
+
return secrets.reduce((acc, secret) => scrubToken(acc, secret), text);
|
|
52990
|
+
}
|
|
52886
52991
|
function missingContractRefusal(verb) {
|
|
52887
52992
|
return [
|
|
52888
|
-
`${CANONICAL_COMMAND} ${verb}: not sent \u2014
|
|
52889
|
-
|
|
52890
|
-
"
|
|
52891
|
-
"
|
|
52892
|
-
|
|
52893
|
-
"`INTERCOM_GUEST_CONTRACT.operations` in cli/src/intercom-guest.ts
|
|
52993
|
+
`${CANONICAL_COMMAND} ${verb}: not sent \u2014 this CLI build carries no Jerv Gateway operation for the '${verb}' verb (${INTERCOM_GUEST_CONTRACT.source}).`,
|
|
52994
|
+
"The published guest contract publishes the method, path and field shape for every verb this client knows",
|
|
52995
|
+
`(${INTERCOM_GUEST_VERBS.join(", ")}), so an empty entry means the contract moved and this build did not follow it \u2014`,
|
|
52996
|
+
"this client refuses instead of guessing an endpoint: a guessed call would come back 404/403 and read as a permission",
|
|
52997
|
+
"or allowlist answer when the real answer is that the operation is unknown here.",
|
|
52998
|
+
"To fix it: check the published contract against `INTERCOM_GUEST_CONTRACT.operations` in cli/src/intercom-guest.ts",
|
|
52999
|
+
"\u2014 that object is the one place the wire shape lives.",
|
|
52894
53000
|
"Nothing was read and nothing was sent: no token was touched and no request was made."
|
|
52895
53001
|
].join(" ");
|
|
52896
53002
|
}
|
|
53003
|
+
function missingInput(request) {
|
|
53004
|
+
if (request.verb === "send") {
|
|
53005
|
+
if (!request.to?.trim()) return "`--to <address>` is required";
|
|
53006
|
+
if (!request.message?.trim()) return "`--message <text>` is required";
|
|
53007
|
+
}
|
|
53008
|
+
if (request.verb === "join" && !request.suite?.trim()) return "`--suite <name>` is required";
|
|
53009
|
+
return void 0;
|
|
53010
|
+
}
|
|
53011
|
+
function coordinatorEndpointId(directoryBody) {
|
|
53012
|
+
let parsed;
|
|
53013
|
+
try {
|
|
53014
|
+
parsed = JSON.parse(directoryBody);
|
|
53015
|
+
} catch {
|
|
53016
|
+
return void 0;
|
|
53017
|
+
}
|
|
53018
|
+
const data = parsed?.data ?? parsed;
|
|
53019
|
+
const items = data?.items;
|
|
53020
|
+
if (!Array.isArray(items)) return void 0;
|
|
53021
|
+
const candidates = items.filter((item) => Boolean(item) && typeof item === "object");
|
|
53022
|
+
const named = candidates.filter((item) => typeof item.displayName === "string" && /^Coordinator(\s|$)/.test(item.displayName) && item.self !== true);
|
|
53023
|
+
const exact = named.find((item) => item.displayName === "Coordinator") ?? named[0];
|
|
53024
|
+
return typeof exact?.endpointId === "string" && exact.endpointId.length > 0 ? exact.endpointId : void 0;
|
|
53025
|
+
}
|
|
53026
|
+
async function readStore(path2) {
|
|
53027
|
+
try {
|
|
53028
|
+
const parsed = JSON.parse(await (0, import_promises5.readFile)(path2, "utf8"));
|
|
53029
|
+
return parsed && typeof parsed === "object" ? parsed : void 0;
|
|
53030
|
+
} catch {
|
|
53031
|
+
return void 0;
|
|
53032
|
+
}
|
|
53033
|
+
}
|
|
53034
|
+
async function writeStore(path2, entry) {
|
|
53035
|
+
await (0, import_promises5.mkdir)((0, import_node_path38.dirname)(path2), { recursive: true, mode: 448 });
|
|
53036
|
+
await (0, import_promises5.writeFile)(path2, `${JSON.stringify(entry, null, 2)}
|
|
53037
|
+
`, { encoding: "utf8", mode: 384 });
|
|
53038
|
+
await (0, import_promises5.chmod)(path2, 384).catch(() => {
|
|
53039
|
+
});
|
|
53040
|
+
}
|
|
53041
|
+
function registrationEntry(gateway, body, previous) {
|
|
53042
|
+
let parsed;
|
|
53043
|
+
try {
|
|
53044
|
+
parsed = JSON.parse(body);
|
|
53045
|
+
} catch {
|
|
53046
|
+
return void 0;
|
|
53047
|
+
}
|
|
53048
|
+
const data = parsed?.data ?? parsed;
|
|
53049
|
+
const credential = typeof data?.credential === "string" ? data.credential : previous?.credential;
|
|
53050
|
+
if (!credential) return void 0;
|
|
53051
|
+
return {
|
|
53052
|
+
gateway,
|
|
53053
|
+
endpointId: typeof data?.endpointId === "string" ? data.endpointId : previous?.endpointId,
|
|
53054
|
+
deviceId: typeof data?.deviceId === "string" ? data.deviceId : previous?.deviceId,
|
|
53055
|
+
credential,
|
|
53056
|
+
displayName: typeof data?.displayName === "string" ? data.displayName : previous?.displayName,
|
|
53057
|
+
epoch: typeof data?.epoch === "number" ? data.epoch : previous?.epoch
|
|
53058
|
+
};
|
|
53059
|
+
}
|
|
52897
53060
|
async function runIntercomGuest(request, deps = {}) {
|
|
52898
53061
|
const verb = request.verb;
|
|
52899
53062
|
const contract = deps.contract ?? INTERCOM_GUEST_CONTRACT;
|
|
@@ -52901,61 +53064,156 @@ async function runIntercomGuest(request, deps = {}) {
|
|
|
52901
53064
|
if (!operation) {
|
|
52902
53065
|
return { ok: false, verb, code: INTERCOM_GUEST_CONTRACT_MISSING, message: missingContractRefusal(verb), tokenRead: false };
|
|
52903
53066
|
}
|
|
53067
|
+
const inputProblem = missingInput(request);
|
|
53068
|
+
if (inputProblem) {
|
|
53069
|
+
return {
|
|
53070
|
+
ok: false,
|
|
53071
|
+
verb,
|
|
53072
|
+
code: INTERCOM_GUEST_INPUT_MISSING,
|
|
53073
|
+
message: `${CANONICAL_COMMAND} ${verb}: not sent \u2014 ${inputProblem}. Nothing was read and no request was made.`,
|
|
53074
|
+
tokenRead: false
|
|
53075
|
+
};
|
|
53076
|
+
}
|
|
52904
53077
|
const env = deps.env ?? process.env;
|
|
52905
|
-
const baseUrl = env[contract.baseUrlEnv]?.trim();
|
|
53078
|
+
const baseUrl = (env[contract.baseUrlEnv]?.trim() || contract.baseUrl).replace(/\/+$/, "");
|
|
52906
53079
|
if (!baseUrl) {
|
|
52907
53080
|
return {
|
|
52908
53081
|
ok: false,
|
|
52909
53082
|
verb,
|
|
52910
53083
|
code: INTERCOM_GUEST_BASE_URL_MISSING,
|
|
52911
|
-
message: `${CANONICAL_COMMAND} ${verb}: not sent \u2014 ${contract.baseUrlEnv} is
|
|
53084
|
+
message: `${CANONICAL_COMMAND} ${verb}: not sent \u2014 ${contract.baseUrlEnv} is empty and the published contract names no base URL either (${contract.source}). Nothing was read and no request was made.`,
|
|
52912
53085
|
tokenRead: false
|
|
52913
53086
|
};
|
|
52914
53087
|
}
|
|
53088
|
+
const storePath = deps.storePath ?? intercomGuestStorePath(env);
|
|
53089
|
+
const store = await readStore(storePath);
|
|
52915
53090
|
const identity = await (deps.readToken ?? githubKeyringTokenRead)();
|
|
52916
53091
|
if (identity.state !== "ok") {
|
|
52917
53092
|
return {
|
|
52918
53093
|
ok: false,
|
|
52919
53094
|
verb,
|
|
52920
53095
|
code: INTERCOM_GUEST_NO_IDENTITY,
|
|
52921
|
-
message:
|
|
52922
|
-
`${CANONICAL_COMMAND} ${verb}: not sent \u2014 the guest identity is the caller's own \`gh\` login and it could not be read (${identity.detail}). Run \`gh auth login\`, then retry. No request was made
|
|
53096
|
+
message: scrubSecrets(
|
|
53097
|
+
`${CANONICAL_COMMAND} ${verb}: not sent \u2014 the guest identity is the caller's own \`gh\` login and it could not be read (${identity.detail}). Run \`gh auth login\`, then retry. No request was made.`,
|
|
53098
|
+
[]
|
|
52923
53099
|
),
|
|
52924
53100
|
tokenRead: false
|
|
52925
53101
|
};
|
|
52926
53102
|
}
|
|
52927
53103
|
const token = identity.token;
|
|
52928
|
-
|
|
52929
|
-
|
|
52930
|
-
|
|
52931
|
-
|
|
52932
|
-
|
|
52933
|
-
|
|
53104
|
+
let login;
|
|
53105
|
+
if (operation.needsLogin) {
|
|
53106
|
+
login = await (deps.readLogin ?? githubLogin)();
|
|
53107
|
+
if (!login) {
|
|
53108
|
+
return {
|
|
53109
|
+
ok: false,
|
|
53110
|
+
verb,
|
|
53111
|
+
code: INTERCOM_GUEST_NO_IDENTITY,
|
|
53112
|
+
message: scrubSecrets(
|
|
53113
|
+
`${CANONICAL_COMMAND} ${verb}: not sent \u2014 ${operation.operation} needs your GitHub login as \`displayName\` and \`gh api user\` returned none. Run \`gh auth login\`, then retry. No request was made.`,
|
|
53114
|
+
[token]
|
|
53115
|
+
),
|
|
53116
|
+
tokenRead: true
|
|
53117
|
+
};
|
|
53118
|
+
}
|
|
52934
53119
|
}
|
|
52935
|
-
|
|
52936
|
-
|
|
52937
|
-
|
|
52938
|
-
|
|
52939
|
-
|
|
52940
|
-
|
|
53120
|
+
const credential = store?.credential;
|
|
53121
|
+
if (operation.credential === "required" && !credential) {
|
|
53122
|
+
return {
|
|
53123
|
+
ok: false,
|
|
53124
|
+
verb,
|
|
53125
|
+
code: INTERCOM_GUEST_NO_CREDENTIAL,
|
|
53126
|
+
message: scrubSecrets(
|
|
53127
|
+
`${CANONICAL_COMMAND} ${verb}: not sent \u2014 no intercom credential is stored for this machine (${storePath}). ${operation.operation} requires the \`Jerv-Intercom-Credential\` the Gateway returns exactly once, so run \`${CANONICAL_COMMAND} register\` first. Nothing was read and no request was made.`,
|
|
53128
|
+
[token]
|
|
53129
|
+
),
|
|
53130
|
+
tokenRead: true
|
|
53131
|
+
};
|
|
52941
53132
|
}
|
|
52942
|
-
const
|
|
52943
|
-
|
|
53133
|
+
const fetchImpl = deps.fetchImpl ?? ((url, init) => fetch(url, init));
|
|
53134
|
+
const newKey = deps.newIdempotencyKey ?? (() => (0, import_node_crypto19.randomUUID)());
|
|
53135
|
+
const secrets = [token, credential].filter((secret) => Boolean(secret));
|
|
53136
|
+
const callOne = async (op, body2) => {
|
|
53137
|
+
const headers = {
|
|
53138
|
+
accept: "application/json",
|
|
53139
|
+
"content-type": "application/json",
|
|
53140
|
+
"jerv-contract-version": contract.contractVersion,
|
|
53141
|
+
"jerv-guest-github-token": token
|
|
53142
|
+
};
|
|
53143
|
+
if (credential && op.credential !== "never") headers["jerv-intercom-credential"] = credential;
|
|
53144
|
+
if (op.mutation) headers["idempotency-key"] = newKey();
|
|
53145
|
+
let response;
|
|
53146
|
+
try {
|
|
53147
|
+
response = await fetchImpl(new URL(op.path, baseUrl).toString(), { method: op.method, headers, body: JSON.stringify(body2) });
|
|
53148
|
+
} catch (error) {
|
|
53149
|
+
return { transport: error instanceof Error ? error.message : String(error) };
|
|
53150
|
+
}
|
|
53151
|
+
const text = await response.text().catch(() => "");
|
|
53152
|
+
return { status: response.status, ok: response.ok, text };
|
|
53153
|
+
};
|
|
53154
|
+
let context = {
|
|
53155
|
+
login,
|
|
53156
|
+
credential,
|
|
53157
|
+
endpointId: store?.endpointId,
|
|
53158
|
+
displayName: store?.displayName,
|
|
53159
|
+
repo: env.GITHUB_REPOSITORY?.trim() || "unknown",
|
|
53160
|
+
host: (0, import_node_os22.hostname)()
|
|
53161
|
+
};
|
|
53162
|
+
if (operation.needsCoordinator) {
|
|
53163
|
+
const directory = await callOne(contract.discovery, contract.discovery.body?.(request, context) ?? {});
|
|
53164
|
+
if ("transport" in directory) {
|
|
53165
|
+
return { ok: false, verb, code: "intercom-guest-transport-failed", message: scrubSecrets(`${CANONICAL_COMMAND} ${verb}: the Gateway call failed in transport (${directory.transport}).`, secrets), tokenRead: true };
|
|
53166
|
+
}
|
|
53167
|
+
if (!directory.ok) {
|
|
53168
|
+
return {
|
|
53169
|
+
ok: false,
|
|
53170
|
+
verb,
|
|
53171
|
+
code: `intercom-guest-http-${directory.status}`,
|
|
53172
|
+
message: scrubSecrets(`${CANONICAL_COMMAND} ${verb}: ${contract.discovery.operation} answered HTTP ${directory.status}${directory.text ? ` \u2014 ${directory.text.slice(0, 600)}` : ""}`, secrets),
|
|
53173
|
+
tokenRead: true
|
|
53174
|
+
};
|
|
53175
|
+
}
|
|
53176
|
+
const coordinator = coordinatorEndpointId(directory.text);
|
|
53177
|
+
if (!coordinator) {
|
|
53178
|
+
return {
|
|
53179
|
+
ok: false,
|
|
53180
|
+
verb,
|
|
53181
|
+
code: INTERCOM_GUEST_COORDINATOR_MISSING,
|
|
53182
|
+
message: scrubSecrets(
|
|
53183
|
+
`${CANONICAL_COMMAND} ${verb}: ${contract.discovery.operation} listed no live endpoint named \`Coordinator\`, so there is nobody to send to and nothing was sent. The Coordinator's endpoint id comes from that directory, never from this client.`,
|
|
53184
|
+
secrets
|
|
53185
|
+
),
|
|
53186
|
+
tokenRead: true
|
|
53187
|
+
};
|
|
53188
|
+
}
|
|
53189
|
+
context = { ...context, coordinator };
|
|
53190
|
+
}
|
|
53191
|
+
const body = operation.body ? operation.body(request, context) : {};
|
|
53192
|
+
const result = await callOne(operation, body);
|
|
53193
|
+
if ("transport" in result) {
|
|
53194
|
+
return { ok: false, verb, code: "intercom-guest-transport-failed", message: scrubSecrets(`${CANONICAL_COMMAND} ${verb}: the Gateway call failed in transport (${result.transport}).`, secrets), tokenRead: true };
|
|
53195
|
+
}
|
|
53196
|
+
if (!result.ok) {
|
|
52944
53197
|
return {
|
|
52945
53198
|
ok: false,
|
|
52946
53199
|
verb,
|
|
52947
|
-
code: `intercom-guest-http-${
|
|
52948
|
-
message:
|
|
53200
|
+
code: `intercom-guest-http-${result.status}`,
|
|
53201
|
+
message: scrubSecrets(`${CANONICAL_COMMAND} ${verb}: the Gateway answered HTTP ${result.status}${result.text ? ` \u2014 ${result.text.slice(0, 600)}` : ""}`, secrets),
|
|
52949
53202
|
tokenRead: true
|
|
52950
53203
|
};
|
|
52951
53204
|
}
|
|
52952
|
-
|
|
53205
|
+
if (operation.operation === "intercom.register") {
|
|
53206
|
+
const entry = registrationEntry(baseUrl, result.text, store);
|
|
53207
|
+
if (entry) await writeStore(storePath, entry).catch(() => {
|
|
53208
|
+
});
|
|
53209
|
+
}
|
|
53210
|
+
return { ok: true, verb, status: result.status, body: scrubSecrets(result.text, secrets) };
|
|
52953
53211
|
}
|
|
52954
53212
|
function renderIntercomGuestResult(result) {
|
|
52955
53213
|
return result.ok ? result.body : result.message;
|
|
52956
53214
|
}
|
|
52957
53215
|
function registerIntercomGuestCommands(program3, io = {}) {
|
|
52958
|
-
const guest = program3.command("intercom").description("Coordinate with the MM Coordinator through the Jerv Gateway intercom (guest identity; Jerv-Hub#
|
|
53216
|
+
const guest = program3.command("intercom").description("Coordinate with the MM Coordinator through the Jerv Gateway intercom (guest identity; Jerv-Hub#2727)").command("guest").description("Guest coordination verbs: register, read, send, join, leave \u2014 coordination only, never orders");
|
|
52959
53217
|
const out = io.out ?? ((line) => process.stdout.write(`${line}
|
|
52960
53218
|
`));
|
|
52961
53219
|
const err = io.err ?? ((line) => process.stderr.write(`${line}
|
|
@@ -52970,19 +53228,21 @@ function registerIntercomGuestCommands(program3, io = {}) {
|
|
|
52970
53228
|
return;
|
|
52971
53229
|
}
|
|
52972
53230
|
err(renderIntercomGuestResult(result));
|
|
52973
|
-
setExitCode(
|
|
53231
|
+
setExitCode(
|
|
53232
|
+
result.code === INTERCOM_GUEST_CONTRACT_MISSING || result.code === INTERCOM_GUEST_BASE_URL_MISSING || result.code === INTERCOM_GUEST_NO_CREDENTIAL ? 2 : 1
|
|
53233
|
+
);
|
|
52974
53234
|
};
|
|
52975
|
-
guest.command("register").description("Register this guest endpoint with the Gateway using your `gh
|
|
53235
|
+
guest.command("register").description("Register this guest endpoint with the Gateway, using your `gh` login as the display name").action(async () => {
|
|
52976
53236
|
await run({ verb: "register" });
|
|
52977
53237
|
});
|
|
52978
|
-
guest.command("read").description(
|
|
52979
|
-
const limit = Number(options.limit ??
|
|
52980
|
-
await run({ verb: "read", limit:
|
|
53238
|
+
guest.command("read").description(`Read the deliveries waiting for this guest endpoint (default ${DELIVERIES_LIMIT_DEFAULT}, at most ${DELIVERIES_LIMIT_MAX})`).option("--limit <n>", `how many deliveries to look at (1-${DELIVERIES_LIMIT_MAX})`, String(DELIVERIES_LIMIT_DEFAULT)).action(async (options) => {
|
|
53239
|
+
const limit = Number(options.limit ?? DELIVERIES_LIMIT_DEFAULT);
|
|
53240
|
+
await run({ verb: "read", limit: deliveriesLimit(limit) });
|
|
52981
53241
|
});
|
|
52982
|
-
guest.command("send").description("Send a coordination message to
|
|
53242
|
+
guest.command("send").description("Send a coordination message to the MM Coordinator").requiredOption("--to <address>", "peer endpoint id or display name (the MM Coordinator)").requiredOption("--message <text>", "the coordination message").action(async (options) => {
|
|
52983
53243
|
await run({ verb: "send", to: options.to, message: options.message });
|
|
52984
53244
|
});
|
|
52985
|
-
guest.command("join").description("Request to join a suite").requiredOption("--suite <name>", "suite name").action(async (options) => {
|
|
53245
|
+
guest.command("join").description("Request to join a suite (a message to the MM Coordinator, who grants it)").requiredOption("--suite <name>", "suite name").action(async (options) => {
|
|
52986
53246
|
await run({ verb: "join", suite: options.suite });
|
|
52987
53247
|
});
|
|
52988
53248
|
guest.command("leave").description("Leave the suite and withdraw this guest endpoint").action(async () => {
|
|
@@ -52997,7 +53257,7 @@ init_github_client();
|
|
|
52997
53257
|
init_cli_shared();
|
|
52998
53258
|
|
|
52999
53259
|
// src/suite-status.ts
|
|
53000
|
-
var
|
|
53260
|
+
var import_node_crypto20 = require("node:crypto");
|
|
53001
53261
|
var SUITE_REPO = "mutmutco/MM-Work";
|
|
53002
53262
|
var REPOS = {
|
|
53003
53263
|
"mmi-scout": "mutmutco/MMI-Scout",
|
|
@@ -53025,7 +53285,7 @@ function parseSuiteMapping(body) {
|
|
|
53025
53285
|
return void 0;
|
|
53026
53286
|
}
|
|
53027
53287
|
}
|
|
53028
|
-
var sha2562 = (b) => (0,
|
|
53288
|
+
var sha2562 = (b) => (0, import_node_crypto20.createHash)("sha256").update(b).digest("hex");
|
|
53029
53289
|
async function proveBundle(url, tag, fetchUrl) {
|
|
53030
53290
|
const get = async (u) => {
|
|
53031
53291
|
try {
|
|
@@ -53281,8 +53541,8 @@ async function waitSuiteDev(deps, opts) {
|
|
|
53281
53541
|
|
|
53282
53542
|
// src/suite-train.ts
|
|
53283
53543
|
var import_node_fs41 = require("node:fs");
|
|
53284
|
-
var
|
|
53285
|
-
var
|
|
53544
|
+
var import_node_path39 = require("node:path");
|
|
53545
|
+
var import_node_crypto21 = require("node:crypto");
|
|
53286
53546
|
|
|
53287
53547
|
// src/kit-version.ts
|
|
53288
53548
|
var parse = (v) => /^(\d+)\.(\d+)\.(\d+)(-.+)?$/.exec(typeof v === "string" ? v.trim() : "");
|
|
@@ -53383,8 +53643,8 @@ function readSuiteCut(path2) {
|
|
|
53383
53643
|
return record2;
|
|
53384
53644
|
}
|
|
53385
53645
|
function writeSuiteCut(path2, record2) {
|
|
53386
|
-
(0, import_node_fs41.mkdirSync)((0,
|
|
53387
|
-
const temp = `${path2}.${(0,
|
|
53646
|
+
(0, import_node_fs41.mkdirSync)((0, import_node_path39.dirname)(path2), { recursive: true });
|
|
53647
|
+
const temp = `${path2}.${(0, import_node_crypto21.randomBytes)(8).toString("hex")}.tmp`;
|
|
53388
53648
|
try {
|
|
53389
53649
|
(0, import_node_fs41.writeFileSync)(temp, JSON.stringify(record2, null, 2), { flag: "wx" });
|
|
53390
53650
|
(0, import_node_fs41.renameSync)(temp, path2);
|
|
@@ -53443,7 +53703,7 @@ async function retireFailedLeadRcLedger(deps, ownerGo) {
|
|
|
53443
53703
|
if (ledger.repo !== SUITE_REPO || ledger.lane !== "rcand" || ledger.phases.promotion.state === "complete" || !states.includes("failed")) return void 0;
|
|
53444
53704
|
if (!ownerGo) throw new Error(`the lead's failed rcand ledger for ${ledger.tag} blocks every train; retire it with suite abandon --owner-go`);
|
|
53445
53705
|
if ((await deps.rcHead())?.toLowerCase() === ledger.tagSha.toLowerCase()) throw new Error(`origin rc already points at ${ledger.tag}; it was promoted, so its ledger is not retired`);
|
|
53446
|
-
const archive = (0,
|
|
53706
|
+
const archive = (0, import_node_path39.join)((0, import_node_path39.dirname)(deps.ledgerPath), `phases.archive-${ledger.tag}.json`);
|
|
53447
53707
|
if ((0, import_node_fs41.existsSync)(archive)) throw new Error(`ledger archive already exists at ${archive}; inspect before retiring again`);
|
|
53448
53708
|
await deps.markAbandoned(SUITE_REPO, ledger.tag, ledger.tagSha);
|
|
53449
53709
|
await fence(() => (0, import_node_fs41.renameSync)(deps.ledgerPath, archive));
|
|
@@ -53810,7 +54070,7 @@ Each member's live release must serve <data>/main/module.js at its main pin path
|
|
|
53810
54070
|
}
|
|
53811
54071
|
return record2;
|
|
53812
54072
|
}
|
|
53813
|
-
var hotfixRecordPath = (deps) => (0,
|
|
54073
|
+
var hotfixRecordPath = (deps) => (0, import_node_path39.join)((0, import_node_path39.dirname)(deps.recordPath), "hotfix.json");
|
|
53814
54074
|
function readSuiteHotfix(path2) {
|
|
53815
54075
|
let raw;
|
|
53816
54076
|
try {
|
|
@@ -54125,20 +54385,20 @@ async function runRcDataSwitch(deps, opts) {
|
|
|
54125
54385
|
|
|
54126
54386
|
// src/suite-train-io.ts
|
|
54127
54387
|
var import_node_child_process19 = require("node:child_process");
|
|
54128
|
-
var import_node_path51 = require("node:path");
|
|
54129
|
-
var import_node_fs55 = require("node:fs");
|
|
54130
54388
|
var import_node_path52 = require("node:path");
|
|
54389
|
+
var import_node_fs55 = require("node:fs");
|
|
54390
|
+
var import_node_path53 = require("node:path");
|
|
54131
54391
|
init_cli_shared();
|
|
54132
54392
|
|
|
54133
54393
|
// src/command-register-train-operations.ts
|
|
54134
|
-
var
|
|
54394
|
+
var import_promises10 = require("node:fs/promises");
|
|
54135
54395
|
init_clean_exit();
|
|
54136
54396
|
init_cli_shared();
|
|
54137
54397
|
init_client_version();
|
|
54138
54398
|
init_house_map();
|
|
54139
54399
|
|
|
54140
54400
|
// src/hotfix-apply.ts
|
|
54141
|
-
var
|
|
54401
|
+
var import_promises6 = require("node:fs/promises");
|
|
54142
54402
|
|
|
54143
54403
|
// src/release-announce.ts
|
|
54144
54404
|
var ANNOUNCE_REPO = "mutmutco/MMI-Hub";
|
|
@@ -54481,8 +54741,8 @@ async function preflightHotfixBatchPicks(deps, sources, pickTolerated) {
|
|
|
54481
54741
|
if (sources.length === 0) return { failures: [], skipped: [] };
|
|
54482
54742
|
const { mkdtemp: mkdtemp2, rm: rm2 } = await import("node:fs/promises");
|
|
54483
54743
|
const { tmpdir: tmpdir13 } = await import("node:os");
|
|
54484
|
-
const { join:
|
|
54485
|
-
const dir = await mkdtemp2(
|
|
54744
|
+
const { join: join55 } = await import("node:path");
|
|
54745
|
+
const dir = await mkdtemp2(join55(tmpdir13(), "mmi-hotfix-preflight-"));
|
|
54486
54746
|
const wt = { run: (file, args) => deps.run(file, file === "git" ? ["-C", dir, ...args] : args) };
|
|
54487
54747
|
const failures = [];
|
|
54488
54748
|
const skipped = [];
|
|
@@ -55194,7 +55454,7 @@ async function runHotfixReleaseLocked(deps, versionInput, options, doctor) {
|
|
|
55194
55454
|
}
|
|
55195
55455
|
let lines2;
|
|
55196
55456
|
try {
|
|
55197
|
-
lines2 = summaryFileLines(await (deps.readFile ?? ((p) => (0,
|
|
55457
|
+
lines2 = summaryFileLines(await (deps.readFile ?? ((p) => (0, import_promises6.readFile)(p, "utf8")))(options.announceSummaryFile));
|
|
55198
55458
|
} catch (e) {
|
|
55199
55459
|
throw new Error(`could not read --announce-summary-file ${options.announceSummaryFile}: ${e.message} \u2014 see https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#announce-summary-missing`);
|
|
55200
55460
|
}
|
|
@@ -55820,8 +56080,8 @@ function checkHotfixCarries(options) {
|
|
|
55820
56080
|
|
|
55821
56081
|
// src/merge-cleanup.ts
|
|
55822
56082
|
var import_node_fs42 = require("node:fs");
|
|
55823
|
-
var
|
|
55824
|
-
var
|
|
56083
|
+
var import_node_path40 = require("node:path");
|
|
56084
|
+
var import_node_os23 = require("node:os");
|
|
55825
56085
|
init_cli_shared();
|
|
55826
56086
|
init_github_client();
|
|
55827
56087
|
|
|
@@ -56228,8 +56488,8 @@ function resolveSquashMergeBodyText(commits, allowedClosing, cwd) {
|
|
|
56228
56488
|
return rewritten === base ? null : rewritten;
|
|
56229
56489
|
}
|
|
56230
56490
|
function writeSquashBodyFile(body) {
|
|
56231
|
-
const dir = (0, import_node_fs42.mkdtempSync)((0,
|
|
56232
|
-
const path2 = (0,
|
|
56491
|
+
const dir = (0, import_node_fs42.mkdtempSync)((0, import_node_path40.join)((0, import_node_os23.tmpdir)(), "mmi-squash-body-"));
|
|
56492
|
+
const path2 = (0, import_node_path40.join)(dir, "body.txt");
|
|
56233
56493
|
(0, import_node_fs42.writeFileSync)(path2, body.endsWith("\n") ? body : `${body}
|
|
56234
56494
|
`, "utf8");
|
|
56235
56495
|
return { path: path2, cleanup: () => {
|
|
@@ -56485,9 +56745,9 @@ async function deleteMergedRemoteBranch(options) {
|
|
|
56485
56745
|
init_github_client();
|
|
56486
56746
|
|
|
56487
56747
|
// src/release-custody.ts
|
|
56488
|
-
var
|
|
56748
|
+
var import_node_crypto22 = require("node:crypto");
|
|
56489
56749
|
var import_node_fs43 = require("node:fs");
|
|
56490
|
-
var
|
|
56750
|
+
var import_node_path41 = require("node:path");
|
|
56491
56751
|
init_github_client();
|
|
56492
56752
|
|
|
56493
56753
|
// src/release-custody-bootstrap.ts
|
|
@@ -56709,7 +56969,7 @@ var ReleaseCustodyError = class extends Error {
|
|
|
56709
56969
|
this.name = "ReleaseCustodyError";
|
|
56710
56970
|
}
|
|
56711
56971
|
};
|
|
56712
|
-
var custodyDigest = (value) => (0,
|
|
56972
|
+
var custodyDigest = (value) => (0, import_node_crypto22.createHash)("sha256").update(value).digest("hex");
|
|
56713
56973
|
function parseCustody(raw, repo) {
|
|
56714
56974
|
const s = JSON.parse(raw);
|
|
56715
56975
|
if (s.schema !== "mmi-release-custody/v1" || s.repo !== repo || !s.precutId || !Number.isSafeInteger(s.revision) || s.revision < 1 || !s.controller || !Number.isSafeInteger(s.controller.runId) || s.controller.runId <= 0 || !Number.isSafeInteger(s.controller.runAttempt) || s.controller.runAttempt <= 0 || !s.controller.token || !(s.ledger === null || typeof s.ledger === "string") || !s.archives || !s.effects) {
|
|
@@ -56810,7 +57070,7 @@ var ReleaseCustodySession = class _ReleaseCustodySession {
|
|
|
56810
57070
|
}
|
|
56811
57071
|
}
|
|
56812
57072
|
let state = {
|
|
56813
|
-
...found.state ?? { schema: "mmi-release-custody/v1", repo, precutId: (0,
|
|
57073
|
+
...found.state ?? { schema: "mmi-release-custody/v1", repo, precutId: (0, import_node_crypto22.randomUUID)(), effects: {}, ...await initialize() },
|
|
56814
57074
|
revision: (found.state?.revision ?? 0) + 1,
|
|
56815
57075
|
controller
|
|
56816
57076
|
};
|
|
@@ -56871,7 +57131,7 @@ var ReleaseCustodySession = class _ReleaseCustodySession {
|
|
|
56871
57131
|
proof: { kind: "ledger-lifecycle", controller: state.controller }
|
|
56872
57132
|
};
|
|
56873
57133
|
}
|
|
56874
|
-
return { ...state, ledger: raw, archives, precutId: state.ledger && !raw ? (0,
|
|
57134
|
+
return { ...state, ledger: raw, archives, precutId: state.ledger && !raw ? (0, import_node_crypto22.randomUUID)() : state.precutId };
|
|
56875
57135
|
});
|
|
56876
57136
|
}
|
|
56877
57137
|
async preserveLocal(raw) {
|
|
@@ -56987,10 +57247,10 @@ function localRaw(path2) {
|
|
|
56987
57247
|
function hydrateLocal(path2, raw) {
|
|
56988
57248
|
const previous = localRaw(path2);
|
|
56989
57249
|
if (previous === raw) return;
|
|
56990
|
-
(0, import_node_fs43.mkdirSync)((0,
|
|
57250
|
+
(0, import_node_fs43.mkdirSync)((0, import_node_path41.dirname)(path2), { recursive: true });
|
|
56991
57251
|
if (previous !== null) {
|
|
56992
57252
|
const ledger = parseReleaseLedger(previous);
|
|
56993
|
-
const archive = (0,
|
|
57253
|
+
const archive = (0, import_node_path41.join)((0, import_node_path41.dirname)(path2), `phases.local-${ledger.tagSha}-${custodyDigest(previous)}.json`);
|
|
56994
57254
|
if (!(0, import_node_fs43.existsSync)(archive)) (0, import_node_fs43.writeFileSync)(archive, previous, { flag: "wx" });
|
|
56995
57255
|
if (raw === null) (0, import_node_fs43.renameSync)(path2, `${path2}.retired-${custodyDigest(previous)}`);
|
|
56996
57256
|
}
|
|
@@ -57105,7 +57365,7 @@ function withHubReleaseCustody(deps) {
|
|
|
57105
57365
|
if (!authority.ok || !authority.train || authority.authenticatedDelegation !== true) {
|
|
57106
57366
|
throw new ReleaseCustodyError("repository custody requires the server-verified owner-triggered train session");
|
|
57107
57367
|
}
|
|
57108
|
-
const controller = { ...runIdentity, token: (0,
|
|
57368
|
+
const controller = { ...runIdentity, token: (0, import_node_crypto22.randomUUID)(), ...process.env.GITHUB_JOB ? { job: process.env.GITHUB_JOB } : {} };
|
|
57109
57369
|
const raw = localRaw(path2);
|
|
57110
57370
|
const requiredContexts = () => discoverRequiredCheckContexts(
|
|
57111
57371
|
deps,
|
|
@@ -57186,7 +57446,7 @@ function withHubReleaseCustody(deps) {
|
|
|
57186
57446
|
|
|
57187
57447
|
// src/project-info-sync.ts
|
|
57188
57448
|
var import_node_fs44 = require("node:fs");
|
|
57189
|
-
var
|
|
57449
|
+
var import_node_path42 = require("node:path");
|
|
57190
57450
|
var UPDATE_PROJECT_INFO = `mutation($projectId: ID!, $shortDescription: String!, $readme: String!) {
|
|
57191
57451
|
updateProjectV2(input: { projectId: $projectId, shortDescription: $shortDescription, readme: $readme }) {
|
|
57192
57452
|
projectV2 { id }
|
|
@@ -57233,7 +57493,7 @@ function sharedName(entries, fallback) {
|
|
|
57233
57493
|
}
|
|
57234
57494
|
function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
|
|
57235
57495
|
if (!project2.projectId) throw new Error(`org project sync-info: ${targetRepo2} registry META has no projectId`);
|
|
57236
|
-
const readmePath = (0,
|
|
57496
|
+
const readmePath = (0, import_node_path42.join)(repoRoot2, "README.md");
|
|
57237
57497
|
if (!(0, import_node_fs44.existsSync)(readmePath)) throw new Error(`org project sync-info: ${targetRepo2} has no README.md`);
|
|
57238
57498
|
const entries = entriesFor(project2, projects);
|
|
57239
57499
|
const memberRepos = [...new Set(entries.flatMap((entry) => entry.repos ?? []))].filter((repo) => /^[^/]+\/[^/]+$/.test(repo)).sort((a, b) => a.localeCompare(b));
|
|
@@ -57259,8 +57519,8 @@ function buildProjectInfoSyncPlan(targetRepo2, project2, projects, repoRoot2) {
|
|
|
57259
57519
|
const targetBase = `https://github.com/${targetRepo2}`;
|
|
57260
57520
|
const targetBranch = branchFor(targetRepo2, projects);
|
|
57261
57521
|
const orgDocs = [
|
|
57262
|
-
(0, import_node_fs44.existsSync)((0,
|
|
57263
|
-
(0, import_node_fs44.existsSync)((0,
|
|
57522
|
+
(0, import_node_fs44.existsSync)((0, import_node_path42.join)(repoRoot2, "architecture.md")) ? `- [Hub architecture](${targetBase}/blob/${targetBranch}/architecture.md)` : "",
|
|
57523
|
+
(0, import_node_fs44.existsSync)((0, import_node_path42.join)(repoRoot2, "docs", "Architecture", "agentic-dev-environment.md")) ? `- [Agentic development environment](${targetBase}/blob/${targetBranch}/docs/Architecture/agentic-dev-environment.md)` : ""
|
|
57264
57524
|
].filter(Boolean);
|
|
57265
57525
|
if (orgDocs.length) lines2.push("", "## Organisation docs", "", ...orgDocs);
|
|
57266
57526
|
return { projectId: project2.projectId, projectName, targetRepo: targetRepo2, memberRepos, shortDescription, readme: `${lines2.join("\n")}
|
|
@@ -57283,7 +57543,7 @@ async function syncProjectInfo(plan, client, apply) {
|
|
|
57283
57543
|
|
|
57284
57544
|
// src/train-commands.ts
|
|
57285
57545
|
var import_node_fs45 = require("node:fs");
|
|
57286
|
-
var
|
|
57546
|
+
var import_node_path43 = require("node:path");
|
|
57287
57547
|
init_cli_shared();
|
|
57288
57548
|
init_clean_exit();
|
|
57289
57549
|
init_client_version();
|
|
@@ -57298,7 +57558,7 @@ function resolveReleaseBumpIntent(raw) {
|
|
|
57298
57558
|
}
|
|
57299
57559
|
function readRepoVersion() {
|
|
57300
57560
|
try {
|
|
57301
|
-
return JSON.parse((0, import_node_fs45.readFileSync)((0,
|
|
57561
|
+
return JSON.parse((0, import_node_fs45.readFileSync)((0, import_node_path43.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
|
|
57302
57562
|
} catch {
|
|
57303
57563
|
return void 0;
|
|
57304
57564
|
}
|
|
@@ -57408,8 +57668,8 @@ function releaseProgressVerdict(status, subject = "Release") {
|
|
|
57408
57668
|
}
|
|
57409
57669
|
|
|
57410
57670
|
// src/suite-pin.ts
|
|
57411
|
-
var
|
|
57412
|
-
var
|
|
57671
|
+
var import_promises7 = require("node:fs/promises");
|
|
57672
|
+
var import_node_path44 = require("node:path");
|
|
57413
57673
|
var SuitePinError = class _SuitePinError extends Error {
|
|
57414
57674
|
diagnostic;
|
|
57415
57675
|
constructor(repo, tag, error) {
|
|
@@ -57477,8 +57737,8 @@ async function openSuiteCutPinPr(deps, input) {
|
|
|
57477
57737
|
if (input.carriedOnly) return { status: "unchanged" };
|
|
57478
57738
|
throw new Error("pins already match without a merged cut PR \u2014 provenance unverified");
|
|
57479
57739
|
}
|
|
57480
|
-
await (0,
|
|
57481
|
-
scratch = await (0,
|
|
57740
|
+
await (0, import_promises7.mkdir)((0, import_node_path44.join)(deps.root, "tmp"), { recursive: true });
|
|
57741
|
+
scratch = await (0, import_promises7.mkdtemp)((0, import_node_path44.join)(deps.root, "tmp", "suite-pin-"));
|
|
57482
57742
|
const run = (file, args) => deps.run(file, args, scratch);
|
|
57483
57743
|
await run("git", ["clone", "--quiet", "--branch", prs.length ? branch : "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
|
|
57484
57744
|
if (prs.length) {
|
|
@@ -57490,8 +57750,8 @@ async function openSuiteCutPinPr(deps, input) {
|
|
|
57490
57750
|
await run("git", ["switch", "-c", branch]);
|
|
57491
57751
|
}
|
|
57492
57752
|
for (const stage of ["rc", "main"]) {
|
|
57493
|
-
const path2 = (0,
|
|
57494
|
-
await (0,
|
|
57753
|
+
const path2 = (0, import_node_path44.join)(scratch, `${stage}-pins.json`);
|
|
57754
|
+
await (0, import_promises7.writeFile)(path2, JSON.stringify(input.pins.map((p) => ({ module: p.module, url: p[stage] }))));
|
|
57495
57755
|
await run("node", ["scripts/pin-modules.mjs", "--stage", stage, "--pins", path2]);
|
|
57496
57756
|
}
|
|
57497
57757
|
await run("git", ["add", "seed/modules.json"]);
|
|
@@ -57521,7 +57781,7 @@ async function openSuiteCutPinPr(deps, input) {
|
|
|
57521
57781
|
} catch (e) {
|
|
57522
57782
|
throw new Error(`suite cut pin PR FAILED: ${e.message}; merge/verify the single ${SUITE_REPO} development pin PR, then rerun the cut (never recut member tags)`);
|
|
57523
57783
|
} finally {
|
|
57524
|
-
if (scratch) await (0,
|
|
57784
|
+
if (scratch) await (0, import_promises7.rm)(scratch, { recursive: true, force: true });
|
|
57525
57785
|
}
|
|
57526
57786
|
}
|
|
57527
57787
|
async function openSuiteRestorePinPr(deps, input) {
|
|
@@ -57543,13 +57803,13 @@ async function openSuiteRestorePinPr(deps, input) {
|
|
|
57543
57803
|
}
|
|
57544
57804
|
});
|
|
57545
57805
|
if (!todo.length) return void 0;
|
|
57546
|
-
await (0,
|
|
57547
|
-
scratch = await (0,
|
|
57806
|
+
await (0, import_promises7.mkdir)((0, import_node_path44.join)(deps.root, "tmp"), { recursive: true });
|
|
57807
|
+
scratch = await (0, import_promises7.mkdtemp)((0, import_node_path44.join)(deps.root, "tmp", "suite-pin-"));
|
|
57548
57808
|
const run = (file, args) => deps.run(file, args, scratch);
|
|
57549
57809
|
await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
|
|
57550
57810
|
await run("git", ["switch", "-c", branch]);
|
|
57551
|
-
const path2 = (0,
|
|
57552
|
-
await (0,
|
|
57811
|
+
const path2 = (0, import_node_path44.join)(scratch, "main-pins.json");
|
|
57812
|
+
await (0, import_promises7.writeFile)(path2, JSON.stringify(todo.map((p) => ({ module: p.module, url: p.prior }))));
|
|
57553
57813
|
await run("node", ["scripts/pin-modules.mjs", "--stage", "main", "--pins", path2]);
|
|
57554
57814
|
await run("git", ["add", "seed/modules.json"]);
|
|
57555
57815
|
await run("git", ["commit", "-m", `Restore main pins of abandoned suite cut ${input.cut.slice(0, 12)} (#7758)`]);
|
|
@@ -57574,7 +57834,7 @@ async function openSuiteRestorePinPr(deps, input) {
|
|
|
57574
57834
|
} catch (e) {
|
|
57575
57835
|
throw new Error(`suite restore pin PR FAILED: ${e.message}; rerun suite abandon --owner-go (the record is kept until the restore PR exists)`);
|
|
57576
57836
|
} finally {
|
|
57577
|
-
if (scratch) await (0,
|
|
57837
|
+
if (scratch) await (0, import_promises7.rm)(scratch, { recursive: true, force: true });
|
|
57578
57838
|
}
|
|
57579
57839
|
}
|
|
57580
57840
|
async function openSuitePinPr(deps, input) {
|
|
@@ -57622,8 +57882,8 @@ async function openSuitePinPr(deps, input) {
|
|
|
57622
57882
|
if (newer.length) return { status: "superseded", pr: newer[0].url, url: pin };
|
|
57623
57883
|
const open2 = onBranch.find((p) => p.state === "OPEN");
|
|
57624
57884
|
if (open2 && tagOf(open2.title ?? "") === tag) return { status: "pending", pr: open2.url, url: pin };
|
|
57625
|
-
await (0,
|
|
57626
|
-
scratch = await (0,
|
|
57885
|
+
await (0, import_promises7.mkdir)((0, import_node_path44.join)(deps.root, "tmp"), { recursive: true });
|
|
57886
|
+
scratch = await (0, import_promises7.mkdtemp)((0, import_node_path44.join)(deps.root, "tmp", "suite-pin-"));
|
|
57627
57887
|
const run = (file, args) => deps.run(file, args, scratch);
|
|
57628
57888
|
await run("git", ["clone", "--quiet", "--branch", "development", "--single-branch", `https://github.com/${SUITE_REPO}.git`, "."]);
|
|
57629
57889
|
await run("git", ["switch", "-c", branch]);
|
|
@@ -57650,7 +57910,7 @@ async function openSuitePinPr(deps, input) {
|
|
|
57650
57910
|
} finally {
|
|
57651
57911
|
if (scratch) {
|
|
57652
57912
|
try {
|
|
57653
|
-
await (0,
|
|
57913
|
+
await (0, import_promises7.rm)(scratch, { recursive: true, force: true });
|
|
57654
57914
|
} catch (e) {
|
|
57655
57915
|
const cleanupFailure = failure ?? new SuitePinError(repo, tag, e);
|
|
57656
57916
|
cleanupFailure.diagnostic.cleanupFailed = true;
|
|
@@ -57676,7 +57936,7 @@ function prTitleRefusal(title) {
|
|
|
57676
57936
|
// src/command-register-collaboration.ts
|
|
57677
57937
|
var import_node_child_process18 = require("node:child_process");
|
|
57678
57938
|
var import_node_fs54 = require("node:fs");
|
|
57679
|
-
var
|
|
57939
|
+
var import_promises9 = require("node:fs/promises");
|
|
57680
57940
|
init_clean_exit();
|
|
57681
57941
|
init_cli_shared();
|
|
57682
57942
|
init_error_codes();
|
|
@@ -57699,11 +57959,11 @@ function spawnDetachedSelf(args, deps, opts = {}) {
|
|
|
57699
57959
|
}
|
|
57700
57960
|
|
|
57701
57961
|
// src/command-register-collaboration.ts
|
|
57702
|
-
var
|
|
57962
|
+
var import_node_path51 = require("node:path");
|
|
57703
57963
|
init_house_map();
|
|
57704
57964
|
|
|
57705
57965
|
// src/issue-body.ts
|
|
57706
|
-
var
|
|
57966
|
+
var import_node_os24 = require("node:os");
|
|
57707
57967
|
init_error_codes();
|
|
57708
57968
|
var TextArgError = class extends Error {
|
|
57709
57969
|
constructor(message2, code, offendingFlag) {
|
|
@@ -57716,7 +57976,7 @@ var TextArgError = class extends Error {
|
|
|
57716
57976
|
offendingFlag;
|
|
57717
57977
|
};
|
|
57718
57978
|
function emptyStdinMessage(fileFlag) {
|
|
57719
|
-
if ((0,
|
|
57979
|
+
if ((0, import_node_os24.platform)() === "win32") {
|
|
57720
57980
|
return `${fileFlag} - read empty stdin (on Windows, ${fileFlag} - is unreliable through the npm .cmd shim \u2014 use ${fileFlag} <path>, or pipe to \`node cli/dist/index.cjs\` directly)`;
|
|
57721
57981
|
}
|
|
57722
57982
|
return `${fileFlag} - read empty stdin (nothing piped \u2014 pass a heredoc/pipe, or ${fileFlag} <path>)`;
|
|
@@ -57817,7 +58077,7 @@ init_github_quota();
|
|
|
57817
58077
|
|
|
57818
58078
|
// src/issue-commands.ts
|
|
57819
58079
|
var import_node_fs46 = require("node:fs");
|
|
57820
|
-
var
|
|
58080
|
+
var import_node_crypto23 = require("node:crypto");
|
|
57821
58081
|
init_cli_shared();
|
|
57822
58082
|
init_clean_exit();
|
|
57823
58083
|
init_error_codes();
|
|
@@ -58294,7 +58554,7 @@ function rowIdempotencyKey(batchKey, spec) {
|
|
|
58294
58554
|
const identity = `${spec.type}
|
|
58295
58555
|
${spec.title.trim()}
|
|
58296
58556
|
${spec.body ?? ""}`;
|
|
58297
|
-
const hash = (0,
|
|
58557
|
+
const hash = (0, import_node_crypto23.createHash)("sha256").update(identity).digest("hex").slice(0, 16);
|
|
58298
58558
|
return `${batchKey}:${hash}`;
|
|
58299
58559
|
}
|
|
58300
58560
|
var BATCH_SPEC_KEYS = /* @__PURE__ */ new Set(["type", "title", "body", "priority", "labels", "label", "parent", "repo", "surface"]);
|
|
@@ -58754,7 +59014,7 @@ ${lines2}`, {
|
|
|
58754
59014
|
|
|
58755
59015
|
// src/post-merge-recon.ts
|
|
58756
59016
|
var import_node_fs47 = require("node:fs");
|
|
58757
|
-
var
|
|
59017
|
+
var import_node_path45 = require("node:path");
|
|
58758
59018
|
|
|
58759
59019
|
// src/cross-repo-filing-issue.ts
|
|
58760
59020
|
init_github_client();
|
|
@@ -58924,7 +59184,7 @@ function buildPostMergeReconRecovery(input) {
|
|
|
58924
59184
|
}
|
|
58925
59185
|
function writePostMergeReconRecovery(cwd, recovery) {
|
|
58926
59186
|
const path2 = postMergeReconStatePath(cwd, recovery.repo, recovery.pr);
|
|
58927
|
-
(0, import_node_fs47.mkdirSync)((0,
|
|
59187
|
+
(0, import_node_fs47.mkdirSync)((0, import_node_path45.dirname)(path2), { recursive: true });
|
|
58928
59188
|
(0, import_node_fs47.writeFileSync)(path2, `${JSON.stringify(recovery, null, 2)}
|
|
58929
59189
|
`, "utf8");
|
|
58930
59190
|
return path2;
|
|
@@ -58964,7 +59224,7 @@ function postMergeReconWarnings(input) {
|
|
|
58964
59224
|
}
|
|
58965
59225
|
|
|
58966
59226
|
// src/pr-commands.ts
|
|
58967
|
-
var
|
|
59227
|
+
var import_promises8 = require("node:fs/promises");
|
|
58968
59228
|
init_cli_shared();
|
|
58969
59229
|
|
|
58970
59230
|
// src/api-read.ts
|
|
@@ -60457,10 +60717,10 @@ function registerPrLifecycleCommands(program3) {
|
|
|
60457
60717
|
let body;
|
|
60458
60718
|
try {
|
|
60459
60719
|
if (o.title || o.titleFile) {
|
|
60460
|
-
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
60720
|
+
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
|
|
60461
60721
|
}
|
|
60462
60722
|
if (o.body || o.bodyFile) {
|
|
60463
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
60723
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
|
|
60464
60724
|
}
|
|
60465
60725
|
} catch (e) {
|
|
60466
60726
|
return fail(`pr edit: ${e.message}`);
|
|
@@ -60491,7 +60751,7 @@ function registerPrLifecycleCommands(program3) {
|
|
|
60491
60751
|
}
|
|
60492
60752
|
let body;
|
|
60493
60753
|
try {
|
|
60494
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
60754
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
|
|
60495
60755
|
} catch (e) {
|
|
60496
60756
|
return fail(`pr comment: ${e.message}`);
|
|
60497
60757
|
}
|
|
@@ -60776,8 +61036,8 @@ function registerPrLifecycleCommands(program3) {
|
|
|
60776
61036
|
// src/review-verdict.ts
|
|
60777
61037
|
var import_node_child_process15 = require("node:child_process");
|
|
60778
61038
|
var import_node_fs49 = require("node:fs");
|
|
60779
|
-
var
|
|
60780
|
-
var
|
|
61039
|
+
var import_node_os25 = require("node:os");
|
|
61040
|
+
var import_node_path46 = require("node:path");
|
|
60781
61041
|
init_cli_shared();
|
|
60782
61042
|
var REVIEW_VERDICT_MARKER = "<!-- zeroci-review v1 -->";
|
|
60783
61043
|
var REVIEW_VERDICTS = ["PROCEED", "CORRECT", "ESCALATE"];
|
|
@@ -60942,8 +61202,8 @@ async function readPrIssueComments(number, repo) {
|
|
|
60942
61202
|
return comments;
|
|
60943
61203
|
}
|
|
60944
61204
|
async function postPrCommentFromFile(number, repo, body) {
|
|
60945
|
-
const dir = (0, import_node_fs49.mkdtempSync)((0,
|
|
60946
|
-
const path2 = (0,
|
|
61205
|
+
const dir = (0, import_node_fs49.mkdtempSync)((0, import_node_path46.join)((0, import_node_os25.tmpdir)(), "mmi-review-verdict-"));
|
|
61206
|
+
const path2 = (0, import_node_path46.join)(dir, "body.md");
|
|
60947
61207
|
try {
|
|
60948
61208
|
(0, import_node_fs49.writeFileSync)(path2, body, "utf8");
|
|
60949
61209
|
const { stdout } = await execFileP("gh", ["pr", "comment", number, "--repo", repo, "--body-file", path2], { timeout: GH_MUTATION_TIMEOUT_MS });
|
|
@@ -61439,17 +61699,17 @@ function createPreparationDeps(input, io = {}) {
|
|
|
61439
61699
|
|
|
61440
61700
|
// src/worktree-residue-sweep.ts
|
|
61441
61701
|
var import_node_fs53 = require("node:fs");
|
|
61442
|
-
var
|
|
61702
|
+
var import_node_path50 = require("node:path");
|
|
61443
61703
|
|
|
61444
61704
|
// src/worktree-merge-cleanup.ts
|
|
61445
61705
|
var import_node_fs52 = require("node:fs");
|
|
61446
|
-
var
|
|
61706
|
+
var import_node_path49 = require("node:path");
|
|
61447
61707
|
init_cli_shared();
|
|
61448
61708
|
|
|
61449
61709
|
// src/stage-runner.ts
|
|
61450
61710
|
var import_node_child_process17 = require("node:child_process");
|
|
61451
61711
|
var import_node_fs51 = require("node:fs");
|
|
61452
|
-
var
|
|
61712
|
+
var import_node_path48 = require("node:path");
|
|
61453
61713
|
var import_node_net = require("node:net");
|
|
61454
61714
|
var import_node_util5 = require("node:util");
|
|
61455
61715
|
|
|
@@ -61460,7 +61720,7 @@ function normalizeEol2(s) {
|
|
|
61460
61720
|
|
|
61461
61721
|
// src/env-detection.ts
|
|
61462
61722
|
var import_node_fs50 = require("node:fs");
|
|
61463
|
-
var
|
|
61723
|
+
var import_node_path47 = require("node:path");
|
|
61464
61724
|
var SKIPPED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".jerv", ".pi", ".venv", "venv"]);
|
|
61465
61725
|
function isEnvBaseName(name) {
|
|
61466
61726
|
return name.toLowerCase() === ".env";
|
|
@@ -61478,13 +61738,13 @@ function findEnvFiles(root) {
|
|
|
61478
61738
|
const relPath = rel ? `${rel}/${entry.name}` : entry.name;
|
|
61479
61739
|
if (entry.isDirectory()) {
|
|
61480
61740
|
if (SKIPPED_DIRS.has(entry.name)) continue;
|
|
61481
|
-
walk2((0,
|
|
61741
|
+
walk2((0, import_node_path47.join)(dir, entry.name), relPath);
|
|
61482
61742
|
continue;
|
|
61483
61743
|
}
|
|
61484
61744
|
if (isEnvBaseName(entry.name)) {
|
|
61485
61745
|
let isDir = false;
|
|
61486
61746
|
try {
|
|
61487
|
-
isDir = (0, import_node_fs50.lstatSync)((0,
|
|
61747
|
+
isDir = (0, import_node_fs50.lstatSync)((0, import_node_path47.join)(dir, entry.name)).isDirectory();
|
|
61488
61748
|
} catch {
|
|
61489
61749
|
}
|
|
61490
61750
|
if (!isDir) found.push(relPath);
|
|
@@ -61623,10 +61883,10 @@ var DOCKER_TIMEOUT_MS = 15e3;
|
|
|
61623
61883
|
function stageBash() {
|
|
61624
61884
|
if (process.platform !== "win32") return "bash";
|
|
61625
61885
|
const configured = process.env.SHELL;
|
|
61626
|
-
if (configured && (0,
|
|
61886
|
+
if (configured && (0, import_node_path48.isAbsolute)(configured) && /[/\\]bash(?:\.exe)?$/i.test(configured) && !/[/\\](?:System32|Sysnative)[/\\]bash(?:\.exe)?$/i.test(configured) && (0, import_node_fs51.existsSync)(configured)) return configured;
|
|
61627
61887
|
const candidates = [
|
|
61628
|
-
(0,
|
|
61629
|
-
...process.env.LOCALAPPDATA ? [(0,
|
|
61888
|
+
(0, import_node_path48.join)(process.env.ProgramFiles || "C:\\Program Files", "Git", "bin", "bash.exe"),
|
|
61889
|
+
...process.env.LOCALAPPDATA ? [(0, import_node_path48.join)(process.env.LOCALAPPDATA, "Programs", "Git", "bin", "bash.exe")] : []
|
|
61630
61890
|
];
|
|
61631
61891
|
const bash = candidates.find((path2) => (0, import_node_fs51.existsSync)(path2));
|
|
61632
61892
|
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.");
|
|
@@ -61766,7 +62026,7 @@ function appendForceRecreate(up) {
|
|
|
61766
62026
|
return `${up.trimEnd()} --force-recreate`;
|
|
61767
62027
|
}
|
|
61768
62028
|
function stageStatePath(cwd = process.cwd()) {
|
|
61769
|
-
return (0,
|
|
62029
|
+
return (0, import_node_path48.join)(cwd, "tmp", "stage", "state.json");
|
|
61770
62030
|
}
|
|
61771
62031
|
function normPath(path2) {
|
|
61772
62032
|
return path2.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
|
|
@@ -61983,7 +62243,7 @@ function stageProcessEnv(stagePort, extraEnv) {
|
|
|
61983
62243
|
}
|
|
61984
62244
|
function composeResolvesPort(cwd) {
|
|
61985
62245
|
if (process.env.PORT) return true;
|
|
61986
|
-
const envFile = (0,
|
|
62246
|
+
const envFile = (0, import_node_path48.join)(cwd, ".env");
|
|
61987
62247
|
return (0, import_node_fs51.existsSync)(envFile) && envFileKeys((0, import_node_fs51.readFileSync)(envFile, "utf8")).has("PORT");
|
|
61988
62248
|
}
|
|
61989
62249
|
function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
|
|
@@ -61999,13 +62259,13 @@ function stageComposeEnv(config, stagePort, vaultEnvMerge, cwd) {
|
|
|
61999
62259
|
function stageComposeFiles(cwd) {
|
|
62000
62260
|
const files = ["docker-compose.yml"];
|
|
62001
62261
|
for (const conventional of ["docker-compose.override.yml", "docker-compose.override.yaml"]) {
|
|
62002
|
-
if ((0, import_node_fs51.existsSync)((0,
|
|
62262
|
+
if ((0, import_node_fs51.existsSync)((0, import_node_path48.join)(cwd, conventional))) files.push(conventional);
|
|
62003
62263
|
}
|
|
62004
62264
|
return [...files, RUNTIME_ENV_OVERRIDE_RELPATH];
|
|
62005
62265
|
}
|
|
62006
62266
|
async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
|
|
62007
62267
|
const keys = Object.keys(vaultEnvMerge ?? {});
|
|
62008
|
-
if (!keys.length || !(0, import_node_fs51.existsSync)((0,
|
|
62268
|
+
if (!keys.length || !(0, import_node_fs51.existsSync)((0, import_node_path48.join)(cwd, "docker-compose.yml"))) return {};
|
|
62009
62269
|
let configJson;
|
|
62010
62270
|
try {
|
|
62011
62271
|
const { stdout } = await execFileP3("docker", ["compose", "config", "--format", "json"], {
|
|
@@ -62021,15 +62281,15 @@ async function prepareRuntimeEnvPassthrough(cwd, composeEnv, vaultEnvMerge) {
|
|
|
62021
62281
|
}
|
|
62022
62282
|
const body = renderRuntimeEnvOverride(runtimeEnvMarkedServices(configJson), keys, runtimeEnvExcludes(configJson), runtimeEnvSelects(configJson));
|
|
62023
62283
|
if (!body) return {};
|
|
62024
|
-
const overridePath = (0,
|
|
62025
|
-
(0, import_node_fs51.mkdirSync)((0,
|
|
62284
|
+
const overridePath = (0, import_node_path48.join)(cwd, RUNTIME_ENV_OVERRIDE_RELPATH);
|
|
62285
|
+
(0, import_node_fs51.mkdirSync)((0, import_node_path48.join)(cwd, "tmp", "stage"), { recursive: true });
|
|
62026
62286
|
(0, import_node_fs51.writeFileSync)(overridePath, body, "utf8");
|
|
62027
62287
|
return stageComposeFileEnv(stageComposeFiles(cwd));
|
|
62028
62288
|
}
|
|
62029
62289
|
async function ensureStageRuntimeEnv(config, opts, cwd) {
|
|
62030
62290
|
if (!config.ensureEnv) return;
|
|
62031
|
-
const target = (0,
|
|
62032
|
-
const example = (0,
|
|
62291
|
+
const target = (0, import_node_path48.join)(cwd, config.ensureEnv.target);
|
|
62292
|
+
const example = (0, import_node_path48.join)(cwd, config.ensureEnv.example);
|
|
62033
62293
|
if (!(0, import_node_fs51.existsSync)(target) && (0, import_node_fs51.existsSync)(example)) {
|
|
62034
62294
|
(0, import_node_fs51.copyFileSync)(example, target);
|
|
62035
62295
|
} else if ((0, import_node_fs51.existsSync)(target) && (0, import_node_fs51.existsSync)(example)) {
|
|
@@ -62383,7 +62643,7 @@ function normPath2(p) {
|
|
|
62383
62643
|
return p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
62384
62644
|
}
|
|
62385
62645
|
function unlinkNodeModulesJunction(wtPath) {
|
|
62386
|
-
const nm = (0,
|
|
62646
|
+
const nm = (0, import_node_path49.join)(wtPath, "node_modules");
|
|
62387
62647
|
try {
|
|
62388
62648
|
if ((0, import_node_fs52.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs52.rmdirSync)(nm);
|
|
62389
62649
|
return { ok: true };
|
|
@@ -62520,7 +62780,7 @@ async function preCleanWorktreeForRemoval(wtPath, execGit) {
|
|
|
62520
62780
|
}
|
|
62521
62781
|
async function listNestedIgnoredNodeModules(wtPath, execGit) {
|
|
62522
62782
|
const out = await execGit(["-C", wtPath, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory"]).catch(() => "");
|
|
62523
|
-
return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0,
|
|
62783
|
+
return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path49.join)(wtPath, line.slice(0, -1)));
|
|
62524
62784
|
}
|
|
62525
62785
|
function safeRemoveTree(path2) {
|
|
62526
62786
|
const stat4 = (0, import_node_fs52.lstatSync)(path2);
|
|
@@ -62533,7 +62793,7 @@ function safeRemoveTree(path2) {
|
|
|
62533
62793
|
return;
|
|
62534
62794
|
}
|
|
62535
62795
|
if (stat4.isDirectory()) {
|
|
62536
|
-
for (const entry of (0, import_node_fs52.readdirSync)(path2)) safeRemoveTree((0,
|
|
62796
|
+
for (const entry of (0, import_node_fs52.readdirSync)(path2)) safeRemoveTree((0, import_node_path49.join)(path2, entry));
|
|
62537
62797
|
(0, import_node_fs52.rmdirSync)(path2);
|
|
62538
62798
|
return;
|
|
62539
62799
|
}
|
|
@@ -62541,7 +62801,7 @@ function safeRemoveTree(path2) {
|
|
|
62541
62801
|
}
|
|
62542
62802
|
async function removeWorktreeNodeModules(wtPath) {
|
|
62543
62803
|
try {
|
|
62544
|
-
safeRemoveTree((0,
|
|
62804
|
+
safeRemoveTree((0, import_node_path49.join)(wtPath, "node_modules"));
|
|
62545
62805
|
return { ok: true };
|
|
62546
62806
|
} catch (e) {
|
|
62547
62807
|
if (e.code === "ENOENT") return { ok: true };
|
|
@@ -62586,7 +62846,7 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
|
|
|
62586
62846
|
return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
|
|
62587
62847
|
}
|
|
62588
62848
|
for (const entry of entries) {
|
|
62589
|
-
const child2 = (0,
|
|
62849
|
+
const child2 = (0, import_node_path49.join)(dir, entry.name);
|
|
62590
62850
|
if (entry.isSymbolicLink()) {
|
|
62591
62851
|
let target = "";
|
|
62592
62852
|
try {
|
|
@@ -62913,7 +63173,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
|
|
|
62913
63173
|
const preHelperGuard = unlinkEscapingReparsePoints(wtPath, options.primaryRoot);
|
|
62914
63174
|
if (!preHelperGuard.ok) return refuseReparseEscape(preHelperGuard.error);
|
|
62915
63175
|
unlinkedReparsePoints.push(...preHelperGuard.unlinked);
|
|
62916
|
-
if (pathExists((0,
|
|
63176
|
+
if (pathExists((0, import_node_path49.join)(wtPath, "node_modules"))) {
|
|
62917
63177
|
const nmRemoved = await (options.removeRealNodeModules ?? removeWorktreeNodeModules)(wtPath);
|
|
62918
63178
|
if (!nmRemoved.ok) {
|
|
62919
63179
|
report.worktree = {
|
|
@@ -63049,35 +63309,35 @@ function renderPrMergeCleanupLines(cleanup) {
|
|
|
63049
63309
|
// src/worktree-residue-sweep.ts
|
|
63050
63310
|
var RESIDUE_LEDGER_FILE = "mmi-worktree-residue.json";
|
|
63051
63311
|
function canonicalWorktreeRoot(primary) {
|
|
63052
|
-
return (0,
|
|
63312
|
+
return (0, import_node_path50.join)((0, import_node_path50.dirname)(primary), "mmi-worktrees", (0, import_node_path50.basename)(primary));
|
|
63053
63313
|
}
|
|
63054
63314
|
function lastSegment(p) {
|
|
63055
|
-
return (0,
|
|
63315
|
+
return (0, import_node_path50.basename)(p.split(/[\\/]+/).filter(Boolean).pop() ?? p);
|
|
63056
63316
|
}
|
|
63057
63317
|
function readProvenance(folder, gitCommonDir, exists) {
|
|
63058
63318
|
const found = {
|
|
63059
63319
|
path: folder,
|
|
63060
63320
|
gitdirPresent: false,
|
|
63061
|
-
registrationId: (0,
|
|
63321
|
+
registrationId: (0, import_node_path50.basename)(folder),
|
|
63062
63322
|
registrationPresent: false
|
|
63063
63323
|
};
|
|
63064
63324
|
try {
|
|
63065
|
-
const pointer = /^\s*gitdir:\s*(.+?)\s*$/m.exec((0, import_node_fs53.readFileSync)((0,
|
|
63325
|
+
const pointer = /^\s*gitdir:\s*(.+?)\s*$/m.exec((0, import_node_fs53.readFileSync)((0, import_node_path50.join)(folder, ".git"), "utf8"));
|
|
63066
63326
|
if (pointer) {
|
|
63067
63327
|
const target = pointer[1];
|
|
63068
|
-
found.gitdir = (0,
|
|
63328
|
+
found.gitdir = (0, import_node_path50.isAbsolute)(target) ? target : (0, import_node_path50.join)(folder, target);
|
|
63069
63329
|
found.gitdirPresent = exists(found.gitdir);
|
|
63070
63330
|
found.registrationId = lastSegment(found.gitdir);
|
|
63071
63331
|
}
|
|
63072
63332
|
} catch {
|
|
63073
63333
|
}
|
|
63074
63334
|
try {
|
|
63075
|
-
found.registrationPresent = exists((0,
|
|
63335
|
+
found.registrationPresent = exists((0, import_node_path50.join)(gitCommonDir, "worktrees", found.registrationId));
|
|
63076
63336
|
} catch {
|
|
63077
63337
|
}
|
|
63078
63338
|
if (found.gitdir && found.gitdirPresent) {
|
|
63079
63339
|
try {
|
|
63080
|
-
const head = (0, import_node_fs53.readFileSync)((0,
|
|
63340
|
+
const head = (0, import_node_fs53.readFileSync)((0, import_node_path50.join)(found.gitdir, "HEAD"), "utf8").trim();
|
|
63081
63341
|
const branch = /^ref:\s*(.+?)\s*$/.exec(head);
|
|
63082
63342
|
if (branch) found.head = branch[1].startsWith("refs/heads/") ? branch[1].slice("refs/heads/".length) : `ref ${branch[1]}`;
|
|
63083
63343
|
else if (/^[0-9a-f]{7,64}$/i.test(head)) found.head = `detached ${head.slice(0, 12)}`;
|
|
@@ -63096,7 +63356,7 @@ function norm2(p) {
|
|
|
63096
63356
|
return process.platform === "win32" ? s.toLowerCase() : s;
|
|
63097
63357
|
}
|
|
63098
63358
|
function residueLedgerPath(gitCommonDir) {
|
|
63099
|
-
return (0,
|
|
63359
|
+
return (0, import_node_path50.join)(gitCommonDir, RESIDUE_LEDGER_FILE);
|
|
63100
63360
|
}
|
|
63101
63361
|
function readPaths(file, deps) {
|
|
63102
63362
|
try {
|
|
@@ -63109,7 +63369,7 @@ function readPaths(file, deps) {
|
|
|
63109
63369
|
function writePaths(file, paths, deps) {
|
|
63110
63370
|
try {
|
|
63111
63371
|
const write = deps.writeLedger ?? ((f, t) => {
|
|
63112
|
-
(0, import_node_fs53.mkdirSync)((0,
|
|
63372
|
+
(0, import_node_fs53.mkdirSync)((0, import_node_path50.dirname)(f), { recursive: true });
|
|
63113
63373
|
(0, import_node_fs53.writeFileSync)(f, t, "utf8");
|
|
63114
63374
|
});
|
|
63115
63375
|
write(file, `${JSON.stringify([...new Set(paths)], null, 1)}
|
|
@@ -63169,7 +63429,7 @@ async function sweepWorktreeResidue(gitCommonDir, registered, deps = {}) {
|
|
|
63169
63429
|
} catch {
|
|
63170
63430
|
}
|
|
63171
63431
|
for (const name of children) {
|
|
63172
|
-
const child2 = (0,
|
|
63432
|
+
const child2 = (0, import_node_path50.join)(root, name);
|
|
63173
63433
|
const key = norm2(child2);
|
|
63174
63434
|
if (live.has(key) || key === primary || keptKeys.has(key) || !isDir(child2)) continue;
|
|
63175
63435
|
let entries;
|
|
@@ -63221,10 +63481,10 @@ function argvWantsJson2() {
|
|
|
63221
63481
|
return process.argv.some((a) => a === "--json" || a.startsWith("--json="));
|
|
63222
63482
|
}
|
|
63223
63483
|
function hubRoot() {
|
|
63224
|
-
const fromPkg = (0,
|
|
63484
|
+
const fromPkg = (0, import_node_path51.join)(__dirname, "..", "..");
|
|
63225
63485
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
63226
|
-
if ((0, import_node_fs54.existsSync)((0,
|
|
63227
|
-
if ((0, import_node_fs54.existsSync)((0,
|
|
63486
|
+
if ((0, import_node_fs54.existsSync)((0, import_node_path51.join)(fromPkg, marker))) return fromPkg;
|
|
63487
|
+
if ((0, import_node_fs54.existsSync)((0, import_node_path51.join)(process.cwd(), marker))) return process.cwd();
|
|
63228
63488
|
return null;
|
|
63229
63489
|
}
|
|
63230
63490
|
function ciAuditDeps() {
|
|
@@ -63236,7 +63496,7 @@ function ciAuditDeps() {
|
|
|
63236
63496
|
getProjectMeta: async (slug) => fetchProjectBySlug(slug, registryClientDeps(await cfgPromise)),
|
|
63237
63497
|
readSeedFile: (path2) => {
|
|
63238
63498
|
if (!root) return null;
|
|
63239
|
-
const fullPath = (0,
|
|
63499
|
+
const fullPath = (0, import_node_path51.join)(root, path2);
|
|
63240
63500
|
return (0, import_node_fs54.existsSync)(fullPath) ? (0, import_node_fs54.readFileSync)(fullPath, "utf8") : null;
|
|
63241
63501
|
}
|
|
63242
63502
|
};
|
|
@@ -63461,7 +63721,7 @@ function registerCollaborationCommands(program3) {
|
|
|
63461
63721
|
try {
|
|
63462
63722
|
title = await resolveIssueTitle(
|
|
63463
63723
|
{ title: opts.title, titleFile: opts.titleFile },
|
|
63464
|
-
{ readFile:
|
|
63724
|
+
{ readFile: import_promises9.readFile, readStdin }
|
|
63465
63725
|
);
|
|
63466
63726
|
} catch (e) {
|
|
63467
63727
|
return fail(
|
|
@@ -63515,8 +63775,8 @@ function registerCollaborationCommands(program3) {
|
|
|
63515
63775
|
let surfaceInferred;
|
|
63516
63776
|
try {
|
|
63517
63777
|
issueType = resolveCreateType(o.type, "issue create", o.label);
|
|
63518
|
-
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
63519
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
63778
|
+
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises9.readFile, readStdin });
|
|
63779
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
|
|
63520
63780
|
if (o.idempotencyKey) body = appendIdempotencyMarker(body, o.idempotencyKey);
|
|
63521
63781
|
priority = resolveCreatePriority(o.priority, "issue create");
|
|
63522
63782
|
extraLabels = [...o.label ?? []];
|
|
@@ -63831,7 +64091,7 @@ function registerCollaborationCommands(program3) {
|
|
|
63831
64091
|
}
|
|
63832
64092
|
let body;
|
|
63833
64093
|
try {
|
|
63834
|
-
body = o.edit !== void 0 ? "" : await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
64094
|
+
body = o.edit !== void 0 ? "" : await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
|
|
63835
64095
|
} catch (e) {
|
|
63836
64096
|
return fail(`issue comment: ${e.message}`);
|
|
63837
64097
|
}
|
|
@@ -63910,8 +64170,8 @@ ${list}`);
|
|
|
63910
64170
|
let title;
|
|
63911
64171
|
const sourceRepo = o.repo ?? await resolveRepo(void 0);
|
|
63912
64172
|
try {
|
|
63913
|
-
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
63914
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
64173
|
+
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises9.readFile, readStdin });
|
|
64174
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
|
|
63915
64175
|
priority = resolveCreatePriority(o.priority, "report");
|
|
63916
64176
|
if (!ISSUE_TYPES.includes(o.type)) {
|
|
63917
64177
|
throw new Error(`unknown issue type "${o.type}" \u2014 expected one of: ${ISSUE_TYPES.join(", ")}`);
|
|
@@ -63965,8 +64225,8 @@ ${list}`);
|
|
|
63965
64225
|
let args;
|
|
63966
64226
|
try {
|
|
63967
64227
|
skill = assertSkillName(o.skill);
|
|
63968
|
-
rawBody = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
63969
|
-
const rawTitle = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
64228
|
+
rawBody = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
|
|
64229
|
+
const rawTitle = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises9.readFile, readStdin });
|
|
63970
64230
|
title = buildSkillLessonTitle(skill, rawTitle);
|
|
63971
64231
|
priority = resolveCreatePriority(o.priority, "skill-lesson");
|
|
63972
64232
|
body = buildSkillLessonBody(rawBody, sourceRepo, pluginSha);
|
|
@@ -64027,8 +64287,8 @@ ${list}`);
|
|
|
64027
64287
|
let body;
|
|
64028
64288
|
let title;
|
|
64029
64289
|
try {
|
|
64030
|
-
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
64031
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
64290
|
+
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises9.readFile, readStdin });
|
|
64291
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises9.readFile, readStdin });
|
|
64032
64292
|
} catch (e) {
|
|
64033
64293
|
return fail(`pr create: ${e.message}`, e instanceof TextArgError ? { code: e.code, offending_flag: e.offendingFlag } : void 0);
|
|
64034
64294
|
}
|
|
@@ -64122,11 +64382,11 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
|
|
|
64122
64382
|
}
|
|
64123
64383
|
});
|
|
64124
64384
|
async function listCiWorkflowPaths(cwd = process.cwd()) {
|
|
64125
|
-
const wfDir = (0,
|
|
64385
|
+
const wfDir = (0, import_node_path51.join)(cwd, ".github", "workflows");
|
|
64126
64386
|
if (!(0, import_node_fs54.existsSync)(wfDir)) return [];
|
|
64127
64387
|
return (0, import_node_fs54.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
|
|
64128
64388
|
try {
|
|
64129
|
-
return workflowReportsPrChecks((0, import_node_fs54.readFileSync)((0,
|
|
64389
|
+
return workflowReportsPrChecks((0, import_node_fs54.readFileSync)((0, import_node_path51.join)(wfDir, name), "utf8"));
|
|
64130
64390
|
} catch {
|
|
64131
64391
|
return true;
|
|
64132
64392
|
}
|
|
@@ -64381,7 +64641,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
|
|
|
64381
64641
|
}
|
|
64382
64642
|
class PrHeadBehindBaseError extends Error {
|
|
64383
64643
|
}
|
|
64384
|
-
pr.command("land <numbers...>").description("agent merge path (#1440): train probe \u2014 checks-wait \u2014 merge --auto \u2014 poll enqueued \u2014 development PRs only. Several PR numbers land together (#8322): all are enqueued, waited on together, a queue-ejected PR is updated and re-enqueued once, a queue merge is followed by worktree/branch cleanup and board Done, and one table (or --json) reports each outcome").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the PR repo)").option("--enqueue-only", "return once queue membership is confirmed; without a merge queue, land normally").option("--abandon-admission", "one stuck-receipt recovery, one PR per call: journal the saved non-terminal (pending/enqueued) queue-admission receipt terminal ONLY after positively observing the PR OPEN at the receipt head and absent from the queue; any unprovable observation refuses and changes nothing (#9951). The next pr land then submits a new intent with no new head").option("--no-require-train", "skip train-authority preflight (not recommended for autonomous agents)").option("--force", "silence the leftover-scratch warning (scratch never blocks, #8785) and acknowledge a negated-closing-keyword (#3718) or ambiguous-cross-repo-closing (#4279) refusal").option("--without-review <reason>", "compatibility option; shared merge helpers do not require a review verdict").option("--timeout <minutes>", `merge-queue wait per PR (default ${PR_LAND_QUEUE_TIMEOUT_MS / 6e4} minutes, one window per ${PR_LAND_QUEUE_BATCH_SIZE} PRs \u2014 per-repo ruleset check_response_timeout_minutes is 15 default with 30/45/60 overrides in .github/rulesets/mmi-development-merge-queue.json; agents never edit the ruleset to shorten a queue wait)`).option("--preserve-worktree", "after a queue merge keep the local worktree and branch (skips the post-merge cleanup)").option("--expect-head <sha>", "pin the PR head to this full 40-hex SHA (#8456): checked before landing, after checks and by GitHub at enqueue (--match-head-commit); never updates a BEHIND head and never retries an ejection \u2014 it stops with pinnedHead.refused instead. One PR only").action(async (numbers, opts) => {
|
|
64644
|
+
pr.command("land <numbers...>").description("agent merge path (#1440): train probe \u2014 checks-wait \u2014 merge --auto \u2014 poll enqueued \u2014 development PRs only. Several PR numbers land together (#8322): all are enqueued, waited on together, a queue-ejected PR is updated and re-enqueued once, a queue merge is followed by worktree/branch cleanup and board Done, and one table (or --json) reports each outcome").option("--json", "machine-readable output").option("--repo <owner/repo>", "target repo (defaults to the PR repo)").option("--enqueue-only", "return once queue membership is confirmed; without a merge queue, land normally").option("--abandon-admission", "one stuck-receipt recovery, one PR per call: journal the saved non-terminal (pending/enqueued, or a dispatching send that saved no operation UUID after its sender died \u2014 #9995) queue-admission receipt terminal ONLY after positively observing the PR OPEN at the receipt head and absent from the queue; any unprovable observation refuses and changes nothing (#9951). The next pr land then submits a new intent with no new head").option("--no-require-train", "skip train-authority preflight (not recommended for autonomous agents)").option("--force", "silence the leftover-scratch warning (scratch never blocks, #8785) and acknowledge a negated-closing-keyword (#3718) or ambiguous-cross-repo-closing (#4279) refusal").option("--without-review <reason>", "compatibility option; shared merge helpers do not require a review verdict").option("--timeout <minutes>", `merge-queue wait per PR (default ${PR_LAND_QUEUE_TIMEOUT_MS / 6e4} minutes, one window per ${PR_LAND_QUEUE_BATCH_SIZE} PRs \u2014 per-repo ruleset check_response_timeout_minutes is 15 default with 30/45/60 overrides in .github/rulesets/mmi-development-merge-queue.json; agents never edit the ruleset to shorten a queue wait)`).option("--preserve-worktree", "after a queue merge keep the local worktree and branch (skips the post-merge cleanup)").option("--expect-head <sha>", "pin the PR head to this full 40-hex SHA (#8456): checked before landing, after checks and by GitHub at enqueue (--match-head-commit); never updates a BEHIND head and never retries an ejection \u2014 it stops with pinnedHead.refused instead. One PR only").action(async (numbers, opts) => {
|
|
64385
64645
|
const timeoutMinutes = opts.timeout === void 0 ? void 0 : Number(opts.timeout);
|
|
64386
64646
|
if (timeoutMinutes !== void 0 && !(timeoutMinutes > 0)) return fail("pr land: --timeout must be a positive number of minutes");
|
|
64387
64647
|
if (opts.abandonAdmission) {
|
|
@@ -64722,7 +64982,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
|
|
|
64722
64982
|
const remote = foreignCwd ? `https://github.com/${targetRepo2}.git` : "origin";
|
|
64723
64983
|
let foreignCheckout;
|
|
64724
64984
|
if (foreignCwd) {
|
|
64725
|
-
const sibling = (0,
|
|
64985
|
+
const sibling = (0, import_node_path51.join)((0, import_node_path51.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
|
|
64726
64986
|
const siblingRepo = repoFromRemoteUrl(await gitOut(["-C", sibling, "remote", "get-url", "origin"]).catch(() => ""));
|
|
64727
64987
|
if (siblingRepo?.toLowerCase() === targetRepo2.toLowerCase()) {
|
|
64728
64988
|
const siblingWorktrees = await execFileP("git", ["-C", sibling, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => parseGitWorktreePorcelain(r.stdout)).catch(() => void 0);
|
|
@@ -64956,7 +65216,7 @@ ${preparation.findings.map((finding) => `[${finding.check}/${finding.state}] ${f
|
|
|
64956
65216
|
let residueSweep;
|
|
64957
65217
|
if (!(foreignCwd && !foreignCheckout)) {
|
|
64958
65218
|
try {
|
|
64959
|
-
gitCommonDir = (0,
|
|
65219
|
+
gitCommonDir = (0, import_node_path51.resolve)(primaryRoot, (await execFileP("git", ["-C", primaryRoot, "rev-parse", "--git-common-dir"], { timeout: GIT_TIMEOUT_MS })).stdout.trim());
|
|
64960
65220
|
residueSweep = await sweepWorktreeResidue(gitCommonDir, beforeWorktrees.map((w) => w.path));
|
|
64961
65221
|
} catch {
|
|
64962
65222
|
}
|
|
@@ -65176,7 +65436,7 @@ function trainGitArgs(args) {
|
|
|
65176
65436
|
async function announceSummaryLineCountRefusal(path2) {
|
|
65177
65437
|
let content;
|
|
65178
65438
|
try {
|
|
65179
|
-
content = await (0,
|
|
65439
|
+
content = await (0, import_promises10.readFile)(path2, "utf8");
|
|
65180
65440
|
} catch (e) {
|
|
65181
65441
|
return `release: could not read --announce-summary-file ${path2}: ${e.message} \u2014 see https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#announce-summary-missing`;
|
|
65182
65442
|
}
|
|
@@ -65188,7 +65448,7 @@ async function announceSummaryLineCountRefusal(path2) {
|
|
|
65188
65448
|
async function announceSummaryRefusal(path2, isHub = false, isWorkSuite = false) {
|
|
65189
65449
|
let lines2;
|
|
65190
65450
|
try {
|
|
65191
|
-
lines2 = summaryFileLines(await (0,
|
|
65451
|
+
lines2 = summaryFileLines(await (0, import_promises10.readFile)(path2, "utf8"));
|
|
65192
65452
|
} catch (e) {
|
|
65193
65453
|
return `release: could not read --announce-summary-file ${path2}: ${e.message} \u2014 see https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#announce-summary-missing`;
|
|
65194
65454
|
}
|
|
@@ -65326,8 +65586,8 @@ function trainApplyDeps() {
|
|
|
65326
65586
|
}
|
|
65327
65587
|
return body.status;
|
|
65328
65588
|
},
|
|
65329
|
-
readFile: (path2) => (0,
|
|
65330
|
-
removeFile: (path2) => (0,
|
|
65589
|
+
readFile: (path2) => (0, import_promises10.readFile)(path2, "utf8"),
|
|
65590
|
+
removeFile: (path2) => (0, import_promises10.unlink)(path2),
|
|
65331
65591
|
// #6521/#6523: the project's own release channel AND releaseLanguage, read from registry META in ONE
|
|
65332
65592
|
// checked read. Same shape as fetchEdgeDomains below: a FAILED read refuses by name so the announce
|
|
65333
65593
|
// note reports a failed read, never a project that configured nothing.
|
|
@@ -66255,7 +66515,7 @@ function rcRunCauseFromLog(log) {
|
|
|
66255
66515
|
function memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles) {
|
|
66256
66516
|
return repo === SUITE_REPO ? summaryFile : memberSummaryFiles[repo];
|
|
66257
66517
|
}
|
|
66258
|
-
var suiteStateDir = (root) => (0,
|
|
66518
|
+
var suiteStateDir = (root) => (0, import_node_path53.join)(resolvePrimaryGitDir(root), "mmi-runtime", "suite");
|
|
66259
66519
|
async function runSuiteMemberRcand(repo, previousRc, rcWasAbsent) {
|
|
66260
66520
|
const deps = trainApplyDeps();
|
|
66261
66521
|
deps.suiteCut = suiteCutContext(repo, SUITE_REPO);
|
|
@@ -66302,16 +66562,16 @@ async function rcandInCheckout(repo, deps, previousRc, rcWasAbsent) {
|
|
|
66302
66562
|
}
|
|
66303
66563
|
}
|
|
66304
66564
|
function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr, memberSummaryFilesTr = {}) {
|
|
66305
|
-
const recordPath = (0,
|
|
66306
|
-
const base = (0,
|
|
66565
|
+
const recordPath = (0, import_node_path53.join)(suiteStateDir(root), "cut.json");
|
|
66566
|
+
const base = (0, import_node_path53.join)(suiteStateDir(root), "checkouts");
|
|
66307
66567
|
const checkout = async (repo) => {
|
|
66308
66568
|
if (repo === SUITE_REPO) return root;
|
|
66309
|
-
const target = (0,
|
|
66569
|
+
const target = (0, import_node_path53.join)(base, repo.split("/")[1]);
|
|
66310
66570
|
if (!(0, import_node_fs55.existsSync)(target)) {
|
|
66311
66571
|
(0, import_node_fs55.mkdirSync)(base, { recursive: true });
|
|
66312
66572
|
await exec("git", ["clone", "--quiet", "--branch", "development", `https://github.com/${repo}.git`, target], root, WATCH_TIMEOUT);
|
|
66313
66573
|
}
|
|
66314
|
-
if (!(0, import_node_fs55.existsSync)((0,
|
|
66574
|
+
if (!(0, import_node_fs55.existsSync)((0, import_node_path53.join)(target, ".git"))) throw new Error(`${repo}: suite checkout has no .git at ${target}; stop`);
|
|
66315
66575
|
const origin = await exec("git", ["remote", "get-url", "origin"], target);
|
|
66316
66576
|
if (!origin.toLowerCase().endsWith(`/${repo.toLowerCase()}.git`) && !origin.toLowerCase().endsWith(`/${repo.toLowerCase()}`))
|
|
66317
66577
|
throw new Error(`${repo}: suite checkout origin mismatch at ${target}; stop`);
|
|
@@ -66375,7 +66635,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
|
|
|
66375
66635
|
if (repo === SUITE_REPO) return inTrain(repo, (deps) => rcandInCheckout(repo, deps, previousRc, rcWasAbsent));
|
|
66376
66636
|
const target = await checkout(repo);
|
|
66377
66637
|
return new Promise((resolveResult, reject2) => {
|
|
66378
|
-
const child2 = (0, import_node_child_process19.fork)((0,
|
|
66638
|
+
const child2 = (0, import_node_child_process19.fork)((0, import_node_path52.resolve)(process.argv[1]), ["devops", "suite", "member-rcand-internal", repo, previousRc ?? "", ...rcWasAbsent ? ["--rc-was-absent"] : []], {
|
|
66379
66639
|
cwd: target,
|
|
66380
66640
|
stdio: ["ignore", "inherit", "inherit", "ipc"],
|
|
66381
66641
|
execArgv: []
|
|
@@ -66619,7 +66879,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr,
|
|
|
66619
66879
|
if (parseSuiteMapping(body)) return;
|
|
66620
66880
|
const dir = suiteStateDir(root);
|
|
66621
66881
|
(0, import_node_fs55.mkdirSync)(dir, { recursive: true });
|
|
66622
|
-
const file = (0,
|
|
66882
|
+
const file = (0, import_node_path53.join)(dir, `notes-${leadTag}.md`);
|
|
66623
66883
|
(0, import_node_fs55.writeFileSync)(file, `${body}
|
|
66624
66884
|
|
|
66625
66885
|
${suiteMappingBlock(leadTag, mapping)}`);
|
|
@@ -66996,8 +67256,8 @@ function registerJevCommands(program3) {
|
|
|
66996
67256
|
// src/packages-adopt-export.ts
|
|
66997
67257
|
var import_node_child_process20 = require("node:child_process");
|
|
66998
67258
|
var import_node_fs57 = require("node:fs");
|
|
66999
|
-
var
|
|
67000
|
-
var
|
|
67259
|
+
var import_node_os26 = require("node:os");
|
|
67260
|
+
var import_node_path54 = require("node:path");
|
|
67001
67261
|
var import_node_util6 = require("node:util");
|
|
67002
67262
|
init_cli_shared();
|
|
67003
67263
|
|
|
@@ -67617,25 +67877,25 @@ function expectedFromRun(run, opts) {
|
|
|
67617
67877
|
}
|
|
67618
67878
|
async function adoptExport(opts, deps) {
|
|
67619
67879
|
if (!/^sha256:[0-9a-f]{64}$/.test(opts.digest)) throw new Error("--digest must be sha256:<64 hex>, from the export run summary");
|
|
67620
|
-
const packagePath = (0,
|
|
67621
|
-
const lockPath = (0,
|
|
67880
|
+
const packagePath = (0, import_node_path54.join)(opts.dir, "package.json");
|
|
67881
|
+
const lockPath = (0, import_node_path54.join)(opts.dir, "package-lock.json");
|
|
67622
67882
|
const packageText = (0, import_node_fs57.readFileSync)(packagePath, "utf8");
|
|
67623
67883
|
const lockText = (0, import_node_fs57.readFileSync)(lockPath, "utf8");
|
|
67624
|
-
const work = (0, import_node_fs57.mkdtempSync)((0,
|
|
67884
|
+
const work = (0, import_node_fs57.mkdtempSync)((0, import_node_path54.join)((0, import_node_os26.tmpdir)(), "mmi-adopt-export-"));
|
|
67625
67885
|
try {
|
|
67626
67886
|
const run = JSON.parse((await deps.ghApi(`repos/${EXPORT_REPO}/actions/runs/${opts.run}`)).toString("utf8"));
|
|
67627
|
-
(0, import_node_fs57.writeFileSync)((0,
|
|
67628
|
-
(0, import_node_fs57.writeFileSync)((0,
|
|
67629
|
-
(0, import_node_fs57.writeFileSync)((0,
|
|
67630
|
-
const script = (0,
|
|
67887
|
+
(0, import_node_fs57.writeFileSync)((0, import_node_path54.join)(work, "expected.json"), JSON.stringify(expectedFromRun(run, opts)));
|
|
67888
|
+
(0, import_node_fs57.writeFileSync)((0, import_node_path54.join)(work, "provider.json"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}`));
|
|
67889
|
+
(0, import_node_fs57.writeFileSync)((0, import_node_path54.join)(work, "artifact.zip"), await deps.ghApi(`repos/${EXPORT_REPO}/actions/artifacts/${opts.artifact}/zip`));
|
|
67890
|
+
const script = (0, import_node_path54.join)(work, "package_export.py");
|
|
67631
67891
|
(0, import_node_fs57.writeFileSync)(script, package_export_default);
|
|
67632
67892
|
await deps.python(script, ["verify", work, opts.ds, opts.screens]);
|
|
67633
|
-
const verified = (0,
|
|
67634
|
-
const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs57.readFileSync)((0,
|
|
67893
|
+
const verified = (0, import_node_path54.join)(work, "verified");
|
|
67894
|
+
const metadata = Object.fromEntries(PACKAGES.map(({ name, short: short3 }) => [name, JSON.parse((0, import_node_fs57.readFileSync)((0, import_node_path54.join)(verified, `${short3}.metadata.json`), "utf8"))]));
|
|
67635
67895
|
const plan = planAdoption(packageText, lockText, metadata);
|
|
67636
67896
|
for (const { name } of plan.result.adopted) {
|
|
67637
67897
|
const short3 = PACKAGES.find((p) => p.name === name).short;
|
|
67638
|
-
await deps.npm(["cache", "add", (0,
|
|
67898
|
+
await deps.npm(["cache", "add", (0, import_node_path54.join)(verified, `${short3}.tgz`)], opts.dir);
|
|
67639
67899
|
}
|
|
67640
67900
|
(0, import_node_fs57.writeFileSync)(packagePath, plan.packageText);
|
|
67641
67901
|
(0, import_node_fs57.writeFileSync)(lockPath, plan.lockText);
|
|
@@ -67825,8 +68085,8 @@ async function collectWaveStatus(deps) {
|
|
|
67825
68085
|
init_github_client();
|
|
67826
68086
|
init_cli_shared();
|
|
67827
68087
|
var import_node_fs59 = require("node:fs");
|
|
67828
|
-
var
|
|
67829
|
-
var
|
|
68088
|
+
var import_node_os27 = require("node:os");
|
|
68089
|
+
var import_node_path55 = require("node:path");
|
|
67830
68090
|
var GC_GH_TIMEOUT_MS3 = 2e4;
|
|
67831
68091
|
var defaultStatusDeps = {
|
|
67832
68092
|
repo: resolveRepo,
|
|
@@ -68045,10 +68305,10 @@ async function collectOnboardStatus(opts = {}) {
|
|
|
68045
68305
|
else if (top) nextCommand = `mmi-cli oracle board claim ${top.number} # ${top.title}`;
|
|
68046
68306
|
else nextCommand = "mmi-cli oracle board read \u2014 no claimable items found";
|
|
68047
68307
|
}
|
|
68048
|
-
const home = (0,
|
|
68308
|
+
const home = (0, import_node_os27.homedir)();
|
|
68049
68309
|
const plugin = onboardPluginGate({
|
|
68050
|
-
readKnown: () => readFileSyncSafe((0,
|
|
68051
|
-
readSettings: () => readFileSyncSafe((0,
|
|
68310
|
+
readKnown: () => readFileSyncSafe((0, import_node_path55.join)(home, ...KNOWN_MARKETPLACES_RELATIVE), import_node_fs59.readFileSync),
|
|
68311
|
+
readSettings: () => readFileSyncSafe((0, import_node_path55.join)(home, ".claude", "settings.json"), import_node_fs59.readFileSync)
|
|
68052
68312
|
});
|
|
68053
68313
|
return {
|
|
68054
68314
|
guide: "Read the MMI org-guide skill before project work; load only the relevant topic. Use mmi-help for a short introduction.",
|
|
@@ -70685,7 +70945,7 @@ function registerConnectionsOauth(program3, deps) {
|
|
|
70685
70945
|
}
|
|
70686
70946
|
|
|
70687
70947
|
// src/schedules-commands.ts
|
|
70688
|
-
var
|
|
70948
|
+
var import_promises11 = require("node:fs/promises");
|
|
70689
70949
|
init_clean_exit();
|
|
70690
70950
|
init_github_client();
|
|
70691
70951
|
init_cli_shared();
|
|
@@ -70865,9 +71125,9 @@ function registerSchedulesCommands(program3) {
|
|
|
70865
71125
|
await failGraceful("org schedules --doc: refusing to regenerate the doc from an incomplete read (see warnings above).");
|
|
70866
71126
|
return;
|
|
70867
71127
|
}
|
|
70868
|
-
const docText = await (0,
|
|
71128
|
+
const docText = await (0, import_promises11.readFile)(o.doc, "utf8");
|
|
70869
71129
|
const spliced = spliceDoc(docText, renderDocSection(entries, now.toISOString()));
|
|
70870
|
-
await (0,
|
|
71130
|
+
await (0, import_promises11.writeFile)(o.doc, spliced, "utf8");
|
|
70871
71131
|
reportParked(parkedLines);
|
|
70872
71132
|
reportDrift(drift);
|
|
70873
71133
|
console.log(`org schedules: wrote ${entries.length} entries into ${o.doc}`);
|
|
@@ -71180,7 +71440,7 @@ function registerSessionReport(program3) {
|
|
|
71180
71440
|
|
|
71181
71441
|
// src/stage-commands.ts
|
|
71182
71442
|
var import_node_fs60 = require("node:fs");
|
|
71183
|
-
var
|
|
71443
|
+
var import_node_path56 = require("node:path");
|
|
71184
71444
|
init_cli_shared();
|
|
71185
71445
|
init_clean_exit();
|
|
71186
71446
|
|
|
@@ -71428,8 +71688,8 @@ function registerStageCommands(program3) {
|
|
|
71428
71688
|
const repo = Array.isArray(project2?.repos) && typeof project2.repos[0] === "string" ? project2.repos[0] : slug;
|
|
71429
71689
|
const resolution = decideStage({
|
|
71430
71690
|
registry: { deployModel: project2?.deployModel, portRange, error: read.ok ? void 0 : read.error },
|
|
71431
|
-
hasCompose: (0, import_node_fs60.existsSync)((0,
|
|
71432
|
-
hasEnvExample: (0, import_node_fs60.existsSync)((0,
|
|
71691
|
+
hasCompose: (0, import_node_fs60.existsSync)((0, import_node_path56.join)(process.cwd(), "docker-compose.yml")),
|
|
71692
|
+
hasEnvExample: (0, import_node_fs60.existsSync)((0, import_node_path56.join)(process.cwd(), ".env.example")),
|
|
71433
71693
|
repo
|
|
71434
71694
|
});
|
|
71435
71695
|
if (resolution.source === "derived" && resolution.derived) {
|
|
@@ -71721,21 +71981,21 @@ vercel preview (${preview.branch}): ${d.state}${d.url ? ` \u2014 ${d.url}` : ""}
|
|
|
71721
71981
|
}
|
|
71722
71982
|
|
|
71723
71983
|
// src/tenant-artifact.ts
|
|
71724
|
-
var
|
|
71984
|
+
var import_node_crypto24 = require("node:crypto");
|
|
71725
71985
|
var import_node_fs61 = require("node:fs");
|
|
71726
|
-
var
|
|
71727
|
-
var
|
|
71986
|
+
var import_promises12 = require("node:fs/promises");
|
|
71987
|
+
var import_node_path57 = require("node:path");
|
|
71728
71988
|
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}$/;
|
|
71729
71989
|
var MAX_BYTES2 = 5 * 1024 * 1024 * 1024;
|
|
71730
71990
|
async function sha256File(path2) {
|
|
71731
|
-
const hash = (0,
|
|
71991
|
+
const hash = (0, import_node_crypto24.createHash)("sha256");
|
|
71732
71992
|
for await (const chunk of (0, import_node_fs61.createReadStream)(path2)) hash.update(chunk);
|
|
71733
71993
|
return hash.digest("hex");
|
|
71734
71994
|
}
|
|
71735
71995
|
async function putTenantArtifact(repo, stage, inputPath, deps) {
|
|
71736
71996
|
if (!["dev", "rc", "main"].includes(stage)) throw new Error("tenant artifact put: <stage> must be dev, rc, or main");
|
|
71737
|
-
const path2 = (0,
|
|
71738
|
-
const info = await (0,
|
|
71997
|
+
const path2 = (0, import_node_path57.resolve)(inputPath);
|
|
71998
|
+
const info = await (0, import_promises12.stat)(path2);
|
|
71739
71999
|
if (!info.isFile()) throw new Error("tenant artifact put: input path must be a file");
|
|
71740
72000
|
if (!Number.isSafeInteger(info.size) || info.size < 1 || info.size > MAX_BYTES2) throw new Error(`tenant artifact put: file must be 1..${MAX_BYTES2} bytes`);
|
|
71741
72001
|
const sha2564 = await sha256File(path2);
|
|
@@ -72214,12 +72474,12 @@ async function resolveWhoami(deps) {
|
|
|
72214
72474
|
}
|
|
72215
72475
|
|
|
72216
72476
|
// src/command-register-developer.ts
|
|
72217
|
-
var
|
|
72477
|
+
var import_node_path64 = require("node:path");
|
|
72218
72478
|
|
|
72219
72479
|
// src/doc-refs-command-source.ts
|
|
72220
72480
|
var import_node_child_process21 = require("node:child_process");
|
|
72221
72481
|
var import_node_fs62 = require("node:fs");
|
|
72222
|
-
var
|
|
72482
|
+
var import_node_path58 = require("node:path");
|
|
72223
72483
|
var IN_PROCESS_SOURCE = "in-process";
|
|
72224
72484
|
var BUNDLE_MANIFEST_TIMEOUT_MS = 12e4;
|
|
72225
72485
|
var BUNDLE_MANIFEST_MAX_BUFFER = 64 * 1024 * 1024;
|
|
@@ -72241,7 +72501,7 @@ function inventoryFromManifest(manifest, source) {
|
|
|
72241
72501
|
function readBundleManifest(bundle, exec3 = import_node_child_process21.execFileSync) {
|
|
72242
72502
|
try {
|
|
72243
72503
|
const text = exec3(process.execPath, [bundle, "commands", "--all", "--json"], {
|
|
72244
|
-
cwd: (0,
|
|
72504
|
+
cwd: (0, import_node_path58.dirname)(bundle),
|
|
72245
72505
|
encoding: "utf8",
|
|
72246
72506
|
windowsHide: true,
|
|
72247
72507
|
timeout: BUNDLE_MANIFEST_TIMEOUT_MS,
|
|
@@ -72257,16 +72517,16 @@ function readBundleManifest(bundle, exec3 = import_node_child_process21.execFile
|
|
|
72257
72517
|
function isRunningBundle(bundle, argv1 = process.argv[1], platform2 = process.platform) {
|
|
72258
72518
|
if (!argv1) return false;
|
|
72259
72519
|
const norm3 = (path2) => {
|
|
72260
|
-
const absolute = (0,
|
|
72520
|
+
const absolute = (0, import_node_path58.resolve)(path2);
|
|
72261
72521
|
return platform2 === "win32" ? absolute.toLowerCase() : absolute;
|
|
72262
72522
|
};
|
|
72263
72523
|
const running = norm3(argv1);
|
|
72264
|
-
if (!["main.cjs", "index.cjs"].includes((0,
|
|
72265
|
-
return (0,
|
|
72524
|
+
if (!["main.cjs", "index.cjs"].includes((0, import_node_path58.basename)(running))) return false;
|
|
72525
|
+
return (0, import_node_path58.dirname)(running) === (0, import_node_path58.dirname)(norm3(bundle));
|
|
72266
72526
|
}
|
|
72267
72527
|
function nameUnknownCommandSources(findings, source, root) {
|
|
72268
|
-
const checkoutBundle = (0,
|
|
72269
|
-
const recovery = source !== IN_PROCESS_SOURCE && (0,
|
|
72528
|
+
const checkoutBundle = (0, import_node_path58.resolve)(root, "cli", "dist", "main.cjs");
|
|
72529
|
+
const recovery = source !== IN_PROCESS_SOURCE && (0, import_node_path58.resolve)(source) === checkoutBundle ? "; rebuild with `npm --prefix cli run build` and retry, or pass `--commands-from <bundle>`" : "";
|
|
72270
72530
|
for (const finding of findings) {
|
|
72271
72531
|
if (finding.kind !== "unknown-command") continue;
|
|
72272
72532
|
finding.commandSource = source;
|
|
@@ -72278,7 +72538,7 @@ function resolveCommandInventory(deps) {
|
|
|
72278
72538
|
const read = deps.read ?? ((bundle) => readBundleManifest(bundle));
|
|
72279
72539
|
const warnings = [];
|
|
72280
72540
|
if (deps.from) {
|
|
72281
|
-
const bundle = (0,
|
|
72541
|
+
const bundle = (0, import_node_path58.isAbsolute)(deps.from) ? deps.from : (0, import_node_path58.resolve)(deps.root, deps.from);
|
|
72282
72542
|
if (!exists(bundle)) {
|
|
72283
72543
|
throw new Error(`docs refs --commands-from: ${bundle} does not exist \u2014 name the CLI bundle to read commands from (usually cli/dist/main.cjs)`);
|
|
72284
72544
|
}
|
|
@@ -72288,7 +72548,7 @@ function resolveCommandInventory(deps) {
|
|
|
72288
72548
|
}
|
|
72289
72549
|
return { inventory: inventory2, warnings };
|
|
72290
72550
|
}
|
|
72291
|
-
const treeBundle = (0,
|
|
72551
|
+
const treeBundle = (0, import_node_path58.join)(deps.root, "cli", "dist", "main.cjs");
|
|
72292
72552
|
if (!exists(treeBundle)) {
|
|
72293
72553
|
return { inventory: deps.inProcess(), warnings };
|
|
72294
72554
|
}
|
|
@@ -72408,26 +72668,26 @@ async function executeWaveLand(plan, deps) {
|
|
|
72408
72668
|
|
|
72409
72669
|
// src/dist-drift.ts
|
|
72410
72670
|
var import_node_child_process22 = require("node:child_process");
|
|
72411
|
-
var
|
|
72671
|
+
var import_node_crypto26 = require("node:crypto");
|
|
72412
72672
|
var import_node_fs64 = require("node:fs");
|
|
72413
|
-
var
|
|
72414
|
-
var
|
|
72673
|
+
var import_node_os28 = require("node:os");
|
|
72674
|
+
var import_node_path60 = require("node:path");
|
|
72415
72675
|
|
|
72416
72676
|
// ../scripts/distribution-digest.mjs
|
|
72417
|
-
var
|
|
72677
|
+
var import_node_crypto25 = require("node:crypto");
|
|
72418
72678
|
var import_node_fs63 = require("node:fs");
|
|
72419
|
-
var
|
|
72679
|
+
var import_node_path59 = require("node:path");
|
|
72420
72680
|
var slash = (value) => value.replaceAll("\\", "/");
|
|
72421
72681
|
function repoPath(root, declaredPath, label) {
|
|
72422
|
-
const absoluteRoot = (0,
|
|
72423
|
-
const target = (0,
|
|
72424
|
-
if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${
|
|
72682
|
+
const absoluteRoot = (0, import_node_path59.resolve)(root);
|
|
72683
|
+
const target = (0, import_node_path59.resolve)(root, declaredPath);
|
|
72684
|
+
if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path59.sep}`)) {
|
|
72425
72685
|
throw new Error(`${label} ${declaredPath} escapes the repository root`);
|
|
72426
72686
|
}
|
|
72427
72687
|
return target;
|
|
72428
72688
|
}
|
|
72429
72689
|
function digestFiles(files) {
|
|
72430
|
-
const hash = (0,
|
|
72690
|
+
const hash = (0, import_node_crypto25.createHash)("sha256");
|
|
72431
72691
|
for (const file of [...files].sort((a, b) => a.relative.localeCompare(b.relative))) {
|
|
72432
72692
|
const content = file.stat.isSymbolicLink() ? Buffer.from((0, import_node_fs63.readlinkSync)(file.absolute), "utf8") : (0, import_node_fs63.readFileSync)(file.absolute);
|
|
72433
72693
|
hash.update(file.relative, "utf8");
|
|
@@ -72458,7 +72718,7 @@ var DIST_ARTIFACTS = [
|
|
|
72458
72718
|
];
|
|
72459
72719
|
var BOM_DIST_TREE_ID = "mmi-cli-dist";
|
|
72460
72720
|
var ABSENT = "absent";
|
|
72461
|
-
var sha2563 = (bytes) => `sha256:${(0,
|
|
72721
|
+
var sha2563 = (bytes) => `sha256:${(0, import_node_crypto26.createHash)("sha256").update(bytes).digest("hex")}`;
|
|
72462
72722
|
function artifactDrift(path2, committedBytes, rebuiltBytes) {
|
|
72463
72723
|
const committed = committedBytes ? sha2563(committedBytes) : ABSENT;
|
|
72464
72724
|
const rebuiltExpected = rebuiltBytes ? sha2563(rebuiltBytes) : ABSENT;
|
|
@@ -72536,7 +72796,7 @@ function walkFiles(root) {
|
|
|
72536
72796
|
const files = [];
|
|
72537
72797
|
const walk2 = (directory) => {
|
|
72538
72798
|
for (const entry of (0, import_node_fs64.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
72539
|
-
const child2 = (0,
|
|
72799
|
+
const child2 = (0, import_node_path60.join)(directory, entry.name);
|
|
72540
72800
|
if (entry.isDirectory()) walk2(child2);
|
|
72541
72801
|
else files.push(child2);
|
|
72542
72802
|
}
|
|
@@ -72546,10 +72806,10 @@ function walkFiles(root) {
|
|
|
72546
72806
|
}
|
|
72547
72807
|
function bomPathFor(root) {
|
|
72548
72808
|
try {
|
|
72549
|
-
const registry2 = JSON.parse((0, import_node_fs64.readFileSync)((0,
|
|
72550
|
-
return (0,
|
|
72809
|
+
const registry2 = JSON.parse((0, import_node_fs64.readFileSync)((0, import_node_path60.join)(root, "surfaces.json"), "utf8"));
|
|
72810
|
+
return (0, import_node_path60.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
|
|
72551
72811
|
} catch {
|
|
72552
|
-
return (0,
|
|
72812
|
+
return (0, import_node_path60.join)(root, "distribution-bom.json");
|
|
72553
72813
|
}
|
|
72554
72814
|
}
|
|
72555
72815
|
function rebuildTo(packageRoot, outDir) {
|
|
@@ -72562,28 +72822,28 @@ function rebuildTo(packageRoot, outDir) {
|
|
|
72562
72822
|
});
|
|
72563
72823
|
}
|
|
72564
72824
|
function runDistStatus(root) {
|
|
72565
|
-
const stage = (0, import_node_fs64.mkdtempSync)((0,
|
|
72825
|
+
const stage = (0, import_node_fs64.mkdtempSync)((0, import_node_path60.join)((0, import_node_os28.tmpdir)(), "mmi-dist-drift-"));
|
|
72566
72826
|
let overlayCount = 0;
|
|
72567
72827
|
try {
|
|
72568
|
-
const cliOut = (0,
|
|
72569
|
-
const hubOut = (0,
|
|
72570
|
-
rebuildTo((0,
|
|
72571
|
-
rebuildTo((0,
|
|
72828
|
+
const cliOut = (0, import_node_path60.join)(stage, "cli-dist");
|
|
72829
|
+
const hubOut = (0, import_node_path60.join)(stage, "hub-dist");
|
|
72830
|
+
rebuildTo((0, import_node_path60.join)(root, "cli"), cliOut);
|
|
72831
|
+
rebuildTo((0, import_node_path60.join)(root, "updater"), hubOut);
|
|
72572
72832
|
const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
|
|
72573
72833
|
const rebuilt = (path2) => {
|
|
72574
72834
|
const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
|
|
72575
|
-
return spec ? readOrNull((0,
|
|
72835
|
+
return spec ? readOrNull((0, import_node_path60.join)(outDirFor(spec.packageDir), spec.output)) : null;
|
|
72576
72836
|
};
|
|
72577
|
-
const committed = (path2) => readOrNull((0,
|
|
72578
|
-
const tree = (path2) => readOrNull((0,
|
|
72579
|
-
const distRoot = (0,
|
|
72580
|
-
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0,
|
|
72837
|
+
const committed = (path2) => readOrNull((0, import_node_path60.join)(root, path2));
|
|
72838
|
+
const tree = (path2) => readOrNull((0, import_node_path60.join)(root, path2));
|
|
72839
|
+
const distRoot = (0, import_node_path60.join)(root, "cli", "dist");
|
|
72840
|
+
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path60.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
|
|
72581
72841
|
const bom = JSON.parse((0, import_node_fs64.readFileSync)(bomPathFor(root), "utf8"));
|
|
72582
72842
|
const digest = (entries) => {
|
|
72583
|
-
const overlay = (0,
|
|
72843
|
+
const overlay = (0, import_node_path60.join)(stage, `overlay-${overlayCount++}`);
|
|
72584
72844
|
for (const entry of entries) {
|
|
72585
|
-
const target = (0,
|
|
72586
|
-
(0, import_node_fs64.mkdirSync)((0,
|
|
72845
|
+
const target = (0, import_node_path60.join)(overlay, entry.path);
|
|
72846
|
+
(0, import_node_fs64.mkdirSync)((0, import_node_path60.dirname)(target), { recursive: true });
|
|
72587
72847
|
(0, import_node_fs64.writeFileSync)(target, entry.bytes);
|
|
72588
72848
|
}
|
|
72589
72849
|
return digestPackedFiles(overlay, entries.map((entry) => entry.path));
|
|
@@ -72595,7 +72855,7 @@ function runDistStatus(root) {
|
|
|
72595
72855
|
}
|
|
72596
72856
|
|
|
72597
72857
|
// src/doc-refs-live.ts
|
|
72598
|
-
var
|
|
72858
|
+
var import_node_path61 = require("node:path");
|
|
72599
72859
|
var concrete = (value) => !!value && !/[<>{}$]/.test(value);
|
|
72600
72860
|
var liveOption = (tokens2, flag) => {
|
|
72601
72861
|
const index = tokens2.indexOf(flag);
|
|
@@ -72668,7 +72928,7 @@ async function runLiveDocRefs(root, deps, live) {
|
|
|
72668
72928
|
const offline = runDocRefs(root, { ...deps, runbooksOnly: true });
|
|
72669
72929
|
const read = deps.readFile ?? readFileOrNull;
|
|
72670
72930
|
const docs = Object.fromEntries((deps.listDocs ?? defaultListDocs)(root).flatMap((doc) => {
|
|
72671
|
-
const body = read((0,
|
|
72931
|
+
const body = read((0, import_node_path61.join)(root, doc));
|
|
72672
72932
|
return body !== null && isRunbook(doc, body) && !deps.isIgnored?.([doc]).has(doc) ? [[doc, body]] : [];
|
|
72673
72933
|
}));
|
|
72674
72934
|
const remote = await checkRunbookLive(docs, live);
|
|
@@ -72717,13 +72977,13 @@ init_cli_shared();
|
|
|
72717
72977
|
// src/edge-tunnel.ts
|
|
72718
72978
|
var HOSTNAME_RE = /^(?=.{1,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)+$/;
|
|
72719
72979
|
var UPSTREAM_RE = /^https?:\/\/[^/\s]+(?::\d+)?(?:\/.*)?$/;
|
|
72720
|
-
function tunnelNameFromHostname(
|
|
72721
|
-
return
|
|
72980
|
+
function tunnelNameFromHostname(hostname5) {
|
|
72981
|
+
return hostname5.replace(/\./g, "-").slice(0, 63);
|
|
72722
72982
|
}
|
|
72723
|
-
function planInfraTunnel(
|
|
72724
|
-
const host =
|
|
72983
|
+
function planInfraTunnel(hostname5, upstream) {
|
|
72984
|
+
const host = hostname5.trim().toLowerCase();
|
|
72725
72985
|
const origin = upstream.trim();
|
|
72726
|
-
if (!HOSTNAME_RE.test(host)) throw new Error(`invalid hostname ${JSON.stringify(
|
|
72986
|
+
if (!HOSTNAME_RE.test(host)) throw new Error(`invalid hostname ${JSON.stringify(hostname5)}`);
|
|
72727
72987
|
if (!UPSTREAM_RE.test(origin)) throw new Error(`invalid upstream ${JSON.stringify(upstream)} \u2014 expected http(s)://host:port`);
|
|
72728
72988
|
const tunnelName = tunnelNameFromHostname(host);
|
|
72729
72989
|
const configYaml = [
|
|
@@ -72878,8 +73138,8 @@ async function diagnoseHub(deps) {
|
|
|
72878
73138
|
}
|
|
72879
73139
|
|
|
72880
73140
|
// src/schedules-lift-command.ts
|
|
72881
|
-
var
|
|
72882
|
-
var
|
|
73141
|
+
var import_promises13 = require("node:fs/promises");
|
|
73142
|
+
var import_node_path62 = require("node:path");
|
|
72883
73143
|
init_clean_exit();
|
|
72884
73144
|
init_cli_shared();
|
|
72885
73145
|
var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
|
|
@@ -72901,14 +73161,14 @@ var RegistryUnreachableError = class extends Error {
|
|
|
72901
73161
|
async function readWorkflowFiles(dir) {
|
|
72902
73162
|
let names;
|
|
72903
73163
|
try {
|
|
72904
|
-
names = await (0,
|
|
73164
|
+
names = await (0, import_promises13.readdir)(dir);
|
|
72905
73165
|
} catch {
|
|
72906
73166
|
return [];
|
|
72907
73167
|
}
|
|
72908
73168
|
const files = [];
|
|
72909
73169
|
for (const name of names.sort()) {
|
|
72910
73170
|
if (!/\.ya?ml$/.test(name)) continue;
|
|
72911
|
-
files.push({ path: `.github/workflows/${name}`, text: await (0,
|
|
73171
|
+
files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises13.readFile)((0, import_node_path62.join)(dir, name), "utf8") });
|
|
72912
73172
|
}
|
|
72913
73173
|
return files;
|
|
72914
73174
|
}
|
|
@@ -72992,7 +73252,7 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
|
|
|
72992
73252
|
// src/spawn-policy-core.ts
|
|
72993
73253
|
var import_node_child_process24 = require("node:child_process");
|
|
72994
73254
|
var import_node_fs65 = require("node:fs");
|
|
72995
|
-
var
|
|
73255
|
+
var import_node_path63 = require("node:path");
|
|
72996
73256
|
var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
|
|
72997
73257
|
var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
|
|
72998
73258
|
var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
|
|
@@ -73078,7 +73338,7 @@ function runSpawnPolicy(root) {
|
|
|
73078
73338
|
for (const file of files) {
|
|
73079
73339
|
let raw;
|
|
73080
73340
|
try {
|
|
73081
|
-
raw = (0, import_node_fs65.readFileSync)((0,
|
|
73341
|
+
raw = (0, import_node_fs65.readFileSync)((0, import_node_path63.join)(root, file), "utf8");
|
|
73082
73342
|
} catch {
|
|
73083
73343
|
continue;
|
|
73084
73344
|
}
|
|
@@ -73098,7 +73358,7 @@ function runSpawnPolicy(root) {
|
|
|
73098
73358
|
function registerDeveloperCommands(program3) {
|
|
73099
73359
|
const rules = program3.command("rules").description("org-managed .gitignore delivery");
|
|
73100
73360
|
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) => {
|
|
73101
|
-
const path2 = (0,
|
|
73361
|
+
const path2 = (0, import_node_path64.join)(process.cwd(), ".gitignore");
|
|
73102
73362
|
const current = (0, import_node_fs66.existsSync)(path2) ? (0, import_node_fs66.readFileSync)(path2, "utf8") : null;
|
|
73103
73363
|
const plan = planManagedGitignore(current);
|
|
73104
73364
|
const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
|
|
@@ -73428,12 +73688,12 @@ ${r.stderr ?? ""}`).catch(() => "");
|
|
|
73428
73688
|
var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
|
|
73429
73689
|
var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
|
|
73430
73690
|
function envHealLockPath(home) {
|
|
73431
|
-
return (0,
|
|
73691
|
+
return (0, import_node_path65.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
|
|
73432
73692
|
}
|
|
73433
73693
|
async function withEnvHealLock(what, run) {
|
|
73434
73694
|
try {
|
|
73435
73695
|
return await withFileLock(
|
|
73436
|
-
envHealLockPath((0,
|
|
73696
|
+
envHealLockPath((0, import_node_os29.homedir)()),
|
|
73437
73697
|
{ staleMs: ENV_HEAL_LOCK_STALE_MS, maxWaitMs: ENV_HEAL_LOCK_MAX_WAIT_MS, label: "mmi env-heal lock" },
|
|
73438
73698
|
run
|
|
73439
73699
|
);
|
|
@@ -73531,7 +73791,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
73531
73791
|
const configRoot = surfaceConfigRoot(surface);
|
|
73532
73792
|
const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
|
|
73533
73793
|
const plan = buildPluginCachePlan(
|
|
73534
|
-
(0,
|
|
73794
|
+
(0, import_node_os29.homedir)(),
|
|
73535
73795
|
running,
|
|
73536
73796
|
pluginCacheFsDeps(configRoot, () => 0),
|
|
73537
73797
|
{ configRoot, includeStaging: surface !== "codex" }
|
|
@@ -73559,7 +73819,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
73559
73819
|
const running = surface === "codex" ? installedActivePluginVersion(surface) : runningPluginVersion(process.env, resolveClientVersion());
|
|
73560
73820
|
const installed = installedActivePluginVersion(surface);
|
|
73561
73821
|
const plan = buildPluginCachePlan(
|
|
73562
|
-
(0,
|
|
73822
|
+
(0, import_node_os29.homedir)(),
|
|
73563
73823
|
running,
|
|
73564
73824
|
pluginCacheFsDeps(configRoot, () => 0),
|
|
73565
73825
|
{ configRoot, includeStaging: surface !== "codex", installedVersion: installed }
|
|
@@ -73601,7 +73861,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
73601
73861
|
// has no generated routing index would
|
|
73602
73862
|
// get a permanent — demanding an artifact it never asked for.
|
|
73603
73863
|
docsIndexState: (root) => {
|
|
73604
|
-
if (!(0, import_node_fs67.existsSync)((0,
|
|
73864
|
+
if (!(0, import_node_fs67.existsSync)((0, import_node_path65.join)(root, DOCS_INDEX_PATH))) return void 0;
|
|
73605
73865
|
const real = createDocsIndexDeps(root);
|
|
73606
73866
|
let docs;
|
|
73607
73867
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -73610,7 +73870,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
73610
73870
|
},
|
|
73611
73871
|
// #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
|
|
73612
73872
|
healDocsIndex: (root) => {
|
|
73613
|
-
if (!(0, import_node_fs67.existsSync)((0,
|
|
73873
|
+
if (!(0, import_node_fs67.existsSync)((0, import_node_path65.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
|
|
73614
73874
|
const real = createDocsIndexDeps(root);
|
|
73615
73875
|
let docs;
|
|
73616
73876
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -74841,16 +75101,16 @@ function ciAuditDeps2() {
|
|
|
74841
75101
|
// gate re-seed step is skipped gracefully rather than failing mid-run.
|
|
74842
75102
|
readSeedFile: (path2) => {
|
|
74843
75103
|
if (!root) return null;
|
|
74844
|
-
const fullPath = (0,
|
|
75104
|
+
const fullPath = (0, import_node_path65.join)(root, path2);
|
|
74845
75105
|
return (0, import_node_fs67.existsSync)(fullPath) ? (0, import_node_fs67.readFileSync)(fullPath, "utf8") : null;
|
|
74846
75106
|
}
|
|
74847
75107
|
};
|
|
74848
75108
|
}
|
|
74849
75109
|
function hubRoot2() {
|
|
74850
|
-
const fromPkg = (0,
|
|
75110
|
+
const fromPkg = (0, import_node_path65.join)(__dirname, "..", "..");
|
|
74851
75111
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
74852
|
-
if ((0, import_node_fs67.existsSync)((0,
|
|
74853
|
-
if ((0, import_node_fs67.existsSync)((0,
|
|
75112
|
+
if ((0, import_node_fs67.existsSync)((0, import_node_path65.join)(fromPkg, marker))) return fromPkg;
|
|
75113
|
+
if ((0, import_node_fs67.existsSync)((0, import_node_path65.join)(process.cwd(), marker))) return process.cwd();
|
|
74854
75114
|
return null;
|
|
74855
75115
|
}
|
|
74856
75116
|
registerQueryCommands(program2);
|
|
@@ -75064,7 +75324,7 @@ function directoryBytes(path2) {
|
|
|
75064
75324
|
return 0;
|
|
75065
75325
|
}
|
|
75066
75326
|
for (const entry of entries) {
|
|
75067
|
-
const child2 = (0,
|
|
75327
|
+
const child2 = (0, import_node_path65.join)(path2, entry.name);
|
|
75068
75328
|
if (entry.isDirectory()) total += directoryBytes(child2);
|
|
75069
75329
|
else {
|
|
75070
75330
|
try {
|
|
@@ -75094,7 +75354,7 @@ function pluginCacheFsDeps(configRoot, dirBytes) {
|
|
|
75094
75354
|
dirBytes,
|
|
75095
75355
|
listStagingDirs: (root) => (0, import_node_fs67.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
|
|
75096
75356
|
try {
|
|
75097
|
-
return { name: d.name, mtimeMs: newestMtimeMs((0,
|
|
75357
|
+
return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path65.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs67.statSync)(p).mtimeMs) };
|
|
75098
75358
|
} catch {
|
|
75099
75359
|
return { name: d.name, mtimeMs: Date.now() };
|
|
75100
75360
|
}
|
|
@@ -75108,7 +75368,7 @@ function stagingApplyFsGuard(configRoot) {
|
|
|
75108
75368
|
return {
|
|
75109
75369
|
referencedPaths: () => readInstalledPluginRefs(configRoot),
|
|
75110
75370
|
mtimeMs: (name) => {
|
|
75111
|
-
const p = (0,
|
|
75371
|
+
const p = (0, import_node_path65.join)(stagingRoot, name);
|
|
75112
75372
|
if (!(0, import_node_fs67.existsSync)(p)) return null;
|
|
75113
75373
|
try {
|
|
75114
75374
|
return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs67.statSync)(q).mtimeMs);
|
|
@@ -75131,7 +75391,7 @@ program2.command("plugin-prune").description(`prune stale cached MMI plugin vers
|
|
|
75131
75391
|
return;
|
|
75132
75392
|
}
|
|
75133
75393
|
const plan = buildPluginCachePlan(
|
|
75134
|
-
(0,
|
|
75394
|
+
(0, import_node_os29.homedir)(),
|
|
75135
75395
|
running,
|
|
75136
75396
|
pluginCacheFsDeps(configRoot, directoryBytes),
|
|
75137
75397
|
{ withBytes: true, configRoot, includeStaging: surface !== "codex" }
|
|
@@ -75147,7 +75407,7 @@ program2.command("archive-prune").description("inventory worktree evidence archi
|
|
|
75147
75407
|
let primary = o.repoRoot;
|
|
75148
75408
|
if (!primary) {
|
|
75149
75409
|
const common = await gitOut(["rev-parse", "--path-format=absolute", "--git-common-dir"]);
|
|
75150
|
-
primary = common ? (0,
|
|
75410
|
+
primary = common ? (0, import_node_path65.dirname)(common) : "";
|
|
75151
75411
|
}
|
|
75152
75412
|
if (!primary) {
|
|
75153
75413
|
const detail = "archive-prune: not inside a git checkout (pass --repo-root <primary checkout>)";
|