@mutmutco/claude-plugin 4.6.37 → 4.6.38
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/.claude-plugin/plugin.json +1 -1
- package/cli/dist/main.cjs +83 -44
- package/cli/package.json +1 -1
- package/package.json +1 -1
package/cli/dist/main.cjs
CHANGED
|
@@ -15691,6 +15691,9 @@ var APP_SUBPROCESS_ROUTED_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
15691
15691
|
// #9871: queue enqueue + auto-merge fallback ride ghFilingAppEnv (#9490/#9528; receipt credential app_installation).
|
|
15692
15692
|
"pr land"
|
|
15693
15693
|
]);
|
|
15694
|
+
function ineligibleActorNote(commandPath4) {
|
|
15695
|
+
return commandPath4 === "board move" ? "app actor: board move retains the existing process identity; status-write credential is selected separately and reported in its receipt" : `app actor: note, not a failure \u2014 '${commandPath4}' is personal-only (viewer/@me/authorship), so it ran on the personal token despite ${APP_ACTOR_ENV}=app`;
|
|
15696
|
+
}
|
|
15694
15697
|
async function activateAppActor(commandPath4, env, mint, note = (line) => process.stderr.write(`${line}
|
|
15695
15698
|
`)) {
|
|
15696
15699
|
activeQuotaScope = void 0;
|
|
@@ -15703,7 +15706,7 @@ async function activateAppActor(commandPath4, env, mint, note = (line) => proces
|
|
|
15703
15706
|
if (!APP_ELIGIBLE_COMMANDS.has(commandPath4) && !APP_WRITE_COMMANDS.has(commandPath4)) {
|
|
15704
15707
|
if (requested === "app" && !notedIneligibleCommand && !APP_SUBPROCESS_ROUTED_COMMANDS.has(commandPath4)) {
|
|
15705
15708
|
notedIneligibleCommand = true;
|
|
15706
|
-
note(
|
|
15709
|
+
note(ineligibleActorNote(commandPath4));
|
|
15707
15710
|
}
|
|
15708
15711
|
return "personal";
|
|
15709
15712
|
}
|
|
@@ -22767,23 +22770,8 @@ var BOARD_WRITE_REFUSAL_TYPES = /* @__PURE__ */ new Set(["INSUFFICIENT_SCOPES",
|
|
|
22767
22770
|
async function updateItemSingleSelect(client, projectId, itemId, fieldId, optionId) {
|
|
22768
22771
|
if (process.env.MMI_ACTOR?.trim() === "app") {
|
|
22769
22772
|
const { writeHubBoardField: writeHubBoardField2 } = await Promise.resolve().then(() => (init_board_write(), board_write_exports));
|
|
22770
|
-
|
|
22771
|
-
|
|
22772
|
-
return { credential: "app_installation" };
|
|
22773
|
-
} catch (error) {
|
|
22774
|
-
const refusal = error;
|
|
22775
|
-
if (refusal?.rateLimited !== true || refusal.status !== 503 && refusal.status !== 429) throw error;
|
|
22776
|
-
try {
|
|
22777
|
-
const identity = await githubKeyringTokenRead();
|
|
22778
|
-
if (identity.state !== "ok") throw error;
|
|
22779
|
-
const owner = createGitHubClient({ token: async () => identity.token });
|
|
22780
|
-
await owner.graphql(UPDATE_ITEM_FIELD_MUTATION, { projectId, itemId, fieldId, optionId });
|
|
22781
|
-
} catch {
|
|
22782
|
-
throw error;
|
|
22783
|
-
}
|
|
22784
|
-
process.stderr.write("board write: Hub App allowance exhausted \u2014 wrote with your own GitHub login (#9053)\n");
|
|
22785
|
-
return { credential: "user" };
|
|
22786
|
-
}
|
|
22773
|
+
await writeHubBoardField2({ projectId, itemId, fieldId, optionId });
|
|
22774
|
+
return { credential: "app_installation" };
|
|
22787
22775
|
}
|
|
22788
22776
|
try {
|
|
22789
22777
|
await client.graphql(UPDATE_ITEM_FIELD_MUTATION, { projectId, itemId, fieldId, optionId });
|
|
@@ -22928,19 +22916,20 @@ function renderBoardItem(item) {
|
|
|
22928
22916
|
}
|
|
22929
22917
|
return lines2.join("\n");
|
|
22930
22918
|
}
|
|
22919
|
+
var CACHED_CONFIRM_CLAUSE = " \xB7 items closed/created after the build may still differ \u2014 confirm with --direct";
|
|
22931
22920
|
function renderCachedBoardSource(report) {
|
|
22932
22921
|
if (typeof report.stale?.ageMs === "number") {
|
|
22933
22922
|
const ageSeconds = Math.floor(report.stale.ageMs / 1e3);
|
|
22934
|
-
return `source: cache \xB7 built ${report.builtAt ? `${report.builtAt} (${ageSeconds}s old)` : `${ageSeconds}s ago`} \xB7 stale`;
|
|
22923
|
+
return `source: cache \xB7 built ${report.builtAt ? `${report.builtAt} (${ageSeconds}s old)` : `${ageSeconds}s ago`} \xB7 stale${CACHED_CONFIRM_CLAUSE}`;
|
|
22935
22924
|
}
|
|
22936
22925
|
if (report.builtAt) {
|
|
22937
22926
|
const builtMs = Date.parse(report.builtAt);
|
|
22938
22927
|
if (Number.isFinite(builtMs)) {
|
|
22939
|
-
return `source: cache \xB7 built ${report.builtAt} (${Math.max(0, Math.floor((Date.now() - builtMs) / 1e3))}s old) \xB7 fresh`;
|
|
22928
|
+
return `source: cache \xB7 built ${report.builtAt} (${Math.max(0, Math.floor((Date.now() - builtMs) / 1e3))}s old) \xB7 fresh${CACHED_CONFIRM_CLAUSE}`;
|
|
22940
22929
|
}
|
|
22941
|
-
return `source: cache \xB7 built ${report.builtAt} \xB7 fresh`;
|
|
22930
|
+
return `source: cache \xB7 built ${report.builtAt} \xB7 fresh${CACHED_CONFIRM_CLAUSE}`;
|
|
22942
22931
|
}
|
|
22943
|
-
return
|
|
22932
|
+
return `source: cache${CACHED_CONFIRM_CLAUSE}`;
|
|
22944
22933
|
}
|
|
22945
22934
|
function renderBoardReport(report) {
|
|
22946
22935
|
const lines2 = [`Board \xB7 ${report.project.title} \xB7 @${report.viewer}`, report.source === "cache" ? renderCachedBoardSource(report) : renderBoardSource()];
|
|
@@ -25235,6 +25224,20 @@ function upsertManagedSeedBlock(current, desired, begin, end) {
|
|
|
25235
25224
|
action: "replace"
|
|
25236
25225
|
};
|
|
25237
25226
|
}
|
|
25227
|
+
async function headStrictlyBehind(execGit, head, remoteSha, defaultBranch) {
|
|
25228
|
+
try {
|
|
25229
|
+
await execGit(["fetch", "--no-tags", "--quiet", "origin", `refs/heads/${defaultBranch}`]);
|
|
25230
|
+
} catch (e) {
|
|
25231
|
+
return { superseded: false, unknown: `could not fetch origin/${defaultBranch} to check ancestry (${e.message})` };
|
|
25232
|
+
}
|
|
25233
|
+
try {
|
|
25234
|
+
await execGit(["merge-base", "--is-ancestor", head, remoteSha]);
|
|
25235
|
+
return { superseded: true };
|
|
25236
|
+
} catch (e) {
|
|
25237
|
+
if (e.code === 1) return { superseded: false };
|
|
25238
|
+
return { superseded: false, unknown: `could not prove whether this checkout is an ancestor of origin/${defaultBranch} (${e.message}) \u2014 a shallow checkout cannot prove ancestry, so fetch full history` };
|
|
25239
|
+
}
|
|
25240
|
+
}
|
|
25238
25241
|
async function resolveHubSeedSource(execGit, defaultBranch = "development") {
|
|
25239
25242
|
let status;
|
|
25240
25243
|
try {
|
|
@@ -25262,9 +25265,19 @@ remedy (non-destructive): run this command from a clean dedicated worktree \u201
|
|
|
25262
25265
|
return { ok: false, reason: `\`git ls-remote origin refs/heads/${defaultBranch}\` returned nothing \u2014 refusing to read seeds without a known upstream revision` };
|
|
25263
25266
|
}
|
|
25264
25267
|
if (head !== remoteSha) {
|
|
25268
|
+
const behind = await headStrictlyBehind(execGit, head, remoteSha, defaultBranch);
|
|
25269
|
+
if (behind.superseded) {
|
|
25270
|
+
return {
|
|
25271
|
+
ok: false,
|
|
25272
|
+
superseded: true,
|
|
25273
|
+
head,
|
|
25274
|
+
remoteSha,
|
|
25275
|
+
reason: `this checkout (${head}) is behind origin/${defaultBranch} (${remoteSha}) \u2014 a newer commit overtook this run, whose own queued run owns the tick; seeding nothing and exiting green`
|
|
25276
|
+
};
|
|
25277
|
+
}
|
|
25265
25278
|
return {
|
|
25266
25279
|
ok: false,
|
|
25267
|
-
reason: `this checkout (${head}) is not origin/${defaultBranch} (${remoteSha}) \u2014 fast-forward to origin/${defaultBranch} first; a stale or ahead checkout must not seed the fleet`
|
|
25280
|
+
reason: `this checkout (${head}) is not origin/${defaultBranch} (${remoteSha}) \u2014 fast-forward to origin/${defaultBranch} first; a stale or ahead checkout must not seed the fleet${behind.unknown ? ` (${behind.unknown})` : ""}`
|
|
25268
25281
|
};
|
|
25269
25282
|
}
|
|
25270
25283
|
return { ok: true, sha: head };
|
|
@@ -28392,10 +28405,10 @@ var rollout_plan_default = {
|
|
|
28392
28405
|
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)."
|
|
28393
28406
|
},
|
|
28394
28407
|
baseline: {
|
|
28395
|
-
version: "4.6.
|
|
28396
|
-
tag: "v4.6.
|
|
28397
|
-
commit: "
|
|
28398
|
-
npm: "@mutmutco/cli@4.6.
|
|
28408
|
+
version: "4.6.38",
|
|
28409
|
+
tag: "v4.6.38",
|
|
28410
|
+
commit: "975581f0f6ce",
|
|
28411
|
+
npm: "@mutmutco/cli@4.6.38"
|
|
28399
28412
|
},
|
|
28400
28413
|
exitCriterion: "fleet-n-of-n",
|
|
28401
28414
|
hubOnlyShortcut: "forbidden",
|
|
@@ -28412,14 +28425,14 @@ var rollout_plan_default = {
|
|
|
28412
28425
|
repo: "mutmutco/mmi-hub",
|
|
28413
28426
|
role: "canary",
|
|
28414
28427
|
schedule: "train",
|
|
28415
|
-
v3Target: "v4.6.
|
|
28428
|
+
v3Target: "v4.6.38"
|
|
28416
28429
|
}
|
|
28417
28430
|
],
|
|
28418
28431
|
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.",
|
|
28419
28432
|
rollback: {
|
|
28420
28433
|
independent: true,
|
|
28421
|
-
mechanism: "npm dist-tag latest -> 4.6.
|
|
28422
|
-
v3Target: "v4.6.
|
|
28434
|
+
mechanism: "npm dist-tag latest -> 4.6.38 and redeploy the Hub Lambda from tag v4.6.38 (975581f0f6ce); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
28435
|
+
v3Target: "v4.6.38 (@mutmutco/cli@4.6.38, tag commit 975581f0f6ce \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
28423
28436
|
}
|
|
28424
28437
|
},
|
|
28425
28438
|
{
|
|
@@ -46446,7 +46459,7 @@ function refuseNotClaimable(e, json) {
|
|
|
46446
46459
|
process.exitCode = 1;
|
|
46447
46460
|
return true;
|
|
46448
46461
|
}
|
|
46449
|
-
var BOARD_READ_HELP = "\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\nWhen using Windows PowerShell 5.1, avoid shell redirects: 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\nThe --json report is an OBJECT \u2014 never an array:\n {project, viewer, repo, primary, secondary, items, warnings, partial[, source, builtAt, eventCursor, ...]}\n`primary` is this repo and `secondary` the other repos in scope; each is a bucket object\n {userOwned, claimable, taken, unownedInFlight}\nand each bucket is an array of items. Filter the BUCKET for ownership context:\n mmi-cli oracle board read --json --out .jerv/tmp/board.json\n node -e \"const b=require('./.jerv/tmp/board.json');console.log(b.primary.claimable.length)\"\n\n`items` (#9974) is that same flat row array, already on the full report: {ref,number,title,status,assignees,labels,bucket,claim,openPullRequests}\n node -e \"const b=require('./.jerv/tmp/board.json');for(const i of b.items)console.log(i.number,i.status,i.title)\"\nIt is built from the same flattener as --flat, so `const rows = j.items || j` is now safe on either form.\n\nAdd --flat with --json for that array as the WHOLE output (no project/viewer/warnings envelope):\n(#9595: claim is the parsed mmi-claim evidence object, null when unclaimed; openPullRequests lists the OPEN\n PRs whose closing-issue body links name the item. On the FULL JSON object that list lives at\n `report.pullRequests` \u2014 there is no top-level `openPullRequests`, and #9596 hand-written projections\n that assume one crash on `.filter`.)\n\nNever sniff the envelope \u2014 read `report.items` (or `primary`/`secondary`) by name. `j.items ?? j.rows ?? j`,\n`Object.values(j)` and any generic \"find the list\" wrapper are still guesses: before `items` existed they\nthrew `items is not iterable` before any row was read (#9956), and `j.rows` has never been a key. For a\nnumber|status|claim|title projection across non-Done rows, read --json --flat --out .jerv/tmp/board.json\nand filter that array locally (identical rows to `report.items`):\n mmi-cli oracle board read --json --flat --out .jerv/tmp/board.json\n\nA cached snapshot read renders `source: cache \xB7 built <timestamp> \xB7 fresh|stale` (#9584) and carries\n`builtAt` under --json, so a same-turn re-read of the same builtAt buys nothing new.\n\nUnder --json, parse stdout ONLY and check the exit code first. A failure still prints a\nhuman-readable reason on stderr, so never pipe 2>&1 into a JSON parser (#9151) \u2014 the merged\ntext is not JSON and hides the real board failure.\n\nA zero-byte or empty .jerv/tmp/*.json means the read FAILED \u2014 `Unexpected end of JSON input` is\nthe symptom of shell-redirected empty stdout, not malformed JSON \u2014 re-run with --out (which writes\nthe file only on success) and check the exit code before parsing.\n\nChanging an existing item's Status is a move, never a hand-written `gh api graphql`\n`updateProjectV2ItemFieldValue` mutation with copied `PVT_`/`PVTI_` node ids and a manual Status\nfield-id lookup:\n mmi-cli oracle board move <status> <ref>\n";
|
|
46462
|
+
var BOARD_READ_HELP = "\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\nWhen using Windows PowerShell 5.1, avoid shell redirects: 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\nThe --json report is an OBJECT \u2014 never an array:\n {project, viewer, repo, primary, secondary, items, warnings, partial[, source, builtAt, eventCursor, ...]}\n`primary` is this repo and `secondary` the other repos in scope; each is a bucket object\n {userOwned, claimable, taken, unownedInFlight}\nand each bucket is an array of items. Filter the BUCKET for ownership context:\n mmi-cli oracle board read --json --out .jerv/tmp/board.json\n node -e \"const b=require('./.jerv/tmp/board.json');console.log(b.primary.claimable.length)\"\n\n`items` (#9974) is that same flat row array, already on the full report: {ref,number,title,status,assignees,labels,bucket,claim,openPullRequests}\n node -e \"const b=require('./.jerv/tmp/board.json');for(const i of b.items)console.log(i.number,i.status,i.title)\"\nIt is built from the same flattener as --flat, so `const rows = j.items || j` is now safe on either form.\n\nAdd --flat with --json for that array as the WHOLE output (no project/viewer/warnings envelope):\n(#9595: claim is the parsed mmi-claim evidence object, null when unclaimed; openPullRequests lists the OPEN\n PRs whose closing-issue body links name the item. On the FULL JSON object that list lives at\n `report.pullRequests` \u2014 there is no top-level `openPullRequests`, and #9596 hand-written projections\n that assume one crash on `.filter`.)\n\nNever sniff the envelope \u2014 read `report.items` (or `primary`/`secondary`) by name. `j.items ?? j.rows ?? j`,\n`Object.values(j)` and any generic \"find the list\" wrapper are still guesses: before `items` existed they\nthrew `items is not iterable` before any row was read (#9956), and `j.rows` has never been a key. For a\nnumber|status|claim|title projection across non-Done rows, read --json --flat --out .jerv/tmp/board.json\nand filter that array locally (identical rows to `report.items`):\n mmi-cli oracle board read --json --flat --out .jerv/tmp/board.json\n\nA cached snapshot read renders `source: cache \xB7 built <timestamp> \xB7 fresh|stale` (#9584) and carries\n`builtAt` under --json, so a same-turn re-read of the same builtAt buys nothing new. That age grades the\nCOPY, not its content: the line ends `\xB7 items closed/created after the build may still differ \u2014 confirm\nwith --direct` (#10028), so re-read with --direct before treating a row as still open or still present.\n\nUnder --json, parse stdout ONLY and check the exit code first. A failure still prints a\nhuman-readable reason on stderr, so never pipe 2>&1 into a JSON parser (#9151) \u2014 the merged\ntext is not JSON and hides the real board failure.\n\nA zero-byte or empty .jerv/tmp/*.json means the read FAILED \u2014 `Unexpected end of JSON input` is\nthe symptom of shell-redirected empty stdout, not malformed JSON \u2014 re-run with --out (which writes\nthe file only on success) and check the exit code before parsing.\n\nChanging an existing item's Status is a move, never a hand-written `gh api graphql`\n`updateProjectV2ItemFieldValue` mutation with copied `PVT_`/`PVTI_` node ids and a manual Status\nfield-id lookup:\n mmi-cli oracle board move <status> <ref>\n";
|
|
46450
46463
|
function flattenBoardReport(report) {
|
|
46451
46464
|
const closingByRef = /* @__PURE__ */ new Map();
|
|
46452
46465
|
for (const pull of report.pullRequests ?? []) {
|
|
@@ -51148,6 +51161,13 @@ var declaredProjectAdmins = (meta) => {
|
|
|
51148
51161
|
return Array.isArray(list) ? list.filter((entry) => typeof entry === "string") : [];
|
|
51149
51162
|
};
|
|
51150
51163
|
var execGitForSeedSource = async (args) => (await execFileP("git", args, { timeout: GIT_TIMEOUT_MS })).stdout;
|
|
51164
|
+
function reportSuperseded(prefix, source, json) {
|
|
51165
|
+
const head = source.head.slice(0, 8);
|
|
51166
|
+
const remote = source.remoteSha.slice(0, 8);
|
|
51167
|
+
const summary = `${prefix}: superseded \u2014 this checkout (${head}) is behind origin/development (${remote}); a newer run owns this tick, nothing seeded`;
|
|
51168
|
+
if (json) console.log(JSON.stringify({ status: "superseded", checkoutSha: source.head, remoteSha: source.remoteSha, summary }, null, 2));
|
|
51169
|
+
else console.log(summary);
|
|
51170
|
+
}
|
|
51151
51171
|
async function gateRenderDiff(current, rendered) {
|
|
51152
51172
|
const dir = (0, import_node_fs40.mkdtempSync)((0, import_node_path37.join)((0, import_node_os21.tmpdir)(), "mmi-gate-diff-"));
|
|
51153
51173
|
const before = (0, import_node_path37.join)(dir, "committed-gate.yml");
|
|
@@ -51235,7 +51255,10 @@ async function propagationScope(classes, what) {
|
|
|
51235
51255
|
}
|
|
51236
51256
|
async function propagatePins(apply, json) {
|
|
51237
51257
|
const source = await resolveHubSeedSource(execGitForSeedSource);
|
|
51238
|
-
if (apply && !source.ok)
|
|
51258
|
+
if (apply && !source.ok) {
|
|
51259
|
+
if (source.superseded) return reportSuperseded("bootstrap propagate --pins --apply", source, json);
|
|
51260
|
+
return fail(`bootstrap propagate --pins --apply: ${source.reason}`);
|
|
51261
|
+
}
|
|
51239
51262
|
const { classOf, inClassRepos, canarySlug, sourcePilot } = await propagationScope(null, "hub action pins");
|
|
51240
51263
|
const gh2 = async (args) => execFileP("gh", args, { timeout: 2e4 });
|
|
51241
51264
|
const repos = [];
|
|
@@ -52360,7 +52383,10 @@ LIVE apply to ${repo}:
|
|
|
52360
52383
|
const manifestPath = "skills/bootstrap/seeds/manifest.json";
|
|
52361
52384
|
if (!(0, import_node_fs40.existsSync)(manifestPath)) return fail(`bootstrap propagate: ${manifestPath} not found; run from the MMI-Hub repo root \u2014 the Hub's copies ARE the desired state this tick propagates`);
|
|
52362
52385
|
const seedSource = await resolveHubSeedSource(execGitForSeedSource);
|
|
52363
|
-
if (!seedSource.ok)
|
|
52386
|
+
if (!seedSource.ok) {
|
|
52387
|
+
if (seedSource.superseded) return reportSuperseded("bootstrap propagate", seedSource, o.json);
|
|
52388
|
+
return fail(`bootstrap propagate: ${seedSource.reason}`);
|
|
52389
|
+
}
|
|
52364
52390
|
const manifest = loadBootstrapSeeds((0, import_node_fs40.readFileSync)(manifestPath, "utf8"));
|
|
52365
52391
|
const propagatable = manifest.seeds.filter(isPropagatableSeed);
|
|
52366
52392
|
if (!o.target) {
|
|
@@ -53359,7 +53385,7 @@ async function stageStatus(member, stage, deps) {
|
|
|
53359
53385
|
if (pin) {
|
|
53360
53386
|
served = pin;
|
|
53361
53387
|
source = "registry-pin";
|
|
53362
|
-
} else
|
|
53388
|
+
} else {
|
|
53363
53389
|
try {
|
|
53364
53390
|
const status = await deps.deploy(member.repo, stage);
|
|
53365
53391
|
deployStatus = status;
|
|
@@ -53505,10 +53531,12 @@ async function newestGreen(deps, repo) {
|
|
|
53505
53531
|
async function readSuiteDev(deps) {
|
|
53506
53532
|
const report = await deps.status();
|
|
53507
53533
|
return Promise.all(report.members.map(async (m) => {
|
|
53508
|
-
const
|
|
53534
|
+
const track = deps.releaseTrack ? await deps.releaseTrack(m.repo).catch(() => void 0) : void 0;
|
|
53535
|
+
const stage = track === "single" ? "main" : "dev";
|
|
53536
|
+
const st = m.stages.find((s) => s.stage === stage);
|
|
53509
53537
|
const row = { repo: m.repo, head: st.head, served: st.served };
|
|
53510
|
-
if (st.source === "n/a") return { ...row, state: "converged", note:
|
|
53511
|
-
if (st.lag === false) return { ...row, state: "converged", note:
|
|
53538
|
+
if (st.source === "n/a") return { ...row, state: "converged", note: `no ${stage} stage` };
|
|
53539
|
+
if (st.lag === false) return { ...row, state: "converged", note: `${stage} serves the development head` };
|
|
53512
53540
|
let green;
|
|
53513
53541
|
try {
|
|
53514
53542
|
green = await newestGreen(deps, m.repo);
|
|
@@ -53516,10 +53544,10 @@ async function readSuiteDev(deps) {
|
|
|
53516
53544
|
return { ...row, state: "unknown", note: `checks unreadable (${e.message})` };
|
|
53517
53545
|
}
|
|
53518
53546
|
const last = st.deployStatus?.lastRun;
|
|
53519
|
-
if (st.served === "unknown") return { ...row, green, state: "unknown", note:
|
|
53520
|
-
if (same(st.served, green)) return { ...row, green, state: "converged", note:
|
|
53547
|
+
if (st.served === "unknown") return { ...row, green, state: "unknown", note: `${stage} version unproven (health probe failed or no deploy record)${last?.url ? `; last deploy ${last.conclusion ?? last.status}: ${last.url}` : ""}` };
|
|
53548
|
+
if (same(st.served, green)) return { ...row, green, state: "converged", note: `${stage} serves the newest green SHA; head ${short2(st.head)} is not green yet` };
|
|
53521
53549
|
if (!green) return { ...row, state: "blocked", note: `no green SHA in the last ${WALK} development commits` };
|
|
53522
|
-
if (last?.conclusion === "failure") return { ...row, green, state: "blocked", note: `last
|
|
53550
|
+
if (last?.conclusion === "failure") return { ...row, green, state: "blocked", note: `last ${stage} deploy failed: ${last.url ?? "no run url"}` };
|
|
53523
53551
|
return { ...row, green, state: "lagging", note: `newest green ${short2(green)} not deployed yet; the dev auto-deploy sweep (every 15 min) picks it up` };
|
|
53524
53552
|
}));
|
|
53525
53553
|
}
|
|
@@ -58738,6 +58766,11 @@ ${lines2}`);
|
|
|
58738
58766
|
if (deps.attach) {
|
|
58739
58767
|
const attached = await deps.attach(row.number, rowRepo(spec), rowPriority);
|
|
58740
58768
|
row.onBoard = attached.onBoard;
|
|
58769
|
+
if (attached.prioritySet === false) {
|
|
58770
|
+
row.status = "partial";
|
|
58771
|
+
row.prioritySet = false;
|
|
58772
|
+
row.priorityError = attached.priorityError;
|
|
58773
|
+
}
|
|
58741
58774
|
if (attached.projectItemId) row.projectItemId = attached.projectItemId;
|
|
58742
58775
|
if (attached.boardAttach) {
|
|
58743
58776
|
row.boardAttach = attached.boardAttach;
|
|
@@ -63536,8 +63569,10 @@ async function attachToProject(issueNumber, repo, priority) {
|
|
|
63536
63569
|
await setBoardItemPriority(defaultGitHubClient(), cfg, projectItemId2, priority);
|
|
63537
63570
|
} catch (e) {
|
|
63538
63571
|
const err = e;
|
|
63539
|
-
|
|
63572
|
+
const priorityError = (err.stderr || err.message || String(e)).trim();
|
|
63573
|
+
process.stderr.write(`warning: issue #${issueNumber} board Priority not set: ${priorityError}; issue and board attachment already exist; do not recreate the issue
|
|
63540
63574
|
`);
|
|
63575
|
+
return { projectItemId: projectItemId2, onBoard: true, credential: "app_installation", prioritySet: false, priorityError };
|
|
63541
63576
|
}
|
|
63542
63577
|
}
|
|
63543
63578
|
return { projectItemId: projectItemId2, onBoard: true, credential: "app_installation" };
|
|
@@ -63887,12 +63922,13 @@ function registerCollaborationCommands(program3) {
|
|
|
63887
63922
|
`);
|
|
63888
63923
|
const linkRecovery = parentRecoveryRef !== void 0 && !parent ? `mmi-cli oracle issue link-child ${parentRecoveryRef} ${childRef}` : void 0;
|
|
63889
63924
|
console.log(JSON.stringify({
|
|
63890
|
-
status: boardRecovery || linkRecovery ? "partial" : "created",
|
|
63925
|
+
status: boardRecovery || linkRecovery || attached.prioritySet === false ? "partial" : "created",
|
|
63891
63926
|
...created,
|
|
63892
63927
|
label: issueType,
|
|
63893
63928
|
priority,
|
|
63894
63929
|
projectItemId,
|
|
63895
63930
|
onBoard,
|
|
63931
|
+
...attached.prioritySet === false ? { prioritySet: false, priorityError: attached.priorityError } : {},
|
|
63896
63932
|
...attachCredential ? { credential: attachCredential } : {},
|
|
63897
63933
|
// #5489: partial receipt when the GitHub issue landed but Project v2 attach hit GraphQL quota.
|
|
63898
63934
|
...!onBoard ? {
|
|
@@ -64279,8 +64315,9 @@ ${list}`);
|
|
|
64279
64315
|
}
|
|
64280
64316
|
}
|
|
64281
64317
|
const created = requireGhCreateOk(await ghCreate(args), "skill-lesson");
|
|
64282
|
-
const
|
|
64283
|
-
|
|
64318
|
+
const attached = await attachToProject(created.number, targetRepo2, priority);
|
|
64319
|
+
const { projectItemId, onBoard } = attached;
|
|
64320
|
+
console.log(JSON.stringify({ ...created, projectItemId, onBoard, ...attached.prioritySet === false ? { status: "partial", prioritySet: false, priorityError: attached.priorityError } : {} }));
|
|
64284
64321
|
});
|
|
64285
64322
|
const pr = program3.command("pr").description("pull requests \u2014 reliable create with structured output");
|
|
64286
64323
|
withExamples(pr.command("create").description("create a PR and print {number,url} JSON").option("--title <title>", "PR title").option("--title-file <path|->", "read the PR title from a UTF-8 file, or from stdin with -").option("--body <body>", "PR body (markdown)").option("--body-file <path|->", "read PR body from a UTF-8 file, or from stdin with -").option("--base <branch>", "base branch (defaults to the repo default)").option("--head <branch>", "head branch (defaults to the current branch)").option("--repo <owner/repo>", "target repo (defaults to the current repo)").option("--draft", "open the PR in draft state (#2667)").option("--no-zeroci", "compatibility option; pr create does not mint receipts").option("--json", "machine-readable output (default; accepted for parity)").action(async (o) => {
|
|
@@ -67123,6 +67160,8 @@ function registerSuiteCommands(program3) {
|
|
|
67123
67160
|
const status = suiteStatusDeps(github, registry2);
|
|
67124
67161
|
const deps = {
|
|
67125
67162
|
status: () => readSuiteStatus(status),
|
|
67163
|
+
// #10020: a single-track member's one live stage is `main`; judge that row instead of the dev one.
|
|
67164
|
+
releaseTrack: status.releaseTrack,
|
|
67126
67165
|
commits: async (repo, limit) => (await github.rest("GET", `repos/${repo}/commits?sha=development&per_page=${limit}`) ?? []).map((c) => c.sha),
|
|
67127
67166
|
checkRuns: async (repo, sha) => (await github.rest("GET", `repos/${repo}/commits/${sha}/check-runs?per_page=100`))?.check_runs ?? [],
|
|
67128
67167
|
requiredChecks: async (repo) => {
|
package/cli/package.json
CHANGED