@mutmutco/cli 4.1.4 → 4.1.6
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 +177 -20
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -8220,6 +8220,7 @@ function createDocsIndexDeps(repoRoot2) {
|
|
|
8220
8220
|
|
|
8221
8221
|
// src/gate-budget.ts
|
|
8222
8222
|
var BLESSED_RUN_WITH_BUDGET_SHA = "ea2cf8710949dec53566c29836e29cd7515a4e23";
|
|
8223
|
+
var BLESSED_RUNNER_GATE_SHA = "dfe45da73f05190fb721563a1411e0bcd47093f4";
|
|
8223
8224
|
var REMOTE_USE = /^mutmutco\/MMI-Hub\/\.github\/actions\/run-with-budget@(\S+)$/;
|
|
8224
8225
|
var LOCAL_USE = "./.github/actions/run-with-budget";
|
|
8225
8226
|
var FULL_SHA = /^[0-9a-f]{40}$/;
|
|
@@ -8668,7 +8669,8 @@ function gateSeedVars(cls, releaseTrack, runtime = "node", requiredCheckBranches
|
|
|
8668
8669
|
GATE_PY_VERSION: DEFAULT_GATE_PY_VERSION,
|
|
8669
8670
|
GATE_MAX_SECONDS: DEFAULT_GATE_MAX_SECONDS,
|
|
8670
8671
|
// The pin is the CLI's blessed SHA, not an operator knob — one central place to bump (#3178).
|
|
8671
|
-
GATE_BUDGET_SHA: BLESSED_RUN_WITH_BUDGET_SHA
|
|
8672
|
+
GATE_BUDGET_SHA: BLESSED_RUN_WITH_BUDGET_SHA,
|
|
8673
|
+
GATE_RUNNER_SHA: BLESSED_RUNNER_GATE_SHA
|
|
8672
8674
|
};
|
|
8673
8675
|
const track = releaseTrack ?? (cls === "content" ? "trunk" : "full");
|
|
8674
8676
|
const trackBranches = track === "trunk" ? ["main"] : track === "direct" ? ["development", "main"] : ["development", "rc", "main"];
|
|
@@ -9034,6 +9036,25 @@ function parseVerifyBroker(stdout) {
|
|
|
9034
9036
|
return out;
|
|
9035
9037
|
}
|
|
9036
9038
|
|
|
9039
|
+
// src/release-auxiliary-workflows.ts
|
|
9040
|
+
var AUXILIARY_RELEASE_WORKFLOW_NAMES = /* @__PURE__ */ new Set([
|
|
9041
|
+
"Wake Merv on hub release",
|
|
9042
|
+
"Wake Merv on learning issues"
|
|
9043
|
+
]);
|
|
9044
|
+
var AUXILIARY_RELEASE_CHECK_CONTEXTS = /* @__PURE__ */ new Set([
|
|
9045
|
+
...AUXILIARY_RELEASE_WORKFLOW_NAMES,
|
|
9046
|
+
"wake-merv"
|
|
9047
|
+
]);
|
|
9048
|
+
function isAuxiliaryReleaseWorkflowRun(row) {
|
|
9049
|
+
return AUXILIARY_RELEASE_WORKFLOW_NAMES.has(row.workflowName ?? "");
|
|
9050
|
+
}
|
|
9051
|
+
function isReleaseShaDeployEnumerationCandidate(row, nonDeployEvents) {
|
|
9052
|
+
if (nonDeployEvents.has(row.event ?? "")) return false;
|
|
9053
|
+
if (isAuxiliaryReleaseWorkflowRun(row)) return false;
|
|
9054
|
+
if (row.event === "release") return false;
|
|
9055
|
+
return true;
|
|
9056
|
+
}
|
|
9057
|
+
|
|
9037
9058
|
// src/train-apply.ts
|
|
9038
9059
|
var import_node_fs15 = require("node:fs");
|
|
9039
9060
|
var import_promises2 = require("node:fs/promises");
|
|
@@ -13131,10 +13152,10 @@ var rollout_plan_default = {
|
|
|
13131
13152
|
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)."
|
|
13132
13153
|
},
|
|
13133
13154
|
baseline: {
|
|
13134
|
-
version: "4.1.
|
|
13135
|
-
tag: "v4.1.
|
|
13136
|
-
commit: "
|
|
13137
|
-
npm: "@mutmutco/cli@4.1.
|
|
13155
|
+
version: "4.1.6",
|
|
13156
|
+
tag: "v4.1.6",
|
|
13157
|
+
commit: "45c61a1dd6f6",
|
|
13158
|
+
npm: "@mutmutco/cli@4.1.6"
|
|
13138
13159
|
},
|
|
13139
13160
|
exitCriterion: "fleet-n-of-n",
|
|
13140
13161
|
hubOnlyShortcut: "forbidden",
|
|
@@ -13151,14 +13172,14 @@ var rollout_plan_default = {
|
|
|
13151
13172
|
repo: "mutmutco/mmi-hub",
|
|
13152
13173
|
role: "canary",
|
|
13153
13174
|
schedule: "train",
|
|
13154
|
-
v3Target: "v4.1.
|
|
13175
|
+
v3Target: "v4.1.6"
|
|
13155
13176
|
}
|
|
13156
13177
|
],
|
|
13157
13178
|
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.",
|
|
13158
13179
|
rollback: {
|
|
13159
13180
|
independent: true,
|
|
13160
|
-
mechanism: "npm dist-tag latest -> 4.1.
|
|
13161
|
-
v3Target: "v4.1.
|
|
13181
|
+
mechanism: "npm dist-tag latest -> 4.1.6 and redeploy the Hub Lambda from tag v4.1.6 (45c61a1dd6f6); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
13182
|
+
v3Target: "v4.1.6 (@mutmutco/cli@4.1.6, tag commit 45c61a1dd6f6 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
13162
13183
|
}
|
|
13163
13184
|
},
|
|
13164
13185
|
{
|
|
@@ -16702,7 +16723,7 @@ async function discoverShaWorkflowRuns(deps, repo, headSha, seenRunIds) {
|
|
|
16702
16723
|
if (rows.length >= SHA_ENUM_LIMIT) extra.push({ workflow: `${marker} truncated`, conclusion: "pending" });
|
|
16703
16724
|
for (const row of rows) {
|
|
16704
16725
|
if (typeof row.databaseId !== "number" || seenRunIds.has(row.databaseId)) continue;
|
|
16705
|
-
if (
|
|
16726
|
+
if (!isReleaseShaDeployEnumerationCandidate(row, NON_DEPLOY_EVENTS)) continue;
|
|
16706
16727
|
extra.push({
|
|
16707
16728
|
workflow: row.workflowName ?? `run:${row.databaseId}`,
|
|
16708
16729
|
runId: row.databaseId,
|
|
@@ -17080,6 +17101,68 @@ async function runFoldStage(deps, startBranch, preFold, resumeCommand, fn) {
|
|
|
17080
17101
|
throw await recoverFailedFold(deps, e, startBranch, preFold.mainSha, resumeCommand);
|
|
17081
17102
|
}
|
|
17082
17103
|
}
|
|
17104
|
+
var GATE_NODE_BUNDLED_NPM = {
|
|
17105
|
+
"24.19.0": "11.17.0"
|
|
17106
|
+
};
|
|
17107
|
+
function parseGateNodeVersionPins(workflowBody) {
|
|
17108
|
+
if (!/runner-node-toolchain/.test(workflowBody)) return [];
|
|
17109
|
+
const pins = [];
|
|
17110
|
+
for (const match of workflowBody.matchAll(/^\s*node-version:\s*['"]?([^'"\s#]+)/gm)) {
|
|
17111
|
+
pins.push(match[1].replace(/^['"]|['"]$/g, ""));
|
|
17112
|
+
}
|
|
17113
|
+
return pins;
|
|
17114
|
+
}
|
|
17115
|
+
function preferGateNodePin(pins) {
|
|
17116
|
+
const exact = pins.filter((pin) => /^\d+\.\d+\.\d+/.test(pin));
|
|
17117
|
+
if (exact.length) return [...exact].sort().at(-1);
|
|
17118
|
+
return pins[0];
|
|
17119
|
+
}
|
|
17120
|
+
function bundledNpmForNodePin(nodePin) {
|
|
17121
|
+
return GATE_NODE_BUNDLED_NPM[nodePin];
|
|
17122
|
+
}
|
|
17123
|
+
function resolveGreenGateNpmFromGateWorkflows(files) {
|
|
17124
|
+
if (!files?.length) return void 0;
|
|
17125
|
+
const pin = preferGateNodePin(files.flatMap((file) => parseGateNodeVersionPins(file.body)));
|
|
17126
|
+
return pin ? bundledNpmForNodePin(pin) : void 0;
|
|
17127
|
+
}
|
|
17128
|
+
function npmMajor(version) {
|
|
17129
|
+
const match = /^(\d+)/.exec(version.trim());
|
|
17130
|
+
return match ? Number(match[1]) : void 0;
|
|
17131
|
+
}
|
|
17132
|
+
function subprocessFailureDetail(e) {
|
|
17133
|
+
if (!(e instanceof Error)) return String(e);
|
|
17134
|
+
const err = e;
|
|
17135
|
+
const parts = [err.message];
|
|
17136
|
+
if (typeof err.stderr === "string" && err.stderr.trim()) parts.push(err.stderr.trim());
|
|
17137
|
+
if (typeof err.stdout === "string" && err.stdout.trim()) parts.push(err.stdout.trim());
|
|
17138
|
+
return parts.join("\n");
|
|
17139
|
+
}
|
|
17140
|
+
function isNpmInternalModuleNotFound(detail) {
|
|
17141
|
+
if (!/(?:MODULE_NOT_FOUND|Cannot find module)/i.test(detail)) return false;
|
|
17142
|
+
return /(?:node_modules\/(?:npm|libnpmpublish|@npmcli)\/|Require stack:[\s\S]*node_modules\/npm\/)/i.test(detail);
|
|
17143
|
+
}
|
|
17144
|
+
function classifyPublishDryRunFailure(opts) {
|
|
17145
|
+
const underlying = subprocessFailureDetail(opts.underlying);
|
|
17146
|
+
const cmd = `npm ${opts.publishArgs.join(" ")}`;
|
|
17147
|
+
if (isNpmInternalModuleNotFound(underlying)) {
|
|
17148
|
+
const gateNpm = opts.gateNpm?.trim();
|
|
17149
|
+
const localNpm = opts.localNpm.trim();
|
|
17150
|
+
if (gateNpm && localNpm && localNpm !== gateNpm) {
|
|
17151
|
+
const localMajor = npmMajor(localNpm);
|
|
17152
|
+
const gateMajor = npmMajor(gateNpm);
|
|
17153
|
+
const majorNote = localMajor !== void 0 && gateMajor !== void 0 && localMajor !== gateMajor ? ` (npm major ${localMajor} locally vs ${gateMajor} on the green gate)` : "";
|
|
17154
|
+
return new Error(
|
|
17155
|
+
`${opts.repo}: pre-tag publish dry run failed inside npm internals (${cmd}) \u2014 local npm ${localNpm} \u2260 green-gate npm ${gateNpm}${majorNote}. This is toolchain corruption / an npm-major mismatch (#5616/#4578), NOT a malformed publish surface. Compare toolchains BEFORE inspecting package contents: align local npm to the green gate (\`npm install -g npm@${gateNpm}\`), then rerun. Underlying error: ${underlying}`
|
|
17156
|
+
);
|
|
17157
|
+
}
|
|
17158
|
+
return new Error(
|
|
17159
|
+
`${opts.repo}: pre-tag publish dry run failed inside npm internals (${cmd}) \u2014 local npm ${localNpm}${gateNpm ? ` (green-gate npm ${gateNpm} when known)` : ""}. This is toolchain corruption, NOT a malformed publish surface (#5616). Compare \`npm -v\` with the green gate log's toolchain-preflight line (#3446) BEFORE inspecting package contents; repair or align the local npm install, then rerun. Underlying error: ${underlying}`
|
|
17160
|
+
);
|
|
17161
|
+
}
|
|
17162
|
+
return new Error(
|
|
17163
|
+
`${opts.repo}: pre-tag publish dry run failed for '${opts.publishDir}' (${cmd}) \u2014 refusing to tag a release that would fail to publish (#2753). Fix the publish surface (deleted dir, malformed package.json, missing files), then rerun. Underlying error: ${underlying}`
|
|
17164
|
+
);
|
|
17165
|
+
}
|
|
17083
17166
|
async function verifyPublishDryRun(deps, ctx, meta, deployModel) {
|
|
17084
17167
|
if (!(deployModel === "registry-publish" || meta.publishRequired === true)) return;
|
|
17085
17168
|
const publishDir = typeof meta.publishDir === "string" && meta.publishDir.trim() ? meta.publishDir.trim() : ".";
|
|
@@ -17087,9 +17170,20 @@ async function verifyPublishDryRun(deps, ctx, meta, deployModel) {
|
|
|
17087
17170
|
try {
|
|
17088
17171
|
await deps.run("npm", publishArgs);
|
|
17089
17172
|
} catch (e) {
|
|
17090
|
-
|
|
17091
|
-
|
|
17092
|
-
|
|
17173
|
+
let localNpm = "version-unreadable";
|
|
17174
|
+
try {
|
|
17175
|
+
localNpm = clean2(await deps.run("npm", ["-v"]));
|
|
17176
|
+
} catch {
|
|
17177
|
+
}
|
|
17178
|
+
const gateNpm = resolveGreenGateNpmFromGateWorkflows((deps.readGateWorkflows ?? readLocalGateWorkflows)());
|
|
17179
|
+
throw classifyPublishDryRunFailure({
|
|
17180
|
+
repo: ctx.repo,
|
|
17181
|
+
publishDir,
|
|
17182
|
+
publishArgs,
|
|
17183
|
+
underlying: e,
|
|
17184
|
+
localNpm,
|
|
17185
|
+
gateNpm
|
|
17186
|
+
});
|
|
17093
17187
|
}
|
|
17094
17188
|
}
|
|
17095
17189
|
var TRUE_MERGE_GATE_BRANCH_PREFIX = "train/check/";
|
|
@@ -26287,17 +26381,28 @@ async function gcRepoIndexCloud(deps) {
|
|
|
26287
26381
|
{ attempts: 1, timeoutMs, sleep: deps.retrySleep }
|
|
26288
26382
|
);
|
|
26289
26383
|
const body = await res.json().catch(() => ({}));
|
|
26290
|
-
if (!res.ok)
|
|
26384
|
+
if (!res.ok) {
|
|
26385
|
+
const detail = typeof body.error === "string" ? body.error : `gc HTTP ${res.status}`;
|
|
26386
|
+
return { ok: false, error: detail };
|
|
26387
|
+
}
|
|
26388
|
+
if (body.ok === false) {
|
|
26389
|
+
return { ok: false, error: typeof body.error === "string" ? body.error : "repo-index gc failed" };
|
|
26390
|
+
}
|
|
26291
26391
|
const removed = Array.isArray(body.removed) ? body.removed.filter((repo) => typeof repo === "string") : [];
|
|
26292
26392
|
const kept = Number(body.kept);
|
|
26393
|
+
const pendingRepos = Array.isArray(body.pendingRepos) ? body.pendingRepos.filter((repo) => typeof repo === "string") : void 0;
|
|
26394
|
+
const repoErrors = body.repoErrors && typeof body.repoErrors === "object" && !Array.isArray(body.repoErrors) ? Object.fromEntries(Object.entries(body.repoErrors).filter((entry) => typeof entry[1] === "string")) : void 0;
|
|
26293
26395
|
return {
|
|
26294
26396
|
ok: true,
|
|
26397
|
+
...body.partial === true ? { partial: true } : {},
|
|
26295
26398
|
removed,
|
|
26296
26399
|
kept: Number.isFinite(kept) ? kept : 0,
|
|
26297
26400
|
v4: {
|
|
26298
26401
|
dryRun: body.v4?.dryRun === true,
|
|
26299
26402
|
repos: normalizeGcV4Repos(body.v4?.repos)
|
|
26300
|
-
}
|
|
26403
|
+
},
|
|
26404
|
+
...pendingRepos?.length ? { pendingRepos } : {},
|
|
26405
|
+
...repoErrors && Object.keys(repoErrors).length ? { repoErrors } : {}
|
|
26301
26406
|
};
|
|
26302
26407
|
} catch (e) {
|
|
26303
26408
|
const msg = e.message || String(e);
|
|
@@ -33307,7 +33412,7 @@ function registerBoardCommands(program3) {
|
|
|
33307
33412
|
includeBundleDetails: o.bundleDetails,
|
|
33308
33413
|
includeAllBodies: o.bodies,
|
|
33309
33414
|
allowPartial: o.allowPartial
|
|
33310
|
-
}, { snapshot: registryClientDeps(config) });
|
|
33415
|
+
}, o.direct ? {} : { snapshot: registryClientDeps(config) });
|
|
33311
33416
|
console.log(o.json ? JSON.stringify(report) : renderBoardReport(report));
|
|
33312
33417
|
} catch (e) {
|
|
33313
33418
|
return failGraceful(`board read failed: ${withDiscoverMissDetail(e.message)}`);
|
|
@@ -33317,7 +33422,7 @@ function registerBoardCommands(program3) {
|
|
|
33317
33422
|
return alreadyClaimed ? `Check ${ref}: claimed and In Progress, no live contest - claim would renew the lease (nothing written)` : `Check ${ref}: free - claim would proceed (nothing written)`;
|
|
33318
33423
|
}
|
|
33319
33424
|
const board = program3.command("board").description("read, claim, show, and move Project v2 work items for the current repo");
|
|
33320
|
-
board.command("read", { isDefault: true }).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("--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").addHelpText("after", "\nread is always the authoritative live GitHub Project v2 board (#4926).\n--allow-partial applies to the paginated path and detail reads.\n").action((o) => runBoardRead(o));
|
|
33425
|
+
board.command("read", { isDefault: true }).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").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").action((o) => runBoardRead(o));
|
|
33321
33426
|
withExamples(mutating(
|
|
33322
33427
|
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)").addHelpText("after", "\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").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"),
|
|
33323
33428
|
(_opts, args) => ({ command: "board claim", issues: args[0] ?? [] })
|
|
@@ -33598,12 +33703,13 @@ function derivePollState(buckets) {
|
|
|
33598
33703
|
return anyPending ? "pending" : "success";
|
|
33599
33704
|
}
|
|
33600
33705
|
function partitionByRequired(entries, requiredContexts) {
|
|
33706
|
+
const scoped = entries.filter((entry) => !AUXILIARY_RELEASE_CHECK_CONTEXTS.has(entry.name));
|
|
33601
33707
|
if (!requiredContexts || requiredContexts.size === 0) {
|
|
33602
|
-
return { relevant:
|
|
33708
|
+
return { relevant: scoped.map((e) => e.bucket), ignoredFailures: [] };
|
|
33603
33709
|
}
|
|
33604
33710
|
const relevant = [];
|
|
33605
33711
|
const ignoredFailures = [];
|
|
33606
|
-
for (const entry of
|
|
33712
|
+
for (const entry of scoped) {
|
|
33607
33713
|
if (requiredContexts.has(entry.name)) {
|
|
33608
33714
|
relevant.push(entry.bucket);
|
|
33609
33715
|
} else if (entry.bucket === "fail") {
|
|
@@ -33709,8 +33815,8 @@ async function fetchHeadCheckEntries(headSha, repo, gh) {
|
|
|
33709
33815
|
]);
|
|
33710
33816
|
const statuses = parseNdjsonLines(statusesOut);
|
|
33711
33817
|
return [
|
|
33712
|
-
...runs.map((run) => ({ name: run.name ?? `check-run ${run.id ?? "unknown"}`, bucket: classifyCheckRun(run) })),
|
|
33713
|
-
...statuses.map((s) => ({ name: s.context ?? "unknown-status", bucket: classifyCommitStatus(s.state) }))
|
|
33818
|
+
...runs.filter((run) => !AUXILIARY_RELEASE_CHECK_CONTEXTS.has(run.name ?? "")).map((run) => ({ name: run.name ?? `check-run ${run.id ?? "unknown"}`, bucket: classifyCheckRun(run) })),
|
|
33819
|
+
...statuses.filter((s) => !AUXILIARY_RELEASE_CHECK_CONTEXTS.has(s.context ?? "")).map((s) => ({ name: s.context ?? "unknown-status", bucket: classifyCommitStatus(s.state) }))
|
|
33714
33820
|
];
|
|
33715
33821
|
}
|
|
33716
33822
|
async function pollRestPrChecks(prNumber, repo, gh = defaultGhApi, requiredContexts) {
|
|
@@ -35328,6 +35434,7 @@ Next command: ${report.nextCommand}`);
|
|
|
35328
35434
|
// src/explain-command.ts
|
|
35329
35435
|
init_cli_shared();
|
|
35330
35436
|
init_error_codes();
|
|
35437
|
+
init_house_map();
|
|
35331
35438
|
var LOOP_PLAYBOOKS = {
|
|
35332
35439
|
agent: {
|
|
35333
35440
|
title: "Agent",
|
|
@@ -35518,7 +35625,50 @@ function explainCommandManifest(manifest, command, opts = {}) {
|
|
|
35518
35625
|
}
|
|
35519
35626
|
};
|
|
35520
35627
|
}
|
|
35628
|
+
function houseEntryAsChild(entry, house) {
|
|
35629
|
+
return {
|
|
35630
|
+
name: entry.path.split(" ").pop() ?? entry.path,
|
|
35631
|
+
path: entry.canonical,
|
|
35632
|
+
flat_path: entry.path,
|
|
35633
|
+
house,
|
|
35634
|
+
canonical: entry.canonical,
|
|
35635
|
+
...entry.description ? { description: entry.description } : {},
|
|
35636
|
+
arguments: [],
|
|
35637
|
+
options: [],
|
|
35638
|
+
subcommands: [],
|
|
35639
|
+
category: "core",
|
|
35640
|
+
discovery: "primary",
|
|
35641
|
+
help_group: "Plan and work",
|
|
35642
|
+
module_owner: "unclassified",
|
|
35643
|
+
consumer: "unclassified"
|
|
35644
|
+
};
|
|
35645
|
+
}
|
|
35646
|
+
function houseRootAsParent(manifest, house) {
|
|
35647
|
+
const subcommands = house.commands.map(
|
|
35648
|
+
(entry) => findCommandInManifest(manifest, entry.canonical) ?? houseEntryAsChild(entry, house.root)
|
|
35649
|
+
);
|
|
35650
|
+
return {
|
|
35651
|
+
name: house.root,
|
|
35652
|
+
path: house.root,
|
|
35653
|
+
flat_path: house.root,
|
|
35654
|
+
house: house.root,
|
|
35655
|
+
canonical: house.root,
|
|
35656
|
+
description: HOUSE_QUESTIONS[house.root],
|
|
35657
|
+
arguments: [],
|
|
35658
|
+
options: [],
|
|
35659
|
+
subcommands,
|
|
35660
|
+
category: "core",
|
|
35661
|
+
discovery: "primary",
|
|
35662
|
+
help_group: "Plan and work",
|
|
35663
|
+
module_owner: "unclassified",
|
|
35664
|
+
consumer: "unclassified"
|
|
35665
|
+
};
|
|
35666
|
+
}
|
|
35521
35667
|
function findCommandInManifest(manifest, commandPath3) {
|
|
35668
|
+
if (isHouseRoot(commandPath3)) {
|
|
35669
|
+
const house = manifest.houses.find((entry) => entry.root === commandPath3);
|
|
35670
|
+
return house ? houseRootAsParent(manifest, house) : void 0;
|
|
35671
|
+
}
|
|
35522
35672
|
const visit = (command) => {
|
|
35523
35673
|
if (command.path === commandPath3 || command.flat_path === commandPath3) return command;
|
|
35524
35674
|
for (const child2 of command.subcommands) {
|
|
@@ -40592,6 +40742,13 @@ repoIndex.command("gc").description("remove v4 cloud authority material for repo
|
|
|
40592
40742
|
console.log(
|
|
40593
40743
|
`repo-index: gc tombstoned ${res.removed.length} orphan authorit${res.removed.length === 1 ? "y" : "ies"}, removed ${artifactsRemoved} artifact(s); kept ${res.kept} authorit${res.kept === 1 ? "y" : "ies"}, ${artifactsKept} artifact(s)`
|
|
40594
40744
|
);
|
|
40745
|
+
if (res.partial) {
|
|
40746
|
+
const pending = res.pendingRepos?.length ?? 0;
|
|
40747
|
+
const errors = res.repoErrors ? Object.keys(res.repoErrors).length : 0;
|
|
40748
|
+
console.warn(
|
|
40749
|
+
`repo-index: gc partial \u2014 ${pending} repo(s) pending${errors ? `, ${errors} repo error(s)` : ""}; retry gc until pendingRepos is empty`
|
|
40750
|
+
);
|
|
40751
|
+
}
|
|
40595
40752
|
} catch (e) {
|
|
40596
40753
|
return await failGraceful(e.message);
|
|
40597
40754
|
}
|
package/package.json
CHANGED