@mutmutco/cli 4.0.2 → 4.0.3
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 +80 -39
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -9155,6 +9155,7 @@ var OWNER2 = "mutmutco";
|
|
|
9155
9155
|
var SSM_ROOT = "/mmi-future";
|
|
9156
9156
|
var PROJECT_TIER_SEGMENT = "dev";
|
|
9157
9157
|
var ORG_INFRA_SLUG = "_org";
|
|
9158
|
+
var JERV_VAULT_POINTER = "Not in the MMI vault? Jerv service, personal API and model-provider credentials live in the separate Jerv AWS Vault \u2014 enumerate: `jerv-cli vault list`; consume keyless: `jerv-cli vault use <KEY> -- <cmd>` (values are never printed).";
|
|
9158
9159
|
var KEY_MAX_PATH_SEGMENTS = 4;
|
|
9159
9160
|
var KEY_RE = new RegExp(`^(?:[a-z0-9][a-z0-9-]*/){0,${KEY_MAX_PATH_SEGMENTS}}[A-Za-z][A-Za-z0-9_]*$`);
|
|
9160
9161
|
function isValidSecretKey(key) {
|
|
@@ -9171,7 +9172,7 @@ function secretParamName(slug, key) {
|
|
|
9171
9172
|
return `${SSM_ROOT}/${slug}/${key}`;
|
|
9172
9173
|
}
|
|
9173
9174
|
function formatSecretList(items) {
|
|
9174
|
-
if (!items.length) return
|
|
9175
|
+
if (!items.length) return `no secrets \u2014 ${JERV_VAULT_POINTER}`;
|
|
9175
9176
|
const width = Math.max(...items.map((i) => i.key.length));
|
|
9176
9177
|
return items.map((i) => {
|
|
9177
9178
|
const head = `${i.canManage ? "*" : " "} ${i.key.padEnd(width)} ${i.tier}`;
|
|
@@ -9362,7 +9363,7 @@ function formatCapabilities(r) {
|
|
|
9362
9363
|
const items = [...r.capabilities ?? []].sort((a, b) => a.scope.localeCompare(b.scope));
|
|
9363
9364
|
if (!items.length) return `${head}
|
|
9364
9365
|
|
|
9365
|
-
no vault credentials visible`;
|
|
9366
|
+
no vault credentials visible \u2014 ${JERV_VAULT_POINTER}`;
|
|
9366
9367
|
const width = Math.max(...items.map((i) => i.scope.length));
|
|
9367
9368
|
const lines = items.map(
|
|
9368
9369
|
(i) => `${i.accessible ? "+" : " "} ${i.scope.padEnd(width)} ${i.tier.padEnd(7)} ${i.grantScope ? `${i.reason} (${i.grantScope})` : i.reason}`
|
|
@@ -9485,7 +9486,8 @@ function resolveNotFoundGuidance(input) {
|
|
|
9485
9486
|
const lines = [
|
|
9486
9487
|
`Secret ${key} was not found at ${tried}, and no key named ${leaf} is visible to you.`,
|
|
9487
9488
|
`Locate it by intent first: \`mmi-cli vault secrets find "<what it is for>"\` \u2014 it returns the exact keyless-use command.`,
|
|
9488
|
-
mnemonic
|
|
9489
|
+
mnemonic,
|
|
9490
|
+
JERV_VAULT_POINTER
|
|
9489
9491
|
];
|
|
9490
9492
|
if (isMaster) {
|
|
9491
9493
|
lines.push("You are master: if it truly does not exist yet, create it with `mmi-cli vault secrets set` rather than requesting a grant from yourself.");
|
|
@@ -9767,6 +9769,7 @@ async function secretsVerify(deps, key, opts) {
|
|
|
9767
9769
|
if (!value) {
|
|
9768
9770
|
deps.err(`${key}: ABSENT or unreachable at this coordinate \u2014 no value could be read`);
|
|
9769
9771
|
deps.err(`Locate a key across every vault you can reach: mmi-cli oracle org access capabilities${opts.repo ? ` --repo ${opts.repo}` : ""}`);
|
|
9772
|
+
deps.err(JERV_VAULT_POINTER);
|
|
9770
9773
|
return false;
|
|
9771
9774
|
}
|
|
9772
9775
|
deps.log(`${key}: PRESENT (${value.length} chars) \u2014 reachability only; no provider verifier is configured for ${secretLeafName(key)}, so the credential itself was not validated`);
|
|
@@ -10422,6 +10425,7 @@ async function fetchSecretForUse(deps, { repo, key, slug }) {
|
|
|
10422
10425
|
// src/report.ts
|
|
10423
10426
|
var HUB_REPO = "mutmutco/MMI-Hub";
|
|
10424
10427
|
var REPORT_LABEL = "report";
|
|
10428
|
+
var LEARNING_LABEL = "learning";
|
|
10425
10429
|
var REPORT_LOOP_KIND = "friction";
|
|
10426
10430
|
var REPORT_SURFACE_WAIVER_REASON = "Hub-only friction filing; attribution repo is footer-only; no honest single surface";
|
|
10427
10431
|
function preflightReportSurface() {
|
|
@@ -10819,10 +10823,10 @@ var rollout_plan_default = {
|
|
|
10819
10823
|
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)."
|
|
10820
10824
|
},
|
|
10821
10825
|
baseline: {
|
|
10822
|
-
version: "4.0.
|
|
10823
|
-
tag: "v4.0.
|
|
10824
|
-
commit: "
|
|
10825
|
-
npm: "@mutmutco/cli@4.0.
|
|
10826
|
+
version: "4.0.3",
|
|
10827
|
+
tag: "v4.0.3",
|
|
10828
|
+
commit: "3a588e3fa3a3",
|
|
10829
|
+
npm: "@mutmutco/cli@4.0.3"
|
|
10826
10830
|
},
|
|
10827
10831
|
exitCriterion: "fleet-n-of-n",
|
|
10828
10832
|
hubOnlyShortcut: "forbidden",
|
|
@@ -10839,14 +10843,14 @@ var rollout_plan_default = {
|
|
|
10839
10843
|
repo: "mutmutco/mmi-hub",
|
|
10840
10844
|
role: "canary",
|
|
10841
10845
|
schedule: "train",
|
|
10842
|
-
v3Target: "v4.0.
|
|
10846
|
+
v3Target: "v4.0.3"
|
|
10843
10847
|
}
|
|
10844
10848
|
],
|
|
10845
10849
|
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.",
|
|
10846
10850
|
rollback: {
|
|
10847
10851
|
independent: true,
|
|
10848
|
-
mechanism: "npm dist-tag latest -> 4.0.
|
|
10849
|
-
v3Target: "v4.0.
|
|
10852
|
+
mechanism: "npm dist-tag latest -> 4.0.3 and redeploy the Hub Lambda from tag v4.0.3 (3a588e3fa3a3); installed clients repair via `mmi-cli doctor`. No other cohort is touched.",
|
|
10853
|
+
v3Target: "v4.0.3 (@mutmutco/cli@4.0.3, tag commit 3a588e3fa3a3 \u2014 last known-good release carrying the repo-index v4-only contract)"
|
|
10850
10854
|
}
|
|
10851
10855
|
},
|
|
10852
10856
|
{
|
|
@@ -17606,6 +17610,7 @@ async function postIssueComment(client, input) {
|
|
|
17606
17610
|
|
|
17607
17611
|
// src/skill-lesson.ts
|
|
17608
17612
|
var SKILL_LESSON_LABEL = "skill-lesson";
|
|
17613
|
+
var SKILL_LESSON_FILE_LABELS = [SKILL_LESSON_LABEL, LEARNING_LABEL];
|
|
17609
17614
|
var SKILL_LESSON_LOOP_KIND = "lesson";
|
|
17610
17615
|
var SKILL_NAMES = ["bootstrap", "browser-automation", "doctor", "epic", "hotfix", "mmi", "onboard", "rcand", "release", "resume", "secrets", "stage"];
|
|
17611
17616
|
function assertSkillName(name) {
|
|
@@ -17638,6 +17643,7 @@ function findDuplicateLesson(source, openLessons) {
|
|
|
17638
17643
|
}
|
|
17639
17644
|
|
|
17640
17645
|
// src/session-identity.ts
|
|
17646
|
+
var import_node_crypto4 = require("node:crypto");
|
|
17641
17647
|
var import_node_os7 = require("node:os");
|
|
17642
17648
|
|
|
17643
17649
|
// src/plugin-guard-io.ts
|
|
@@ -18625,12 +18631,19 @@ async function runPluginHeal(surface = detectSurface(process.env)) {
|
|
|
18625
18631
|
// src/session-identity.ts
|
|
18626
18632
|
var SESSION_ID_ENV_VARS = [
|
|
18627
18633
|
"MMI_SESSION_ID",
|
|
18634
|
+
"MMI_GATE_SESSION_ID",
|
|
18628
18635
|
"CLAUDE_SESSION_ID",
|
|
18629
18636
|
"CLAUDE_CODE_SESSION_ID",
|
|
18630
18637
|
"CODEX_SESSION_ID",
|
|
18638
|
+
"CODEX_THREAD_ID",
|
|
18631
18639
|
"CURSOR_SESSION_ID",
|
|
18640
|
+
"HERMES_SESSION_ID",
|
|
18632
18641
|
"PI_SESSION_ID"
|
|
18633
18642
|
];
|
|
18643
|
+
var SYNTH_SESSION_PREFIX = "synth-";
|
|
18644
|
+
function isHostSessionId(session) {
|
|
18645
|
+
return Boolean(session) && !session.startsWith(SYNTH_SESSION_PREFIX);
|
|
18646
|
+
}
|
|
18634
18647
|
function readSessionId(env) {
|
|
18635
18648
|
for (const key of SESSION_ID_ENV_VARS) {
|
|
18636
18649
|
const value = env[key]?.trim();
|
|
@@ -18638,11 +18651,18 @@ function readSessionId(env) {
|
|
|
18638
18651
|
}
|
|
18639
18652
|
return void 0;
|
|
18640
18653
|
}
|
|
18654
|
+
var synthesizedSessionId;
|
|
18655
|
+
function fallbackSessionId(surface) {
|
|
18656
|
+
if (!synthesizedSessionId) {
|
|
18657
|
+
synthesizedSessionId = `${SYNTH_SESSION_PREFIX}${surface}-${process.pid}-${(0, import_node_crypto4.randomBytes)(3).toString("hex")}`;
|
|
18658
|
+
}
|
|
18659
|
+
return synthesizedSessionId;
|
|
18660
|
+
}
|
|
18641
18661
|
function describeSessionIdentity(env = process.env) {
|
|
18642
|
-
const
|
|
18662
|
+
const surface = detectSurface(env);
|
|
18643
18663
|
return {
|
|
18644
|
-
|
|
18645
|
-
surface
|
|
18664
|
+
session: readSessionId(env) ?? fallbackSessionId(surface),
|
|
18665
|
+
surface,
|
|
18646
18666
|
host: (0, import_node_os7.hostname)()
|
|
18647
18667
|
};
|
|
18648
18668
|
}
|
|
@@ -19910,7 +19930,7 @@ async function postClaimMarkerComment(client, item) {
|
|
|
19910
19930
|
const actor = describeSessionIdentity();
|
|
19911
19931
|
const marker = {
|
|
19912
19932
|
v: 1,
|
|
19913
|
-
|
|
19933
|
+
session: actor.session,
|
|
19914
19934
|
surface: actor.surface,
|
|
19915
19935
|
host: actor.host,
|
|
19916
19936
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -20051,7 +20071,7 @@ function sameClaimHost(a, b) {
|
|
|
20051
20071
|
}
|
|
20052
20072
|
function laneOwnership(marker, current) {
|
|
20053
20073
|
if (!marker) return "unknown";
|
|
20054
|
-
if (marker.session && current.session) {
|
|
20074
|
+
if (isHostSessionId(marker.session) && isHostSessionId(current.session)) {
|
|
20055
20075
|
return marker.session === current.session ? "mine" : "other";
|
|
20056
20076
|
}
|
|
20057
20077
|
if (marker.surface && current.surface && marker.surface !== current.surface) return "other";
|
|
@@ -21727,14 +21747,14 @@ function renderVerifyBroker(input) {
|
|
|
21727
21747
|
}
|
|
21728
21748
|
|
|
21729
21749
|
// src/tenant-artifact.ts
|
|
21730
|
-
var
|
|
21750
|
+
var import_node_crypto5 = require("node:crypto");
|
|
21731
21751
|
var import_node_fs22 = require("node:fs");
|
|
21732
21752
|
var import_promises3 = require("node:fs/promises");
|
|
21733
21753
|
var import_node_path20 = require("node:path");
|
|
21734
21754
|
var ARTIFACT_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
21735
21755
|
var MAX_BYTES = 5 * 1024 * 1024 * 1024;
|
|
21736
21756
|
async function sha256File(path2) {
|
|
21737
|
-
const hash = (0,
|
|
21757
|
+
const hash = (0, import_node_crypto5.createHash)("sha256");
|
|
21738
21758
|
for await (const chunk of (0, import_node_fs22.createReadStream)(path2)) hash.update(chunk);
|
|
21739
21759
|
return hash.digest("hex");
|
|
21740
21760
|
}
|
|
@@ -22874,7 +22894,7 @@ async function announceRelease(deps, args) {
|
|
|
22874
22894
|
}
|
|
22875
22895
|
|
|
22876
22896
|
// src/repo-index.ts
|
|
22877
|
-
var
|
|
22897
|
+
var import_node_crypto6 = require("node:crypto");
|
|
22878
22898
|
var import_node_child_process12 = require("node:child_process");
|
|
22879
22899
|
var import_node_fs23 = require("node:fs");
|
|
22880
22900
|
var import_node_path21 = require("node:path");
|
|
@@ -23064,7 +23084,7 @@ function rebuildRepoIndex(cwd, repoSlug3) {
|
|
|
23064
23084
|
continue;
|
|
23065
23085
|
}
|
|
23066
23086
|
if (text.length > 15e5) continue;
|
|
23067
|
-
const hash = (0,
|
|
23087
|
+
const hash = (0, import_node_crypto6.createHash)("sha256").update(text).digest("hex").slice(0, 16);
|
|
23068
23088
|
const symbols = extractSymbols(text);
|
|
23069
23089
|
const docBlurb = extractModuleBlurb(text);
|
|
23070
23090
|
const top = rel.includes("/") ? rel.split("/")[0] : "";
|
|
@@ -23169,16 +23189,16 @@ function inferRepoSlug(cwd, exec = import_node_child_process12.execFileSync) {
|
|
|
23169
23189
|
}
|
|
23170
23190
|
|
|
23171
23191
|
// src/repo-index-cloud-client.ts
|
|
23172
|
-
var
|
|
23192
|
+
var import_node_crypto9 = require("node:crypto");
|
|
23173
23193
|
|
|
23174
23194
|
// src/repo-index-v4/builder.ts
|
|
23175
|
-
var
|
|
23195
|
+
var import_node_crypto8 = require("node:crypto");
|
|
23176
23196
|
var import_node_child_process13 = require("node:child_process");
|
|
23177
23197
|
var import_node_fs25 = require("node:fs");
|
|
23178
23198
|
var import_node_path23 = require("node:path");
|
|
23179
23199
|
|
|
23180
23200
|
// src/repo-index-v4/chunks.ts
|
|
23181
|
-
var
|
|
23201
|
+
var import_node_crypto7 = require("node:crypto");
|
|
23182
23202
|
var import_node_fs24 = require("node:fs");
|
|
23183
23203
|
var import_node_path22 = require("node:path");
|
|
23184
23204
|
|
|
@@ -23245,7 +23265,7 @@ async function parserFor(language) {
|
|
|
23245
23265
|
return parser;
|
|
23246
23266
|
}
|
|
23247
23267
|
function sha256(value) {
|
|
23248
|
-
return (0,
|
|
23268
|
+
return (0, import_node_crypto7.createHash)("sha256").update(value).digest("hex");
|
|
23249
23269
|
}
|
|
23250
23270
|
function pointerId(path2, kind, contentHash, start, end, symbol) {
|
|
23251
23271
|
return sha256(["repo-index-v4", path2, kind, contentHash, String(start), String(end), symbol ?? ""].join("\0"));
|
|
@@ -23365,7 +23385,7 @@ function canonicalJson(value) {
|
|
|
23365
23385
|
return `{${Object.keys(record).sort().map((k) => `${JSON.stringify(k)}:${canonicalJson(record[k])}`).join(",")}}`;
|
|
23366
23386
|
}
|
|
23367
23387
|
function sha2562(value) {
|
|
23368
|
-
return (0,
|
|
23388
|
+
return (0, import_node_crypto8.createHash)("sha256").update(canonicalJson(value)).digest("hex");
|
|
23369
23389
|
}
|
|
23370
23390
|
function quantizeV4Vector(vector) {
|
|
23371
23391
|
return vector.map((value) => Number(value.toFixed(V4_VECTOR_DECIMAL_PLACES)));
|
|
@@ -23692,7 +23712,7 @@ async function searchRepoIndexCloud(query, opts, deps) {
|
|
|
23692
23712
|
const body = await res.json().catch(() => ({}));
|
|
23693
23713
|
if (!res.ok) return { ok: false, error: body.error ?? `search HTTP ${res.status}`, status: res.status };
|
|
23694
23714
|
const shadowRate = Math.max(0, Math.min(1, Number(process.env.MMI_REPO_INDEX_V4_SHADOW_RATE ?? 0.1) || 0));
|
|
23695
|
-
if ((0,
|
|
23715
|
+
if ((0, import_node_crypto9.createHash)("sha256").update(query).digest()[0] / 256 < shadowRate) {
|
|
23696
23716
|
void fetchWithRetry(
|
|
23697
23717
|
deps.fetch ?? fetch,
|
|
23698
23718
|
`${deps.baseUrl.replace(/\/$/, "")}/repo-index/v4/shadow`,
|
|
@@ -26031,7 +26051,7 @@ function registerSecretsCommands(program3) {
|
|
|
26031
26051
|
}
|
|
26032
26052
|
|
|
26033
26053
|
// src/app-actor.ts
|
|
26034
|
-
var
|
|
26054
|
+
var import_node_crypto10 = require("node:crypto");
|
|
26035
26055
|
var APP_ACTOR_ENV = "MMI_ACTOR";
|
|
26036
26056
|
var APP_VAULT_REPO = "mutmutco/MMI-Hub";
|
|
26037
26057
|
var APP_VAULT_KEYS = ["GITHUB_APP_ID", "GITHUB_APP_INSTALLATION_ID", "GITHUB_APP_PRIVATE_KEY"];
|
|
@@ -26075,7 +26095,7 @@ function mintAppJwt(appId, privateKeyPem, nowSec) {
|
|
|
26075
26095
|
exp: now + APP_JWT_TTL_S,
|
|
26076
26096
|
iss: appId
|
|
26077
26097
|
}));
|
|
26078
|
-
const signer = (0,
|
|
26098
|
+
const signer = (0, import_node_crypto10.createSign)("RSA-SHA256");
|
|
26079
26099
|
signer.update(`${header}.${payload}`);
|
|
26080
26100
|
return `${header}.${payload}.${signer.sign(privateKeyPem, "base64url")}`;
|
|
26081
26101
|
}
|
|
@@ -27003,7 +27023,7 @@ var import_node_os14 = require("node:os");
|
|
|
27003
27023
|
var import_node_path32 = require("node:path");
|
|
27004
27024
|
|
|
27005
27025
|
// src/bootstrap-drift.ts
|
|
27006
|
-
var
|
|
27026
|
+
var import_node_crypto11 = require("node:crypto");
|
|
27007
27027
|
function byteComparableSeeds(manifest, cls) {
|
|
27008
27028
|
return manifest.seeds.filter((s) => s.ownership === "org" && s.source === "self" && s.classes.includes(cls));
|
|
27009
27029
|
}
|
|
@@ -27023,7 +27043,7 @@ function compareSeedBytes(hubContent, repoContent) {
|
|
|
27023
27043
|
return normalize(hubContent) === normalize(repoContent) ? "match" : "drift";
|
|
27024
27044
|
}
|
|
27025
27045
|
function seedContentHash(content) {
|
|
27026
|
-
return (0,
|
|
27046
|
+
return (0, import_node_crypto11.createHash)("sha256").update(content.replace(/\r\n/g, "\n"), "utf8").digest("hex");
|
|
27027
27047
|
}
|
|
27028
27048
|
function auditRepoSeedDrift(repo, seeds, hubContents, repoReads) {
|
|
27029
27049
|
const byTarget = new Map(repoReads.map((r) => [r.target, r.content]));
|
|
@@ -27186,7 +27206,7 @@ function renderPropagationReport(plan) {
|
|
|
27186
27206
|
}
|
|
27187
27207
|
|
|
27188
27208
|
// src/bootstrap-propagation-identity.ts
|
|
27189
|
-
var
|
|
27209
|
+
var import_node_crypto12 = require("node:crypto");
|
|
27190
27210
|
var PROPAGATION_BRANCH_PREFIX = "seed-propagate-";
|
|
27191
27211
|
var TARGET_MARKER_NAME = "mmi-bootstrap-propagation-target";
|
|
27192
27212
|
function safeBranchPart(value, maxLength, fallback) {
|
|
@@ -27199,7 +27219,7 @@ function repoSlug2(repo) {
|
|
|
27199
27219
|
function propagationBranch(repo, target) {
|
|
27200
27220
|
const repoPart = safeBranchPart(repoSlug2(repo), 32, "repo");
|
|
27201
27221
|
const targetPart = safeBranchPart(target, 48, "target");
|
|
27202
|
-
const hash = (0,
|
|
27222
|
+
const hash = (0, import_node_crypto12.createHash)("sha256").update(repo.trim().toLowerCase()).update("\0").update(target).digest("hex").slice(0, 12);
|
|
27203
27223
|
return `${PROPAGATION_BRANCH_PREFIX}${repoPart}-${targetPart}-${hash}`;
|
|
27204
27224
|
}
|
|
27205
27225
|
function legacyPropagationBranch(repo) {
|
|
@@ -29739,7 +29759,7 @@ function registerBoardCommands(program3) {
|
|
|
29739
29759
|
const board = program3.command("board").description("read, claim, show, and move Project v2 work items for the current repo");
|
|
29740
29760
|
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));
|
|
29741
29761
|
withExamples(mutating(
|
|
29742
|
-
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)").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"),
|
|
29762
|
+
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"),
|
|
29743
29763
|
(_opts, args) => ({ command: "board claim", issues: args[0] ?? [] })
|
|
29744
29764
|
).action(async (issueRefs, o) => {
|
|
29745
29765
|
if (issueRefs.length === 1) {
|
|
@@ -30360,7 +30380,7 @@ async function checkDocsIndexAtHead(opts, deps) {
|
|
|
30360
30380
|
|
|
30361
30381
|
// src/issue-commands.ts
|
|
30362
30382
|
var import_node_fs38 = require("node:fs");
|
|
30363
|
-
var
|
|
30383
|
+
var import_node_crypto13 = require("node:crypto");
|
|
30364
30384
|
var ghRunner = async (args, timeoutMs) => (await execFileP2("gh", args, { timeout: timeoutMs })).stdout;
|
|
30365
30385
|
var ReparentConflictError = class extends Error {
|
|
30366
30386
|
constructor(message, payload) {
|
|
@@ -30651,7 +30671,7 @@ function rowIdempotencyKey(batchKey, spec) {
|
|
|
30651
30671
|
const identity = `${spec.type}
|
|
30652
30672
|
${spec.title.trim()}
|
|
30653
30673
|
${spec.body ?? ""}`;
|
|
30654
|
-
const hash = (0,
|
|
30674
|
+
const hash = (0, import_node_crypto13.createHash)("sha256").update(identity).digest("hex").slice(0, 16);
|
|
30655
30675
|
return `${batchKey}:${hash}`;
|
|
30656
30676
|
}
|
|
30657
30677
|
var BATCH_SPEC_KEYS = /* @__PURE__ */ new Set(["type", "title", "body", "priority", "labels", "label", "parent", "repo", "surface"]);
|
|
@@ -31283,7 +31303,23 @@ async function collectStatus() {
|
|
|
31283
31303
|
} catch {
|
|
31284
31304
|
stage = { running: false };
|
|
31285
31305
|
}
|
|
31286
|
-
|
|
31306
|
+
let releaseTrack;
|
|
31307
|
+
let branches;
|
|
31308
|
+
try {
|
|
31309
|
+
const cfg = await loadConfigOrDiscover();
|
|
31310
|
+
if (cfg.sagaApiUrl) {
|
|
31311
|
+
const slug = await repoSlug();
|
|
31312
|
+
const deps = registryClientDeps(cfg);
|
|
31313
|
+
const read = await fetchProjectBySlugChecked(slug, deps);
|
|
31314
|
+
if (read.ok && read.project) {
|
|
31315
|
+
const trackRepo = repo ?? `mutmutco/${slug}`;
|
|
31316
|
+
releaseTrack = resolveReleaseTrack(read.project, void 0, trackRepo);
|
|
31317
|
+
branches = branchesForTrack(releaseTrack);
|
|
31318
|
+
}
|
|
31319
|
+
}
|
|
31320
|
+
} catch {
|
|
31321
|
+
}
|
|
31322
|
+
return { repo, branch, releaseTrack, branches, worktrees, myOpenPrs, claimedItems, stage };
|
|
31287
31323
|
}
|
|
31288
31324
|
var PRIORITY_RANK = {
|
|
31289
31325
|
Urgent: 0,
|
|
@@ -31428,6 +31464,9 @@ function registerDiscoveryCommands(program3) {
|
|
|
31428
31464
|
} else {
|
|
31429
31465
|
console.log(`repo: ${report.repo ?? "unknown"}`);
|
|
31430
31466
|
console.log(`branch: ${report.branch}`);
|
|
31467
|
+
if (report.releaseTrack) {
|
|
31468
|
+
console.log(`release track: ${report.releaseTrack} (${(report.branches ?? []).join(" -> ")})`);
|
|
31469
|
+
}
|
|
31431
31470
|
console.log(`worktrees: ${report.worktrees.length} linked`);
|
|
31432
31471
|
console.log(`my open PRs: ${report.myOpenPrs.length}`);
|
|
31433
31472
|
console.log(`claimed board items: ${report.claimedItems.length}`);
|
|
@@ -37568,7 +37607,7 @@ program2.command("skill-lesson").description("file a skill-lesson on the Hub boa
|
|
|
37568
37607
|
title = buildSkillLessonTitle(skill, rawTitle);
|
|
37569
37608
|
priority = resolveCreatePriority(o.priority, "skill-lesson");
|
|
37570
37609
|
body = buildSkillLessonBody(rawBody, sourceRepo, pluginSha);
|
|
37571
|
-
args = buildIssueArgs({ type: "task", title, body, priority, repo: targetRepo3, labels: [
|
|
37610
|
+
args = buildIssueArgs({ type: "task", title, body, priority, repo: targetRepo3, labels: [...SKILL_LESSON_FILE_LABELS] });
|
|
37572
37611
|
} catch (e) {
|
|
37573
37612
|
return fail(`skill-lesson: ${e.message}`);
|
|
37574
37613
|
}
|
|
@@ -37610,9 +37649,11 @@ program2.command("skill-lesson").description("file a skill-lesson on the Hub boa
|
|
|
37610
37649
|
});
|
|
37611
37650
|
if (surfaceWarn) process.stderr.write(`${surfaceWarn}
|
|
37612
37651
|
`);
|
|
37613
|
-
|
|
37614
|
-
|
|
37615
|
-
|
|
37652
|
+
for (const [label, color] of [[SKILL_LESSON_LABEL, "c2e0c6"], [LEARNING_LABEL, "ededed"]]) {
|
|
37653
|
+
try {
|
|
37654
|
+
await execFileP2("gh", ["label", "create", label, "--color", color, "--repo", targetRepo3], { timeout: GH_MUTATION_TIMEOUT_MS });
|
|
37655
|
+
} catch {
|
|
37656
|
+
}
|
|
37616
37657
|
}
|
|
37617
37658
|
const created = await ghCreate(args);
|
|
37618
37659
|
const { projectItemId, onBoard } = await attachToProject(created.number, targetRepo3, priority);
|
package/package.json
CHANGED