@mutmutco/cli 4.3.19 → 4.3.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.cjs +225 -165
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -5227,7 +5227,7 @@ function unknownCommandDomainGuide(parentPath, token) {
|
|
|
5227
5227
|
|
|
5228
5228
|
// src/command-composition.ts
|
|
5229
5229
|
var import_node_os22 = require("node:os");
|
|
5230
|
-
var
|
|
5230
|
+
var import_node_path48 = require("node:path");
|
|
5231
5231
|
|
|
5232
5232
|
// src/board-read.ts
|
|
5233
5233
|
var import_node_fs13 = require("node:fs");
|
|
@@ -13353,7 +13353,7 @@ function extractForwardRefs(markdown) {
|
|
|
13353
13353
|
});
|
|
13354
13354
|
return refs;
|
|
13355
13355
|
}
|
|
13356
|
-
function checkPins(root,
|
|
13356
|
+
function checkPins(root, readFile10, docs) {
|
|
13357
13357
|
const findings = [];
|
|
13358
13358
|
for (const [doc, markdown] of Object.entries(docs)) {
|
|
13359
13359
|
for (const pin of extractPins(markdown)) {
|
|
@@ -13361,7 +13361,7 @@ function checkPins(root, readFile9, docs) {
|
|
|
13361
13361
|
findings.push({ kind: "malformed-pin", doc, line: pin.line, detail: pin.text });
|
|
13362
13362
|
continue;
|
|
13363
13363
|
}
|
|
13364
|
-
const source =
|
|
13364
|
+
const source = readFile10((0, import_node_path12.join)(root, pin.file));
|
|
13365
13365
|
if (source == null) {
|
|
13366
13366
|
findings.push({ kind: "missing-test", doc, line: pin.line, detail: pin.file });
|
|
13367
13367
|
continue;
|
|
@@ -13576,7 +13576,7 @@ function defaultTrackedFirstSegments(root, firstSegments, exec = import_node_chi
|
|
|
13576
13576
|
}
|
|
13577
13577
|
}
|
|
13578
13578
|
function runDocRefs(root, deps = {}) {
|
|
13579
|
-
const
|
|
13579
|
+
const readFile10 = deps.readFile ?? readFileOrNull;
|
|
13580
13580
|
const exists = deps.exists ?? import_node_fs14.existsSync;
|
|
13581
13581
|
const listDocs = deps.listDocs ?? defaultListDocs;
|
|
13582
13582
|
const isIgnored = deps.isIgnored ?? ((paths) => defaultIsIgnored(root, paths));
|
|
@@ -13585,11 +13585,11 @@ function runDocRefs(root, deps = {}) {
|
|
|
13585
13585
|
const walked = listDocs(root);
|
|
13586
13586
|
const ignoredDocs = walked.length ? isIgnored(walked) : /* @__PURE__ */ new Set();
|
|
13587
13587
|
const docs = Object.fromEntries(
|
|
13588
|
-
walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel,
|
|
13588
|
+
walked.filter((rel) => !ignoredDocs.has(rel)).map((rel) => [rel, readFile10((0, import_node_path12.join)(root, rel))]).filter(([, body]) => body != null)
|
|
13589
13589
|
);
|
|
13590
13590
|
const refResult = checkRefs(root, { exists, isIgnored, trackedFirstSegments }, docs);
|
|
13591
13591
|
const findings = [
|
|
13592
|
-
...checkPins(root,
|
|
13592
|
+
...checkPins(root, readFile10, docs).findings,
|
|
13593
13593
|
...refResult.findings
|
|
13594
13594
|
];
|
|
13595
13595
|
if (commandPaths == null) {
|
|
@@ -14186,22 +14186,22 @@ function labelsToPrune(orgLabelNames) {
|
|
|
14186
14186
|
const org = new Set(orgLabelNames);
|
|
14187
14187
|
return GITHUB_DEFAULT_LABELS.filter((name) => !org.has(name));
|
|
14188
14188
|
}
|
|
14189
|
-
function resolveSeedContent(seed, vars,
|
|
14190
|
-
if (seed.source === "self") return
|
|
14189
|
+
function resolveSeedContent(seed, vars, readFile10) {
|
|
14190
|
+
if (seed.source === "self") return readFile10(seed.target);
|
|
14191
14191
|
if (seed.source.startsWith("seed:")) {
|
|
14192
|
-
const tmpl =
|
|
14192
|
+
const tmpl = readFile10(`skills/bootstrap/seeds/${seed.source.slice("seed:".length)}`);
|
|
14193
14193
|
return tmpl == null ? null : renderSeed(tmpl, vars);
|
|
14194
14194
|
}
|
|
14195
14195
|
return null;
|
|
14196
14196
|
}
|
|
14197
|
-
function resolveSeedWriteContent(seed, vars,
|
|
14197
|
+
function resolveSeedWriteContent(seed, vars, readFile10, remoteContent) {
|
|
14198
14198
|
if (!seed.managedBlock) {
|
|
14199
|
-
return { ok: true, content: resolveSeedContent(seed, vars,
|
|
14199
|
+
return { ok: true, content: resolveSeedContent(seed, vars, readFile10), managed: seed.source === "managed-block" };
|
|
14200
14200
|
}
|
|
14201
|
-
const base = remoteContent ?? resolveSeedContent(seed, vars,
|
|
14201
|
+
const base = remoteContent ?? resolveSeedContent(seed, vars, readFile10);
|
|
14202
14202
|
if (base == null) return { ok: true, content: null, managed: true };
|
|
14203
14203
|
const blockSeed = { ...seed, source: seed.managedBlock.source, managedBlock: void 0 };
|
|
14204
|
-
const desired = resolveSeedContent(blockSeed, vars,
|
|
14204
|
+
const desired = resolveSeedContent(blockSeed, vars, readFile10);
|
|
14205
14205
|
if (desired == null) return { ok: true, content: null, managed: true };
|
|
14206
14206
|
const result = upsertManagedSeedBlock(base, desired, seed.managedBlock.begin, seed.managedBlock.end);
|
|
14207
14207
|
return result.ok ? { ok: true, content: result.content, managed: true } : { ok: false, reason: result.reason, managed: true };
|
|
@@ -15502,10 +15502,10 @@ var rollout_plan_default = {
|
|
|
15502
15502
|
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)."
|
|
15503
15503
|
},
|
|
15504
15504
|
baseline: {
|
|
15505
|
-
version: "4.3.
|
|
15506
|
-
tag: "v4.3.
|
|
15507
|
-
commit: "
|
|
15508
|
-
npm: "@mutmutco/cli@4.3.
|
|
15505
|
+
version: "4.3.20",
|
|
15506
|
+
tag: "v4.3.20",
|
|
15507
|
+
commit: "f33217850417",
|
|
15508
|
+
npm: "@mutmutco/cli@4.3.20"
|
|
15509
15509
|
},
|
|
15510
15510
|
exitCriterion: "fleet-n-of-n",
|
|
15511
15511
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15522,14 +15522,14 @@ var rollout_plan_default = {
|
|
|
15522
15522
|
repo: "mutmutco/mmi-hub",
|
|
15523
15523
|
role: "canary",
|
|
15524
15524
|
schedule: "train",
|
|
15525
|
-
v3Target: "v4.3.
|
|
15525
|
+
v3Target: "v4.3.20"
|
|
15526
15526
|
}
|
|
15527
15527
|
],
|
|
15528
15528
|
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.",
|
|
15529
15529
|
rollback: {
|
|
15530
15530
|
independent: true,
|
|
15531
|
-
mechanism: "npm dist-tag latest -> 4.3.
|
|
15532
|
-
v3Target: "v4.3.
|
|
15531
|
+
mechanism: "npm dist-tag latest -> 4.3.20 and redeploy the Hub Lambda from tag v4.3.20 (f33217850417); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15532
|
+
v3Target: "v4.3.20 (@mutmutco/cli@4.3.20, tag commit f33217850417 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15533
15533
|
}
|
|
15534
15534
|
},
|
|
15535
15535
|
{
|
|
@@ -27537,7 +27537,7 @@ function registerBootstrapCommands(program3) {
|
|
|
27537
27537
|
}
|
|
27538
27538
|
const onlyManagedBlock = onlyTarget ? seedsToApply[0]?.managedBlock != null : false;
|
|
27539
27539
|
const gh = async (args) => execFileP("gh", args, { timeout: 2e4 });
|
|
27540
|
-
const
|
|
27540
|
+
const readFile10 = (p) => (0, import_node_fs26.existsSync)(p) ? (0, import_node_fs26.readFileSync)(p, "utf8") : null;
|
|
27541
27541
|
const enc = (p) => p.split("/").map(encodeURIComponent).join("/");
|
|
27542
27542
|
const putSeed = async (target, content, ref, sha) => {
|
|
27543
27543
|
const tmp = (0, import_node_path25.join)((0, import_node_os14.tmpdir)(), `mmi-seed-${process.pid}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}.json`);
|
|
@@ -27686,7 +27686,7 @@ function registerBootstrapCommands(program3) {
|
|
|
27686
27686
|
if (isLegacyBlock) {
|
|
27687
27687
|
content = upsertManagedGitignoreBlock(remoteContent).content;
|
|
27688
27688
|
} else {
|
|
27689
|
-
const writeContent = resolveSeedWriteContent(resolved, vars,
|
|
27689
|
+
const writeContent = resolveSeedWriteContent(resolved, vars, readFile10, remoteContent);
|
|
27690
27690
|
if (!writeContent.ok) {
|
|
27691
27691
|
return fail(`bootstrap apply: ${resolved.target}: ${writeContent.reason} \u2014 refusing to overwrite repo-owned content`);
|
|
27692
27692
|
}
|
|
@@ -27823,7 +27823,7 @@ ${onlyManagedBlock ? `Only the marker-bounded Hub-managed block inside repo-owne
|
|
|
27823
27823
|
}
|
|
27824
27824
|
const rulesetSeed = repo.toLowerCase() === "mutmutco/mmi-hub" ? void 0 : manifest.seeds.find((s) => s.target === ".github/rulesets/mmi-product-required-checks.json");
|
|
27825
27825
|
if (rulesetSeed) {
|
|
27826
|
-
const rulesetContent = resolveSeedContent({ ...rulesetSeed, target: rulesetSeed.target.replace("{{REPO_SLUG}}", slug) }, vars,
|
|
27826
|
+
const rulesetContent = resolveSeedContent({ ...rulesetSeed, target: rulesetSeed.target.replace("{{REPO_SLUG}}", slug) }, vars, readFile10);
|
|
27827
27827
|
if (rulesetContent) {
|
|
27828
27828
|
try {
|
|
27829
27829
|
const client = controlClient;
|
|
@@ -35940,7 +35940,7 @@ function renderVerifySecrets(body) {
|
|
|
35940
35940
|
// src/command-register-collaboration.ts
|
|
35941
35941
|
var import_node_child_process16 = require("node:child_process");
|
|
35942
35942
|
var import_node_fs43 = require("node:fs");
|
|
35943
|
-
var
|
|
35943
|
+
var import_promises8 = require("node:fs/promises");
|
|
35944
35944
|
|
|
35945
35945
|
// src/session-runtime.ts
|
|
35946
35946
|
var WIN32_TRAMPOLINE = "const{spawn}=require('node:child_process');const a=JSON.parse(process.argv[1]);const c=spawn(a.cmd,a.args,{stdio:'ignore',windowsHide:true,cwd:a.cwd});c.on('exit',x=>process.exit(x??0));c.on('error',()=>process.exit(1));";
|
|
@@ -35959,7 +35959,7 @@ function spawnDetachedSelf(args, deps, opts = {}) {
|
|
|
35959
35959
|
}
|
|
35960
35960
|
|
|
35961
35961
|
// src/command-register-collaboration.ts
|
|
35962
|
-
var
|
|
35962
|
+
var import_node_path41 = require("node:path");
|
|
35963
35963
|
|
|
35964
35964
|
// src/attach-to-project.ts
|
|
35965
35965
|
function boardAttachRateLimitedReceipt(resetEpochSeconds) {
|
|
@@ -36762,8 +36762,8 @@ function annotateChangeMeaning(changed, policy, read) {
|
|
|
36762
36762
|
function isMeaningfulRow(file) {
|
|
36763
36763
|
return file.meaningful !== false;
|
|
36764
36764
|
}
|
|
36765
|
-
function loadPolicy(root,
|
|
36766
|
-
const raw =
|
|
36765
|
+
function loadPolicy(root, readFile10 = readFileOrNull2) {
|
|
36766
|
+
const raw = readFile10((0, import_node_path33.join)(root, POLICY_FILE));
|
|
36767
36767
|
if (raw == null) return { mandatory: [], declared: false };
|
|
36768
36768
|
return parsePolicy(raw, POLICY_FILE);
|
|
36769
36769
|
}
|
|
@@ -37960,6 +37960,120 @@ async function checkDocsIndexAtHead(opts, deps) {
|
|
|
37960
37960
|
};
|
|
37961
37961
|
}
|
|
37962
37962
|
|
|
37963
|
+
// src/pr-create-zeroci.ts
|
|
37964
|
+
var import_promises7 = require("node:fs/promises");
|
|
37965
|
+
var import_node_path38 = require("node:path");
|
|
37966
|
+
|
|
37967
|
+
// src/jervcode-node-modules-cleanup.ts
|
|
37968
|
+
var import_node_fs40 = require("node:fs");
|
|
37969
|
+
var import_node_os20 = require("node:os");
|
|
37970
|
+
var import_node_path37 = require("node:path");
|
|
37971
|
+
var JERVCODE_PACKAGE_ENTRY = (0, import_node_path37.join)("node_modules", "@jervaise", "jervcode", "dist", "launcher-entry.js");
|
|
37972
|
+
var WIN_NAMES2 = ["jervcode.cmd", "jervcode"];
|
|
37973
|
+
var POSIX_NAMES2 = ["jervcode"];
|
|
37974
|
+
var NODE_MODULES_CLEANUP_TIMEOUT_MS = 3e5;
|
|
37975
|
+
function jervcodeCandidatePaths(env = process.env, home = (0, import_node_os20.homedir)(), platform2 = process.platform) {
|
|
37976
|
+
const names = platform2 === "win32" ? WIN_NAMES2 : POSIX_NAMES2;
|
|
37977
|
+
const out = [];
|
|
37978
|
+
for (const dir of jervCliCandidateDirs(env, home, platform2)) {
|
|
37979
|
+
for (const name of names) out.push((0, import_node_path37.join)(dir, name));
|
|
37980
|
+
}
|
|
37981
|
+
return out;
|
|
37982
|
+
}
|
|
37983
|
+
function resolveJervcodePath(env = process.env, home = (0, import_node_os20.homedir)(), platform2 = process.platform, exists = import_node_fs40.existsSync) {
|
|
37984
|
+
for (const candidate of jervcodeCandidatePaths(env, home, platform2)) {
|
|
37985
|
+
if (exists(candidate)) return candidate;
|
|
37986
|
+
}
|
|
37987
|
+
return void 0;
|
|
37988
|
+
}
|
|
37989
|
+
function jervcodeExecFileArgs(args, opts = {}) {
|
|
37990
|
+
const platform2 = opts.platform ?? process.platform;
|
|
37991
|
+
const exists = opts.exists ?? import_node_fs40.existsSync;
|
|
37992
|
+
const resolved = resolveJervcodePath(opts.env ?? process.env, opts.home ?? (0, import_node_os20.homedir)(), platform2, exists);
|
|
37993
|
+
if (resolved) {
|
|
37994
|
+
const entry = (0, import_node_path37.join)((0, import_node_path37.join)(resolved, ".."), JERVCODE_PACKAGE_ENTRY);
|
|
37995
|
+
if (exists(entry)) {
|
|
37996
|
+
return { file: opts.execPath ?? process.execPath, args: [entry, ...args], via: "node-entry" };
|
|
37997
|
+
}
|
|
37998
|
+
}
|
|
37999
|
+
const bin = resolved ?? "jervcode";
|
|
38000
|
+
if (platform2 === "win32") {
|
|
38001
|
+
return { file: "cmd.exe", args: ["/c", bin, ...args], via: resolved ? "cmd-shim" : "bare" };
|
|
38002
|
+
}
|
|
38003
|
+
return { file: bin, args: [...args], via: resolved ? "posix" : "bare" };
|
|
38004
|
+
}
|
|
38005
|
+
async function removeWorktreeNodeModulesViaHelper(wtPath, opts = {}) {
|
|
38006
|
+
const { cwd, timeoutMs = NODE_MODULES_CLEANUP_TIMEOUT_MS } = opts;
|
|
38007
|
+
const env = opts.env ?? process.env;
|
|
38008
|
+
const exec = opts.exec ?? execFileP;
|
|
38009
|
+
const candidates = jervcodeCandidatePaths(env, opts.home, opts.platform ?? process.platform);
|
|
38010
|
+
const plan = jervcodeExecFileArgs(["worktree-node-modules-cleanup", "--worktree", wtPath], opts);
|
|
38011
|
+
const execOptions = { timeout: timeoutMs, ...cwd ? { cwd } : {} };
|
|
38012
|
+
try {
|
|
38013
|
+
await exec(plan.file, plan.args, execOptions);
|
|
38014
|
+
return { ok: true };
|
|
38015
|
+
} catch (e) {
|
|
38016
|
+
const err = e;
|
|
38017
|
+
const base = formatJervCliSpawnFailure(err, plan, candidates);
|
|
38018
|
+
const stderr = typeof err.stderr === "string" ? err.stderr.trim() : "";
|
|
38019
|
+
const detail = stderr.split("\n")[0] || base;
|
|
38020
|
+
return { ok: false, error: `jervcode worktree-node-modules-cleanup failed: ${detail}` };
|
|
38021
|
+
}
|
|
38022
|
+
}
|
|
38023
|
+
|
|
38024
|
+
// src/pr-create-zeroci.ts
|
|
38025
|
+
var GATE_WORKFLOW_PATH = ".github/workflows/gate.yml";
|
|
38026
|
+
var ZEROCI_MINT_MARKER = "zeroci-mint: seat";
|
|
38027
|
+
var ZEROCI_MINT_TIMEOUT_MS = 18e5;
|
|
38028
|
+
var ZEROCI_MINT_MAX_BUFFER = 32 * 1024 * 1024;
|
|
38029
|
+
function createPrCreateZeroCiDeps() {
|
|
38030
|
+
const git3 = createPrCreateDocsIndexDeps();
|
|
38031
|
+
return {
|
|
38032
|
+
worktreeRoot: git3.worktreeRoot,
|
|
38033
|
+
originRepo: git3.originRepo,
|
|
38034
|
+
readGateWorkflow: async (root) => {
|
|
38035
|
+
try {
|
|
38036
|
+
return await (0, import_promises7.readFile)((0, import_node_path38.join)(root, GATE_WORKFLOW_PATH), "utf8");
|
|
38037
|
+
} catch {
|
|
38038
|
+
return void 0;
|
|
38039
|
+
}
|
|
38040
|
+
},
|
|
38041
|
+
mint: async (root) => {
|
|
38042
|
+
const plan = jervcodeExecFileArgs(["zeroci-receipt", "--from-gate"]);
|
|
38043
|
+
try {
|
|
38044
|
+
await execFileHard(plan.file, plan.args, {
|
|
38045
|
+
cwd: root,
|
|
38046
|
+
timeout: ZEROCI_MINT_TIMEOUT_MS,
|
|
38047
|
+
maxBuffer: ZEROCI_MINT_MAX_BUFFER,
|
|
38048
|
+
step: "jervcode zeroci-receipt --from-gate"
|
|
38049
|
+
});
|
|
38050
|
+
} catch (e) {
|
|
38051
|
+
const err = e;
|
|
38052
|
+
const stderr = typeof err.stderr === "string" ? err.stderr.trim() : "";
|
|
38053
|
+
throw new Error(stderr.split("\n").filter(Boolean).pop() || formatJervCliSpawnFailure(err, plan, jervcodeCandidatePaths()));
|
|
38054
|
+
}
|
|
38055
|
+
}
|
|
38056
|
+
};
|
|
38057
|
+
}
|
|
38058
|
+
async function mintZeroCiReceipt(opts, deps) {
|
|
38059
|
+
if (opts.zeroci === false) return void 0;
|
|
38060
|
+
const root = await deps.worktreeRoot();
|
|
38061
|
+
if (!root) return void 0;
|
|
38062
|
+
if (opts.repo) {
|
|
38063
|
+
const origin = await deps.originRepo(root);
|
|
38064
|
+
if (!origin || origin.toLowerCase() !== opts.repo.toLowerCase()) return void 0;
|
|
38065
|
+
}
|
|
38066
|
+
const gate = await deps.readGateWorkflow(root);
|
|
38067
|
+
if (!gate || !gate.includes("zeroci-verify")) return void 0;
|
|
38068
|
+
if (!gate.includes(ZEROCI_MINT_MARKER)) return void 0;
|
|
38069
|
+
try {
|
|
38070
|
+
await deps.mint(root);
|
|
38071
|
+
return void 0;
|
|
38072
|
+
} catch (e) {
|
|
38073
|
+
return `pr create: WARNING \u2014 ZeroCI receipt not minted, opening the PR anyway (the gate runs in full): ${e.message}`;
|
|
38074
|
+
}
|
|
38075
|
+
}
|
|
38076
|
+
|
|
37963
38077
|
// src/pr-create-claim-guard.ts
|
|
37964
38078
|
var CLAIM_GUARD_RATE_LIMIT_WAIT_CAP_MS = 3e4;
|
|
37965
38079
|
function withRateLimitRetry(client, seams = {}) {
|
|
@@ -38018,68 +38132,11 @@ async function prCreateClaimRefusal(body, repoOption, deps = {}) {
|
|
|
38018
38132
|
|
|
38019
38133
|
// src/worktree-merge-cleanup.ts
|
|
38020
38134
|
var import_node_fs42 = require("node:fs");
|
|
38021
|
-
var
|
|
38022
|
-
|
|
38023
|
-
// src/jervcode-node-modules-cleanup.ts
|
|
38024
|
-
var import_node_fs40 = require("node:fs");
|
|
38025
|
-
var import_node_os20 = require("node:os");
|
|
38026
|
-
var import_node_path37 = require("node:path");
|
|
38027
|
-
var JERVCODE_PACKAGE_ENTRY = (0, import_node_path37.join)("node_modules", "@jervaise", "jervcode", "dist", "launcher-entry.js");
|
|
38028
|
-
var WIN_NAMES2 = ["jervcode.cmd", "jervcode"];
|
|
38029
|
-
var POSIX_NAMES2 = ["jervcode"];
|
|
38030
|
-
var NODE_MODULES_CLEANUP_TIMEOUT_MS = 3e5;
|
|
38031
|
-
function jervcodeCandidatePaths(env = process.env, home = (0, import_node_os20.homedir)(), platform2 = process.platform) {
|
|
38032
|
-
const names = platform2 === "win32" ? WIN_NAMES2 : POSIX_NAMES2;
|
|
38033
|
-
const out = [];
|
|
38034
|
-
for (const dir of jervCliCandidateDirs(env, home, platform2)) {
|
|
38035
|
-
for (const name of names) out.push((0, import_node_path37.join)(dir, name));
|
|
38036
|
-
}
|
|
38037
|
-
return out;
|
|
38038
|
-
}
|
|
38039
|
-
function resolveJervcodePath(env = process.env, home = (0, import_node_os20.homedir)(), platform2 = process.platform, exists = import_node_fs40.existsSync) {
|
|
38040
|
-
for (const candidate of jervcodeCandidatePaths(env, home, platform2)) {
|
|
38041
|
-
if (exists(candidate)) return candidate;
|
|
38042
|
-
}
|
|
38043
|
-
return void 0;
|
|
38044
|
-
}
|
|
38045
|
-
function jervcodeExecFileArgs(args, opts = {}) {
|
|
38046
|
-
const platform2 = opts.platform ?? process.platform;
|
|
38047
|
-
const exists = opts.exists ?? import_node_fs40.existsSync;
|
|
38048
|
-
const resolved = resolveJervcodePath(opts.env ?? process.env, opts.home ?? (0, import_node_os20.homedir)(), platform2, exists);
|
|
38049
|
-
if (resolved) {
|
|
38050
|
-
const entry = (0, import_node_path37.join)((0, import_node_path37.join)(resolved, ".."), JERVCODE_PACKAGE_ENTRY);
|
|
38051
|
-
if (exists(entry)) {
|
|
38052
|
-
return { file: opts.execPath ?? process.execPath, args: [entry, ...args], via: "node-entry" };
|
|
38053
|
-
}
|
|
38054
|
-
}
|
|
38055
|
-
const bin = resolved ?? "jervcode";
|
|
38056
|
-
if (platform2 === "win32") {
|
|
38057
|
-
return { file: "cmd.exe", args: ["/c", bin, ...args], via: resolved ? "cmd-shim" : "bare" };
|
|
38058
|
-
}
|
|
38059
|
-
return { file: bin, args: [...args], via: resolved ? "posix" : "bare" };
|
|
38060
|
-
}
|
|
38061
|
-
async function removeWorktreeNodeModulesViaHelper(wtPath, opts = {}) {
|
|
38062
|
-
const { cwd, timeoutMs = NODE_MODULES_CLEANUP_TIMEOUT_MS } = opts;
|
|
38063
|
-
const env = opts.env ?? process.env;
|
|
38064
|
-
const exec = opts.exec ?? execFileP;
|
|
38065
|
-
const candidates = jervcodeCandidatePaths(env, opts.home, opts.platform ?? process.platform);
|
|
38066
|
-
const plan = jervcodeExecFileArgs(["worktree-node-modules-cleanup", "--worktree", wtPath], opts);
|
|
38067
|
-
const execOptions = { timeout: timeoutMs, ...cwd ? { cwd } : {} };
|
|
38068
|
-
try {
|
|
38069
|
-
await exec(plan.file, plan.args, execOptions);
|
|
38070
|
-
return { ok: true };
|
|
38071
|
-
} catch (e) {
|
|
38072
|
-
const err = e;
|
|
38073
|
-
const base = formatJervCliSpawnFailure(err, plan, candidates);
|
|
38074
|
-
const stderr = typeof err.stderr === "string" ? err.stderr.trim() : "";
|
|
38075
|
-
const detail = stderr.split("\n")[0] || base;
|
|
38076
|
-
return { ok: false, error: `jervcode worktree-node-modules-cleanup failed: ${detail}` };
|
|
38077
|
-
}
|
|
38078
|
-
}
|
|
38135
|
+
var import_node_path40 = require("node:path");
|
|
38079
38136
|
|
|
38080
38137
|
// src/worktree-evidence-archive.ts
|
|
38081
38138
|
var import_node_fs41 = require("node:fs");
|
|
38082
|
-
var
|
|
38139
|
+
var import_node_path39 = require("node:path");
|
|
38083
38140
|
var JERV_ARTIFACT_RUN_SCOPE_ENV_VARS = ["JERV_RUN_ID", ...SESSION_ID_ENV_VARS];
|
|
38084
38141
|
function sanitizeArchiveSegment(value, max = 80) {
|
|
38085
38142
|
const scrubbed = value.replace(/[^A-Za-z0-9._@+-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -38111,7 +38168,7 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
|
|
|
38111
38168
|
const resolveRoot = deps.resolveArchiveRoot ?? repoRuntimeStatePath;
|
|
38112
38169
|
if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
|
|
38113
38170
|
if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
|
|
38114
|
-
const source = (0,
|
|
38171
|
+
const source = (0, import_node_path39.join)(args.worktreePath, ".jerv");
|
|
38115
38172
|
if (!exists(source)) return { status: "absent" };
|
|
38116
38173
|
if (!isDirectory(source)) return { status: "skipped", reason: "jerv-not-a-directory" };
|
|
38117
38174
|
const runScope = resolveArtifactRunScope(env);
|
|
@@ -38119,7 +38176,7 @@ function archiveWorktreeJervArtifacts(args, deps = {}) {
|
|
|
38119
38176
|
const stamp = now().toISOString().replace(/[:.]/g, "-");
|
|
38120
38177
|
const dest = resolveRoot(args.primaryRoot, "jerv-artifacts", runScope, branchSlug, stamp, ".jerv");
|
|
38121
38178
|
try {
|
|
38122
|
-
mkdirp((0,
|
|
38179
|
+
mkdirp((0, import_node_path39.dirname)(dest));
|
|
38123
38180
|
copyDir(source, dest);
|
|
38124
38181
|
if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
|
|
38125
38182
|
return { status: "archived", path: dest, runScope };
|
|
@@ -38135,7 +38192,7 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
|
|
|
38135
38192
|
const exists = deps.exists ?? import_node_fs41.existsSync;
|
|
38136
38193
|
const stat4 = deps.stat ?? defaultStat;
|
|
38137
38194
|
const readdir2 = deps.readdir ?? import_node_fs41.readdirSync;
|
|
38138
|
-
const tmpRoot = (0,
|
|
38195
|
+
const tmpRoot = (0, import_node_path39.join)(worktreePath, "tmp");
|
|
38139
38196
|
if (!exists(tmpRoot)) return [];
|
|
38140
38197
|
const entries = [];
|
|
38141
38198
|
const walk2 = (dir) => {
|
|
@@ -38146,14 +38203,14 @@ function scanWorktreeTmpEvidence(worktreePath, newerThanMs, deps = {}) {
|
|
|
38146
38203
|
return;
|
|
38147
38204
|
}
|
|
38148
38205
|
for (const name of names) {
|
|
38149
|
-
const full = (0,
|
|
38206
|
+
const full = (0, import_node_path39.join)(dir, name);
|
|
38150
38207
|
let st;
|
|
38151
38208
|
try {
|
|
38152
38209
|
st = stat4(full);
|
|
38153
38210
|
} catch {
|
|
38154
38211
|
continue;
|
|
38155
38212
|
}
|
|
38156
|
-
const relPath = (0,
|
|
38213
|
+
const relPath = (0, import_node_path39.relative)(worktreePath, full).replace(/\\/g, "/");
|
|
38157
38214
|
if (st.isDirectory()) {
|
|
38158
38215
|
if (st.mtimeMs > newerThanMs) entries.push({ relPath, bytes: 0, mtimeMs: st.mtimeMs });
|
|
38159
38216
|
walk2(full);
|
|
@@ -38178,7 +38235,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
|
|
|
38178
38235
|
if (!args.primaryRoot?.trim()) return { status: "skipped", reason: "missing-primary-root" };
|
|
38179
38236
|
if (!args.worktreePath?.trim()) return { status: "skipped", reason: "missing-worktree-path" };
|
|
38180
38237
|
const scanned = scanWorktreeTmpEvidence(args.worktreePath, args.newerThanMs, deps);
|
|
38181
|
-
const source = (0,
|
|
38238
|
+
const source = (0, import_node_path39.join)(args.worktreePath, "tmp");
|
|
38182
38239
|
if (!scanned.length) return { status: "absent" };
|
|
38183
38240
|
if (!exists(source)) return { status: "absent" };
|
|
38184
38241
|
const runScope = resolveArtifactRunScope(env);
|
|
@@ -38186,7 +38243,7 @@ function archiveWorktreeTmpArtifacts(args, deps = {}) {
|
|
|
38186
38243
|
const stamp = now().toISOString().replace(/[:.]/g, "-");
|
|
38187
38244
|
const dest = resolveRoot(args.primaryRoot, "worktree-artifacts", runScope, branchSlug, stamp, "tmp");
|
|
38188
38245
|
try {
|
|
38189
|
-
mkdirp((0,
|
|
38246
|
+
mkdirp((0, import_node_path39.dirname)(dest));
|
|
38190
38247
|
copyDir(source, dest);
|
|
38191
38248
|
if (!exists(dest)) return { status: "failed", error: `archive write left no directory at ${dest}` };
|
|
38192
38249
|
const bytes = scanned.reduce((sum, e) => sum + e.bytes, 0);
|
|
@@ -38255,7 +38312,7 @@ function normPath2(p) {
|
|
|
38255
38312
|
return p.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
38256
38313
|
}
|
|
38257
38314
|
function unlinkNodeModulesJunction(wtPath) {
|
|
38258
|
-
const nm = (0,
|
|
38315
|
+
const nm = (0, import_node_path40.join)(wtPath, "node_modules");
|
|
38259
38316
|
try {
|
|
38260
38317
|
if ((0, import_node_fs42.lstatSync)(nm).isSymbolicLink()) (0, import_node_fs42.rmdirSync)(nm);
|
|
38261
38318
|
return { ok: true };
|
|
@@ -38392,7 +38449,7 @@ async function preCleanWorktreeForRemoval(wtPath, execGit) {
|
|
|
38392
38449
|
}
|
|
38393
38450
|
async function listNestedIgnoredNodeModules(wtPath, execGit) {
|
|
38394
38451
|
const out = await execGit(["-C", wtPath, "ls-files", "--others", "--ignored", "--exclude-standard", "--directory"]).catch(() => "");
|
|
38395
|
-
return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0,
|
|
38452
|
+
return out.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.endsWith("node_modules/") && line !== "node_modules/").map((line) => (0, import_node_path40.join)(wtPath, line.slice(0, -1)));
|
|
38396
38453
|
}
|
|
38397
38454
|
function safeRemoveTree(path2) {
|
|
38398
38455
|
const stat4 = (0, import_node_fs42.lstatSync)(path2);
|
|
@@ -38405,7 +38462,7 @@ function safeRemoveTree(path2) {
|
|
|
38405
38462
|
return;
|
|
38406
38463
|
}
|
|
38407
38464
|
if (stat4.isDirectory()) {
|
|
38408
|
-
for (const entry of (0, import_node_fs42.readdirSync)(path2)) safeRemoveTree((0,
|
|
38465
|
+
for (const entry of (0, import_node_fs42.readdirSync)(path2)) safeRemoveTree((0, import_node_path40.join)(path2, entry));
|
|
38409
38466
|
(0, import_node_fs42.rmdirSync)(path2);
|
|
38410
38467
|
return;
|
|
38411
38468
|
}
|
|
@@ -38448,7 +38505,7 @@ function unlinkEscapingReparsePoints(root, primaryRoot) {
|
|
|
38448
38505
|
return { ok: false, error: `cannot scan ${normPath2(dir)} for reparse points: ${errorMessage(e)}` };
|
|
38449
38506
|
}
|
|
38450
38507
|
for (const entry of entries) {
|
|
38451
|
-
const child2 = (0,
|
|
38508
|
+
const child2 = (0, import_node_path40.join)(dir, entry.name);
|
|
38452
38509
|
if (entry.isSymbolicLink()) {
|
|
38453
38510
|
let target = "";
|
|
38454
38511
|
try {
|
|
@@ -38482,7 +38539,7 @@ async function describePreCleanFailure(wtPath, execGit, error) {
|
|
|
38482
38539
|
const more = remaining.length > 10 ? ` (+${remaining.length - 10} more)` : "";
|
|
38483
38540
|
const quote = (path2) => path2.replace(/'/g, "''");
|
|
38484
38541
|
const nested = remaining.find((path2) => path2.endsWith("node_modules/") && path2 !== "node_modules/");
|
|
38485
|
-
const remediation = remaining.includes("node_modules/") ? `jervcode worktree-node-modules-cleanup --worktree '${quote(wtPath)}'` : nested ? `Remove-Item -LiteralPath '${quote((0,
|
|
38542
|
+
const remediation = remaining.includes("node_modules/") ? `jervcode worktree-node-modules-cleanup --worktree '${quote(wtPath)}'` : nested ? `Remove-Item -LiteralPath '${quote((0, import_node_path40.join)(wtPath, nested.slice(0, -1)))}' -Recurse -Force` : void 0;
|
|
38486
38543
|
return { ok: false, error: `${error}; remaining ignored paths: ${shown}${more}`, ...remediation ? { remediation } : {} };
|
|
38487
38544
|
}
|
|
38488
38545
|
function formatWorktreeRemovalFailureDetail(options) {
|
|
@@ -38776,7 +38833,7 @@ async function cleanupPrMergeLocalBranch(branch, options) {
|
|
|
38776
38833
|
const preHelperGuard = unlinkEscapingReparsePoints(wtPath, options.primaryRoot);
|
|
38777
38834
|
if (!preHelperGuard.ok) return refuseReparseEscape(preHelperGuard.error);
|
|
38778
38835
|
unlinkedReparsePoints.push(...preHelperGuard.unlinked);
|
|
38779
|
-
if (pathExists((0,
|
|
38836
|
+
if (pathExists((0, import_node_path40.join)(wtPath, "node_modules"))) {
|
|
38780
38837
|
const nmRemoved = await (options.removeRealNodeModules ?? ((p) => removeWorktreeNodeModulesViaHelper(p, { cwd: mainWorktreePath })))(wtPath);
|
|
38781
38838
|
if (!nmRemoved.ok) {
|
|
38782
38839
|
report.worktree = {
|
|
@@ -38943,10 +39000,10 @@ function argvWantsJson2() {
|
|
|
38943
39000
|
return process.argv.some((a) => a === "--json" || a.startsWith("--json="));
|
|
38944
39001
|
}
|
|
38945
39002
|
function hubRoot() {
|
|
38946
|
-
const fromPkg = (0,
|
|
39003
|
+
const fromPkg = (0, import_node_path41.join)(__dirname, "..", "..");
|
|
38947
39004
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
38948
|
-
if ((0, import_node_fs43.existsSync)((0,
|
|
38949
|
-
if ((0, import_node_fs43.existsSync)((0,
|
|
39005
|
+
if ((0, import_node_fs43.existsSync)((0, import_node_path41.join)(fromPkg, marker))) return fromPkg;
|
|
39006
|
+
if ((0, import_node_fs43.existsSync)((0, import_node_path41.join)(process.cwd(), marker))) return process.cwd();
|
|
38950
39007
|
return null;
|
|
38951
39008
|
}
|
|
38952
39009
|
function ciAuditDeps() {
|
|
@@ -38958,7 +39015,7 @@ function ciAuditDeps() {
|
|
|
38958
39015
|
getProjectMeta: async (slug) => fetchProjectBySlug(slug, registryClientDeps(await cfgPromise)),
|
|
38959
39016
|
readSeedFile: (path2) => {
|
|
38960
39017
|
if (!root) return null;
|
|
38961
|
-
const fullPath = (0,
|
|
39018
|
+
const fullPath = (0, import_node_path41.join)(root, path2);
|
|
38962
39019
|
return (0, import_node_fs43.existsSync)(fullPath) ? (0, import_node_fs43.readFileSync)(fullPath, "utf8") : null;
|
|
38963
39020
|
}
|
|
38964
39021
|
};
|
|
@@ -39109,7 +39166,7 @@ function registerCollaborationCommands(program3) {
|
|
|
39109
39166
|
try {
|
|
39110
39167
|
title = await resolveIssueTitle(
|
|
39111
39168
|
{ title: opts.title, titleFile: opts.titleFile },
|
|
39112
|
-
{ readFile:
|
|
39169
|
+
{ readFile: import_promises8.readFile, readStdin }
|
|
39113
39170
|
);
|
|
39114
39171
|
} catch (e) {
|
|
39115
39172
|
return fail(
|
|
@@ -39151,8 +39208,8 @@ function registerCollaborationCommands(program3) {
|
|
|
39151
39208
|
let surfaceFlagLabel;
|
|
39152
39209
|
try {
|
|
39153
39210
|
issueType = resolveCreateType(o.type, "issue create", o.label);
|
|
39154
|
-
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
39155
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
39211
|
+
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39212
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39156
39213
|
if (o.idempotencyKey) body = appendIdempotencyMarker(body, o.idempotencyKey);
|
|
39157
39214
|
priority = resolveCreatePriority(o.priority, "issue create");
|
|
39158
39215
|
extraLabels = [...o.label ?? []];
|
|
@@ -39360,7 +39417,7 @@ function registerCollaborationCommands(program3) {
|
|
|
39360
39417
|
}
|
|
39361
39418
|
let body;
|
|
39362
39419
|
try {
|
|
39363
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
39420
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39364
39421
|
} catch (e) {
|
|
39365
39422
|
return fail(`issue comment: ${e.message}`);
|
|
39366
39423
|
}
|
|
@@ -39420,8 +39477,8 @@ ${list}`);
|
|
|
39420
39477
|
let title;
|
|
39421
39478
|
const sourceRepo = o.repo ?? await resolveRepo(void 0);
|
|
39422
39479
|
try {
|
|
39423
|
-
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
39424
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
39480
|
+
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39481
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39425
39482
|
priority = resolveCreatePriority(o.priority, "report");
|
|
39426
39483
|
if (!ISSUE_TYPES.includes(o.type)) {
|
|
39427
39484
|
throw new Error(`unknown issue type "${o.type}" \u2014 expected one of: ${ISSUE_TYPES.join(", ")}`);
|
|
@@ -39476,8 +39533,8 @@ ${list}`);
|
|
|
39476
39533
|
let args;
|
|
39477
39534
|
try {
|
|
39478
39535
|
skill = assertSkillName(o.skill);
|
|
39479
|
-
rawBody = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
39480
|
-
const rawTitle = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
39536
|
+
rawBody = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39537
|
+
const rawTitle = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39481
39538
|
title = buildSkillLessonTitle(skill, rawTitle);
|
|
39482
39539
|
priority = resolveCreatePriority(o.priority, "skill-lesson");
|
|
39483
39540
|
body = buildSkillLessonBody(rawBody, sourceRepo, pluginSha);
|
|
@@ -39534,12 +39591,12 @@ ${list}`);
|
|
|
39534
39591
|
console.log(JSON.stringify({ ...created, projectItemId, onBoard }));
|
|
39535
39592
|
});
|
|
39536
39593
|
const pr = program3.command("pr").description("pull requests \u2014 reliable create with structured output");
|
|
39537
|
-
withExamples(pr.command("create").description("create a PR and print {number,url} JSON").option("--title <title>", "PR title").option("--title-file <path|->", "read the PR title from a UTF-8 file, or from stdin with -").option("--body <body>", "PR body (markdown)").option("--body-file <path|->", "read PR body from a UTF-8 file, or from stdin with -").option("--base <branch>", "base branch (defaults to the repo default)").option("--head <branch>", "head branch (defaults to the current branch)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--draft", "open the PR in draft state (#2667)").option("--json", "machine-readable output (default; accepted for parity)").action(async (o) => {
|
|
39594
|
+
withExamples(pr.command("create").description("create a PR and print {number,url} JSON").option("--title <title>", "PR title").option("--title-file <path|->", "read the PR title from a UTF-8 file, or from stdin with -").option("--body <body>", "PR body (markdown)").option("--body-file <path|->", "read PR body from a UTF-8 file, or from stdin with -").option("--base <branch>", "base branch (defaults to the repo default)").option("--head <branch>", "head branch (defaults to the current branch)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--draft", "open the PR in draft state (#2667)").option("--no-zeroci", "skip minting the ZeroCI receipt. By default pr create mints it first, which runs the gate commands locally \u2014 pr create then takes as long as this seat needs for its own gate run, and the CI gate skips them (#6284)").option("--json", "machine-readable output (default; accepted for parity)").action(async (o) => {
|
|
39538
39595
|
let body;
|
|
39539
39596
|
let title;
|
|
39540
39597
|
try {
|
|
39541
|
-
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile:
|
|
39542
|
-
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile:
|
|
39598
|
+
title = await resolveIssueTitle({ title: o.title, titleFile: o.titleFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39599
|
+
body = await resolveIssueBody({ body: o.body, bodyFile: o.bodyFile }, { readFile: import_promises8.readFile, readStdin });
|
|
39543
39600
|
} catch (e) {
|
|
39544
39601
|
return fail(`pr create: ${e.message}`, e instanceof TextArgError ? { code: e.code, offending_flag: e.offendingFlag } : void 0);
|
|
39545
39602
|
}
|
|
@@ -39559,6 +39616,9 @@ ${list}`);
|
|
|
39559
39616
|
}
|
|
39560
39617
|
const claimRefusal = await prCreateClaimRefusal(body, o.repo);
|
|
39561
39618
|
if (claimRefusal) return fail(claimRefusal);
|
|
39619
|
+
const zeroCiWarn = await mintZeroCiReceipt({ repo: o.repo, zeroci: o.zeroci }, createPrCreateZeroCiDeps());
|
|
39620
|
+
if (zeroCiWarn) process.stderr.write(`${zeroCiWarn}
|
|
39621
|
+
`);
|
|
39562
39622
|
const created = await ghCreate(buildPrArgs({ title, body, base: o.base, head: o.head, repo: o.repo, draft: o.draft }));
|
|
39563
39623
|
if (isGhCreateRateLimited(created)) {
|
|
39564
39624
|
console.log(JSON.stringify(created));
|
|
@@ -39602,11 +39662,11 @@ ${list}`);
|
|
|
39602
39662
|
}
|
|
39603
39663
|
});
|
|
39604
39664
|
async function listCiWorkflowPaths(cwd = process.cwd()) {
|
|
39605
|
-
const wfDir = (0,
|
|
39665
|
+
const wfDir = (0, import_node_path41.join)(cwd, ".github", "workflows");
|
|
39606
39666
|
if (!(0, import_node_fs43.existsSync)(wfDir)) return [];
|
|
39607
39667
|
return (0, import_node_fs43.readdirSync)(wfDir).filter((name) => /\.(ya?ml)$/i.test(name)).filter((name) => {
|
|
39608
39668
|
try {
|
|
39609
|
-
return workflowReportsPrChecks((0, import_node_fs43.readFileSync)((0,
|
|
39669
|
+
return workflowReportsPrChecks((0, import_node_fs43.readFileSync)((0, import_node_path41.join)(wfDir, name), "utf8"));
|
|
39610
39670
|
} catch {
|
|
39611
39671
|
return true;
|
|
39612
39672
|
}
|
|
@@ -40094,7 +40154,7 @@ ${list}`);
|
|
|
40094
40154
|
const remote = foreignCwd ? `https://github.com/${targetRepo2}.git` : "origin";
|
|
40095
40155
|
let foreignCheckout;
|
|
40096
40156
|
if (foreignCwd) {
|
|
40097
|
-
const sibling = (0,
|
|
40157
|
+
const sibling = (0, import_node_path41.join)((0, import_node_path41.dirname)(beforeWorktrees[0]?.path || startingPath || process.cwd()), targetRepo2.split("/")[1]);
|
|
40098
40158
|
const siblingRepo = repoFromRemoteUrl(await gitOut(["-C", sibling, "remote", "get-url", "origin"]).catch(() => ""));
|
|
40099
40159
|
if (siblingRepo?.toLowerCase() === targetRepo2.toLowerCase()) {
|
|
40100
40160
|
const siblingWorktrees = await execFileP("git", ["-C", sibling, "worktree", "list", "--porcelain"], { timeout: GIT_TIMEOUT_MS }).then((r) => parseGitWorktreePorcelain(r.stdout)).catch(() => void 0);
|
|
@@ -40464,7 +40524,7 @@ async function resolveWhoami(deps) {
|
|
|
40464
40524
|
}
|
|
40465
40525
|
|
|
40466
40526
|
// src/command-register-developer.ts
|
|
40467
|
-
var
|
|
40527
|
+
var import_node_path46 = require("node:path");
|
|
40468
40528
|
|
|
40469
40529
|
// src/wave-land.ts
|
|
40470
40530
|
function planWaveLand(prs) {
|
|
@@ -40721,17 +40781,17 @@ var import_node_child_process17 = require("node:child_process");
|
|
|
40721
40781
|
var import_node_crypto12 = require("node:crypto");
|
|
40722
40782
|
var import_node_fs46 = require("node:fs");
|
|
40723
40783
|
var import_node_os21 = require("node:os");
|
|
40724
|
-
var
|
|
40784
|
+
var import_node_path43 = require("node:path");
|
|
40725
40785
|
|
|
40726
40786
|
// ../scripts/distribution-digest.mjs
|
|
40727
40787
|
var import_node_crypto11 = require("node:crypto");
|
|
40728
40788
|
var import_node_fs45 = require("node:fs");
|
|
40729
|
-
var
|
|
40789
|
+
var import_node_path42 = require("node:path");
|
|
40730
40790
|
var slash = (value) => value.replaceAll("\\", "/");
|
|
40731
40791
|
function repoPath(root, declaredPath, label) {
|
|
40732
|
-
const absoluteRoot = (0,
|
|
40733
|
-
const target = (0,
|
|
40734
|
-
if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${
|
|
40792
|
+
const absoluteRoot = (0, import_node_path42.resolve)(root);
|
|
40793
|
+
const target = (0, import_node_path42.resolve)(root, declaredPath);
|
|
40794
|
+
if (target !== absoluteRoot && !target.startsWith(`${absoluteRoot}${import_node_path42.sep}`)) {
|
|
40735
40795
|
throw new Error(`${label} ${declaredPath} escapes the repository root`);
|
|
40736
40796
|
}
|
|
40737
40797
|
return target;
|
|
@@ -40845,7 +40905,7 @@ function walkFiles(root) {
|
|
|
40845
40905
|
const files = [];
|
|
40846
40906
|
const walk2 = (directory) => {
|
|
40847
40907
|
for (const entry of (0, import_node_fs46.readdirSync)(directory, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
40848
|
-
const child2 = (0,
|
|
40908
|
+
const child2 = (0, import_node_path43.join)(directory, entry.name);
|
|
40849
40909
|
if (entry.isDirectory()) walk2(child2);
|
|
40850
40910
|
else files.push(child2);
|
|
40851
40911
|
}
|
|
@@ -40855,10 +40915,10 @@ function walkFiles(root) {
|
|
|
40855
40915
|
}
|
|
40856
40916
|
function bomPathFor(root) {
|
|
40857
40917
|
try {
|
|
40858
|
-
const registry2 = JSON.parse((0, import_node_fs46.readFileSync)((0,
|
|
40859
|
-
return (0,
|
|
40918
|
+
const registry2 = JSON.parse((0, import_node_fs46.readFileSync)((0, import_node_path43.join)(root, "surfaces.json"), "utf8"));
|
|
40919
|
+
return (0, import_node_path43.join)(root, registry2?.sharedAgentCore?.releaseMetadata?.bomPath ?? "distribution-bom.json");
|
|
40860
40920
|
} catch {
|
|
40861
|
-
return (0,
|
|
40921
|
+
return (0, import_node_path43.join)(root, "distribution-bom.json");
|
|
40862
40922
|
}
|
|
40863
40923
|
}
|
|
40864
40924
|
function rebuildTo(packageRoot, outDir) {
|
|
@@ -40871,28 +40931,28 @@ function rebuildTo(packageRoot, outDir) {
|
|
|
40871
40931
|
});
|
|
40872
40932
|
}
|
|
40873
40933
|
function runDistStatus(root) {
|
|
40874
|
-
const stage = (0, import_node_fs46.mkdtempSync)((0,
|
|
40934
|
+
const stage = (0, import_node_fs46.mkdtempSync)((0, import_node_path43.join)((0, import_node_os21.tmpdir)(), "mmi-dist-drift-"));
|
|
40875
40935
|
let overlayCount = 0;
|
|
40876
40936
|
try {
|
|
40877
|
-
const cliOut = (0,
|
|
40878
|
-
const hubOut = (0,
|
|
40879
|
-
rebuildTo((0,
|
|
40880
|
-
rebuildTo((0,
|
|
40937
|
+
const cliOut = (0, import_node_path43.join)(stage, "cli-dist");
|
|
40938
|
+
const hubOut = (0, import_node_path43.join)(stage, "hub-dist");
|
|
40939
|
+
rebuildTo((0, import_node_path43.join)(root, "cli"), cliOut);
|
|
40940
|
+
rebuildTo((0, import_node_path43.join)(root, "updater"), hubOut);
|
|
40881
40941
|
const outDirFor = (packageDir) => packageDir === "cli" ? cliOut : hubOut;
|
|
40882
40942
|
const rebuilt = (path2) => {
|
|
40883
40943
|
const spec = DIST_ARTIFACTS.find((entry) => entry.path === path2);
|
|
40884
|
-
return spec ? readOrNull((0,
|
|
40944
|
+
return spec ? readOrNull((0, import_node_path43.join)(outDirFor(spec.packageDir), spec.output)) : null;
|
|
40885
40945
|
};
|
|
40886
|
-
const committed = (path2) => readOrNull((0,
|
|
40887
|
-
const tree = (path2) => readOrNull((0,
|
|
40888
|
-
const distRoot = (0,
|
|
40889
|
-
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0,
|
|
40946
|
+
const committed = (path2) => readOrNull((0, import_node_path43.join)(root, path2));
|
|
40947
|
+
const tree = (path2) => readOrNull((0, import_node_path43.join)(root, path2));
|
|
40948
|
+
const distRoot = (0, import_node_path43.join)(root, "cli", "dist");
|
|
40949
|
+
const distTree = () => walkFiles(distRoot).map((absolute) => `cli/dist/${(0, import_node_path43.relative)(distRoot, absolute).replaceAll("\\", "/")}`);
|
|
40890
40950
|
const bom = JSON.parse((0, import_node_fs46.readFileSync)(bomPathFor(root), "utf8"));
|
|
40891
40951
|
const digest = (entries) => {
|
|
40892
|
-
const overlay = (0,
|
|
40952
|
+
const overlay = (0, import_node_path43.join)(stage, `overlay-${overlayCount++}`);
|
|
40893
40953
|
for (const entry of entries) {
|
|
40894
|
-
const target = (0,
|
|
40895
|
-
(0, import_node_fs46.mkdirSync)((0,
|
|
40954
|
+
const target = (0, import_node_path43.join)(overlay, entry.path);
|
|
40955
|
+
(0, import_node_fs46.mkdirSync)((0, import_node_path43.dirname)(target), { recursive: true });
|
|
40896
40956
|
(0, import_node_fs46.writeFileSync)(target, entry.bytes);
|
|
40897
40957
|
}
|
|
40898
40958
|
return digestPackedFiles(overlay, entries.map((entry) => entry.path));
|
|
@@ -40970,8 +41030,8 @@ function registerEdgeCommands(program3) {
|
|
|
40970
41030
|
}
|
|
40971
41031
|
|
|
40972
41032
|
// src/schedules-lift-command.ts
|
|
40973
|
-
var
|
|
40974
|
-
var
|
|
41033
|
+
var import_promises9 = require("node:fs/promises");
|
|
41034
|
+
var import_node_path44 = require("node:path");
|
|
40975
41035
|
var DEFAULT_WORKFLOWS_DIR = ".github/workflows";
|
|
40976
41036
|
var SCHEDULE_REPO_RE = /^[A-Za-z0-9_.-]+$/;
|
|
40977
41037
|
var SchedulesLiftUsageError = class extends Error {
|
|
@@ -40991,14 +41051,14 @@ var RegistryUnreachableError = class extends Error {
|
|
|
40991
41051
|
async function readWorkflowFiles(dir) {
|
|
40992
41052
|
let names;
|
|
40993
41053
|
try {
|
|
40994
|
-
names = await (0,
|
|
41054
|
+
names = await (0, import_promises9.readdir)(dir);
|
|
40995
41055
|
} catch {
|
|
40996
41056
|
return [];
|
|
40997
41057
|
}
|
|
40998
41058
|
const files = [];
|
|
40999
41059
|
for (const name of names.sort()) {
|
|
41000
41060
|
if (!/\.ya?ml$/.test(name)) continue;
|
|
41001
|
-
files.push({ path: `.github/workflows/${name}`, text: await (0,
|
|
41061
|
+
files.push({ path: `.github/workflows/${name}`, text: await (0, import_promises9.readFile)((0, import_node_path44.join)(dir, name), "utf8") });
|
|
41002
41062
|
}
|
|
41003
41063
|
return files;
|
|
41004
41064
|
}
|
|
@@ -41082,7 +41142,7 @@ function registerSchedulesLiftCommand(program3, deps = {}) {
|
|
|
41082
41142
|
// src/spawn-policy-core.ts
|
|
41083
41143
|
var import_node_child_process18 = require("node:child_process");
|
|
41084
41144
|
var import_node_fs47 = require("node:fs");
|
|
41085
|
-
var
|
|
41145
|
+
var import_node_path45 = require("node:path");
|
|
41086
41146
|
var SPAWNERS = ["spawn", "spawnSync", "exec", "execSync", "execFile", "execFileSync"];
|
|
41087
41147
|
var CALL_SOURCE = String.raw`(^|[^.\w$])(${SPAWNERS.join("|")})\s*\(`;
|
|
41088
41148
|
var SOURCE_EXT = /\.(ts|mts|cts|js|mjs|cjs)$/;
|
|
@@ -41168,7 +41228,7 @@ function runSpawnPolicy(root) {
|
|
|
41168
41228
|
for (const file of files) {
|
|
41169
41229
|
let raw;
|
|
41170
41230
|
try {
|
|
41171
|
-
raw = (0, import_node_fs47.readFileSync)((0,
|
|
41231
|
+
raw = (0, import_node_fs47.readFileSync)((0, import_node_path45.join)(root, file), "utf8");
|
|
41172
41232
|
} catch {
|
|
41173
41233
|
continue;
|
|
41174
41234
|
}
|
|
@@ -41188,7 +41248,7 @@ function runSpawnPolicy(root) {
|
|
|
41188
41248
|
function registerDeveloperCommands(program3) {
|
|
41189
41249
|
const rules = program3.command("rules").description("org-managed .gitignore delivery");
|
|
41190
41250
|
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) => {
|
|
41191
|
-
const path2 = (0,
|
|
41251
|
+
const path2 = (0, import_node_path46.join)(process.cwd(), ".gitignore");
|
|
41192
41252
|
const current = (0, import_node_fs48.existsSync)(path2) ? (0, import_node_fs48.readFileSync)(path2, "utf8") : null;
|
|
41193
41253
|
const plan = planManagedGitignore(current);
|
|
41194
41254
|
const drift = [...plan.added.map((l) => `+${l}`), ...plan.removed.map((l) => `-${l}`)].join(", ") || "block normalize";
|
|
@@ -41448,10 +41508,10 @@ function registerDeveloperCommands(program3) {
|
|
|
41448
41508
|
}
|
|
41449
41509
|
|
|
41450
41510
|
// src/command-register-train-operations.ts
|
|
41451
|
-
var
|
|
41511
|
+
var import_promises11 = require("node:fs/promises");
|
|
41452
41512
|
|
|
41453
41513
|
// src/hotfix-apply.ts
|
|
41454
|
-
var
|
|
41514
|
+
var import_promises10 = require("node:fs/promises");
|
|
41455
41515
|
|
|
41456
41516
|
// src/slack-alert.ts
|
|
41457
41517
|
var SSM_REGION = "eu-central-1";
|
|
@@ -42235,7 +42295,7 @@ async function runHotfixRelease(deps, versionInput, options = {}, doctor = runTr
|
|
|
42235
42295
|
}
|
|
42236
42296
|
let lines2;
|
|
42237
42297
|
try {
|
|
42238
|
-
lines2 = summaryFileLines(await (deps.readFile ?? ((p) => (0,
|
|
42298
|
+
lines2 = summaryFileLines(await (deps.readFile ?? ((p) => (0, import_promises10.readFile)(p, "utf8")))(options.announceSummaryFile));
|
|
42239
42299
|
} catch (e) {
|
|
42240
42300
|
throw new Error(`could not read --announce-summary-file ${options.announceSummaryFile}: ${e.message} \u2014 see docs/Guides/train-troubleshooting.md#announce-summary-missing`);
|
|
42241
42301
|
}
|
|
@@ -42794,7 +42854,7 @@ function checkHotfixCarries(options) {
|
|
|
42794
42854
|
|
|
42795
42855
|
// src/train-commands.ts
|
|
42796
42856
|
var import_node_fs49 = require("node:fs");
|
|
42797
|
-
var
|
|
42857
|
+
var import_node_path47 = require("node:path");
|
|
42798
42858
|
var INVOKED_ARGV = process.argv.slice(2);
|
|
42799
42859
|
var RELEASE_BUMP_INTENTS = ["major", "minor", "patch"];
|
|
42800
42860
|
function resolveReleaseBumpIntent(raw) {
|
|
@@ -42806,7 +42866,7 @@ function resolveReleaseBumpIntent(raw) {
|
|
|
42806
42866
|
}
|
|
42807
42867
|
function readRepoVersion() {
|
|
42808
42868
|
try {
|
|
42809
|
-
return JSON.parse((0, import_node_fs49.readFileSync)((0,
|
|
42869
|
+
return JSON.parse((0, import_node_fs49.readFileSync)((0, import_node_path47.join)(process.cwd(), ".claude-plugin", "plugin.json"), "utf8")).version || void 0;
|
|
42810
42870
|
} catch {
|
|
42811
42871
|
return void 0;
|
|
42812
42872
|
}
|
|
@@ -42969,8 +43029,8 @@ function trainApplyDeps() {
|
|
|
42969
43029
|
// Slack release announcement (#883): Hub-only + best-effort inside announceRelease itself.
|
|
42970
43030
|
announce: (args) => announceRelease({
|
|
42971
43031
|
run: async (file, cmdArgs) => (await execFileP(file, cmdArgs, { timeout: GH_TRAIN_TIMEOUT_MS })).stdout,
|
|
42972
|
-
readFile: (path2) => (0,
|
|
42973
|
-
removeFile: (path2) => (0,
|
|
43032
|
+
readFile: (path2) => (0, import_promises11.readFile)(path2, "utf8"),
|
|
43033
|
+
removeFile: (path2) => (0, import_promises11.unlink)(path2)
|
|
42974
43034
|
}, args),
|
|
42975
43035
|
// #4713 (I/O-boundary census): `null` used to mean BOTH "this project configures no edge domains"
|
|
42976
43036
|
// (a real answer) and "the registry read missed" — so a release verdict printed an environments block
|
|
@@ -43356,7 +43416,7 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
|
|
|
43356
43416
|
}
|
|
43357
43417
|
let summaryLines;
|
|
43358
43418
|
try {
|
|
43359
|
-
summaryLines = summaryFileLines(await (0,
|
|
43419
|
+
summaryLines = summaryFileLines(await (0, import_promises11.readFile)(o.announceSummaryFile, "utf8"));
|
|
43360
43420
|
} catch (e) {
|
|
43361
43421
|
return fail(`release: could not read --announce-summary-file ${o.announceSummaryFile}: ${e.message} \u2014 see docs/Guides/train-troubleshooting.md#announce-summary-missing`);
|
|
43362
43422
|
}
|
|
@@ -43550,7 +43610,7 @@ ${r.stderr ?? ""}`).catch(() => "");
|
|
|
43550
43610
|
var ENV_HEAL_LOCK_STALE_MS = 10 * 6e4;
|
|
43551
43611
|
var ENV_HEAL_LOCK_MAX_WAIT_MS = 2 * 6e4;
|
|
43552
43612
|
function envHealLockPath(home) {
|
|
43553
|
-
return (0,
|
|
43613
|
+
return (0, import_node_path48.join)(home, ".claude", "plugins", ".mmi-env-heal.lock");
|
|
43554
43614
|
}
|
|
43555
43615
|
async function withEnvHealLock(what, run) {
|
|
43556
43616
|
try {
|
|
@@ -43721,7 +43781,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
43721
43781
|
// has no generated routing index would
|
|
43722
43782
|
// get a permanent — demanding an artifact it never asked for.
|
|
43723
43783
|
docsIndexState: (root) => {
|
|
43724
|
-
if (!(0, import_node_fs50.existsSync)((0,
|
|
43784
|
+
if (!(0, import_node_fs50.existsSync)((0, import_node_path48.join)(root, DOCS_INDEX_PATH))) return void 0;
|
|
43725
43785
|
const real = createDocsIndexDeps(root);
|
|
43726
43786
|
let docs;
|
|
43727
43787
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -43730,7 +43790,7 @@ function mmiDoctorDeps(opts = {}) {
|
|
|
43730
43790
|
},
|
|
43731
43791
|
// #4168: working-tree heal — write if drifted, then re-check. Commit remains the operator's step.
|
|
43732
43792
|
healDocsIndex: (root) => {
|
|
43733
|
-
if (!(0, import_node_fs50.existsSync)((0,
|
|
43793
|
+
if (!(0, import_node_fs50.existsSync)((0, import_node_path48.join)(root, DOCS_INDEX_PATH))) return { drift: false, docCount: 0 };
|
|
43734
43794
|
const real = createDocsIndexDeps(root);
|
|
43735
43795
|
let docs;
|
|
43736
43796
|
const listDocs = () => docs ??= real.listDocs();
|
|
@@ -44609,16 +44669,16 @@ function ciAuditDeps2() {
|
|
|
44609
44669
|
// gate re-seed step is skipped gracefully rather than failing mid-run.
|
|
44610
44670
|
readSeedFile: (path2) => {
|
|
44611
44671
|
if (!root) return null;
|
|
44612
|
-
const fullPath = (0,
|
|
44672
|
+
const fullPath = (0, import_node_path48.join)(root, path2);
|
|
44613
44673
|
return (0, import_node_fs50.existsSync)(fullPath) ? (0, import_node_fs50.readFileSync)(fullPath, "utf8") : null;
|
|
44614
44674
|
}
|
|
44615
44675
|
};
|
|
44616
44676
|
}
|
|
44617
44677
|
function hubRoot2() {
|
|
44618
|
-
const fromPkg = (0,
|
|
44678
|
+
const fromPkg = (0, import_node_path48.join)(__dirname, "..", "..");
|
|
44619
44679
|
const marker = "skills/bootstrap/seeds/manifest.json";
|
|
44620
|
-
if ((0, import_node_fs50.existsSync)((0,
|
|
44621
|
-
if ((0, import_node_fs50.existsSync)((0,
|
|
44680
|
+
if ((0, import_node_fs50.existsSync)((0, import_node_path48.join)(fromPkg, marker))) return fromPkg;
|
|
44681
|
+
if ((0, import_node_fs50.existsSync)((0, import_node_path48.join)(process.cwd(), marker))) return process.cwd();
|
|
44622
44682
|
return null;
|
|
44623
44683
|
}
|
|
44624
44684
|
registerQueryCommands(program2);
|
|
@@ -44757,7 +44817,7 @@ function directoryBytes(path2) {
|
|
|
44757
44817
|
return 0;
|
|
44758
44818
|
}
|
|
44759
44819
|
for (const entry of entries) {
|
|
44760
|
-
const child2 = (0,
|
|
44820
|
+
const child2 = (0, import_node_path48.join)(path2, entry.name);
|
|
44761
44821
|
if (entry.isDirectory()) total += directoryBytes(child2);
|
|
44762
44822
|
else {
|
|
44763
44823
|
try {
|
|
@@ -44787,7 +44847,7 @@ function pluginCacheFsDeps(configRoot, dirBytes) {
|
|
|
44787
44847
|
dirBytes,
|
|
44788
44848
|
listStagingDirs: (root) => (0, import_node_fs50.readdirSync)(root, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => {
|
|
44789
44849
|
try {
|
|
44790
|
-
return { name: d.name, mtimeMs: newestMtimeMs((0,
|
|
44850
|
+
return { name: d.name, mtimeMs: newestMtimeMs((0, import_node_path48.join)(root, d.name), listDirEntries, (p) => (0, import_node_fs50.statSync)(p).mtimeMs) };
|
|
44791
44851
|
} catch {
|
|
44792
44852
|
return { name: d.name, mtimeMs: Date.now() };
|
|
44793
44853
|
}
|
|
@@ -44801,7 +44861,7 @@ function stagingApplyFsGuard(configRoot) {
|
|
|
44801
44861
|
return {
|
|
44802
44862
|
referencedPaths: () => readInstalledPluginRefs(configRoot),
|
|
44803
44863
|
mtimeMs: (name) => {
|
|
44804
|
-
const p = (0,
|
|
44864
|
+
const p = (0, import_node_path48.join)(stagingRoot, name);
|
|
44805
44865
|
if (!(0, import_node_fs50.existsSync)(p)) return null;
|
|
44806
44866
|
try {
|
|
44807
44867
|
return newestMtimeMs(p, listDirEntries, (q) => (0, import_node_fs50.statSync)(q).mtimeMs);
|
package/package.json
CHANGED