@mutmutco/codex-plugin 4.5.100 → 4.5.101
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/cli/dist/main.cjs
CHANGED
|
@@ -6043,7 +6043,7 @@ function isRetryableGitHubWaitReadError(e) {
|
|
|
6043
6043
|
const codes = /* @__PURE__ */ new Set();
|
|
6044
6044
|
if (typeof status === "number" && status > 0) codes.add(status);
|
|
6045
6045
|
for (const m of text.matchAll(/\bHTTP\/?\d*(?:\.\d)?\s+(\d{3})\b/g)) codes.add(Number(m[1]));
|
|
6046
|
-
const rateLimited = e?.rateLimited === true || /
|
|
6046
|
+
const rateLimited = e?.rateLimited === true || /rate limit (?:already )?exceeded|RATE_LIMITED|secondary rate|abuse detection/i.test(text);
|
|
6047
6047
|
if ([401, 404, 409, 422].some((c) => codes.has(c))) return false;
|
|
6048
6048
|
if (codes.has(403) && !rateLimited) return false;
|
|
6049
6049
|
if (codes.has(429) || rateLimited) return true;
|
|
@@ -17604,10 +17604,10 @@ var rollout_plan_default = {
|
|
|
17604
17604
|
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)."
|
|
17605
17605
|
},
|
|
17606
17606
|
baseline: {
|
|
17607
|
-
version: "4.5.
|
|
17608
|
-
tag: "v4.5.
|
|
17609
|
-
commit: "
|
|
17610
|
-
npm: "@mutmutco/cli@4.5.
|
|
17607
|
+
version: "4.5.101",
|
|
17608
|
+
tag: "v4.5.101",
|
|
17609
|
+
commit: "a3c82f0f7aa3",
|
|
17610
|
+
npm: "@mutmutco/cli@4.5.101"
|
|
17611
17611
|
},
|
|
17612
17612
|
exitCriterion: "fleet-n-of-n",
|
|
17613
17613
|
hubOnlyShortcut: "forbidden",
|
|
@@ -17624,14 +17624,14 @@ var rollout_plan_default = {
|
|
|
17624
17624
|
repo: "mutmutco/mmi-hub",
|
|
17625
17625
|
role: "canary",
|
|
17626
17626
|
schedule: "train",
|
|
17627
|
-
v3Target: "v4.5.
|
|
17627
|
+
v3Target: "v4.5.101"
|
|
17628
17628
|
}
|
|
17629
17629
|
],
|
|
17630
17630
|
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.",
|
|
17631
17631
|
rollback: {
|
|
17632
17632
|
independent: true,
|
|
17633
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
17634
|
-
v3Target: "v4.5.
|
|
17633
|
+
mechanism: "npm dist-tag latest -> 4.5.101 and redeploy the Hub Lambda from tag v4.5.101 (a3c82f0f7aa3); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
17634
|
+
v3Target: "v4.5.101 (@mutmutco/cli@4.5.101, tag commit a3c82f0f7aa3 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
17635
17635
|
}
|
|
17636
17636
|
},
|
|
17637
17637
|
{
|
|
@@ -21823,7 +21823,7 @@ async function runTenantControl(deps, options) {
|
|
|
21823
21823
|
const watch = options.watch ?? tenantControlWatches(action);
|
|
21824
21824
|
const base = { command: "tenant-control", repo, stage, action };
|
|
21825
21825
|
const since = (deps.now ?? Date.now)();
|
|
21826
|
-
const d = await deps.dispatchTenantControl({ repo, stage, action, lines: options.lines, since: options.logSince, until: options.logUntil, task: options.task, artifact: options.artifact, confirmDataLoss: options.confirmDataLoss });
|
|
21826
|
+
const d = await deps.dispatchTenantControl({ repo, stage, action, lines: options.lines, edge: options.edge, since: options.logSince, until: options.logUntil, task: options.task, artifact: options.artifact, confirmDataLoss: options.confirmDataLoss });
|
|
21827
21827
|
if (!d.ok) {
|
|
21828
21828
|
const transport = d.category === "transport-failed";
|
|
21829
21829
|
return {
|
|
@@ -25676,29 +25676,33 @@ Cut by ${formatSessionIdentity(cutBy)}
|
|
|
25676
25676
|
`;
|
|
25677
25677
|
}
|
|
25678
25678
|
var PLAIN_WORDS_HEADING = "## In plain words";
|
|
25679
|
+
var PLAIN_WORDS_HEADING_TR = "## Sade s\xF6zlerle";
|
|
25679
25680
|
var PLAIN_WORDS_MARKER = "<!-- mmi:big -->";
|
|
25680
|
-
function buildPlainWordsSection(lines2, big) {
|
|
25681
|
+
function buildPlainWordsSection(lines2, big, heading = PLAIN_WORDS_HEADING) {
|
|
25681
25682
|
const [title, ...notes] = lines2;
|
|
25682
|
-
const body = [
|
|
25683
|
+
const body = [heading, title ?? "", ...notes.slice(0, 5).map((n) => `- ${n}`)];
|
|
25683
25684
|
if (big) body.push(PLAIN_WORDS_MARKER);
|
|
25684
25685
|
return body.join("\n");
|
|
25685
25686
|
}
|
|
25686
25687
|
function noChangePlainWordsLine(suiteTag) {
|
|
25687
|
-
return `No changes to this module in this release; ships with the MM-Work suite ${suiteTag}
|
|
25688
|
+
return suiteTag ? `No changes to this module in this release; ships with the MM-Work suite ${suiteTag}.` : "No changes to this module in this release.";
|
|
25688
25689
|
}
|
|
25689
25690
|
function upsertPlainWordsSection(body, section) {
|
|
25690
|
-
const lines2 = body.split(/\r?\n/);
|
|
25691
|
-
const at = lines2.findIndex((l) => l.trim() === PLAIN_WORDS_HEADING);
|
|
25692
25691
|
let rest = body;
|
|
25693
|
-
|
|
25694
|
-
|
|
25695
|
-
|
|
25696
|
-
|
|
25697
|
-
|
|
25698
|
-
|
|
25692
|
+
for (const heading of [PLAIN_WORDS_HEADING, PLAIN_WORDS_HEADING_TR]) {
|
|
25693
|
+
const lines2 = rest.split(/\r?\n/);
|
|
25694
|
+
let stripping = false;
|
|
25695
|
+
let found = false;
|
|
25696
|
+
const kept = lines2.filter((line) => {
|
|
25697
|
+
if (line.trim() === heading) {
|
|
25698
|
+
stripping = true;
|
|
25699
|
+
found = true;
|
|
25700
|
+
return false;
|
|
25699
25701
|
}
|
|
25700
|
-
|
|
25701
|
-
|
|
25702
|
+
if (line.trim().startsWith("## ")) stripping = false;
|
|
25703
|
+
return !stripping;
|
|
25704
|
+
});
|
|
25705
|
+
if (found) rest = kept.join("\n");
|
|
25702
25706
|
}
|
|
25703
25707
|
const trimmedRest = rest.trim();
|
|
25704
25708
|
return trimmedRest ? `${section}
|
|
@@ -25711,8 +25715,11 @@ function plainWordsSummaryLines(content) {
|
|
|
25711
25715
|
async function writePlainWordsIfSuiteMember(deps, args) {
|
|
25712
25716
|
if (args.meta?.suite !== "mm-work") return;
|
|
25713
25717
|
try {
|
|
25714
|
-
const lines2 = args.summaryLines && args.summaryLines.length > 0 ? args.summaryLines : [noChangePlainWordsLine(args.suiteTag
|
|
25715
|
-
const section =
|
|
25718
|
+
const lines2 = args.summaryLines && args.summaryLines.length > 0 ? args.summaryLines : [noChangePlainWordsLine(args.suiteTag)];
|
|
25719
|
+
const section = [
|
|
25720
|
+
buildPlainWordsSection(lines2, args.big === true),
|
|
25721
|
+
...args.summaryLinesTr?.length ? [buildPlainWordsSection(args.summaryLinesTr, false, PLAIN_WORDS_HEADING_TR)] : []
|
|
25722
|
+
].join("\n\n");
|
|
25716
25723
|
const body = clean2(await deps.run("gh", ["release", "view", args.tag, "--repo", args.repo, "--json", "body", "-q", ".body"]));
|
|
25717
25724
|
await deps.run("gh", ["release", "edit", args.tag, "--repo", args.repo, "--notes", upsertPlainWordsSection(body, section)]);
|
|
25718
25725
|
} catch {
|
|
@@ -25721,7 +25728,8 @@ async function writePlainWordsIfSuiteMember(deps, args) {
|
|
|
25721
25728
|
async function writePlainWordsSection(deps, options, repo, meta, tag) {
|
|
25722
25729
|
try {
|
|
25723
25730
|
const summaryLines = options.announceSummaryFile ? plainWordsSummaryLines(await (deps.readFile ?? ((p) => (0, import_promises3.readFile)(p, "utf8")))(options.announceSummaryFile)) : void 0;
|
|
25724
|
-
await
|
|
25731
|
+
const summaryLinesTr = options.announceSummaryFileTr ? plainWordsSummaryLines(await (deps.readFile ?? ((p) => (0, import_promises3.readFile)(p, "utf8")))(options.announceSummaryFileTr)) : void 0;
|
|
25732
|
+
await writePlainWordsIfSuiteMember(deps, { repo, tag, meta, summaryLines, summaryLinesTr, big: options.big, suiteTag: options.suiteTag });
|
|
25725
25733
|
} catch {
|
|
25726
25734
|
}
|
|
25727
25735
|
}
|
|
@@ -47518,7 +47526,7 @@ function memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles) {
|
|
|
47518
47526
|
return repo === SUITE_REPO ? summaryFile : memberSummaryFiles[repo];
|
|
47519
47527
|
}
|
|
47520
47528
|
var suiteStateDir = (root) => (0, import_node_path43.join)(resolvePrimaryGitDir(root), "mmi-runtime", "suite");
|
|
47521
|
-
function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}) {
|
|
47529
|
+
function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr, memberSummaryFilesTr = {}) {
|
|
47522
47530
|
const recordPath = (0, import_node_path43.join)(suiteStateDir(root), "cut.json");
|
|
47523
47531
|
const base = (0, import_node_path43.join)(suiteStateDir(root), "checkouts");
|
|
47524
47532
|
const checkout = async (repo) => {
|
|
@@ -47629,7 +47637,12 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}) {
|
|
|
47629
47637
|
});
|
|
47630
47638
|
const release = async (repo, expected, rcSha, opts) => inTrain(repo, async (deps) => {
|
|
47631
47639
|
await prepareRcCheckout((args) => deps.run("git", args), repo);
|
|
47632
|
-
const plainWords = {
|
|
47640
|
+
const plainWords = {
|
|
47641
|
+
announceSummaryFile: memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles),
|
|
47642
|
+
announceSummaryFileTr: memberAnnounceSummaryFile(repo, summaryFileTr, memberSummaryFilesTr),
|
|
47643
|
+
big: opts?.big,
|
|
47644
|
+
suiteTag: opts?.suiteTag
|
|
47645
|
+
};
|
|
47633
47646
|
const current = await tagSha(repo, expected);
|
|
47634
47647
|
if (current) {
|
|
47635
47648
|
await deps.run("git", ["fetch", "origin", "--tags"]);
|
|
@@ -47870,6 +47883,12 @@ function parseMemberSummaryFiles(entries) {
|
|
|
47870
47883
|
}
|
|
47871
47884
|
return memberSummaryFiles;
|
|
47872
47885
|
}
|
|
47886
|
+
function validateSuiteReleaseSummary(path2) {
|
|
47887
|
+
if (!path2) throw new Error("suite release requires --announce-summary-file before promoting any member");
|
|
47888
|
+
const lines2 = (0, import_node_fs44.readFileSync)(path2, "utf8").split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
47889
|
+
if (lines2[0]?.startsWith("No changes to this module")) throw new Error("suite release requires a real MM-Work title, not the no-change placeholder");
|
|
47890
|
+
if (lines2.length < 3 || lines2.length > 6) throw new Error("suite release announcement needs 3\u20136 curated lines before promoting any member");
|
|
47891
|
+
}
|
|
47873
47892
|
function suiteRcDataProdDeps() {
|
|
47874
47893
|
return {
|
|
47875
47894
|
fetch: async (url, init) => {
|
|
@@ -47964,18 +47983,17 @@ function registerSuiteCommands(program3) {
|
|
|
47964
47983
|
return fail(`suite abandon: ${e.message}`);
|
|
47965
47984
|
}
|
|
47966
47985
|
});
|
|
47967
|
-
suite.command("release").description("verify the cut and unchanged live backends, ship members then MM-Work, announce once").option("--owner-go", "explicit owner approval to release the tested candidate").option("--announce-summary-file <path>", "curated suite announcement, posted once after the train; also this cut's plain-words summary for MM-Work itself").option("--member-summary-file <owner/repo=path>", "repeatable: a member's OWN plain-words summary (#7510) \u2014 never the suite lead's summary reused; a member with no entry still ships, with the coordinator-ruled no-change line", (val, prev = []) => [...prev, val], []).option("--big", "marks MM-Work's own release big for the plain-words section (#7510); a member is never marked big through this flag \u2014 it is big only via the read route's automatic minor/major detection").option("--json", "structured receipt").action(async (o) => {
|
|
47986
|
+
suite.command("release").description("verify the cut and unchanged live backends, ship members then MM-Work, announce once").option("--owner-go", "explicit owner approval to release the tested candidate").option("--announce-summary-file <path>", "curated suite announcement, posted once after the train; also this cut's plain-words summary for MM-Work itself").option("--member-summary-file <owner/repo=path>", "repeatable: a member's OWN plain-words summary (#7510) \u2014 never the suite lead's summary reused; a member with no entry still ships, with the coordinator-ruled no-change line", (val, prev = []) => [...prev, val], []).option("--announce-summary-file-tr <path>", "Turkish plain-words summary for MM-Work itself").option("--member-summary-file-tr <owner/repo=path>", "repeatable: a member's own Turkish plain-words summary", (val, prev = []) => [...prev, val], []).option("--big", "marks MM-Work's own release big for the plain-words section (#7510); a member is never marked big through this flag \u2014 it is big only via the read route's automatic minor/major detection").option("--json", "structured receipt").action(async (o) => {
|
|
47968
47987
|
try {
|
|
47969
47988
|
if (!o.ownerGo) throw new Error("suite release requires --owner-go; nothing was written");
|
|
47970
|
-
|
|
47971
|
-
const lines2 = (0, import_node_fs44.readFileSync)(o.announceSummaryFile, "utf8").split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
47972
|
-
if (lines2.length < 3 || lines2.length > 6) throw new Error("suite release announcement needs 3\u20136 curated lines before promoting any member");
|
|
47989
|
+
validateSuiteReleaseSummary(o.announceSummaryFile);
|
|
47973
47990
|
const memberSummaryFiles = parseMemberSummaryFiles(o.memberSummaryFile ?? []);
|
|
47991
|
+
const memberSummaryFilesTr = parseMemberSummaryFiles(o.memberSummaryFileTr ?? []);
|
|
47974
47992
|
const root = await leadRoot();
|
|
47975
47993
|
const unlock = await acquireTrainWriterLock(root, "suite release");
|
|
47976
47994
|
let result;
|
|
47977
47995
|
try {
|
|
47978
|
-
result = await suiteRelease(suiteTrainIo(root, o.announceSummaryFile, memberSummaryFiles), true, o.big === true);
|
|
47996
|
+
result = await suiteRelease(suiteTrainIo(root, o.announceSummaryFile, memberSummaryFiles, o.announceSummaryFileTr, memberSummaryFilesTr), true, o.big === true);
|
|
47979
47997
|
} finally {
|
|
47980
47998
|
await unlock();
|
|
47981
47999
|
}
|
|
@@ -54316,7 +54334,7 @@ async function reportWrite(label, res) {
|
|
|
54316
54334
|
return failGraceful(`${label}: HTTP ${res.status}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
54317
54335
|
}
|
|
54318
54336
|
var tenant = program2.command("tenant").description("tenant runtime control through Hub authority");
|
|
54319
|
-
tenant.command("control <owner/repo> <stage> <action>").description("bounded tenant control plus value-free vault/broker verification; dev/main retire needs master and exact data-loss confirmation").option("--watch", "block on the dispatched run and report its conclusion (status/retire/verify-secrets/verify-broker/logs watch by default)").option("--lines <n>", "logs only: trailing lines of the tenant service to return (1-2000, default 200)").option("--since <utc>", "logs only: read the journal from this UTC time, e.g. 2026-10-07T13:10Z (includes replaced containers)").option("--until <utc>", "logs only: read the journal up to this UTC time").option("--task <name>", "run-task only: registry-declared task name (never a command)").option("--artifact <id>", "run-task only: opaque id returned by tenant artifact put").option("--confirm-data-loss <owner/repo/stage>", "dev/main retire only: exact target to decommission; without it show the dry-run plan").option("--json", "machine-readable output").action(async (repo, stage, action, o) => {
|
|
54337
|
+
tenant.command("control <owner/repo> <stage> <action>").description("bounded tenant control plus value-free vault/broker verification; dev/main retire needs master and exact data-loss confirmation").option("--watch", "block on the dispatched run and report its conclusion (status/retire/verify-secrets/verify-broker/logs watch by default)").option("--lines <n>", "logs only: trailing lines of the tenant service to return (1-2000, default 200)").option("--since <utc>", "logs only: read the journal from this UTC time, e.g. 2026-10-07T13:10Z (includes replaced containers)").option("--until <utc>", "logs only: read the journal up to this UTC time").option("--edge", "logs only: Caddy journal for this stage\u2019s hosts (default window: last 15 minutes)").option("--task <name>", "run-task only: registry-declared task name (never a command)").option("--artifact <id>", "run-task only: opaque id returned by tenant artifact put").option("--confirm-data-loss <owner/repo/stage>", "dev/main retire only: exact target to decommission; without it show the dry-run plan").option("--json", "machine-readable output").action(async (repo, stage, action, o) => {
|
|
54320
54338
|
try {
|
|
54321
54339
|
if (o.confirmDataLoss !== void 0 && (action !== "retire" || stage === "rc")) return fail("runtime tenant control: --confirm-data-loss is dev/main retire-only");
|
|
54322
54340
|
if (action === "retire" && (stage === "dev" || stage === "main")) {
|
|
@@ -54329,6 +54347,7 @@ Dry run: pass --confirm-data-loss ${repo}/${stage} to decommission.`);
|
|
|
54329
54347
|
return;
|
|
54330
54348
|
}
|
|
54331
54349
|
}
|
|
54350
|
+
if (o.edge && action !== "logs") return fail("runtime tenant control: --edge is valid only for the logs action");
|
|
54332
54351
|
let lines2;
|
|
54333
54352
|
if (o.lines !== void 0) {
|
|
54334
54353
|
if (action !== "logs") return fail("runtime tenant control: --lines is valid only for the logs action");
|
|
@@ -54345,7 +54364,7 @@ Dry run: pass --confirm-data-loss ${repo}/${stage} to decommission.`);
|
|
|
54345
54364
|
} else if (o.task || o.artifact) {
|
|
54346
54365
|
return fail("runtime tenant control: --task/--artifact are valid only for run-task");
|
|
54347
54366
|
}
|
|
54348
|
-
const result = await runTenantControl(trainApplyDeps(), { repo, stage, action, watch: o.watch, lines: lines2, logSince: o.since, logUntil: o.until, task: o.task, artifact: o.artifact, confirmDataLoss: o.confirmDataLoss });
|
|
54367
|
+
const result = await runTenantControl(trainApplyDeps(), { repo, stage, action, watch: o.watch, lines: lines2, edge: o.edge, logSince: o.since, logUntil: o.until, task: o.task, artifact: o.artifact, confirmDataLoss: o.confirmDataLoss });
|
|
54349
54368
|
if (!o.json && action === "verify-secrets" && result.secrets) {
|
|
54350
54369
|
const body = { ok: result.conclusion === "success", secrets: result.secrets, ssmStatus: result.conclusion === "success" ? "Success" : "Failed", raw: result.secretsRaw };
|
|
54351
54370
|
const { lines: lines3, failure } = renderVerifySecrets(body);
|
package/cli/package.json
CHANGED
package/package.json
CHANGED
|
@@ -109,6 +109,7 @@ commit, so build and verify the lines from one pass over that range —
|
|
|
109
109
|
subject, body and changed files — never from subjects, PR titles or memory; a line whose claim is not
|
|
110
110
|
in that output does not go in the file. A Hub summary never mentions a Jerv-side project; the train
|
|
111
111
|
refuses such a line.
|
|
112
|
+
MM-Work suite release also requires a real `--announce-summary-file` title (never `No changes to this module`); optional `--announce-summary-file-tr` and repeatable `--member-summary-file-tr owner/repo=path` add Turkish plain words alongside English member files supplied with `--member-summary-file`.
|
|
112
113
|
|
|
113
114
|
Announcement delivery uses the developer's GitHub-authenticated Hub session. The Hub checks project
|
|
114
115
|
authority, resolves the registered channel, and reads the MMI Future Slack key inside its vault boundary.
|
package/skills/release/SKILL.md
CHANGED
|
@@ -15,6 +15,9 @@ Full-track repos ship exactly what is on `rc` (never `development`): merge `rc
|
|
|
15
15
|
|
|
16
16
|
In the suite lead (MM-Work) a plain rcand, release or hotfix refuses: run `mmi-cli devops suite rcand --owner-go` or `mmi-cli devops suite release --owner-go` instead (a lead-only cut needs `--suite-solo --owner-go`). A suite member cannot run standalone rcand, release or hotfix: cut from the suite lead; only a backward-compatible solo backend release/hotfix with explicit owner approval may pass `--suite-solo --owner-go`, and its MM-Work development pin PR must land before the suite is in sync.
|
|
17
17
|
|
|
18
|
+
Suite release requires `--announce-summary-file <path>` with 3–6 curated lines and refuses before promotion when it is missing or its title starts with `No changes to this module`.
|
|
19
|
+
Use `--member-summary-file <owner/repo=path>` for English member notes, `--announce-summary-file-tr <path>` for MM-Work's Turkish notes and repeatable `--member-summary-file-tr <owner/repo=path>` for Turkish member notes; members without English files keep the no-change line.
|
|
20
|
+
|
|
18
21
|
Read META and name the lane before describing or executing anything:
|
|
19
22
|
|
|
20
23
|
```bash
|