@mutmutco/codex-plugin 4.5.100 → 4.5.102
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;
|
|
@@ -6327,6 +6327,24 @@ function parseRateLimitHeaders(out) {
|
|
|
6327
6327
|
};
|
|
6328
6328
|
return { remaining: first("remaining"), limit: first("limit"), resetSec: first("reset") };
|
|
6329
6329
|
}
|
|
6330
|
+
function describeRefusal(out) {
|
|
6331
|
+
const header = (name) => new RegExp(`^${name}:\\s*(.+?)\\s*$`, "im").exec(out)?.[1];
|
|
6332
|
+
let message2 = "";
|
|
6333
|
+
const body = out.slice(out.search(/\r?\n\r?\n/) + 1).trim();
|
|
6334
|
+
try {
|
|
6335
|
+
message2 = String(JSON.parse(body).message ?? "");
|
|
6336
|
+
} catch {
|
|
6337
|
+
message2 = body;
|
|
6338
|
+
}
|
|
6339
|
+
const parts = [
|
|
6340
|
+
["resource", header("x-ratelimit-resource")],
|
|
6341
|
+
["remaining", header("x-ratelimit-remaining")],
|
|
6342
|
+
["reset", header("x-ratelimit-reset")],
|
|
6343
|
+
["retry-after", header("retry-after")]
|
|
6344
|
+
].filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${v}`);
|
|
6345
|
+
const text = message2.replace(/\s+/g, " ").slice(0, 160);
|
|
6346
|
+
return [parts.join(" "), text ? `"${text}"` : ""].filter(Boolean).join(" ") || "no rate-limit headers or message";
|
|
6347
|
+
}
|
|
6330
6348
|
var etagCache = /* @__PURE__ */ new Map();
|
|
6331
6349
|
function appPoolDetail() {
|
|
6332
6350
|
const guard = appPollGuardSnapshot();
|
|
@@ -6360,7 +6378,7 @@ async function defaultGhApi(args) {
|
|
|
6360
6378
|
}
|
|
6361
6379
|
if (source === "app" && appToken && (status === 403 || status === 429)) {
|
|
6362
6380
|
noteAppPollResponse(parseRateLimitHeaders(errOut), true, Date.now());
|
|
6363
|
-
console.warn(`poll credential: App pool refused the read (HTTP ${status}, ${appPoolDetail()}) \u2014 REST poll reads switch to the ambient user token until the App pool resets (#7843)`);
|
|
6381
|
+
console.warn(`poll credential: App pool refused the read (HTTP ${status}, ${appPoolDetail()}; response: ${describeRefusal(errOut)}) \u2014 REST poll reads switch to the ambient user token until the App pool resets (#7843)`);
|
|
6364
6382
|
lastPollSource = "user";
|
|
6365
6383
|
source = "user";
|
|
6366
6384
|
continue;
|
|
@@ -17604,10 +17622,10 @@ var rollout_plan_default = {
|
|
|
17604
17622
|
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
17623
|
},
|
|
17606
17624
|
baseline: {
|
|
17607
|
-
version: "4.5.
|
|
17608
|
-
tag: "v4.5.
|
|
17609
|
-
commit: "
|
|
17610
|
-
npm: "@mutmutco/cli@4.5.
|
|
17625
|
+
version: "4.5.102",
|
|
17626
|
+
tag: "v4.5.102",
|
|
17627
|
+
commit: "69ad9c05771f",
|
|
17628
|
+
npm: "@mutmutco/cli@4.5.102"
|
|
17611
17629
|
},
|
|
17612
17630
|
exitCriterion: "fleet-n-of-n",
|
|
17613
17631
|
hubOnlyShortcut: "forbidden",
|
|
@@ -17624,14 +17642,14 @@ var rollout_plan_default = {
|
|
|
17624
17642
|
repo: "mutmutco/mmi-hub",
|
|
17625
17643
|
role: "canary",
|
|
17626
17644
|
schedule: "train",
|
|
17627
|
-
v3Target: "v4.5.
|
|
17645
|
+
v3Target: "v4.5.102"
|
|
17628
17646
|
}
|
|
17629
17647
|
],
|
|
17630
17648
|
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
17649
|
rollback: {
|
|
17632
17650
|
independent: true,
|
|
17633
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
17634
|
-
v3Target: "v4.5.
|
|
17651
|
+
mechanism: "npm dist-tag latest -> 4.5.102 and redeploy the Hub Lambda from tag v4.5.102 (69ad9c05771f); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
17652
|
+
v3Target: "v4.5.102 (@mutmutco/cli@4.5.102, tag commit 69ad9c05771f \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
17635
17653
|
}
|
|
17636
17654
|
},
|
|
17637
17655
|
{
|
|
@@ -21823,7 +21841,7 @@ async function runTenantControl(deps, options) {
|
|
|
21823
21841
|
const watch = options.watch ?? tenantControlWatches(action);
|
|
21824
21842
|
const base = { command: "tenant-control", repo, stage, action };
|
|
21825
21843
|
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 });
|
|
21844
|
+
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
21845
|
if (!d.ok) {
|
|
21828
21846
|
const transport = d.category === "transport-failed";
|
|
21829
21847
|
return {
|
|
@@ -25676,29 +25694,33 @@ Cut by ${formatSessionIdentity(cutBy)}
|
|
|
25676
25694
|
`;
|
|
25677
25695
|
}
|
|
25678
25696
|
var PLAIN_WORDS_HEADING = "## In plain words";
|
|
25697
|
+
var PLAIN_WORDS_HEADING_TR = "## Sade s\xF6zlerle";
|
|
25679
25698
|
var PLAIN_WORDS_MARKER = "<!-- mmi:big -->";
|
|
25680
|
-
function buildPlainWordsSection(lines2, big) {
|
|
25699
|
+
function buildPlainWordsSection(lines2, big, heading = PLAIN_WORDS_HEADING) {
|
|
25681
25700
|
const [title, ...notes] = lines2;
|
|
25682
|
-
const body = [
|
|
25701
|
+
const body = [heading, title ?? "", ...notes.slice(0, 5).map((n) => `- ${n}`)];
|
|
25683
25702
|
if (big) body.push(PLAIN_WORDS_MARKER);
|
|
25684
25703
|
return body.join("\n");
|
|
25685
25704
|
}
|
|
25686
25705
|
function noChangePlainWordsLine(suiteTag) {
|
|
25687
|
-
return `No changes to this module in this release; ships with the MM-Work suite ${suiteTag}
|
|
25706
|
+
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
25707
|
}
|
|
25689
25708
|
function upsertPlainWordsSection(body, section) {
|
|
25690
|
-
const lines2 = body.split(/\r?\n/);
|
|
25691
|
-
const at = lines2.findIndex((l) => l.trim() === PLAIN_WORDS_HEADING);
|
|
25692
25709
|
let rest = body;
|
|
25693
|
-
|
|
25694
|
-
|
|
25695
|
-
|
|
25696
|
-
|
|
25697
|
-
|
|
25698
|
-
|
|
25710
|
+
for (const heading of [PLAIN_WORDS_HEADING, PLAIN_WORDS_HEADING_TR]) {
|
|
25711
|
+
const lines2 = rest.split(/\r?\n/);
|
|
25712
|
+
let stripping = false;
|
|
25713
|
+
let found = false;
|
|
25714
|
+
const kept = lines2.filter((line) => {
|
|
25715
|
+
if (line.trim() === heading) {
|
|
25716
|
+
stripping = true;
|
|
25717
|
+
found = true;
|
|
25718
|
+
return false;
|
|
25699
25719
|
}
|
|
25700
|
-
|
|
25701
|
-
|
|
25720
|
+
if (line.trim().startsWith("## ")) stripping = false;
|
|
25721
|
+
return !stripping;
|
|
25722
|
+
});
|
|
25723
|
+
if (found) rest = kept.join("\n");
|
|
25702
25724
|
}
|
|
25703
25725
|
const trimmedRest = rest.trim();
|
|
25704
25726
|
return trimmedRest ? `${section}
|
|
@@ -25711,8 +25733,11 @@ function plainWordsSummaryLines(content) {
|
|
|
25711
25733
|
async function writePlainWordsIfSuiteMember(deps, args) {
|
|
25712
25734
|
if (args.meta?.suite !== "mm-work") return;
|
|
25713
25735
|
try {
|
|
25714
|
-
const lines2 = args.summaryLines && args.summaryLines.length > 0 ? args.summaryLines : [noChangePlainWordsLine(args.suiteTag
|
|
25715
|
-
const section =
|
|
25736
|
+
const lines2 = args.summaryLines && args.summaryLines.length > 0 ? args.summaryLines : [noChangePlainWordsLine(args.suiteTag)];
|
|
25737
|
+
const section = [
|
|
25738
|
+
buildPlainWordsSection(lines2, args.big === true),
|
|
25739
|
+
...args.summaryLinesTr?.length ? [buildPlainWordsSection(args.summaryLinesTr, false, PLAIN_WORDS_HEADING_TR)] : []
|
|
25740
|
+
].join("\n\n");
|
|
25716
25741
|
const body = clean2(await deps.run("gh", ["release", "view", args.tag, "--repo", args.repo, "--json", "body", "-q", ".body"]));
|
|
25717
25742
|
await deps.run("gh", ["release", "edit", args.tag, "--repo", args.repo, "--notes", upsertPlainWordsSection(body, section)]);
|
|
25718
25743
|
} catch {
|
|
@@ -25721,7 +25746,8 @@ async function writePlainWordsIfSuiteMember(deps, args) {
|
|
|
25721
25746
|
async function writePlainWordsSection(deps, options, repo, meta, tag) {
|
|
25722
25747
|
try {
|
|
25723
25748
|
const summaryLines = options.announceSummaryFile ? plainWordsSummaryLines(await (deps.readFile ?? ((p) => (0, import_promises3.readFile)(p, "utf8")))(options.announceSummaryFile)) : void 0;
|
|
25724
|
-
await
|
|
25749
|
+
const summaryLinesTr = options.announceSummaryFileTr ? plainWordsSummaryLines(await (deps.readFile ?? ((p) => (0, import_promises3.readFile)(p, "utf8")))(options.announceSummaryFileTr)) : void 0;
|
|
25750
|
+
await writePlainWordsIfSuiteMember(deps, { repo, tag, meta, summaryLines, summaryLinesTr, big: options.big, suiteTag: options.suiteTag });
|
|
25725
25751
|
} catch {
|
|
25726
25752
|
}
|
|
25727
25753
|
}
|
|
@@ -46580,8 +46606,11 @@ function trainApplyDeps() {
|
|
|
46580
46606
|
// Hub-App-authority dispatch of the central tenant-control.yml (#1717) — the Hub fires the
|
|
46581
46607
|
// workflow_dispatch with its App token. Never throws for an expected rejection: it returns the dispatch
|
|
46582
46608
|
// outcome so runTenantControl can map a 5xx (transport-failed, retryable) vs a 4xx (rejected) vs ok.
|
|
46583
|
-
|
|
46584
|
-
|
|
46609
|
+
// #7961: forward every SET field rather than re-listing them, so a new option (e.g. `edge`) cannot be
|
|
46610
|
+
// dropped silently. Unset/false fields are omitted: the route rejects e.g. `edge` on a non-logs action.
|
|
46611
|
+
dispatchTenantControl: async (input) => {
|
|
46612
|
+
const payload = Object.fromEntries(Object.entries(input).filter(([, v]) => v != null && v !== "" && v !== false));
|
|
46613
|
+
const res = await tenantControl(payload, registryClientDeps(await loadConfig()));
|
|
46585
46614
|
if (res.ok) return { ok: true };
|
|
46586
46615
|
const body = res.body;
|
|
46587
46616
|
return { ok: false, category: body?.category, error: body?.error ?? res.error };
|
|
@@ -47518,7 +47547,7 @@ function memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles) {
|
|
|
47518
47547
|
return repo === SUITE_REPO ? summaryFile : memberSummaryFiles[repo];
|
|
47519
47548
|
}
|
|
47520
47549
|
var suiteStateDir = (root) => (0, import_node_path43.join)(resolvePrimaryGitDir(root), "mmi-runtime", "suite");
|
|
47521
|
-
function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}) {
|
|
47550
|
+
function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}, summaryFileTr, memberSummaryFilesTr = {}) {
|
|
47522
47551
|
const recordPath = (0, import_node_path43.join)(suiteStateDir(root), "cut.json");
|
|
47523
47552
|
const base = (0, import_node_path43.join)(suiteStateDir(root), "checkouts");
|
|
47524
47553
|
const checkout = async (repo) => {
|
|
@@ -47629,7 +47658,12 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}) {
|
|
|
47629
47658
|
});
|
|
47630
47659
|
const release = async (repo, expected, rcSha, opts) => inTrain(repo, async (deps) => {
|
|
47631
47660
|
await prepareRcCheckout((args) => deps.run("git", args), repo);
|
|
47632
|
-
const plainWords = {
|
|
47661
|
+
const plainWords = {
|
|
47662
|
+
announceSummaryFile: memberAnnounceSummaryFile(repo, summaryFile, memberSummaryFiles),
|
|
47663
|
+
announceSummaryFileTr: memberAnnounceSummaryFile(repo, summaryFileTr, memberSummaryFilesTr),
|
|
47664
|
+
big: opts?.big,
|
|
47665
|
+
suiteTag: opts?.suiteTag
|
|
47666
|
+
};
|
|
47633
47667
|
const current = await tagSha(repo, expected);
|
|
47634
47668
|
if (current) {
|
|
47635
47669
|
await deps.run("git", ["fetch", "origin", "--tags"]);
|
|
@@ -47870,6 +47904,12 @@ function parseMemberSummaryFiles(entries) {
|
|
|
47870
47904
|
}
|
|
47871
47905
|
return memberSummaryFiles;
|
|
47872
47906
|
}
|
|
47907
|
+
function validateSuiteReleaseSummary(path2) {
|
|
47908
|
+
if (!path2) throw new Error("suite release requires --announce-summary-file before promoting any member");
|
|
47909
|
+
const lines2 = (0, import_node_fs44.readFileSync)(path2, "utf8").split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
47910
|
+
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");
|
|
47911
|
+
if (lines2.length < 3 || lines2.length > 6) throw new Error("suite release announcement needs 3\u20136 curated lines before promoting any member");
|
|
47912
|
+
}
|
|
47873
47913
|
function suiteRcDataProdDeps() {
|
|
47874
47914
|
return {
|
|
47875
47915
|
fetch: async (url, init) => {
|
|
@@ -47964,18 +48004,17 @@ function registerSuiteCommands(program3) {
|
|
|
47964
48004
|
return fail(`suite abandon: ${e.message}`);
|
|
47965
48005
|
}
|
|
47966
48006
|
});
|
|
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) => {
|
|
48007
|
+
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
48008
|
try {
|
|
47969
48009
|
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");
|
|
48010
|
+
validateSuiteReleaseSummary(o.announceSummaryFile);
|
|
47973
48011
|
const memberSummaryFiles = parseMemberSummaryFiles(o.memberSummaryFile ?? []);
|
|
48012
|
+
const memberSummaryFilesTr = parseMemberSummaryFiles(o.memberSummaryFileTr ?? []);
|
|
47974
48013
|
const root = await leadRoot();
|
|
47975
48014
|
const unlock = await acquireTrainWriterLock(root, "suite release");
|
|
47976
48015
|
let result;
|
|
47977
48016
|
try {
|
|
47978
|
-
result = await suiteRelease(suiteTrainIo(root, o.announceSummaryFile, memberSummaryFiles), true, o.big === true);
|
|
48017
|
+
result = await suiteRelease(suiteTrainIo(root, o.announceSummaryFile, memberSummaryFiles, o.announceSummaryFileTr, memberSummaryFilesTr), true, o.big === true);
|
|
47979
48018
|
} finally {
|
|
47980
48019
|
await unlock();
|
|
47981
48020
|
}
|
|
@@ -54316,7 +54355,7 @@ async function reportWrite(label, res) {
|
|
|
54316
54355
|
return failGraceful(`${label}: HTTP ${res.status}${detail ? ` \u2014 ${detail}` : ""}`);
|
|
54317
54356
|
}
|
|
54318
54357
|
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) => {
|
|
54358
|
+
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
54359
|
try {
|
|
54321
54360
|
if (o.confirmDataLoss !== void 0 && (action !== "retire" || stage === "rc")) return fail("runtime tenant control: --confirm-data-loss is dev/main retire-only");
|
|
54322
54361
|
if (action === "retire" && (stage === "dev" || stage === "main")) {
|
|
@@ -54329,6 +54368,7 @@ Dry run: pass --confirm-data-loss ${repo}/${stage} to decommission.`);
|
|
|
54329
54368
|
return;
|
|
54330
54369
|
}
|
|
54331
54370
|
}
|
|
54371
|
+
if (o.edge && action !== "logs") return fail("runtime tenant control: --edge is valid only for the logs action");
|
|
54332
54372
|
let lines2;
|
|
54333
54373
|
if (o.lines !== void 0) {
|
|
54334
54374
|
if (action !== "logs") return fail("runtime tenant control: --lines is valid only for the logs action");
|
|
@@ -54345,7 +54385,7 @@ Dry run: pass --confirm-data-loss ${repo}/${stage} to decommission.`);
|
|
|
54345
54385
|
} else if (o.task || o.artifact) {
|
|
54346
54386
|
return fail("runtime tenant control: --task/--artifact are valid only for run-task");
|
|
54347
54387
|
}
|
|
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 });
|
|
54388
|
+
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
54389
|
if (!o.json && action === "verify-secrets" && result.secrets) {
|
|
54350
54390
|
const body = { ok: result.conclusion === "success", secrets: result.secrets, ssmStatus: result.conclusion === "success" ? "Success" : "Failed", raw: result.secretsRaw };
|
|
54351
54391
|
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
|