@mutmutco/codex-plugin 4.6.8 → 4.6.9
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 +82 -16
- package/cli/package.json +1 -1
- package/package.json +1 -1
package/cli/dist/main.cjs
CHANGED
|
@@ -1236,7 +1236,7 @@ var init_house_map = __esm({
|
|
|
1236
1236
|
api: "devops",
|
|
1237
1237
|
// allowlisted GitHub REST GET reads for automation (pull files, compare, contents)
|
|
1238
1238
|
run: "devops",
|
|
1239
|
-
// #9479: one named workflow run —
|
|
1239
|
+
// #9479: one named workflow run — the bounded `run cancel <id>` and `run rerun <id>` writes
|
|
1240
1240
|
ci: "devops",
|
|
1241
1241
|
// the CI/gate audit
|
|
1242
1242
|
jev: "devops",
|
|
@@ -15347,6 +15347,8 @@ var APP_WRITE_COMMANDS = /* @__PURE__ */ new Map([
|
|
|
15347
15347
|
["ci cancel-orphans", { metadata: "read", actions: "write" }],
|
|
15348
15348
|
// #9479: one named run cancelled under the same actions:write profile as the orphan sweep.
|
|
15349
15349
|
["run cancel", { metadata: "read", actions: "write" }],
|
|
15350
|
+
// #9587: one named run rerun (all or failed jobs) — same actions:write profile, nothing broader.
|
|
15351
|
+
["run rerun", { metadata: "read", actions: "write" }],
|
|
15350
15352
|
["issue comment", { metadata: "read", issues: "write", pull_requests: "write" }],
|
|
15351
15353
|
// #8401: the detached related-issue lookup (issue list/view reads + one marker comment) — no identity contract.
|
|
15352
15354
|
["issue discover-related", { metadata: "read", issues: "write" }]
|
|
@@ -25039,10 +25041,15 @@ function checkRunbookCoverage(docs, base, git3) {
|
|
|
25039
25041
|
const heading = headings[i];
|
|
25040
25042
|
const end = headings.slice(i + 1).find((h) => h.level <= heading.level)?.start ?? lines2.length + 1;
|
|
25041
25043
|
const markerEnd = headings[i + 1]?.start ?? end;
|
|
25042
|
-
const
|
|
25044
|
+
const markers = lines2.slice(heading.start, markerEnd - 1).flatMap((text, j) => {
|
|
25045
|
+
const found = /<!--\s*runbook-covers:\s*(.*?)\s*-->/.exec(text)?.[1].split(",").map((s) => s.trim());
|
|
25046
|
+
return found ? [{ line: heading.start + 1 + j, globs: found }] : [];
|
|
25047
|
+
});
|
|
25048
|
+
const globs = markers.flatMap((m) => m.globs);
|
|
25043
25049
|
const affected = changed.filter((path2) => globs.some((glob) => matches(glob, path2)) && !changesOnlyUses(path2));
|
|
25044
25050
|
if (affected.length && !ranges.some((r) => r.count > 0 && r.start < end && r.start + r.count > heading.start)) {
|
|
25045
|
-
|
|
25051
|
+
const markerLine = markers.find((m) => m.globs.some((glob) => affected.some((path2) => matches(glob, path2)))).line;
|
|
25052
|
+
findings.push({ kind: "runbook-section-stale", doc, line: markerLine, detail: `${heading.title} (lines ${heading.start}\u2013${end - 1}, covers marker at line ${markerLine}): changed ${affected.join(", ")}; update this section's text (lines ${heading.start}\u2013${end - 1}) or runbook-covers list, or add a \`Runbook-Unaffected: <reason>\` trailer to a commit message in this PR`, section: { heading: heading.title, level: heading.level, startLine: heading.start, endLine: end - 1, covers: globs }, sources: affected });
|
|
25046
25053
|
}
|
|
25047
25054
|
}
|
|
25048
25055
|
}
|
|
@@ -27506,10 +27513,10 @@ var rollout_plan_default = {
|
|
|
27506
27513
|
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)."
|
|
27507
27514
|
},
|
|
27508
27515
|
baseline: {
|
|
27509
|
-
version: "4.6.
|
|
27510
|
-
tag: "v4.6.
|
|
27511
|
-
commit: "
|
|
27512
|
-
npm: "@mutmutco/cli@4.6.
|
|
27516
|
+
version: "4.6.9",
|
|
27517
|
+
tag: "v4.6.9",
|
|
27518
|
+
commit: "7cbf84926132",
|
|
27519
|
+
npm: "@mutmutco/cli@4.6.9"
|
|
27513
27520
|
},
|
|
27514
27521
|
exitCriterion: "fleet-n-of-n",
|
|
27515
27522
|
hubOnlyShortcut: "forbidden",
|
|
@@ -27526,14 +27533,14 @@ var rollout_plan_default = {
|
|
|
27526
27533
|
repo: "mutmutco/mmi-hub",
|
|
27527
27534
|
role: "canary",
|
|
27528
27535
|
schedule: "train",
|
|
27529
|
-
v3Target: "v4.6.
|
|
27536
|
+
v3Target: "v4.6.9"
|
|
27530
27537
|
}
|
|
27531
27538
|
],
|
|
27532
27539
|
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.",
|
|
27533
27540
|
rollback: {
|
|
27534
27541
|
independent: true,
|
|
27535
|
-
mechanism: "npm dist-tag latest -> 4.6.
|
|
27536
|
-
v3Target: "v4.6.
|
|
27542
|
+
mechanism: "npm dist-tag latest -> 4.6.9 and redeploy the Hub Lambda from tag v4.6.9 (7cbf84926132); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
27543
|
+
v3Target: "v4.6.9 (@mutmutco/cli@4.6.9, tag commit 7cbf84926132 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
27537
27544
|
}
|
|
27538
27545
|
},
|
|
27539
27546
|
{
|
|
@@ -32106,8 +32113,11 @@ function classifyRunnerCost(selector) {
|
|
|
32106
32113
|
}
|
|
32107
32114
|
var STANDARD_HOSTED_ALLOWLIST = [
|
|
32108
32115
|
["mutmutco/MMI-Hub", ".github/workflows/launcher-build.yml", "build", "windows-latest"],
|
|
32109
|
-
["mutmutco/Jerv-JervCode", ".github/workflows/release-archives.yml", "release-platform-arm64", "windows-11-arm"]
|
|
32116
|
+
["mutmutco/Jerv-JervCode", ".github/workflows/release-archives.yml", "release-platform-arm64", "windows-11-arm"],
|
|
32117
|
+
// #9571 (MM-Work#8894 chooser): owned mmi-heavy first, included ubuntu-latest only on a deep backlog.
|
|
32118
|
+
["mutmutco/MMI-Hub", ".github/workflows/gate.yml", "cli-part", "hosted-spill"]
|
|
32110
32119
|
];
|
|
32120
|
+
var HOSTED_SPILL_RE = /^\$\{\{\s*(?:matrix\.[\w-]+\s*==\s*'[\w-]+'\s*&&\s*'([^']+)'\s*\|\|\s*)?fromJSON\(needs\.[\w-]+\.outputs\.heavy_runs_on\s*\|\|\s*('[^']+')\)\s*\}\}$/;
|
|
32111
32121
|
function standardHostedLabelFor(repo, path2, jobId) {
|
|
32112
32122
|
if (repo === "mutmutco/Jerv-Hub") return ["ubuntu-latest", "windows-latest", "macos-14"];
|
|
32113
32123
|
return STANDARD_HOSTED_ALLOWLIST.find(([r, p, j]) => r === repo && p === path2 && j === jobId)?.[3];
|
|
@@ -32122,6 +32132,8 @@ function classifyJobRunnerCost(job, allowance2) {
|
|
|
32122
32132
|
if (approved(raw) || allowance2 === "windows-11-arm" && raw === allowance2) return "standard-hosted";
|
|
32123
32133
|
const fallback = /^\$\{\{\s*vars\.MMI_RUNNER_FALLBACK\s*==\s*'hosted'\s*&&\s*'([^']+)'\s*\|\|\s*(fromJSON\('[^']+'\))\s*\}\}$/.exec(raw);
|
|
32124
32134
|
if (fallback && approved(fallback[1]) && classifyRunnerCost("${{ " + fallback[2] + " }}") === "self-hosted") return "standard-hosted";
|
|
32135
|
+
const spill = allowance2 === "hosted-spill" ? HOSTED_SPILL_RE.exec(raw) : null;
|
|
32136
|
+
if (spill) return (!spill[1] || spill[1] === "ubuntu-latest") && classifyRunnerCost(`\${{ fromJSON(${spill[2]}) }}`) === "self-hosted" ? "standard-hosted" : "unknown";
|
|
32125
32137
|
const direct = classifyRunnerCost(raw);
|
|
32126
32138
|
const matrix = /^\$\{\{\s*matrix\.([\w-]+)(?:\.([\w-]+))?\s*\}\}$/.exec(raw);
|
|
32127
32139
|
if (!matrix || direct === "hosted") return direct;
|
|
@@ -38643,7 +38655,7 @@ function runsOnLabelSets(job) {
|
|
|
38643
38655
|
if (plainRecord(selector)) selector = selector.labels;
|
|
38644
38656
|
if (typeof selector !== "string" || !selector.includes("${{")) return [toSet(selector)].filter((s) => Boolean(s));
|
|
38645
38657
|
const sets = [];
|
|
38646
|
-
for (const m of selector.matchAll(/fromJSON\('([^']+)'\)/g)) {
|
|
38658
|
+
for (const m of selector.matchAll(/fromJSON\((?:needs\.[\w-]+\.outputs\.[\w-]+\s*\|\|\s*)?'([^']+)'\)/g)) {
|
|
38647
38659
|
try {
|
|
38648
38660
|
const parsed = toSet(JSON.parse(m[1]));
|
|
38649
38661
|
if (parsed) sets.push(parsed);
|
|
@@ -43366,6 +43378,57 @@ function registerRunCancel(run, writeToken) {
|
|
|
43366
43378
|
else console.log(`run cancel: ${receipt.repo} run ${receipt.runId} \u2014 ${receipt.force ? "force-cancel" : "cancel"} requested (status: ${receipt.status}${receipt.runStatus ? `, runStatus: ${receipt.runStatus}` : ""})`);
|
|
43367
43379
|
});
|
|
43368
43380
|
}
|
|
43381
|
+
var RUN_RERUN_STATUS = "rerun-requested";
|
|
43382
|
+
async function rerunWorkflowRun(repo, id, deps, failed2 = false) {
|
|
43383
|
+
const raw = String(id).trim();
|
|
43384
|
+
if (!/^[1-9]\d*$/.test(raw)) throw new Error(`run rerun: <id> must be a positive workflow run id (received '${String(id)}')`);
|
|
43385
|
+
const runId = Number(raw);
|
|
43386
|
+
if (!Number.isSafeInteger(runId)) throw new Error(`run rerun: <id> ${raw} is beyond the safe integer range; refusing to address a different run`);
|
|
43387
|
+
if (!/^[\w.-]+\/[\w.-]+$/.test(repo)) throw new Error(`run rerun: --repo must be owner/repo (received '${repo}')`);
|
|
43388
|
+
const projects = await deps.projects();
|
|
43389
|
+
if (!projects) throw new Error("run rerun: the Hub project registry is unreadable; refusing to rerun on a repo this command cannot prove registered");
|
|
43390
|
+
const key = registryRepoKey(repo);
|
|
43391
|
+
if (!projects.some((p) => (p.repos ?? []).some((r) => typeof r === "string" && registryRepoKey(qualifyRegistryRepo(r)) === key))) {
|
|
43392
|
+
throw new Error(`run rerun: ${repo} is not a registered org repo; App writes are limited to repos in the Hub registry`);
|
|
43393
|
+
}
|
|
43394
|
+
const mode = failed2 ? "failed" : "all";
|
|
43395
|
+
let httpStatus;
|
|
43396
|
+
try {
|
|
43397
|
+
httpStatus = await deps.post(`repos/${repo}/actions/runs/${runId}/${failed2 ? "rerun-failed-jobs" : "rerun"}`);
|
|
43398
|
+
} catch (error) {
|
|
43399
|
+
const e = error;
|
|
43400
|
+
const detail = String(e.stderr ?? error);
|
|
43401
|
+
const code = /\bHTTP(?:\/[\d.]+)? (\d{3})\b/.exec(`${detail} ${e.stdout ?? ""}`)?.[1];
|
|
43402
|
+
if (code === "403") throw new Error(`run rerun: GitHub App denied (HTTP 403) on ${repo}; actions:write permission is required; no personal-token fallback`);
|
|
43403
|
+
if (code === "404") throw new Error(`run rerun: run ${runId} not found on ${repo} (HTTP 404), or the App cannot see that repo`);
|
|
43404
|
+
if (code === "409" || code === "422") throw new Error(`run rerun: run ${runId} is not rerunnable (HTTP ${code}); it may still be in progress, or be past GitHub's rerun window`);
|
|
43405
|
+
throw new Error(`run rerun: ${detail}`);
|
|
43406
|
+
}
|
|
43407
|
+
return { ok: true, repo, runId, mode, httpStatus, credential: "app_installation", status: RUN_RERUN_STATUS };
|
|
43408
|
+
}
|
|
43409
|
+
function appRunPost(writeToken, exec3 = execFileP) {
|
|
43410
|
+
let token;
|
|
43411
|
+
return async (path2) => {
|
|
43412
|
+
token ??= await writeToken();
|
|
43413
|
+
const { stdout } = await exec3("gh", ["api", "--include", "--method", "POST", path2], {
|
|
43414
|
+
timeout: 2e4,
|
|
43415
|
+
env: { ...process.env, GH_TOKEN: token, MMI_GH_POOL: "app" }
|
|
43416
|
+
});
|
|
43417
|
+
return Number(/^HTTP\/[\d.]+ (\d{3})/.exec(stdout)?.[1] ?? 0);
|
|
43418
|
+
};
|
|
43419
|
+
}
|
|
43420
|
+
function registerRunRerun(run, writeToken, projects) {
|
|
43421
|
+
run.command("rerun <id>").description("rerun one workflow run on the org App (actions:write), registered repos only; --failed reruns only the failed jobs; prints a receipt").requiredOption("--repo <owner/repo>", "registered repository that owns the run").option("--failed", "rerun only the failed jobs (POST .../rerun-failed-jobs)").option("--json", "machine-readable receipt").action(async (id, options) => {
|
|
43422
|
+
let receipt;
|
|
43423
|
+
try {
|
|
43424
|
+
receipt = await rerunWorkflowRun(options.repo, id, { projects, post: appRunPost(writeToken) }, options.failed === true);
|
|
43425
|
+
} catch (error) {
|
|
43426
|
+
return fail(error.message);
|
|
43427
|
+
}
|
|
43428
|
+
if (options.json) console.log(JSON.stringify(receipt));
|
|
43429
|
+
else console.log(`run rerun: ${receipt.repo} run ${receipt.runId} \u2014 ${receipt.mode === "failed" ? "failed jobs" : "all jobs"} rerun requested (HTTP ${receipt.httpStatus}, credential: ${receipt.credential})`);
|
|
43430
|
+
});
|
|
43431
|
+
}
|
|
43369
43432
|
|
|
43370
43433
|
// src/board-commands.ts
|
|
43371
43434
|
init_cli_shared();
|
|
@@ -69965,7 +70028,7 @@ registerPreAction.call(program2, "preAction", async (_thisCommand, actionCommand
|
|
|
69965
70028
|
appActorCommand = commandPath4;
|
|
69966
70029
|
setAuditCommand(commandPath4);
|
|
69967
70030
|
if (commandPath4 !== "whoami diagnose-hub") emitCliCallTelemetry(commandPath4);
|
|
69968
|
-
if (commandPath4 === "ci cancel-orphans" || commandPath4 === "run cancel") return;
|
|
70031
|
+
if (commandPath4 === "ci cancel-orphans" || commandPath4 === "run cancel" || commandPath4 === "run rerun") return;
|
|
69969
70032
|
try {
|
|
69970
70033
|
await activateAppActor(commandPath4, process.env, () => APP_WRITE_COMMANDS.has(commandPath4) ? mintCommandWriteToken(appActorDeps(), commandPath4) : mintInstallationToken(appActorDeps()));
|
|
69971
70034
|
} catch (e) {
|
|
@@ -70800,9 +70863,12 @@ ci.command("audit").description("read-only fleet scan: gate workflow, ruleset co
|
|
|
70800
70863
|
});
|
|
70801
70864
|
registerCiChecksWait(ci);
|
|
70802
70865
|
registerCancelOrphans(ci, async () => (await mintCommandWriteToken(appActorDeps(), "ci cancel-orphans")).token);
|
|
70803
|
-
|
|
70804
|
-
|
|
70805
|
-
|
|
70866
|
+
var runRoot = program2.command("run").description("bounded workflow-run writes \u2014 `run cancel <id>` and `run rerun <id> [--failed]`, both on the org App actions:write profile");
|
|
70867
|
+
registerRunCancel(runRoot, async () => activeAppToken() ?? (await mintCommandWriteToken(appActorDeps(), "run cancel")).token);
|
|
70868
|
+
registerRunRerun(
|
|
70869
|
+
runRoot,
|
|
70870
|
+
async () => activeAppToken() ?? (await mintCommandWriteToken(appActorDeps(), "run rerun")).token,
|
|
70871
|
+
async () => fetchProjectsList(registryClientDeps(await loadConfig()))
|
|
70806
70872
|
);
|
|
70807
70873
|
ci.command("reconcile").description("audit + optionally apply merge settings and product ruleset activation (master-admin)").option("--json", "machine-readable output").option("--repo <owner/repo>", "reconcile one repo instead of the full registry").option("--apply", "PATCH merge settings + activate product ruleset when missing (master role required); activation is skipped while the repo's gate has never passed (#3694)").option("--park-ruleset", "stop the product ruleset enforcing without deleting it \u2014 keeps its required contexts (master role required)").action(async (o) => {
|
|
70808
70874
|
if (o.apply && o.parkRuleset) {
|
package/cli/package.json
CHANGED