@mutmutco/cli 4.5.62 → 4.5.63
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 +83 -14
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -8489,6 +8489,22 @@ function shouldWithdrawSurfaceFlag(result) {
|
|
|
8489
8489
|
|
|
8490
8490
|
// src/secrets-transport.ts
|
|
8491
8491
|
init_client_version();
|
|
8492
|
+
|
|
8493
|
+
// ../shared/quota-attribution.ts
|
|
8494
|
+
var ATTRIBUTION_MAX = 120;
|
|
8495
|
+
function sanitizeAttribution(value, max = ATTRIBUTION_MAX) {
|
|
8496
|
+
if (typeof value !== "string" || !Number.isInteger(max) || max < 1) return void 0;
|
|
8497
|
+
const cleaned = value.replace(/[^A-Za-z0-9 ._/@:-]/g, "").replace(/\s+/g, " ").trim().slice(0, max);
|
|
8498
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
8499
|
+
}
|
|
8500
|
+
function attributionFields(attr) {
|
|
8501
|
+
if (!attr) return {};
|
|
8502
|
+
const command = sanitizeAttribution(attr.command);
|
|
8503
|
+
const via = sanitizeAttribution(attr.via);
|
|
8504
|
+
return { ...command ? { for: command } : {}, ...via ? { via } : {} };
|
|
8505
|
+
}
|
|
8506
|
+
|
|
8507
|
+
// src/secrets-transport.ts
|
|
8492
8508
|
var OWNER = "mutmutco";
|
|
8493
8509
|
var SSM_ROOT = "/mmi-future";
|
|
8494
8510
|
var PROJECT_TIER_SEGMENT = "dev";
|
|
@@ -8664,7 +8680,7 @@ async function fetchSecretValue(deps, key, opts, diagnose = false) {
|
|
|
8664
8680
|
const res = await fetchVaultRead(deps, `${deps.apiUrl}/secrets/get`, {
|
|
8665
8681
|
method: "POST",
|
|
8666
8682
|
headers: await deps.headers({ "content-type": "application/json" }),
|
|
8667
|
-
body: JSON.stringify({ repo, key, use: true, ...slug ? { slug } : {} })
|
|
8683
|
+
body: JSON.stringify({ repo, key, use: true, ...slug ? { slug } : {}, ...attributionFields(opts.attribution) })
|
|
8668
8684
|
});
|
|
8669
8685
|
if (!res.ok) {
|
|
8670
8686
|
if (diagnose) {
|
|
@@ -17156,10 +17172,10 @@ var rollout_plan_default = {
|
|
|
17156
17172
|
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)."
|
|
17157
17173
|
},
|
|
17158
17174
|
baseline: {
|
|
17159
|
-
version: "4.5.
|
|
17160
|
-
tag: "v4.5.
|
|
17161
|
-
commit: "
|
|
17162
|
-
npm: "@mutmutco/cli@4.5.
|
|
17175
|
+
version: "4.5.63",
|
|
17176
|
+
tag: "v4.5.63",
|
|
17177
|
+
commit: "89c6b4bfae7e",
|
|
17178
|
+
npm: "@mutmutco/cli@4.5.63"
|
|
17163
17179
|
},
|
|
17164
17180
|
exitCriterion: "fleet-n-of-n",
|
|
17165
17181
|
hubOnlyShortcut: "forbidden",
|
|
@@ -17176,14 +17192,14 @@ var rollout_plan_default = {
|
|
|
17176
17192
|
repo: "mutmutco/mmi-hub",
|
|
17177
17193
|
role: "canary",
|
|
17178
17194
|
schedule: "train",
|
|
17179
|
-
v3Target: "v4.5.
|
|
17195
|
+
v3Target: "v4.5.63"
|
|
17180
17196
|
}
|
|
17181
17197
|
],
|
|
17182
17198
|
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.",
|
|
17183
17199
|
rollback: {
|
|
17184
17200
|
independent: true,
|
|
17185
|
-
mechanism: "npm dist-tag latest -> 4.5.
|
|
17186
|
-
v3Target: "v4.5.
|
|
17201
|
+
mechanism: "npm dist-tag latest -> 4.5.63 and redeploy the Hub Lambda from tag v4.5.63 (89c6b4bfae7e); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
17202
|
+
v3Target: "v4.5.63 (@mutmutco/cli@4.5.63, tag commit 89c6b4bfae7e \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
17187
17203
|
}
|
|
17188
17204
|
},
|
|
17189
17205
|
{
|
|
@@ -35608,6 +35624,16 @@ async function suiteRcand(deps, opts) {
|
|
|
35608
35624
|
];
|
|
35609
35625
|
if (opts.dryRun) return { plan };
|
|
35610
35626
|
let record = readSuiteCut(deps.recordPath);
|
|
35627
|
+
if (record?.leadReleased && record.announcement === "pending") {
|
|
35628
|
+
const reason = await deps.announceSkipReason(record);
|
|
35629
|
+
if (!reason) throw new Error(`the finished cut ${record.leadRcTag} has an unverified announcement (pending); verify whether it was posted, then finish it with suite release --owner-go before a new cut (never post twice)`);
|
|
35630
|
+
record.announcement = "skipped";
|
|
35631
|
+
record.announcementNote = reason;
|
|
35632
|
+
writeSuiteCut(deps.recordPath, record);
|
|
35633
|
+
}
|
|
35634
|
+
if (record?.leadReleased && !record.announcement) {
|
|
35635
|
+
throw new Error(`the cut ${record.leadRcTag} already released the lead but never announced; finish it with suite release --owner-go before a new cut`);
|
|
35636
|
+
}
|
|
35611
35637
|
if ((record?.announcement === "sent" || record?.announcement === "skipped") && record.leadReleased) {
|
|
35612
35638
|
const archive = `${deps.recordPath}.${record.leadRcTag}.json`;
|
|
35613
35639
|
if ((0, import_node_fs29.existsSync)(archive)) throw new Error(`suite cut archive already exists at ${archive}; inspect before a new cut`);
|
|
@@ -35649,6 +35675,17 @@ async function suiteRcand(deps, opts) {
|
|
|
35649
35675
|
writeSuiteCut(deps.recordPath, record);
|
|
35650
35676
|
continue;
|
|
35651
35677
|
}
|
|
35678
|
+
const onHead = [];
|
|
35679
|
+
for (const tag of (await deps.rcTagsAt(member.repo, member.previousRc)).filter((t) => RC_TAG.test(t))) {
|
|
35680
|
+
if (!await deps.tagSha(member.repo, suiteReleaseTag(tag))) onHead.push(tag);
|
|
35681
|
+
}
|
|
35682
|
+
if (onHead.length > 1) throw new Error(`${member.repo}: several unreleased rc tags sit on its rc head (${onHead.join(", ")}); pin the one to reuse before the suite cut`);
|
|
35683
|
+
if (onHead.length === 1) {
|
|
35684
|
+
member.tag = onHead[0];
|
|
35685
|
+
member.sha = member.previousRc;
|
|
35686
|
+
writeSuiteCut(deps.recordPath, record);
|
|
35687
|
+
continue;
|
|
35688
|
+
}
|
|
35652
35689
|
quiet.push(member);
|
|
35653
35690
|
}
|
|
35654
35691
|
if (record.members.every((m) => m.carried || quiet.includes(m))) {
|
|
@@ -44768,6 +44805,16 @@ var GIT_COMMIT_TIMEOUT_MS = 6e4;
|
|
|
44768
44805
|
function trainGitArgs(args) {
|
|
44769
44806
|
return ["-c", "gc.auto=0", "-c", "maintenance.auto=false", ...args];
|
|
44770
44807
|
}
|
|
44808
|
+
async function announceSummaryLineCountRefusal(path2) {
|
|
44809
|
+
let content;
|
|
44810
|
+
try {
|
|
44811
|
+
content = await (0, import_promises9.readFile)(path2, "utf8");
|
|
44812
|
+
} catch (e) {
|
|
44813
|
+
return `release: could not read --announce-summary-file ${path2}: ${e.message} \u2014 see https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#announce-summary-missing`;
|
|
44814
|
+
}
|
|
44815
|
+
const lines2 = summaryFileLines(content);
|
|
44816
|
+
return lines2.length < 3 || lines2.length > 6 ? `release: --announce-summary-file must contain 3-6 non-empty LLM-curated lines (found ${lines2.length}) \u2014 see https://github.com/mutmutco/MMI-Hub/blob/development/docs/Guides/train-troubleshooting.md#announce-summary-missing` : null;
|
|
44817
|
+
}
|
|
44771
44818
|
async function announceSummaryRefusal(path2, isHub = false) {
|
|
44772
44819
|
let lines2;
|
|
44773
44820
|
try {
|
|
@@ -45221,6 +45268,10 @@ function registerTrainOperationsCommands(program3, runProjectInfoSyncCallback) {
|
|
|
45221
45268
|
const retryDeploy = new Option("--retry-deploy", "re-dispatch the FAILED rc deploy of the promoted candidate in the active rcand ledger \u2014 same tag and SHA, never re-cut or re-pushed (#7053)");
|
|
45222
45269
|
trainCmd.addOption(commandName === "rcand" ? retryDeploy : retryDeploy.hideHelp());
|
|
45223
45270
|
trainCmd.option("--repo <owner/repo>", "dry-run plan for a target repo without relying on the current checkout; --apply still uses the current checkout").action(async (o) => {
|
|
45271
|
+
if (commandName === "release" && o.announceSummaryFile) {
|
|
45272
|
+
const refusal = await announceSummaryLineCountRefusal(o.announceSummaryFile);
|
|
45273
|
+
if (refusal) return fail(refusal);
|
|
45274
|
+
}
|
|
45224
45275
|
try {
|
|
45225
45276
|
await requireFreshTrainCli(commandName);
|
|
45226
45277
|
} catch (e) {
|
|
@@ -45693,12 +45744,18 @@ async function withEnv(name, value, fn) {
|
|
|
45693
45744
|
}
|
|
45694
45745
|
}
|
|
45695
45746
|
async function prepareRcCheckout(git3, repo) {
|
|
45696
|
-
|
|
45747
|
+
await prepareLaneCheckout(git3, repo, "rc", "release");
|
|
45748
|
+
}
|
|
45749
|
+
async function prepareDevelopmentCheckout(git3, repo) {
|
|
45750
|
+
await prepareLaneCheckout(git3, repo, "development", "rcand");
|
|
45751
|
+
}
|
|
45752
|
+
async function prepareLaneCheckout(git3, repo, branch, lane) {
|
|
45753
|
+
if ((await git3(["status", "--porcelain"])).trim()) throw new Error(`${repo}: checkout has uncommitted changes; refuse to switch it to ${branch} for ${lane}`);
|
|
45697
45754
|
await git3(["fetch", "origin", "--tags"]);
|
|
45698
|
-
await git3(["switch",
|
|
45699
|
-
await git3(["merge", "--ff-only",
|
|
45700
|
-
const [head, origin] = (await git3(["rev-parse", "HEAD",
|
|
45701
|
-
if (!head || head !== origin) throw new Error(`${repo}: local
|
|
45755
|
+
await git3(["switch", branch]);
|
|
45756
|
+
await git3(["merge", "--ff-only", `origin/${branch}`]);
|
|
45757
|
+
const [head, origin] = (await git3(["rev-parse", "HEAD", `origin/${branch}`])).trim().split(/\s+/);
|
|
45758
|
+
if (!head || head !== origin) throw new Error(`${repo}: local ${branch} ${head?.slice(0, 12)} is not origin/${branch} ${origin?.slice(0, 12)}; stop`);
|
|
45702
45759
|
}
|
|
45703
45760
|
function rcRunCauseFromLog(log) {
|
|
45704
45761
|
const causes = [...new Set([...log.matchAll(/##\[error\](?!Process completed with exit code)([^\r\n]+)/g)].map((m) => m[1].trim()).filter(Boolean))];
|
|
@@ -45775,6 +45832,7 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}) {
|
|
|
45775
45832
|
}
|
|
45776
45833
|
};
|
|
45777
45834
|
const runRcand = async (repo, previousRc, rcWasAbsent) => inTrain(repo, async (deps) => {
|
|
45835
|
+
if (repo !== SUITE_REPO) await prepareDevelopmentCheckout((args) => deps.run("git", args), repo);
|
|
45778
45836
|
await deps.run("git", ["fetch", "origin", "--tags"]);
|
|
45779
45837
|
let rcNow;
|
|
45780
45838
|
try {
|
|
@@ -45924,6 +45982,12 @@ function suiteTrainIo(root, summaryFile, memberSummaryFiles = {}) {
|
|
|
45924
45982
|
}
|
|
45925
45983
|
},
|
|
45926
45984
|
tagSha,
|
|
45985
|
+
rcTagsAt: async (repo, sha) => {
|
|
45986
|
+
if (!/^[0-9a-f]{40}$/i.test(sha)) return [];
|
|
45987
|
+
const target = await checkout(repo);
|
|
45988
|
+
await exec("git", ["fetch", "--quiet", "origin", "--tags"], target, WATCH_TIMEOUT);
|
|
45989
|
+
return (await exec("git", ["tag", "--points-at", sha, "--list", "v*-rc.*"], target)).split("\n").map((t) => t.trim()).filter(Boolean);
|
|
45990
|
+
},
|
|
45927
45991
|
contains: async (repo, ancestor, descendant) => {
|
|
45928
45992
|
const target = await checkout(repo);
|
|
45929
45993
|
await exec("git", ["fetch", "origin", "--tags"], target);
|
|
@@ -51534,9 +51598,13 @@ program2.addHelpText(
|
|
|
51534
51598
|
\`mmi-cli commands\` shows the agentic map; \`mmi-cli <house> --help\` lists one house.
|
|
51535
51599
|
`
|
|
51536
51600
|
);
|
|
51601
|
+
var appActorCommand = "poll";
|
|
51537
51602
|
function appActorDeps() {
|
|
51538
51603
|
return {
|
|
51539
|
-
fetchSecret: async (key) => fetchSecretValue(makeSecretsDeps(await loadConfig()), key, {
|
|
51604
|
+
fetchSecret: async (key) => fetchSecretValue(makeSecretsDeps(await loadConfig()), key, {
|
|
51605
|
+
repo: APP_VAULT_REPO,
|
|
51606
|
+
attribution: { command: appActorCommand, via: formatSessionIdentity(describeSessionIdentity()) }
|
|
51607
|
+
}),
|
|
51540
51608
|
fetch: (url, init) => fetch(url, init)
|
|
51541
51609
|
};
|
|
51542
51610
|
}
|
|
@@ -51544,6 +51612,7 @@ setPollTokenProvider(() => pollTokenOrUndefined(appActorDeps()));
|
|
|
51544
51612
|
var registerPreAction = Reflect.get(program2, ["h", "ook"].join(""));
|
|
51545
51613
|
registerPreAction.call(program2, "preAction", async (_thisCommand, actionCommand) => {
|
|
51546
51614
|
const commandPath3 = commandPathOf(actionCommand);
|
|
51615
|
+
appActorCommand = commandPath3;
|
|
51547
51616
|
emitCliCallTelemetry(commandPath3);
|
|
51548
51617
|
try {
|
|
51549
51618
|
await activateAppActor(commandPath3, process.env, () => mintInstallationToken(appActorDeps()));
|
package/package.json
CHANGED