@mutmutco/cli 4.3.33 → 4.3.35
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 +124 -38
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -3679,6 +3679,8 @@ function buildErrorEnvelope(message2, payload) {
|
|
|
3679
3679
|
if (payload.did_you_mean !== void 0) env.did_you_mean = payload.did_you_mean;
|
|
3680
3680
|
if (payload.corrected_command !== void 0) env.corrected_command = payload.corrected_command;
|
|
3681
3681
|
if (payload.current_parent !== void 0) env.current_parent = payload.current_parent;
|
|
3682
|
+
if (payload.issue_ref !== void 0) env.issue_ref = payload.issue_ref;
|
|
3683
|
+
if (payload.board_status !== void 0) env.board_status = payload.board_status;
|
|
3682
3684
|
return env;
|
|
3683
3685
|
}
|
|
3684
3686
|
function formatErrorEnvelope(message2, payload) {
|
|
@@ -10965,6 +10967,21 @@ function boardNotFoundError(ref, board, opts = {}) {
|
|
|
10965
10967
|
const remedy = opts.remedy ?? "if it lives on a different board, pass --repo <owner/repo> for the repo that owns it";
|
|
10966
10968
|
return new Error(`${ref} ${verb} the ${board.owner} #${board.number} board; ${remedy}`);
|
|
10967
10969
|
}
|
|
10970
|
+
var NotClaimableError = class extends Error {
|
|
10971
|
+
/** The board item's status at refusal time, when the refusal was a status verdict. Absent for the
|
|
10972
|
+
* write-access and dependency refusals, whose cause is not the status. */
|
|
10973
|
+
boardStatus;
|
|
10974
|
+
issueRef;
|
|
10975
|
+
constructor(message2, detail) {
|
|
10976
|
+
super(message2);
|
|
10977
|
+
this.name = "NotClaimableError";
|
|
10978
|
+
this.issueRef = detail.ref;
|
|
10979
|
+
if (detail.status !== void 0) this.boardStatus = detail.status;
|
|
10980
|
+
}
|
|
10981
|
+
};
|
|
10982
|
+
function isNotClaimable(e) {
|
|
10983
|
+
return e instanceof NotClaimableError;
|
|
10984
|
+
}
|
|
10968
10985
|
function evaluateClaim(item, login) {
|
|
10969
10986
|
const others = item.assignees.filter((a) => a.toLowerCase() !== login.toLowerCase());
|
|
10970
10987
|
const mine = item.assignees.some((a) => a.toLowerCase() === login.toLowerCase());
|
|
@@ -12217,8 +12234,9 @@ async function claimOneBoardItem(ctx, selector, options) {
|
|
|
12217
12234
|
const flatItem = findBoardItem(ctx.items, selector, { owner: cfg.projectOwner, number: cfg.projectNumber });
|
|
12218
12235
|
const wouldWrite = flatItem.assignees.length === 0 && (flatItem.status === "Todo" || flatItem.status === "In Progress" || flatItem.status === "In Review");
|
|
12219
12236
|
if (wouldWrite && !ctx.writable.has(flatItem.repository.toLowerCase())) {
|
|
12220
|
-
throw new
|
|
12221
|
-
`${flatItem.ref} is not claimable: the token from ${describeTokenSource()} reports no write access to ${flatItem.repository}
|
|
12237
|
+
throw new NotClaimableError(
|
|
12238
|
+
`${flatItem.ref} is not claimable: the token from ${describeTokenSource()} reports no write access to ${flatItem.repository}`,
|
|
12239
|
+
{ ref: flatItem.ref }
|
|
12222
12240
|
);
|
|
12223
12241
|
}
|
|
12224
12242
|
if (flatItem.contentType === "Issue") {
|
|
@@ -12241,7 +12259,10 @@ async function claimOneBoardItem(ctx, selector, options) {
|
|
|
12241
12259
|
retryCommand: `mmi-cli oracle board claim ${flatItem.number}${options.check ? " --check" : ""}`
|
|
12242
12260
|
});
|
|
12243
12261
|
if (gate.blocked) {
|
|
12244
|
-
throw new
|
|
12262
|
+
throw new NotClaimableError(
|
|
12263
|
+
`${flatItem.ref} is not claimable: blocked on open ${gate.openDependencies.join(", ")}`,
|
|
12264
|
+
{ ref: flatItem.ref }
|
|
12265
|
+
);
|
|
12245
12266
|
}
|
|
12246
12267
|
}
|
|
12247
12268
|
const assignee = options.assignee ?? "@me";
|
|
@@ -12261,12 +12282,12 @@ async function claimOneBoardItem(ctx, selector, options) {
|
|
|
12261
12282
|
const heldReceipt = () => previousHolder ? resumeEvidence ? { outcome: "resumed", holder, previousHolder, resumeEvidence } : { outcome: "took-over", holder, previousHolder } : { outcome: "held", holder };
|
|
12262
12283
|
if (flatItem.contentType !== "Issue") throw new Error(`${flatItem.ref} is not an issue`);
|
|
12263
12284
|
const pre = evaluateClaim(flatItem, assignedLogin);
|
|
12264
|
-
if (!pre.ok) throw new
|
|
12285
|
+
if (!pre.ok) throw new NotClaimableError(pre.reason, { ref: flatItem.ref, status: flatItem.status });
|
|
12265
12286
|
let item = flatItem;
|
|
12266
12287
|
const fresh = (await fetchIssueProjectItem(client, cfg, { repo: item.repository, number: item.number })).item;
|
|
12267
12288
|
if (!fresh) throw new Error(`${item.ref} is not on this project board`);
|
|
12268
12289
|
const verdict = evaluateClaim(fresh, assignedLogin);
|
|
12269
|
-
if (!verdict.ok) throw new
|
|
12290
|
+
if (!verdict.ok) throw new NotClaimableError(verdict.reason, { ref: fresh.ref, status: fresh.status });
|
|
12270
12291
|
item = fresh;
|
|
12271
12292
|
const refuseIfContested = async () => {
|
|
12272
12293
|
const contest = await checkLaneContest(client, item, ctx.session, report.viewer);
|
|
@@ -12951,6 +12972,7 @@ async function waitForPrChecks(deps) {
|
|
|
12951
12972
|
|
|
12952
12973
|
// src/bootstrap-ruleset.ts
|
|
12953
12974
|
var PRODUCT_RULESET_NAME = "mmi-product-required-checks";
|
|
12975
|
+
var PRODUCT_GATE_CONTEXT = "gate";
|
|
12954
12976
|
var PRODUCT_RULESET_PATH = ".github/rulesets/mmi-product-required-checks.json";
|
|
12955
12977
|
function reseedProductRulesetStrictness(current, seed) {
|
|
12956
12978
|
const parse = (raw) => {
|
|
@@ -12993,6 +13015,15 @@ function rulesetStrictPolicy(ruleset) {
|
|
|
12993
13015
|
const rules = (ruleset.rules ?? []).filter((rule) => rule.type === "required_status_checks");
|
|
12994
13016
|
return rules.length > 0 && rules.every((rule) => rule.parameters?.strict_required_status_checks_policy === true);
|
|
12995
13017
|
}
|
|
13018
|
+
function committedRequiredContexts(raw) {
|
|
13019
|
+
if (raw == null) return [PRODUCT_GATE_CONTEXT];
|
|
13020
|
+
try {
|
|
13021
|
+
const contexts = rulesetRequiredContexts(stripRulesetComment(raw));
|
|
13022
|
+
return contexts.length ? [...new Set(contexts)] : [PRODUCT_GATE_CONTEXT];
|
|
13023
|
+
} catch {
|
|
13024
|
+
return [PRODUCT_GATE_CONTEXT];
|
|
13025
|
+
}
|
|
13026
|
+
}
|
|
12996
13027
|
function rulesetBranchIncludes(ruleset) {
|
|
12997
13028
|
const raw = ruleset.conditions?.ref_name?.include;
|
|
12998
13029
|
return Array.isArray(raw) ? [...new Set(raw.filter((ref) => typeof ref === "string" && ref.length > 0))].sort((a, b) => a.localeCompare(b)) : [];
|
|
@@ -15586,10 +15617,10 @@ var rollout_plan_default = {
|
|
|
15586
15617
|
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)."
|
|
15587
15618
|
},
|
|
15588
15619
|
baseline: {
|
|
15589
|
-
version: "4.3.
|
|
15590
|
-
tag: "v4.3.
|
|
15591
|
-
commit: "
|
|
15592
|
-
npm: "@mutmutco/cli@4.3.
|
|
15620
|
+
version: "4.3.35",
|
|
15621
|
+
tag: "v4.3.35",
|
|
15622
|
+
commit: "837f809456ec",
|
|
15623
|
+
npm: "@mutmutco/cli@4.3.35"
|
|
15593
15624
|
},
|
|
15594
15625
|
exitCriterion: "fleet-n-of-n",
|
|
15595
15626
|
hubOnlyShortcut: "forbidden",
|
|
@@ -15606,14 +15637,14 @@ var rollout_plan_default = {
|
|
|
15606
15637
|
repo: "mutmutco/mmi-hub",
|
|
15607
15638
|
role: "canary",
|
|
15608
15639
|
schedule: "train",
|
|
15609
|
-
v3Target: "v4.3.
|
|
15640
|
+
v3Target: "v4.3.35"
|
|
15610
15641
|
}
|
|
15611
15642
|
],
|
|
15612
15643
|
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.",
|
|
15613
15644
|
rollback: {
|
|
15614
15645
|
independent: true,
|
|
15615
|
-
mechanism: "npm dist-tag latest -> 4.3.
|
|
15616
|
-
v3Target: "v4.3.
|
|
15646
|
+
mechanism: "npm dist-tag latest -> 4.3.35 and redeploy the Hub Lambda from tag v4.3.35 (837f809456ec); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
15647
|
+
v3Target: "v4.3.35 (@mutmutco/cli@4.3.35, tag commit 837f809456ec \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
15617
15648
|
}
|
|
15618
15649
|
},
|
|
15619
15650
|
{
|
|
@@ -25653,7 +25684,21 @@ function invalidateStatuslineBoardCache() {
|
|
|
25653
25684
|
function refuseRateLimited(e, json) {
|
|
25654
25685
|
if (!isRateLimitedError(e)) return false;
|
|
25655
25686
|
if (json) console.log(JSON.stringify(e.receipt));
|
|
25656
|
-
else console.error(`mmi-cli board claim failed: ${e.receipt.message} \u2014 retry: ${e.receipt.retryCommand}`);
|
|
25687
|
+
else console.error(`mmi-cli oracle board claim failed: ${e.receipt.message} \u2014 retry: ${e.receipt.retryCommand}`);
|
|
25688
|
+
process.exitCode = 1;
|
|
25689
|
+
return true;
|
|
25690
|
+
}
|
|
25691
|
+
function refuseNotClaimable(e, json) {
|
|
25692
|
+
if (!isNotClaimable(e)) return false;
|
|
25693
|
+
const message2 = `oracle board claim failed: ${e.message}`;
|
|
25694
|
+
if (json) {
|
|
25695
|
+
console.log(formatErrorEnvelope(message2, {
|
|
25696
|
+
code: ERROR_CODES.ERR_STATE_CONFLICT,
|
|
25697
|
+
issue_ref: e.issueRef,
|
|
25698
|
+
...e.boardStatus === void 0 ? {} : { board_status: e.boardStatus }
|
|
25699
|
+
}));
|
|
25700
|
+
}
|
|
25701
|
+
console.error(`mmi-cli ${message2}`);
|
|
25657
25702
|
process.exitCode = 1;
|
|
25658
25703
|
return true;
|
|
25659
25704
|
}
|
|
@@ -25720,7 +25765,7 @@ function registerBoardCommands(program3) {
|
|
|
25720
25765
|
board.command("read", { isDefault: true }).alias("list").description("read the board and print user-owned, claimable, and taken items").option("--json", "machine-readable output").option("--repo <owner/repo>", "current repo (defaults to git origin)").option("--direct", "bypass the Hub snapshot and read the live board through direct GitHub GraphQL").option("--bundle-details", "fetch body/comments only for user-owned and claimable issues").option("--bodies", "fetch body/comments for EVERY scoped row, including taken and unowned in-flight ones \u2014 for consumers that scope by Status rather than ownership (#4861); implies --bundle-details and costs one extra read per row").option("--allow-partial", "return partial board results when later page/detail reads fail").option("--out <path>", "write the output to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5802)").addHelpText("after", "\nread is always the authoritative live GitHub Project v2 board (#4926).\n--direct skips the Hub snapshot and uses the existing direct GitHub GraphQL read immediately.\n--allow-partial applies to the paginated path and detail reads.\n\nNever capture the JSON with a shell redirect on Windows: PowerShell 5.1's `> file.json` is Out-File,\nwhich writes UTF-16LE with a BOM, and Node reading it as 'utf8' then fails JSON.parse at position 1\n(#5802). Use --out instead \u2014 the CLI writes the file itself as UTF-8:\n mmi-cli oracle board read --json --out .jerv/tmp/board.json\n").action((o) => runBoardRead(o));
|
|
25721
25766
|
withExamples(mutating(
|
|
25722
25767
|
board.command("claim <issues...>").description("claim issues: assign them and move their Project v2 Status to In Progress \u2014 idempotent, so an item already yours and In Progress succeeds unchanged (one or more refs); the board scan rides the Hub snapshot, same as board read").addHelpText("after", "\nclaim reads the board through the same Hub snapshot leg as `board read` (the App-installation\ncredential, never your personal GraphQL pool); the direct user-auth read is an emergency fallback\nand is named in a Warning line after the verdict (#6162).\n\nevery claim stamps a lane-identity marker comment on the issue (`<!-- mmi-claim: \u2026 -->`,\nsurface/session@host) so other agents can attribute the hold (#3727). The session is the\nhost-exported id when the surface provides one, otherwise a per-process `synth-` fallback \u2014\na claim is never anonymous (#5245). `board show`, doctor and unclaim read the latest marker.\n\nsame-owner resume (#6035): when the prior marker was posted by YOUR login on THIS host and its\nlocal session is verifiably dead (transcript probe), the claim proceeds as a resume without\n--force and names the evidence. A live, foreign-host, or unprobeable prior lane still refuses.\n\nreclaim from In Review (#6339): an In Review item with no holder, or one held by the claiming\nlogin, is claimable \u2014 it moves back to In Progress and the receipt names the status it came from.\nAn In Review item another login holds is refused (ask the holder, or wait for the review to land),\nand Done stays refused. The board status is the authority; no PR state is consulted.\n").option("--json", "machine-readable output").option("--repo <owner/repo>", "current repo for local issue numbers (defaults to git origin)").option("--for <login>", "assign to this login instead of @me \u2014 agent claims on behalf of the master").option("--force", "take an item already claimed by another lane that shows live evidence of active work (#3727)").option("--check", "read-only: run every claim gate and report the verdict, writing nothing \u2014 exits 1 with the same refusal a real claim would raise (#4511)").option("--allow-partial", "return success JSON if assignment succeeds but the status move fails"),
|
|
25723
|
-
(_opts, args) => ({ command: "board claim", issues: args[0] ?? [] })
|
|
25768
|
+
(_opts, args) => ({ command: "oracle board claim", issues: args[0] ?? [] })
|
|
25724
25769
|
).action(async (issueRefs, o) => {
|
|
25725
25770
|
if (issueRefs.length === 1) {
|
|
25726
25771
|
const issueRef = issueRefs[0];
|
|
@@ -25741,7 +25786,8 @@ function registerBoardCommands(program3) {
|
|
|
25741
25786
|
printClaimWarnings(result.warnings);
|
|
25742
25787
|
} catch (e) {
|
|
25743
25788
|
if (refuseRateLimited(e, o.json)) return;
|
|
25744
|
-
|
|
25789
|
+
if (refuseNotClaimable(e, o.json)) return;
|
|
25790
|
+
return failGraceful(`oracle board claim failed: ${e.message}`);
|
|
25745
25791
|
}
|
|
25746
25792
|
return;
|
|
25747
25793
|
}
|
|
@@ -25769,7 +25815,7 @@ function registerBoardCommands(program3) {
|
|
|
25769
25815
|
if (bulk.failed > 0) process.exitCode = 1;
|
|
25770
25816
|
} catch (e) {
|
|
25771
25817
|
if (refuseRateLimited(e, o.json)) return;
|
|
25772
|
-
return failGraceful(`board claim failed: ${e.message}`);
|
|
25818
|
+
return failGraceful(`oracle board claim failed: ${e.message}`);
|
|
25773
25819
|
}
|
|
25774
25820
|
}), [
|
|
25775
25821
|
"mmi-cli oracle board claim 2680",
|
|
@@ -25781,7 +25827,9 @@ function registerBoardCommands(program3) {
|
|
|
25781
25827
|
"Multiple refs are handled as a batch and return per-item results.",
|
|
25782
25828
|
"--check is the live gate read (it calls GitHub); --dry-run only echoes the parsed argv plan.",
|
|
25783
25829
|
// #5552: agents guess `oracle issue claim`; that route does not exist — board claim is the only write.
|
|
25784
|
-
"Never run `oracle issue claim` \u2014 claims are board mutations; only `oracle board claim <ref>` is valid."
|
|
25830
|
+
"Never run `oracle issue claim` \u2014 claims are board mutations; only `oracle board claim <ref>` is valid.",
|
|
25831
|
+
// Flat Wave 0 alias: agents still type `mmi-cli board claim` and treat the refusal as a tool fault.
|
|
25832
|
+
"Never run the flat `board claim` \u2014 that Wave 0 alias was removed; only `mmi-cli oracle board claim <ref>` parses."
|
|
25785
25833
|
]);
|
|
25786
25834
|
board.command("show <issue>").description("print one board item (status, assignees, type, url) with its body and comments").option("--json", "machine-readable output").option("--repo <owner/repo>", "current repo for local issue numbers (defaults to git origin)").option("--allow-partial", "return the item even if its body/comments fetch fails").option("--out <path>", "write the output to this file as UTF-8 (no BOM) instead of stdout \u2014 the shell-free receipt path (#5802)").action(async (issueRef, o) => {
|
|
25787
25835
|
try {
|
|
@@ -26939,7 +26987,6 @@ var requiredBoardSwimlaneField = "Repository";
|
|
|
26939
26987
|
var requiredBoardCardFields = ["Title", "Assignees", "Status", "Labels", "Linked pull requests", "Parent issue", "Sub-issues progress", "Priority"];
|
|
26940
26988
|
var requiredOrgRulesetTypes = ["pull_request", "non_fast_forward", "deletion"];
|
|
26941
26989
|
var requiredHubStatusChecks = ["cli", "infra", "docs"];
|
|
26942
|
-
var requiredProductStatusChecks = ["gate"];
|
|
26943
26990
|
function expectedBranches(repoClass, releaseTrack) {
|
|
26944
26991
|
if (isReleaseTrack(releaseTrack)) return branchesForTrack(releaseTrack);
|
|
26945
26992
|
return repoClass === "content" ? ["main"] : ["development", "rc", "main"];
|
|
@@ -27080,6 +27127,18 @@ function filledDocCheck(label, text, path2) {
|
|
|
27080
27127
|
const unfilled = unfilledDocPlaceholders(text);
|
|
27081
27128
|
return { ok: unfilled.length === 0, label, detail: unfilled.length ? `unfilled: ${unfilled.join(", ")}` : void 0 };
|
|
27082
27129
|
}
|
|
27130
|
+
var NPMRC_PATHS = [".npmrc", "web/.npmrc"];
|
|
27131
|
+
var SCOPED_GITHUB_PACKAGES_RE = /^\s*@[A-Za-z0-9-]+:registry\s*=\s*https:\/\/npm\.pkg\.github\.com/m;
|
|
27132
|
+
var GITHUB_PACKAGES_AUTH_RE = /^\s*\/\/npm\.pkg\.github\.com\/:_authToken\s*=/m;
|
|
27133
|
+
function npmrcGitHubPackagesAuthCheck(path2, text) {
|
|
27134
|
+
if (text === null || !SCOPED_GITHUB_PACKAGES_RE.test(text)) return null;
|
|
27135
|
+
const ok = GITHUB_PACKAGES_AUTH_RE.test(text);
|
|
27136
|
+
return {
|
|
27137
|
+
ok,
|
|
27138
|
+
label: `${path2} authenticates GitHub Packages`,
|
|
27139
|
+
detail: ok ? void 0 : `${path2} points a scope at npm.pkg.github.com with no token line \u2014 add \`//npm.pkg.github.com/:_authToken=\${NODE_AUTH_TOKEN}\` (the value stays in the environment, never in the file) or npm ci 401s outside a setup-node CI job`
|
|
27140
|
+
};
|
|
27141
|
+
}
|
|
27083
27142
|
function isCentralContainerDeployModel(model) {
|
|
27084
27143
|
return model === "tenant-container" || model === "solo-container";
|
|
27085
27144
|
}
|
|
@@ -27188,12 +27247,25 @@ async function verifyBootstrap(repo, repoClass, deps, releaseTrack) {
|
|
|
27188
27247
|
for (const path2 of requiredIssueTemplates) {
|
|
27189
27248
|
checks.push({ ok: await contentExists2(deps, repo, baseBranch, path2), label: `issue template exists: ${path2}` });
|
|
27190
27249
|
}
|
|
27250
|
+
let productContexts = [PRODUCT_GATE_CONTEXT];
|
|
27191
27251
|
if (repo !== HUB_REPO5 && repoClass === "deployable") {
|
|
27192
|
-
|
|
27193
|
-
|
|
27252
|
+
const rulesetRaw = await contentText(deps, repo, baseBranch, requiredProductRulesetRef);
|
|
27253
|
+
productContexts = committedRequiredContexts(rulesetRaw);
|
|
27254
|
+
const workflowCandidates = [.../* @__PURE__ */ new Set([
|
|
27255
|
+
...productContexts.map((context) => `.github/workflows/${context}.yml`),
|
|
27256
|
+
...requiredProductWorkflows
|
|
27257
|
+
])];
|
|
27258
|
+
const presentWorkflows = [];
|
|
27259
|
+
for (const path2 of workflowCandidates) {
|
|
27260
|
+
if (await contentExists2(deps, repo, baseBranch, path2)) presentWorkflows.push(path2);
|
|
27194
27261
|
}
|
|
27195
27262
|
checks.push({
|
|
27196
|
-
ok:
|
|
27263
|
+
ok: presentWorkflows.length > 0,
|
|
27264
|
+
label: "gate workflow exists",
|
|
27265
|
+
detail: presentWorkflows.length ? presentDetail(presentWorkflows) : `none of: ${workflowCandidates.join(", ")}`
|
|
27266
|
+
});
|
|
27267
|
+
checks.push({
|
|
27268
|
+
ok: rulesetRaw !== null,
|
|
27197
27269
|
label: "product required-check ruleset reference exists",
|
|
27198
27270
|
detail: `expected: ${requiredProductRulesetRef} (apply as an active repo ruleset after bootstrap)`
|
|
27199
27271
|
});
|
|
@@ -27211,6 +27283,10 @@ async function verifyBootstrap(repo, repoClass, deps, releaseTrack) {
|
|
|
27211
27283
|
});
|
|
27212
27284
|
}
|
|
27213
27285
|
}
|
|
27286
|
+
for (const path2 of NPMRC_PATHS) {
|
|
27287
|
+
const check = npmrcGitHubPackagesAuthCheck(path2, await contentText(deps, repo, baseBranch, path2));
|
|
27288
|
+
if (check) checks.push(check);
|
|
27289
|
+
}
|
|
27214
27290
|
const portRangeCheck = centralContainerPortRangeCheck(deps.deployModel, deps.projectMeta?.portRange, repo);
|
|
27215
27291
|
if (portRangeCheck) checks.push(portRangeCheck);
|
|
27216
27292
|
checks.push(...deployRowChecks(
|
|
@@ -27424,7 +27500,7 @@ async function verifyBootstrap(repo, repoClass, deps, releaseTrack) {
|
|
|
27424
27500
|
detail: productRuleset?.enforcement !== "active" ? `${PRODUCT_RULESET_NAME} is ${productRuleset?.enforcement ?? "missing"} \u2014 run mmi-cli devops ci reconcile --apply --repo ${repo} once the gate is green` : void 0
|
|
27425
27501
|
});
|
|
27426
27502
|
const statusChecks = rulesetStatusChecks2(rulesets.filter((r) => r.target === "branch" && r.enforcement === "active"));
|
|
27427
|
-
const missing =
|
|
27503
|
+
const missing = productContexts.filter((check) => !statusChecks.has(check));
|
|
27428
27504
|
checks.push({
|
|
27429
27505
|
ok: missing.length === 0,
|
|
27430
27506
|
label: "product required status checks configured",
|
|
@@ -32394,7 +32470,7 @@ var LOOP_PLAYBOOKS = {
|
|
|
32394
32470
|
{ label: "Read the next board item", command: "mmi-cli oracle board read" },
|
|
32395
32471
|
// #5552: claim is a board mutation only — never guess `oracle issue claim`. Ground unknown write
|
|
32396
32472
|
// routes with `mmi-cli commands` / `mmi-cli explain` before invoking them.
|
|
32397
|
-
{ label: "Claim board work (board mutation only \u2014 never `oracle issue claim`; ground unknown write routes via `commands` / `explain` first)", command: "mmi-cli oracle board claim <ref>" },
|
|
32473
|
+
{ label: "Claim board work (board mutation only \u2014 never `oracle issue claim` or the flat `board claim`; ground unknown write routes via `commands` / `explain` first)", command: "mmi-cli oracle board claim <ref>" },
|
|
32398
32474
|
{ label: "Prepare the local workspace through the host surface" },
|
|
32399
32475
|
{ label: "Before broad docs rewrites, follow docs/Guides/doc-ceremony-cut.md" },
|
|
32400
32476
|
{ label: "Apply the repository test policy, then build the touched package", command: "mmi-cli tests policy --base origin/development && npm run build" },
|
|
@@ -32411,7 +32487,7 @@ var LOOP_PLAYBOOKS = {
|
|
|
32411
32487
|
steps: [
|
|
32412
32488
|
{ label: "Orient in the current repository", command: "mmi-cli onboard" },
|
|
32413
32489
|
{ label: "Read the board item", command: "mmi-cli oracle board show <issue-number>" },
|
|
32414
|
-
{ label: "Claim the item (board mutation only \u2014 never `oracle issue claim`)", command: "mmi-cli oracle board claim <issue-number>" },
|
|
32490
|
+
{ label: "Claim the item (board mutation only \u2014 never `oracle issue claim` or the flat `board claim`)", command: "mmi-cli oracle board claim <issue-number>" },
|
|
32415
32491
|
{ label: "Prepare the local workspace through the host surface" },
|
|
32416
32492
|
{ label: "Start a local stage (deployable repos)", command: "mmi-cli stage run --apply" }
|
|
32417
32493
|
]
|
|
@@ -39633,7 +39709,7 @@ function registerCollaborationCommands(program3) {
|
|
|
39633
39709
|
function surfaceWaived() {
|
|
39634
39710
|
return rawFlag("--no-surface");
|
|
39635
39711
|
}
|
|
39636
|
-
const issue = program3.command("issue").description("issues \u2014 create and view with structured JSON (view; show, get and read alias view for board-verb/gh-shaped callers). Claims are board mutations: use `oracle board claim`, never `oracle issue claim`");
|
|
39712
|
+
const issue = program3.command("issue").description("issues \u2014 create and view with structured JSON (view; show, get and read alias view for board-verb/gh-shaped callers). Claims are board mutations: use `oracle board claim`, never `oracle issue claim` or the flat `board claim`");
|
|
39637
39713
|
withExamples(mutating(
|
|
39638
39714
|
issue.command("create").description("create an issue (type \u2014 label) and print {number,url,label} JSON").addOption(new Option("--type <type>", "bug | feature | task (sets the matching label; required unless --batch)").choices([...ISSUE_TYPES])).option("--title <title>", "issue title").option("--title-file <path|->", "read the issue title from a UTF-8 file, or from stdin with -").option("--body <body>", "issue body (markdown)").option("--body-file <path|->", "read issue body from a UTF-8 file. `-` (stdin) needs a heredoc, which the agent inline-body guard denies (#1473/#2125) \u2014 prefer a real path; a title with backticks needs --title-file for the same reason (#3381)").option("--priority <priority>", "urgent | high | medium | low (defaults to medium; sets the board Priority field only \u2014 never a priority:* label, #416)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--label <label...>", "extra label(s) to attach (repeatable; auto-created if missing)").option("--surface <surface>", "issue surface, with or without the surface: prefix (#3789). Required when the target repo runs the one-surface-label board rule; any value satisfies it, so this is not a closed enum").option("--no-surface", "file without a surface label on a repo that requires one \u2014 for a genuinely exempt filing (e.g. a coop proof issue that spans every surface)").option("--parent <ref>", "file as a native sub-issue of this parent (#123, owner/repo#123, or URL)").option("--no-related", "skip the auto related-issues comment"),
|
|
39639
39715
|
// --dry-run/--validate-only plan: resolve the same title source and validate the same type, priority,
|
|
@@ -45488,6 +45564,19 @@ function recoveryPointerFor(path2) {
|
|
|
45488
45564
|
if (runnable === path2) return `run: mmi-cli ${canonicalPathFor(runnable)} \u2026`;
|
|
45489
45565
|
return `'${path2}' is not a registered command \u2014 run \`mmi-cli ${canonicalPathFor(runnable)} --help\` for what lives under it`;
|
|
45490
45566
|
}
|
|
45567
|
+
function refuseHouseShim(typedPath, message2) {
|
|
45568
|
+
if (argvWantsJson3()) {
|
|
45569
|
+
consoleIo.log(
|
|
45570
|
+
formatErrorEnvelope(message2, {
|
|
45571
|
+
code: ERROR_CODES.ERR_UNKNOWN_FLAG,
|
|
45572
|
+
did_you_mean: canonicalPathFor(registeredPathPrefix(typedPath))
|
|
45573
|
+
})
|
|
45574
|
+
);
|
|
45575
|
+
}
|
|
45576
|
+
process.stderr.write(`${message2}
|
|
45577
|
+
`);
|
|
45578
|
+
hardExit(2);
|
|
45579
|
+
}
|
|
45491
45580
|
function resolveHouseShim(argv) {
|
|
45492
45581
|
const houseToken = argv[2];
|
|
45493
45582
|
if (!houseToken) return;
|
|
@@ -45496,11 +45585,10 @@ function resolveHouseShim(argv) {
|
|
|
45496
45585
|
const flatPath = flatTokens.join(" ");
|
|
45497
45586
|
const flatHouse = houseForPath(flatPath);
|
|
45498
45587
|
if (!flatHouse || flatHouse === "core") return;
|
|
45499
|
-
|
|
45500
|
-
|
|
45501
|
-
`
|
|
45588
|
+
refuseHouseShim(
|
|
45589
|
+
flatPath,
|
|
45590
|
+
`mmi-cli: the flat '${flatPath}' alias was removed in ${COMPAT_SHIM_DEATH_WAVE} (#4316) \u2014 ${recoveryPointerFor(flatPath)}`
|
|
45502
45591
|
);
|
|
45503
|
-
hardExit(2);
|
|
45504
45592
|
}
|
|
45505
45593
|
const remainder = argv.slice(3);
|
|
45506
45594
|
const first = remainder[0];
|
|
@@ -45520,17 +45608,15 @@ function resolveHouseShim(argv) {
|
|
|
45520
45608
|
return;
|
|
45521
45609
|
}
|
|
45522
45610
|
if (actual) {
|
|
45523
|
-
|
|
45524
|
-
|
|
45525
|
-
`
|
|
45526
|
-
);
|
|
45527
|
-
} else {
|
|
45528
|
-
process.stderr.write(
|
|
45529
|
-
`mmi-cli ${houseToken}: '${first}' is not a command of house '${houseToken}' \u2014 run \`mmi-cli ${houseToken} --help\` for its commands
|
|
45530
|
-
`
|
|
45611
|
+
refuseHouseShim(
|
|
45612
|
+
lookupPath,
|
|
45613
|
+
`mmi-cli ${houseToken}: '${lookupPath}' lives in house '${actual}' \u2014 ${recoveryPointerFor(lookupPath)}`
|
|
45531
45614
|
);
|
|
45532
45615
|
}
|
|
45533
|
-
|
|
45616
|
+
refuseHouseShim(
|
|
45617
|
+
lookupPath,
|
|
45618
|
+
`mmi-cli ${houseToken}: '${first}' is not a command of house '${houseToken}' \u2014 run \`mmi-cli ${houseToken} --help\` for its commands`
|
|
45619
|
+
);
|
|
45534
45620
|
}
|
|
45535
45621
|
function printHouseRootHelp(house) {
|
|
45536
45622
|
const manifest = buildCommandManifest(program2);
|
package/package.json
CHANGED