@bridge-ds/core 0.3.0 → 0.5.0

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/index.js CHANGED
@@ -1,7 +1,7 @@
1
- import { n as modeDisplayName, o as modesOf$1, q as isMultiMode, T as TIER_NAMES, s as TIER_AXIS, u as findReferenceProblems, w as evaluatePairs, x as contrastScope, y as contextLabel, S as SINGLE_MODE, z as pathId, A as removeToken, B as moveToken, D as effectiveScopes, E as sameScopes, F as defaultScopes, G as readTokenAt, H as upsertToken, I as serializeTokenFile, J as emptyTokenFile, K as parseTokenFile, L as modeFile, M as defaultFile, N as EXT_SCOPES, O as EXT_ID, P as DEFAULT_PROTECTED_BRANCHES, a as assertSafeBranch, Q as ProtectedBranchError, f as CONFIG_FILE, l as loadConfig, R as ConfigError, U as DEFAULT_TOKEN_PATHS, c as collectHistory, p as packageDirCandidates, b as parseChangelog, r as releasesFromTags, m as mergeReleases, d as buildReport, V as applyTokenEdits, W as buildHistoryEntry, X as resolveBranchPreviews, Y as tokensPath, Z as coerceValue, _ as toConfigJson, $ as parseContrastChecks, a0 as checkLayeredPair, a1 as classifyRisk, a2 as formatChangeset, a3 as RISK_LABELS, a4 as parseJson, a5 as serializeJson, a6 as plainEqual, a7 as toPlain, a8 as getEntry, a9 as fromPlain, aa as previewLinks, ab as slugify, ac as readPreviewComment, ad as findPreviewComment, ae as previewsSettled } from "./component-spec-IRFGJ7XK.js";
2
- import { af, ag, ah, k, C, ai, aj, ak, al, am, an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az, aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, i, aM, aN, aO, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ, a_, a$, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, h, bn, j, bo, bp, bq, br, bs, bt, bu, bv, bw, bx, g, by, bz, bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, e, bM, bN, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ, b_, b$, c0, c1, c2, c3, c4, c5, c6, c7, c8, t, c9, ca, cb, cc, cd, v, ce, cf, cg, ch } from "./component-spec-IRFGJ7XK.js";
3
- import { a as collectRefs, i as isAlias, b as aliasTarget, v as valuesEqual, s as selectTokenFiles, L as LayeredTokenSet, d as validateLayered, f as formatValue } from "./layered-DGate4nv.js";
4
- import { D, e as e2, j as j2, k as k2, c, l, m, g as g2, h as h2, n, p, o, r, q, t as t2, u } from "./layered-DGate4nv.js";
1
+ import { n as modeDisplayName, o as modesOf$1, q as isMultiMode, T as TIER_NAMES, s as TIER_AXIS, u as findReferenceProblems, w as evaluatePairs, x as contrastScope, y as contextLabel, S as SINGLE_MODE, z as pathId, A as flattenTokens, B as serializeTokenFile, D as removeToken, E as upsertToken, F as threeWayDiff, G as emptyTokenFile, H as parseTokenFile, I as EXT_ID, J as EXT_SCOPES, K as resolve, L as moveToken, M as effectiveScopes, N as sameScopes, O as defaultScopes, P as readTokenAt, Q as modeFile, R as defaultFile, U as DEFAULT_PROTECTED_BRANCHES, a as assertSafeBranch, V as ProtectedBranchError, f as CONFIG_FILE, l as loadConfig, W as ConfigError, X as DEFAULT_TOKEN_PATHS, c as collectHistory, p as packageDirCandidates, b as parseChangelog, r as releasesFromTags, m as mergeReleases, d as buildReport, Y as applyTokenEdits, Z as buildHistoryEntry, _ as resolveBranchPreviews, $ as tokensPath, a0 as coerceValue, a1 as toConfigJson, a2 as parseContrastChecks, a3 as checkLayeredPair, a4 as classifyRisk, a5 as formatChangeset, a6 as RISK_LABELS, a7 as parseJson, a8 as serializeJson, a9 as plainEqual, aa as toPlain, ab as getEntry, ac as fromPlain, ad as previewLinks, ae as slugify, af as readPreviewComment, ag as findPreviewComment, ah as previewsSettled } from "./component-spec-cvrSvIZj.js";
2
+ import { ai, aj, ak, k, C, al, am, an, ao, ap, aq, ar, as, at, au, av, aw, ax, ay, az, aA, aB, aC, aD, aE, aF, aG, aH, aI, aJ, aK, aL, aM, aN, aO, i, aP, aQ, aR, aS, aT, aU, aV, aW, aX, aY, aZ, a_, a$, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, bo, h, bp, j, bq, br, bs, bt, bu, bv, bw, bx, by, bz, g, bA, bB, bC, bD, bE, bF, bG, bH, bI, bJ, bK, bL, bM, bN, e, bO, bP, bQ, bR, bS, bT, bU, bV, bW, bX, bY, bZ, b_, b$, c0, c1, c2, c3, c4, c5, c6, c7, c8, t, c9, ca, cb, cc, cd, v, ce, cf, cg, ch } from "./component-spec-cvrSvIZj.js";
3
+ import { a as collectRefs, i as isAlias, b as aliasTarget, v as valuesEqual, p as parseColor, e as rgbaToHex, f as formatValue, s as selectTokenFiles, L as LayeredTokenSet, j as validateLayered } from "./layered-BnbmToGs.js";
4
+ import { D, d, k as k2, l, c, m, n, g as g2, h as h2, o, q, r, t as t2, u } from "./layered-BnbmToGs.js";
5
5
  const issueKey = (i2) => `${i2.code}|${i2.path ?? ""}|${i2.mode ?? ""}|${i2.code === "file-problem" ? i2.message : ""}`;
6
6
  const modeName = (mode) => mode === SINGLE_MODE ? "all modes" : modeDisplayName(mode);
7
7
  const isPalette = (t3) => t3.tier === "brand" && t3.path.startsWith("palette.");
@@ -54,7 +54,7 @@ function checkValue(set, owner, value, mode, where, issues) {
54
54
  }
55
55
  function validateSet(set, pairs) {
56
56
  const issues = [];
57
- for (const p2 of set.problems) issues.push({ code: "file-problem", severity: "error", message: p2 });
57
+ for (const p of set.problems) issues.push({ code: "file-problem", severity: "error", message: p });
58
58
  for (const t3 of set.tokens.values()) {
59
59
  if (t3.scopes?.includes("ALL_SCOPES")) {
60
60
  issues.push({
@@ -102,20 +102,20 @@ function validateSet(set, pairs) {
102
102
  }
103
103
  }
104
104
  const axes = { brand: modesOf$1(set.layout, "brand"), theme: modesOf$1(set.layout, "semantic"), density: modesOf$1(set.layout, "density") };
105
- for (const p2 of findReferenceProblems(set.byPath, axes)) {
105
+ for (const p of findReferenceProblems(set.byPath, axes)) {
106
106
  issues.push(
107
- p2.kind === "broken" ? {
107
+ p.kind === "broken" ? {
108
108
  code: "broken-reference",
109
109
  severity: "error",
110
- path: p2.path,
111
- mode: p2.mode,
112
- message: `${p2.path} points to ${p2.target}, which does not exist (${modeName(p2.mode)}).`
110
+ path: p.path,
111
+ mode: p.mode,
112
+ message: `${p.path} points to ${p.target}, which does not exist (${modeName(p.mode)}).`
113
113
  } : {
114
114
  code: "alias-cycle",
115
115
  severity: "error",
116
- path: p2.path,
117
- mode: p2.mode,
118
- message: `${p2.path} is part of a loop of references: ${p2.chain.join(" -> ")} (${modeName(p2.mode)}).`
116
+ path: p.path,
117
+ mode: p.mode,
118
+ message: `${p.path} is part of a loop of references: ${p.chain.join(" -> ")} (${modeName(p.mode)}).`
119
119
  }
120
120
  );
121
121
  }
@@ -139,16 +139,16 @@ function validateSet(set, pairs) {
139
139
  }
140
140
  function shadowedEdits(set, edits) {
141
141
  const out = [];
142
- for (const e3 of edits) {
143
- if (e3.tier !== "semantic") continue;
142
+ for (const e2 of edits) {
143
+ if (e2.tier !== "semantic") continue;
144
144
  for (const o2 of set.overrides) {
145
- if (o2.path !== e3.path || !e3.modes.includes(o2.theme)) continue;
145
+ if (o2.path !== e2.path || !e2.modes.includes(o2.theme)) continue;
146
146
  out.push({
147
147
  code: "override-shadowed",
148
148
  severity: "warning",
149
- path: e3.path,
149
+ path: e2.path,
150
150
  mode: `${o2.brand}.${o2.theme}`,
151
- message: `${e3.path} is overridden for ${modeDisplayName(o2.brand)} in ${o2.theme} (${o2.file}), so this edit does not change ${modeDisplayName(o2.brand)} ${o2.theme}. Brand overrides stay code-only.`
151
+ message: `${e2.path} is overridden for ${modeDisplayName(o2.brand)} in ${o2.theme} (${o2.file}), so this edit does not change ${modeDisplayName(o2.brand)} ${o2.theme}. Brand overrides stay code-only.`
152
152
  });
153
153
  }
154
154
  }
@@ -180,9 +180,9 @@ function levenshtein(a, b) {
180
180
  for (let i2 = 1; i2 <= a.length; i2++) {
181
181
  let diag = prev[0];
182
182
  prev[0] = i2;
183
- for (let j3 = 1; j3 <= b.length; j3++) {
184
- const tmp = prev[j3];
185
- prev[j3] = Math.min(prev[j3] + 1, prev[j3 - 1] + 1, diag + (a[i2 - 1] === b[j3 - 1] ? 0 : 1));
183
+ for (let j2 = 1; j2 <= b.length; j2++) {
184
+ const tmp = prev[j2];
185
+ prev[j2] = Math.min(prev[j2] + 1, prev[j2 - 1] + 1, diag + (a[i2 - 1] === b[j2 - 1] ? 0 : 1));
186
186
  diag = tmp;
187
187
  }
188
188
  }
@@ -249,17 +249,263 @@ function applyConfirmedRenames(tokens, confirmed) {
249
249
  function idExtensionFor(t3) {
250
250
  return t3.id === pathId(t3.path) ? void 0 : t3.id;
251
251
  }
252
+ const idOf$1 = (f) => {
253
+ const id = f.extensions?.[EXT_ID];
254
+ return typeof id === "string" && id ? id : pathId(f.path);
255
+ };
256
+ function logical(f) {
257
+ const scopes = f.extensions?.[EXT_SCOPES];
258
+ return {
259
+ id: idOf$1(f),
260
+ path: f.path,
261
+ type: f.type ?? "unknown",
262
+ // One file holds one tier: the tier only feeds default scopes, the same on every side.
263
+ tier: "primitive",
264
+ values: { [SINGLE_MODE]: f.value },
265
+ description: f.description,
266
+ scopes: Array.isArray(scopes) ? scopes.map(String) : void 0,
267
+ files: { [SINGLE_MODE]: f.file }
268
+ };
269
+ }
270
+ function readSide(file, text, problems, label) {
271
+ const side = { doc: void 0, flat: /* @__PURE__ */ new Map(), logical: /* @__PURE__ */ new Map() };
272
+ if (text === void 0) return side;
273
+ try {
274
+ side.doc = parseTokenFile(file, text);
275
+ } catch (err) {
276
+ problems.push(`${file} (${label}) is not valid JSON: ${err.message}`);
277
+ return side;
278
+ }
279
+ for (const f of flattenTokens(side.doc)) {
280
+ const id = idOf$1(f);
281
+ side.flat.set(id, f);
282
+ side.logical.set(id, logical(f));
283
+ }
284
+ return side;
285
+ }
286
+ function diffFile(input, file, problems) {
287
+ const base = readSide(file, input.base[file], problems, "shared start");
288
+ const mine = readSide(file, input.mine[file], problems, "this change");
289
+ const theirs = readSide(file, input.theirs[file], problems, "latest library");
290
+ const r2 = threeWayDiff(base.logical, mine.logical, theirs.logical);
291
+ return { file, base, mine, theirs, local: r2.local, remote: r2.remote, conflicts: r2.conflicts };
292
+ }
293
+ function removedSide(c10) {
294
+ if (!c10.base) return null;
295
+ if (!c10.mine && c10.theirs) return "mine";
296
+ if (!c10.theirs && c10.mine) return "theirs";
297
+ return null;
298
+ }
299
+ const defaultChoiceFor = (c10) => removedSide(c10) ? null : "mine";
300
+ function planTokenMerge(input) {
301
+ const problems = [];
302
+ const files = [...new Set(input.files)].sort();
303
+ const conflicts = [];
304
+ let mineOnly = 0;
305
+ let theirsOnly = 0;
306
+ for (const file of files) {
307
+ const d2 = diffFile(input, file, problems);
308
+ mineOnly += d2.local.length;
309
+ theirsOnly += d2.remote.length;
310
+ for (const e2 of d2.conflicts) {
311
+ const c10 = { base: d2.base.flat.get(e2.id), mine: d2.mine.flat.get(e2.id), theirs: d2.theirs.flat.get(e2.id) };
312
+ conflicts.push({ key: `${file}#${e2.id}`, file, path: (c10.mine ?? c10.theirs ?? c10.base).path, ...c10, removedOn: removedSide(c10), defaultChoice: defaultChoiceFor(c10) });
313
+ }
314
+ }
315
+ return { files, conflicts, mineOnly, theirsOnly, problems };
316
+ }
317
+ const choiceFor = (c10, choices) => choices[c10.key] ?? c10.defaultChoice;
318
+ function missingChoices(plan, choices) {
319
+ return plan.conflicts.filter((c10) => choiceFor(c10, choices) === null);
320
+ }
321
+ function takeMine(doc, mine, existing) {
322
+ if (!mine) return existing ? removeToken(doc, existing.path) : false;
323
+ let changed = false;
324
+ if (existing && existing.path !== mine.path) changed = removeToken(doc, existing.path) || changed;
325
+ const extensions = {};
326
+ for (const k3 of Object.keys(existing?.path === mine.path ? existing.extensions ?? {} : {})) extensions[k3] = void 0;
327
+ Object.assign(extensions, mine.extensions ?? {});
328
+ return upsertToken(doc, mine.path, { type: mine.type, value: mine.value, description: mine.description, extensions }) || changed;
329
+ }
330
+ function applyTokenMerge(input, choices) {
331
+ const plan = planTokenMerge(input);
332
+ if (plan.problems.length) throw new Error(plan.problems[0]);
333
+ const missing = missingChoices(plan, choices);
334
+ if (missing.length) throw new Error(`Pick a value for ${missing.map((c10) => c10.path).join(", ")} first.`);
335
+ const byKey = new Map(plan.conflicts.map((c10) => [c10.key, c10]));
336
+ const kept = { mine: 0, theirs: 0 };
337
+ const files = {};
338
+ for (const file of plan.files) {
339
+ const d2 = diffFile(input, file, []);
340
+ const doc = d2.theirs.doc ?? emptyTokenFile(file);
341
+ for (const e2 of d2.local) takeMine(doc, d2.mine.flat.get(e2.id), d2.theirs.flat.get(e2.id) ?? d2.base.flat.get(e2.id));
342
+ for (const e2 of d2.conflicts) {
343
+ const side = choiceFor(byKey.get(`${file}#${e2.id}`), choices);
344
+ kept[side]++;
345
+ if (side === "mine") takeMine(doc, d2.mine.flat.get(e2.id), d2.theirs.flat.get(e2.id));
346
+ }
347
+ const empty = flattenTokens(doc).length === 0;
348
+ files[file] = empty && (input.theirs[file] === void 0 || input.mine[file] === void 0) ? null : serializeTokenFile(doc);
349
+ }
350
+ return { files, kept };
351
+ }
352
+ const idOf = (f) => {
353
+ const id = f.extensions?.[EXT_ID];
354
+ return typeof id === "string" && id ? id : pathId(f.path);
355
+ };
356
+ function tokensOf(file, text, problems, label) {
357
+ const out = /* @__PURE__ */ new Map();
358
+ if (text === void 0) return out;
359
+ try {
360
+ for (const t3 of flattenTokens(parseTokenFile(file, text))) out.set(idOf(t3), t3);
361
+ } catch (err) {
362
+ problems.push(`${file} (${label}) is not valid JSON: ${err.message}`);
363
+ }
364
+ return out;
365
+ }
366
+ const shape = (t3) => t3 ? JSON.stringify([t3.path, t3.type ?? null, t3.value, t3.description ?? null]) : "removed";
367
+ const look = (t3) => t3 ? JSON.stringify([t3.path, t3.type ?? null, t3.value]) : "removed";
368
+ function changeEdits(src) {
369
+ const problems = [];
370
+ const edits = [];
371
+ for (const file of [...new Set(src.files)].sort()) {
372
+ const before = tokensOf(file, src.base[file], problems, "start");
373
+ const after = tokensOf(file, src.head[file], problems, `change ${src.number}`);
374
+ for (const id of /* @__PURE__ */ new Set([...before.keys(), ...after.keys()])) {
375
+ const a = before.get(id);
376
+ const b = after.get(id);
377
+ if (shape(a) === shape(b)) continue;
378
+ edits.push({ key: `${file}#${id}`, file, path: (b ?? a).path, change: src.number, token: b });
379
+ }
380
+ }
381
+ return { number: src.number, edits, problems };
382
+ }
383
+ function byToken(changes) {
384
+ const out = /* @__PURE__ */ new Map();
385
+ for (const c10 of changes) for (const e2 of c10.edits) out.set(e2.key, [...out.get(e2.key) ?? [], e2]);
386
+ return out;
387
+ }
388
+ function optionsOf(edits) {
389
+ const out = [];
390
+ for (const e2 of edits) {
391
+ const l2 = look(e2.token);
392
+ const hit = out.find((o2) => o2.look === l2);
393
+ if (hit) hit.option.changes.push(e2.change);
394
+ else out.push({ look: l2, option: { changes: [e2.change], token: e2.token } });
395
+ }
396
+ return out.map((o2) => o2.option);
397
+ }
398
+ function combineConflicts(changes) {
399
+ const out = [];
400
+ for (const [key, edits] of byToken(changes)) {
401
+ const options = optionsOf(edits);
402
+ if (options.length > 1) out.push({ key, file: edits[0].file, path: edits[0].path, options });
403
+ }
404
+ return out;
405
+ }
406
+ function pickedOption(c10, picks) {
407
+ const n2 = picks[c10.key];
408
+ return n2 === void 0 ? null : c10.options.find((o2) => o2.changes.includes(n2)) ?? null;
409
+ }
410
+ const unpicked = (conflicts, picks) => conflicts.filter((c10) => !pickedOption(c10, picks));
411
+ function combineChanges(latest, changes, picks = {}, opts = {}) {
412
+ const on = opts.include ? changes.filter((c10) => opts.include.includes(c10.number)) : changes;
413
+ const problems = on.flatMap((c10) => c10.problems);
414
+ const groups = byToken(on);
415
+ const conflicts = [];
416
+ const missing = [];
417
+ const from = {};
418
+ const docs = /* @__PURE__ */ new Map();
419
+ const docOf = (file) => {
420
+ if (docs.has(file)) return docs.get(file);
421
+ const text = latest[file];
422
+ let doc;
423
+ try {
424
+ doc = text === void 0 ? emptyTokenFile(file) : parseTokenFile(file, text);
425
+ } catch (err) {
426
+ problems.push(`${file} (latest library) is not valid JSON: ${err.message}`);
427
+ return null;
428
+ }
429
+ docs.set(file, doc);
430
+ return doc;
431
+ };
432
+ for (const [key, edits] of groups) {
433
+ const options = optionsOf(edits);
434
+ let use = options[0];
435
+ if (options.length > 1) {
436
+ const conflict = { key, file: edits[0].file, path: edits[0].path, options };
437
+ conflicts.push(conflict);
438
+ use = pickedOption(conflict, picks);
439
+ if (!use) {
440
+ missing.push(conflict);
441
+ use = opts.unpicked === "first" ? options[0] : null;
442
+ }
443
+ }
444
+ if (!use) continue;
445
+ const doc = docOf(edits[0].file);
446
+ if (!doc) continue;
447
+ const existing = flattenTokens(doc).find((t3) => idOf(t3) === key.slice(key.indexOf("#") + 1));
448
+ takeMine(doc, use.token, existing);
449
+ const path = use.token?.path ?? edits[0].path;
450
+ from[path] = [.../* @__PURE__ */ new Set([...from[path] ?? [], ...use.changes])];
451
+ }
452
+ const files = { ...latest };
453
+ for (const [file, doc] of docs) {
454
+ if (latest[file] === void 0 && flattenTokens(doc).length === 0) continue;
455
+ files[file] = serializeTokenFile(doc);
456
+ }
457
+ const tokens = new Set([...groups.values()].map((e2) => e2[0].path)).size;
458
+ return { files, included: on.map((c10) => c10.number), edits: groups.size, tokens, conflicts, missing, from, problems };
459
+ }
460
+ function encodePicks(picks) {
461
+ return Object.entries(picks).filter(([, n2]) => Number.isSafeInteger(n2) && n2 > 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, n2]) => `${n2}:${key}`).join("~");
462
+ }
463
+ function decodePicks(raw) {
464
+ const out = {};
465
+ for (const part of (raw ?? "").split("~")) {
466
+ const i2 = part.indexOf(":");
467
+ if (i2 < 1) continue;
468
+ const n2 = Number(part.slice(0, i2));
469
+ const key = part.slice(i2 + 1);
470
+ if (/^\d{1,7}$/.test(part.slice(0, i2)) && n2 > 0 && key.includes("#")) out[key] = n2;
471
+ }
472
+ return out;
473
+ }
474
+ function cssOf(type, value) {
475
+ if (value === void 0) return void 0;
476
+ if (type === "color") {
477
+ const hex = value && typeof value === "object" ? value.hex : void 0;
478
+ const c10 = parseColor(value);
479
+ if (!c10) return void 0;
480
+ if (c10.a < 1) return `rgb(${Math.round(c10.r * 255)} ${Math.round(c10.g * 255)} ${Math.round(c10.b * 255)} / ${c10.a})`;
481
+ return typeof hex === "string" ? hex.toLowerCase() : rgbaToHex(c10);
482
+ }
483
+ return formatValue(type, value);
484
+ }
485
+ const cssVarOf = (path) => `--${path.replace(/\./g, "-")}`;
486
+ function previewOverrides(head, proposed, ctx) {
487
+ const out = {};
488
+ const hctx = { ...ctx, overrides: head.overrideIndex };
489
+ const pctx = { ...ctx, overrides: proposed.overrideIndex };
490
+ for (const t3 of proposed.byPath.values()) {
491
+ const a = resolve(head.byPath, t3.path, hctx);
492
+ const b = resolve(proposed.byPath, t3.path, pctx);
493
+ const css = cssOf(t3.type, b.value);
494
+ if (css !== void 0 && JSON.stringify(a.value) !== JSON.stringify(b.value)) out[cssVarOf(t3.path)] = css;
495
+ }
496
+ return out;
497
+ }
252
498
  const modesOf = (t3) => Object.keys(t3.values);
253
499
  function composeFiles(head, originals, changes) {
254
500
  const docs = /* @__PURE__ */ new Map();
255
501
  const doc = (file) => {
256
- let d = docs.get(file);
257
- if (!d) {
502
+ let d2 = docs.get(file);
503
+ if (!d2) {
258
504
  const text = originals[file];
259
- d = text === void 0 ? emptyTokenFile(file) : parseTokenFile(file, text);
260
- docs.set(file, d);
505
+ d2 = text === void 0 ? emptyTokenFile(file) : parseTokenFile(file, text);
506
+ docs.set(file, d2);
261
507
  }
262
- return d;
508
+ return d2;
263
509
  };
264
510
  const fileFor = (t3, mode, current) => current?.files[mode] ?? t3.files[mode] ?? (isMultiMode(t3.tier) ? modeFile(head.layout, t3.tier, mode) : void 0) ?? defaultFile(t3.tier, t3.path, head.options.dirs);
265
511
  for (const { target, current } of changes) {
@@ -270,9 +516,9 @@ function composeFiles(head, originals, changes) {
270
516
  const renamed = !!current && current.path !== target.path;
271
517
  if (current) {
272
518
  for (const mode of modesOf(current)) {
273
- const d = doc(fileFor(current, mode));
274
- if (target.values[mode] === void 0) removeToken(d, current.path);
275
- else if (renamed) moveToken(d, current.path, target.path);
519
+ const d2 = doc(fileFor(current, mode));
520
+ if (target.values[mode] === void 0) removeToken(d2, current.path);
521
+ else if (renamed) moveToken(d2, current.path, target.path);
276
522
  }
277
523
  }
278
524
  const targetScopes = effectiveScopes(target);
@@ -280,14 +526,14 @@ function composeFiles(head, originals, changes) {
280
526
  const scopesChanged = !current || !sameScopes(targetScopes, effectiveScopes(current));
281
527
  const descChanged = (target.description ?? "").trim() !== (current?.description ?? "").trim();
282
528
  for (const mode of modesOf(target)) {
283
- const d = doc(fileFor(target, mode, current));
284
- const existing = readTokenAt(d, target.path);
529
+ const d2 = doc(fileFor(target, mode, current));
530
+ const existing = readTokenAt(d2, target.path);
285
531
  const currentValue = current?.values[mode];
286
532
  const value = currentValue !== void 0 && valuesEqual(target.type, target.values[mode], currentValue) ? currentValue : target.values[mode];
287
533
  const extensions = {};
288
534
  if (scopesChanged) extensions[EXT_SCOPES] = scopesExt;
289
535
  if (renamed || !existing) extensions[EXT_ID] = idExtensionFor(target);
290
- upsertToken(d, target.path, {
536
+ upsertToken(d2, target.path, {
291
537
  type: target.type,
292
538
  value,
293
539
  description: descChanged || !existing ? target.description : existing.description,
@@ -297,8 +543,8 @@ function composeFiles(head, originals, changes) {
297
543
  }
298
544
  const files = {};
299
545
  const allFiles = { ...originals };
300
- for (const [file, d] of docs) {
301
- const text = serializeTokenFile(d);
546
+ for (const [file, d2] of docs) {
547
+ const text = serializeTokenFile(d2);
302
548
  allFiles[file] = text;
303
549
  if (text !== originals[file]) files[file] = text;
304
550
  }
@@ -358,7 +604,7 @@ function refPattern(pattern) {
358
604
  function rulesetTargetsDefault(ruleset, defaultBranch) {
359
605
  if (ruleset.target && ruleset.target !== "branch") return false;
360
606
  const ref = `refs/heads/${defaultBranch}`;
361
- const hit = (p2) => p2 === "~ALL" || p2 === "~DEFAULT_BRANCH" || p2 === ref || p2 === defaultBranch || refPattern(p2.startsWith("refs/") ? p2 : `refs/heads/${p2}`).test(ref);
607
+ const hit = (p) => p === "~ALL" || p === "~DEFAULT_BRANCH" || p === ref || p === defaultBranch || refPattern(p.startsWith("refs/") ? p : `refs/heads/${p}`).test(ref);
362
608
  const cond = ruleset.conditions?.ref_name;
363
609
  if (!cond) return false;
364
610
  if ((cond.exclude ?? []).some(hit)) return false;
@@ -376,12 +622,12 @@ function rulesetParts(ruleset) {
376
622
  }
377
623
  return parts;
378
624
  }
379
- function classicParts(p2) {
625
+ function classicParts(p) {
380
626
  const parts = /* @__PURE__ */ new Set();
381
- if (count(p2.required_pull_request_reviews?.required_approving_review_count) >= 1) parts.add("review");
382
- if (((p2.required_status_checks?.contexts?.length ?? 0) || (p2.required_status_checks?.checks?.length ?? 0)) > 0) parts.add("checks");
383
- if (!p2.allow_force_pushes?.enabled) parts.add("history");
384
- if (!p2.allow_deletions?.enabled) parts.add("deletion");
627
+ if (count(p.required_pull_request_reviews?.required_approving_review_count) >= 1) parts.add("review");
628
+ if (((p.required_status_checks?.contexts?.length ?? 0) || (p.required_status_checks?.checks?.length ?? 0)) > 0) parts.add("checks");
629
+ if (!p.allow_force_pushes?.enabled) parts.add("history");
630
+ if (!p.allow_deletions?.enabled) parts.add("deletion");
385
631
  return parts;
386
632
  }
387
633
  const rulesetUrl = (r2) => r2.html_url ?? r2._links?.html?.href;
@@ -394,10 +640,10 @@ function protectionState(rulesets, branchProtection, defaultBranch) {
394
640
  if (!rulesetTargetsDefault(r2, defaultBranch)) continue;
395
641
  const parts = rulesetParts(r2);
396
642
  if (parts.size && !url) url = rulesetUrl(r2);
397
- parts.forEach((p2) => covered.add(p2));
643
+ parts.forEach((p) => covered.add(p));
398
644
  }
399
- if (branchProtection) classicParts(branchProtection).forEach((p2) => covered.add(p2));
400
- const missing = PROTECTION_PARTS.filter((p2) => !covered.has(p2));
645
+ if (branchProtection) classicParts(branchProtection).forEach((p) => covered.add(p));
646
+ const missing = PROTECTION_PARTS.filter((p) => !covered.has(p));
401
647
  const withUrl = url ? { url } : {};
402
648
  if (!missing.length) return { kind: "protected", missing, ...extra, ...withUrl };
403
649
  const unreadable = rulesets == null || branchProtection === void 0;
@@ -418,7 +664,7 @@ function protectionSentence(state) {
418
664
  case "unprotected":
419
665
  return "Your library can be changed without review.";
420
666
  case "partial": {
421
- const s = joinAnd(state.missing.map((p2) => PROTECTION_PART_PHRASE[p2]));
667
+ const s = joinAnd(state.missing.map((p) => PROTECTION_PART_PHRASE[p]));
422
668
  return `Partly protected: ${s}.`;
423
669
  }
424
670
  default:
@@ -467,18 +713,18 @@ function missingPermissionMessage(permission, action) {
467
713
  }
468
714
  function requiredPermission(path, acceptedHeader) {
469
715
  if (acceptedHeader) {
470
- const first = acceptedHeader.split(";")[0].split(",").map((p22) => p22.trim().split("=")[0].trim()).filter((p22) => p22 && p22 !== "metadata");
716
+ const first = acceptedHeader.split(";")[0].split(",").map((p2) => p2.trim().split("=")[0].trim()).filter((p2) => p2 && p2 !== "metadata");
471
717
  if (first.length) return first[0];
472
718
  }
473
- const p2 = path.replace(/[?#].*$/, "");
474
- if (/\/repos\/[^/]+\/[^/]+\/(issues|labels|milestones)(\/|$)/.test(p2)) return "issues";
475
- if (/\/repos\/[^/]+\/[^/]+\/pulls(\/|$)/.test(p2)) return "pull_requests";
476
- if (/\/repos\/[^/]+\/[^/]+\/(rulesets(\/|$)|branches\/.+\/protection$)/.test(p2)) return "administration";
477
- if (/\/repos\/[^/]+\/[^/]+\/(contents|git|commits|branches|merges)(\/|$)/.test(p2)) return "contents";
478
- if (/\/repos\/[^/]+\/[^/]+\/(check-runs|check-suites)(\/|$)/.test(p2)) return "checks";
479
- if (/\/repos\/[^/]+\/[^/]+\/statuses(\/|$)/.test(p2)) return "statuses";
480
- if (/\/repos\/[^/]+\/[^/]+\/deployments(\/|$)/.test(p2)) return "deployments";
481
- if (/\/repos\/[^/]+\/[^/]+\/actions(\/|$)/.test(p2)) return "actions";
719
+ const p = path.replace(/[?#].*$/, "");
720
+ if (/\/repos\/[^/]+\/[^/]+\/(issues|labels|milestones)(\/|$)/.test(p)) return "issues";
721
+ if (/\/repos\/[^/]+\/[^/]+\/pulls(\/|$)/.test(p)) return "pull_requests";
722
+ if (/\/repos\/[^/]+\/[^/]+\/(rulesets(\/|$)|branches\/.+\/protection$)/.test(p)) return "administration";
723
+ if (/\/repos\/[^/]+\/[^/]+\/(contents|git|commits|branches|merges)(\/|$)/.test(p)) return "contents";
724
+ if (/\/repos\/[^/]+\/[^/]+\/(check-runs|check-suites)(\/|$)/.test(p)) return "checks";
725
+ if (/\/repos\/[^/]+\/[^/]+\/statuses(\/|$)/.test(p)) return "statuses";
726
+ if (/\/repos\/[^/]+\/[^/]+\/deployments(\/|$)/.test(p)) return "deployments";
727
+ if (/\/repos\/[^/]+\/[^/]+\/actions(\/|$)/.test(p)) return "actions";
482
728
  return void 0;
483
729
  }
484
730
  const PERMISSION_DENIED = /not accessible by (personal access token|integration)|must have (admin|push|write) (rights|access)|write access to repository not granted|permission to .* denied/i;
@@ -490,6 +736,12 @@ function classifyAuth(status, detail, opts = {}) {
490
736
  }
491
737
  return {};
492
738
  }
739
+ function rateLimitMessage(x) {
740
+ const when = x.resetsAt ? ` It resets at ${x.resetsAt.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}.` : "";
741
+ if (x.withToken) return `GitHub's hourly request limit for this token is used up.${when} Try again after that.`;
742
+ const hint = x.tokenHint ?? "add a GitHub token";
743
+ return `GitHub's hourly limit for requests without a token (60 an hour) is used up.${when} To keep going now, ${hint}: a token gets 5,000 requests an hour.`;
744
+ }
493
745
  const DEFAULT_RETRY = { attempts: 3, baseDelayMs: 600, sleep: (ms) => new Promise((r2) => setTimeout(r2, ms)) };
494
746
  const isTransient = (status, detail) => status === 0 || status >= 500 || status === 429 || status === 403 && /secondary rate limit/i.test(detail);
495
747
  const API = "https://api.github.com";
@@ -562,8 +814,8 @@ class GitHubClient {
562
814
  try {
563
815
  return await this.once(method, path, body);
564
816
  } catch (err) {
565
- const e3 = err;
566
- if (attempt >= attempts || !(e3 instanceof GitHubError) || !isTransient(e3.status, e3.detail ?? "")) throw err;
817
+ const e2 = err;
818
+ if (attempt >= attempts || !(e2 instanceof GitHubError) || !isTransient(e2.status, e2.detail ?? "")) throw err;
567
819
  await this.retry.sleep(this.retry.baseDelayMs * 2 ** (attempt - 1));
568
820
  }
569
821
  }
@@ -586,19 +838,15 @@ class GitHubClient {
586
838
  let detail = "";
587
839
  try {
588
840
  const data = await res.json();
589
- detail = [data.message, ...(data.errors ?? []).map((e3) => typeof e3 === "string" ? e3 : e3.message)].filter(Boolean).join(" ");
841
+ detail = [data.message, ...(data.errors ?? []).map((e2) => typeof e2 === "string" ? e2 : e2.message)].filter(Boolean).join(" ");
590
842
  } catch {
591
843
  detail = "";
592
844
  }
593
845
  const remaining = res.headers?.get("x-ratelimit-remaining");
594
846
  const reset = res.headers?.get("x-ratelimit-reset");
595
847
  if ((res.status === 403 || res.status === 429) && remaining === "0") {
596
- const when = reset ? new Date(Number(reset) * 1e3) : void 0;
597
- throw new GitHubError(
598
- 429,
599
- `GitHub's hourly request limit for this token is used up.${when ? ` It resets at ${when.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}.` : ""} Try again after that.`,
600
- detail
601
- );
848
+ const resetsAt = reset ? new Date(Number(reset) * 1e3) : void 0;
849
+ throw new GitHubError(429, rateLimitMessage({ withToken: Boolean(this.token), resetsAt, tokenHint: this.options.tokenHint }), detail);
602
850
  }
603
851
  const info = classifyAuth(res.status, detail, {
604
852
  path,
@@ -670,7 +918,7 @@ class GitHubClient {
670
918
  /** Pull requests a commit belongs to (merged ones first): how a commit on main finds its PR. */
671
919
  async listPullRequestsForCommit(sha) {
672
920
  const r2 = await this.request("GET", `${this.repoPath}/commits/${encodeRef(sha)}/pulls`);
673
- return r2.map((p2) => ({ ...toSummary(p2), body: p2.body ?? "", ...p2.merged_at ? { mergedAt: p2.merged_at } : {}, ...p2.merge_commit_sha ? { mergeCommitSha: p2.merge_commit_sha } : {} })).sort((a, b) => Number(Boolean(b.mergedAt)) - Number(Boolean(a.mergedAt)));
921
+ return r2.map((p) => ({ ...toSummary(p), body: p.body ?? "", ...p.merged_at ? { mergedAt: p.merged_at } : {}, ...p.merge_commit_sha ? { mergeCommitSha: p.merge_commit_sha } : {} })).sort((a, b) => Number(Boolean(b.mergedAt)) - Number(Boolean(a.mergedAt)));
674
922
  }
675
923
  /** Tags with the commit they point to, newest first as GitHub lists them. */
676
924
  async listTags(perPage = 30) {
@@ -751,10 +999,29 @@ class GitHubClient {
751
999
  variables: { id: pr.node_id }
752
1000
  });
753
1001
  if (r2?.errors?.length) {
754
- const detail = r2.errors.map((e3) => e3.message).filter(Boolean).join(" ");
1002
+ const detail = r2.errors.map((e2) => e2.message).filter(Boolean).join(" ");
755
1003
  throw new GitHubError(422, `GitHub refused to mark #${n2} ready for review${detail ? `: ${detail}` : "."} Use "Ready for review" on GitHub instead.`, detail);
756
1004
  }
757
1005
  }
1006
+ /**
1007
+ * Turns an open pull request back into a draft: the GraphQL mutation convertPullRequestToDraft (REST cannot set
1008
+ * `draft` either), same token. No-op when it is already a draft.
1009
+ */
1010
+ async convertToDraft(n2) {
1011
+ this.assertToken("Turning a pull request back into a draft");
1012
+ const pr = await this.request("GET", `${this.repoPath}/pulls/${n2}`);
1013
+ if (pr.draft === true) return;
1014
+ if (pr.state && pr.state !== "open") throw new GitHubError(422, `Pull request #${n2} is ${pr.state}: only an open one can go back to draft.`);
1015
+ if (!pr.node_id) throw new GitHubError(422, `Pull request #${n2} has no node id: convert it to draft on GitHub.`);
1016
+ const r2 = await this.request("POST", "/graphql", {
1017
+ query: "mutation($id: ID!) { convertPullRequestToDraft(input: { pullRequestId: $id }) { pullRequest { number isDraft } } }",
1018
+ variables: { id: pr.node_id }
1019
+ });
1020
+ if (r2?.errors?.length) {
1021
+ const detail = r2.errors.map((e2) => e2.message).filter(Boolean).join(" ");
1022
+ throw new GitHubError(422, `GitHub refused to turn #${n2} back into a draft${detail ? `: ${detail}` : "."} Use "Convert to draft" on GitHub instead.`, detail);
1023
+ }
1024
+ }
758
1025
  async createPullRequest(input) {
759
1026
  this.assertWritableBranch(input.head, input.base);
760
1027
  const r2 = await this.request(
@@ -931,7 +1198,7 @@ class GitHubClient {
931
1198
  const q2 = ref ? `?ref=${encodeURIComponent(ref)}` : "";
932
1199
  const r2 = await this.request("GET", `${this.repoPath}/contents/${encodeRef(path)}${q2}`);
933
1200
  if (!Array.isArray(r2)) return [];
934
- return r2.map((e3) => ({ name: e3.name, path: e3.path, type: e3.type, sha: e3.sha, size: e3.size ?? 0 }));
1201
+ return r2.map((e2) => ({ name: e2.name, path: e2.path, type: e2.type, sha: e2.sha, size: e2.size ?? 0 }));
935
1202
  } catch (err) {
936
1203
  if (err instanceof GitHubError && err.status === 404) return [];
937
1204
  throw err;
@@ -984,7 +1251,7 @@ class GitHubClient {
984
1251
  async listFiles(ref) {
985
1252
  const r2 = await this.request("GET", `${this.repoPath}/git/trees/${encodeRef(ref)}?recursive=1`);
986
1253
  if (r2.truncated) throw new GitHubError(413, "The repository tree is too large to read in one request.");
987
- return r2.tree.filter((e3) => e3.type === "blob").map((e3) => e3.path);
1254
+ return r2.tree.filter((e2) => e2.type === "blob").map((e2) => e2.path);
988
1255
  }
989
1256
  // --- Pull requests, reviews, checks ---------------------------------------------------------
990
1257
  async listPullRequests(state = "open") {
@@ -1017,12 +1284,12 @@ class GitHubClient {
1017
1284
  async listDeployments(sha) {
1018
1285
  const list = await this.request("GET", `${this.repoPath}/deployments?sha=${encodeURIComponent(sha)}&per_page=30`);
1019
1286
  const latest = /* @__PURE__ */ new Map();
1020
- for (const d of list) if (!latest.has(d.environment)) latest.set(d.environment, d);
1287
+ for (const d2 of list) if (!latest.has(d2.environment)) latest.set(d2.environment, d2);
1021
1288
  return Promise.all(
1022
- [...latest.values()].map(async (d) => {
1023
- const st = await this.request("GET", `${this.repoPath}/deployments/${d.id}/statuses?per_page=1`).catch(() => []);
1289
+ [...latest.values()].map(async (d2) => {
1290
+ const st = await this.request("GET", `${this.repoPath}/deployments/${d2.id}/statuses?per_page=1`).catch(() => []);
1024
1291
  const s = st[0];
1025
- return { id: d.id, environment: d.environment, state: s?.state ?? null, environmentUrl: s?.environment_url || null };
1292
+ return { id: d2.id, environment: d2.environment, state: s?.state ?? null, environmentUrl: s?.environment_url || null };
1026
1293
  })
1027
1294
  );
1028
1295
  }
@@ -1109,7 +1376,7 @@ class GitHubClient {
1109
1376
  function toCommitSummary(c10) {
1110
1377
  return {
1111
1378
  sha: c10.sha,
1112
- parents: (c10.parents ?? []).map((p2) => p2.sha),
1379
+ parents: (c10.parents ?? []).map((p) => p.sha),
1113
1380
  date: c10.commit?.committer?.date ?? c10.commit?.author?.date ?? "",
1114
1381
  author: c10.author?.login ?? c10.commit?.author?.name ?? "unknown",
1115
1382
  message: c10.commit?.message ?? ""
@@ -1160,7 +1427,7 @@ async function loadRepoFiles(client, commitSha, fallbackTokensPath) {
1160
1427
  const warnings = [];
1161
1428
  let config;
1162
1429
  let configText;
1163
- const configEntry = entries.find((e3) => e3.type === "blob" && e3.path === CONFIG_FILE);
1430
+ const configEntry = entries.find((e2) => e2.type === "blob" && e2.path === CONFIG_FILE);
1164
1431
  if (configEntry) {
1165
1432
  try {
1166
1433
  configText = await client.getBlobText(configEntry.sha);
@@ -1173,16 +1440,16 @@ async function loadRepoFiles(client, commitSha, fallbackTokensPath) {
1173
1440
  const checksFile = config?.tokens.contrastChecks ?? DEFAULT_TOKEN_PATHS.contrastChecks;
1174
1441
  const prefix = tokensPath2 + "/";
1175
1442
  const wanted = entries.filter(
1176
- (e3) => e3.type === "blob" && e3.path.startsWith(prefix) && (e3.path.endsWith(".tokens.json") || e3.path === prefix + checksFile)
1443
+ (e2) => e2.type === "blob" && e2.path.startsWith(prefix) && (e2.path.endsWith(".tokens.json") || e2.path === prefix + checksFile)
1177
1444
  );
1178
- if (!wanted.some((e3) => e3.path.endsWith(".tokens.json"))) throw new Error(`No *.tokens.json files found under ${tokensPath2} at ${commitSha.slice(0, 7)}.`);
1445
+ if (!wanted.some((e2) => e2.path.endsWith(".tokens.json"))) throw new Error(`No *.tokens.json files found under ${tokensPath2} at ${commitSha.slice(0, 7)}.`);
1179
1446
  const files = {};
1180
1447
  let contrastChecks;
1181
1448
  const queue = [...wanted];
1182
1449
  const worker = async () => {
1183
- for (let e3 = queue.shift(); e3; e3 = queue.shift()) {
1184
- const text = await client.getBlobText(e3.sha);
1185
- const rel = e3.path.slice(prefix.length);
1450
+ for (let e2 = queue.shift(); e2; e2 = queue.shift()) {
1451
+ const text = await client.getBlobText(e2.sha);
1452
+ const rel = e2.path.slice(prefix.length);
1186
1453
  if (rel === checksFile) contrastChecks = text;
1187
1454
  else files[rel] = text;
1188
1455
  }
@@ -1215,7 +1482,7 @@ async function loadProtection(client, defaultBranch) {
1215
1482
  }
1216
1483
  async function loadRequiredChecks(client, defaultBranch) {
1217
1484
  const onDefault = await client.listCheckRuns(defaultBranch).catch(() => []);
1218
- const merged = await client.listPullRequests("closed").then((prs) => prs.find((p2) => p2.state === "merged" && p2.baseRef === defaultBranch)).catch(() => void 0);
1485
+ const merged = await client.listPullRequests("closed").then((prs) => prs.find((p) => p.state === "merged" && p.baseRef === defaultBranch)).catch(() => void 0);
1219
1486
  const onPull = merged?.headSha ? await client.listCheckRuns(merged.headSha).catch(() => []) : [];
1220
1487
  return requiredCheckNames(onDefault, onPull);
1221
1488
  }
@@ -1248,11 +1515,11 @@ function importsIn(text) {
1248
1515
  for (const m2 of text.matchAll(IMPORT_RE)) out.add(m2[1] ?? m2[2]);
1249
1516
  return [...out];
1250
1517
  }
1251
- const norm = (p2) => p2.replace(/\\/g, "/").replace(/\/+$/, "");
1252
- const isStory = (p2) => /\.stories\.[cm]?[jt]sx?$/.test(p2);
1253
- const isTest = (p2) => /\.(test|spec)\.[cm]?[jt]sx?$/.test(p2);
1254
- const isCss = (p2) => /\.(css|scss|less)$/.test(p2);
1255
- const isScript = (p2) => /\.[cm]?[jt]sx?$/.test(p2);
1518
+ const norm = (p) => p.replace(/\\/g, "/").replace(/\/+$/, "");
1519
+ const isStory = (p) => /\.stories\.[cm]?[jt]sx?$/.test(p);
1520
+ const isTest = (p) => /\.(test|spec)\.[cm]?[jt]sx?$/.test(p);
1521
+ const isCss = (p) => /\.(css|scss|less)$/.test(p);
1522
+ const isScript = (p) => /\.[cm]?[jt]sx?$/.test(p);
1256
1523
  function componentOf(from, spec, componentsDir) {
1257
1524
  if (!spec.startsWith(".")) return null;
1258
1525
  const parts = from.split("/").slice(0, -1);
@@ -1267,9 +1534,9 @@ function componentOf(from, spec, componentsDir) {
1267
1534
  }
1268
1535
  function componentForPath(path, componentsDir) {
1269
1536
  const dir = norm(componentsDir);
1270
- const p2 = norm(path);
1271
- if (!p2.startsWith(`${dir}/`)) return null;
1272
- const rest = p2.slice(dir.length + 1).split("/");
1537
+ const p = norm(path);
1538
+ if (!p.startsWith(`${dir}/`)) return null;
1539
+ const rest = p.slice(dir.length + 1).split("/");
1273
1540
  return rest.length >= 2 ? rest[0] : null;
1274
1541
  }
1275
1542
  function buildUsageIndex(files, componentsDir) {
@@ -1306,7 +1573,7 @@ function buildUsageIndex(files, componentsDir) {
1306
1573
  mod.files.sort();
1307
1574
  mod.vars = [...vars.get(mod.id) ?? []].sort();
1308
1575
  mod.imports = [...imports.get(mod.id) ?? []].sort();
1309
- mod.storyImports = [...storyImports.get(mod.id) ?? []].filter((d) => !mod.imports.includes(d)).sort();
1576
+ mod.storyImports = [...storyImports.get(mod.id) ?? []].filter((d2) => !mod.imports.includes(d2)).sort();
1310
1577
  for (const v2 of mod.vars) (byVar[v2] ??= []).push(mod.id);
1311
1578
  }
1312
1579
  for (const k3 of Object.keys(byVar)) byVar[k3].sort();
@@ -1328,7 +1595,7 @@ function impactedModules(index, input) {
1328
1595
  if (id && index.modules[id]) add(id, `file changed: ${norm(f)}`, false);
1329
1596
  }
1330
1597
  const renderedBy = /* @__PURE__ */ new Map();
1331
- for (const m2 of Object.values(index.modules)) for (const d of m2.imports) (renderedBy.get(d) ?? renderedBy.set(d, []).get(d)).push(m2.id);
1598
+ for (const m2 of Object.values(index.modules)) for (const d2 of m2.imports) (renderedBy.get(d2) ?? renderedBy.set(d2, []).get(d2)).push(m2.id);
1332
1599
  const queue = [...reasons.keys()];
1333
1600
  while (queue.length) {
1334
1601
  const id = queue.shift();
@@ -1351,10 +1618,10 @@ function tokenUsage(tokens, reads) {
1351
1618
  const used = /* @__PURE__ */ new Set();
1352
1619
  const queue = [...direct];
1353
1620
  while (queue.length) {
1354
- const p2 = queue.pop();
1355
- if (used.has(p2)) continue;
1356
- used.add(p2);
1357
- for (const r2 of byPath.get(p2)?.refs ?? []) if (!used.has(r2) && byPath.has(r2)) queue.push(r2);
1621
+ const p = queue.pop();
1622
+ if (used.has(p)) continue;
1623
+ used.add(p);
1624
+ for (const r2 of byPath.get(p)?.refs ?? []) if (!used.has(r2) && byPath.has(r2)) queue.push(r2);
1358
1625
  }
1359
1626
  return { used, direct };
1360
1627
  }
@@ -1395,7 +1662,7 @@ function gitHubHistoryBackend(client, config, opts = {}) {
1395
1662
  const merges = /* @__PURE__ */ new Map();
1396
1663
  const enriched = await pool(list, async (c10) => {
1397
1664
  const prs = await client.listPullRequestsForCommit(c10.sha).catch(() => []);
1398
- const pr = prs.find((p2) => p2.mergedAt && p2.baseRef === ref) ?? prs.find((p2) => p2.mergedAt);
1665
+ const pr = prs.find((p) => p.mergedAt && p.baseRef === ref) ?? prs.find((p) => p.mergedAt);
1399
1666
  if (!pr) return c10;
1400
1667
  const prInfo = { number: pr.number, title: pr.title, url: pr.url, author: pr.author, ...pr.mergedAt ? { mergedAt: pr.mergedAt } : {}, body: pr.body };
1401
1668
  if (pr.mergeCommitSha && pr.mergeCommitSha !== c10.sha) {
@@ -1419,20 +1686,20 @@ function gitHubHistoryBackend(client, config, opts = {}) {
1419
1686
  },
1420
1687
  async tokenFiles(sha) {
1421
1688
  const entries = await tree(sha);
1422
- const blobs = entries.filter((e3) => e3.type === "blob" && e3.path.startsWith(prefix));
1423
- const picked = new Set(selectTokenFiles(config, blobs.map((e3) => e3.path)));
1424
- const wanted = blobs.filter((e3) => picked.has(prefix ? e3.path.slice(prefix.length) : e3.path));
1425
- const texts = await pool(wanted, async (e3) => [prefix ? e3.path.slice(prefix.length) : e3.path, await client.getBlobText(e3.sha)]);
1689
+ const blobs = entries.filter((e2) => e2.type === "blob" && e2.path.startsWith(prefix));
1690
+ const picked = new Set(selectTokenFiles(config, blobs.map((e2) => e2.path)));
1691
+ const wanted = blobs.filter((e2) => picked.has(prefix ? e2.path.slice(prefix.length) : e2.path));
1692
+ const texts = await pool(wanted, async (e2) => [prefix ? e2.path.slice(prefix.length) : e2.path, await client.getBlobText(e2.sha)]);
1426
1693
  return new Map(texts);
1427
1694
  },
1428
1695
  async changesetPaths(sha) {
1429
1696
  const dir = config.changesets?.dir.replace(/\/$/, "");
1430
1697
  if (!dir) return [];
1431
- return (await tree(sha)).filter((e3) => e3.type === "blob" && e3.path.startsWith(`${dir}/`)).map((e3) => e3.path);
1698
+ return (await tree(sha)).filter((e2) => e2.type === "blob" && e2.path.startsWith(`${dir}/`)).map((e2) => e2.path);
1432
1699
  },
1433
1700
  async readFile(sha, path) {
1434
- const e3 = (await tree(sha)).find((x) => x.type === "blob" && x.path === path);
1435
- return e3 ? client.getBlobText(e3.sha) : null;
1701
+ const e2 = (await tree(sha)).find((x) => x.type === "blob" && x.path === path);
1702
+ return e2 ? client.getBlobText(e2.sha) : null;
1436
1703
  }
1437
1704
  };
1438
1705
  }
@@ -1453,9 +1720,9 @@ async function loadGitHubHistory(client, config, opts = {}) {
1453
1720
  if (head) {
1454
1721
  const files = await backend.tree(head).catch(() => []);
1455
1722
  for (const dir of packageDirCandidates(config)) {
1456
- const p2 = (f) => dir ? `${dir}/${f}` : f;
1457
- const cl = files.find((e3) => e3.path === p2("CHANGELOG.md"));
1458
- const pkg = files.find((e3) => e3.path === p2("package.json"));
1723
+ const p = (f) => dir ? `${dir}/${f}` : f;
1724
+ const cl = files.find((e2) => e2.path === p("CHANGELOG.md"));
1725
+ const pkg = files.find((e2) => e2.path === p("package.json"));
1459
1726
  if (!cl && !pkg) continue;
1460
1727
  if (cl) changelog = parseChangelog(await client.getBlobText(cl.sha));
1461
1728
  if (pkg) {
@@ -1503,14 +1770,14 @@ function demoHistory(config, current) {
1503
1770
  }
1504
1771
  const entries = [];
1505
1772
  kept.forEach((step, i2) => {
1506
- const e3 = buildHistoryEntry({
1773
+ const e2 = buildHistoryEntry({
1507
1774
  config,
1508
1775
  commit: { sha: `demo${String(step.pr).padStart(36, "0")}`, parents: [`demo${String(step.pr - 1).padStart(36, "0")}`], date: step.date, author: step.author, subject: step.title, body: step.why, pr: { number: step.pr, title: step.title, author: step.author, mergedAt: step.date, body: step.why } },
1509
1776
  before: states[i2],
1510
1777
  after: states[i2 + 1],
1511
1778
  demo: true
1512
1779
  });
1513
- if (e3) entries.push(e3);
1780
+ if (e2) entries.push(e2);
1514
1781
  });
1515
1782
  return { ...buildReport({ source: "demo", label: "Demo history (fixture data)", ref: "demo", entries, releases: DEMO_RELEASES, truncated: false }), demo: true };
1516
1783
  }
@@ -1523,14 +1790,14 @@ async function branchPreviewUrls(gh, ref, config, opts = {}) {
1523
1790
  if (typeof ref === "number") {
1524
1791
  pr = ref;
1525
1792
  if (!branch || !sha) {
1526
- const p2 = await gh.getPullRequest(ref);
1527
- branch ??= p2.headRef;
1528
- sha ??= p2.headSha;
1793
+ const p = await gh.getPullRequest(ref);
1794
+ branch ??= p.headRef;
1795
+ sha ??= p.headSha;
1529
1796
  }
1530
1797
  } else {
1531
1798
  sha = ref;
1532
1799
  if (!branch || !opts.comments) {
1533
- const open = (await gh.listPullRequestsForCommit(ref).catch(() => [])).find((p2) => p2.state === "open");
1800
+ const open = (await gh.listPullRequestsForCommit(ref).catch(() => [])).find((p) => p.state === "open");
1534
1801
  if (open) {
1535
1802
  pr = open.number;
1536
1803
  branch ??= open.headRef;
@@ -1655,12 +1922,12 @@ const brandDisplayName = (slug) => slug.split("-").filter(Boolean).map((w) => w[
1655
1922
  function brandLayers(config) {
1656
1923
  const out = {};
1657
1924
  for (const l2 of config.tokens.layers) {
1658
- const ph = (l2.files.match(/\{([^}]+)\}/g) ?? []).map((p2) => p2.slice(1, -1));
1925
+ const ph = (l2.files.match(/\{([^}]+)\}/g) ?? []).map((p) => p.slice(1, -1));
1659
1926
  if (!ph.includes("brand")) continue;
1660
1927
  if (ph.length === 1 && !out.brand) out.brand = l2.files;
1661
1928
  else if (ph.length === 2 && !out.override) {
1662
1929
  out.override = l2.files;
1663
- out.overrideAxis = ph.find((p2) => p2 !== "brand");
1930
+ out.overrideAxis = ph.find((p) => p !== "brand");
1664
1931
  }
1665
1932
  }
1666
1933
  return out;
@@ -1803,8 +2070,8 @@ function planNewBrand(source, input) {
1803
2070
  if (r2.issue) issues.push({ ...r2.issue, path: `palette.${role}` });
1804
2071
  anchors[role] = r2.anchor;
1805
2072
  return r2.ramp;
1806
- } catch (e3) {
1807
- issues.push({ level: "error", code: "invalid-color", message: e3.message, path: `palette.${role}` });
2073
+ } catch (e2) {
2074
+ issues.push({ level: "error", code: "invalid-color", message: e2.message, path: `palette.${role}` });
1808
2075
  return void 0;
1809
2076
  }
1810
2077
  };
@@ -1889,7 +2156,7 @@ function planNewBrand(source, input) {
1889
2156
  const primDir = config.tokens.tiers.primitive?.[0]?.replace(/\/$/, "") ?? config.tokens.primitives;
1890
2157
  const primFile = `${primDir}/${slug}.tokens.json`;
1891
2158
  if (prims.size && files.has(primFile)) issues.push({ level: "error", code: "slug-file-exists", message: `${tokensPath(config, primFile)} already exists. Pick another name.` });
1892
- for (const r2 of prims.keys()) if (before.allPaths().some((p2) => p2.startsWith(`color.${r2}.`))) issues.push({ level: "error", code: "ramp-exists", message: `A primitive ramp color.${r2} already exists. Pick another name.` });
2159
+ for (const r2 of prims.keys()) if (before.allPaths().some((p) => p.startsWith(`color.${r2}.`))) issues.push({ level: "error", code: "ramp-exists", message: `A primitive ramp color.${r2} already exists. Pick another name.` });
1893
2160
  doc.$description = `${name}: created with Bridge, started from ${blank ? "a blank brand" : brandDisplayName(from)}.`;
1894
2161
  doc.$extensions = { ...isObj(doc.$extensions) ? doc.$extensions : {}, "dev.bridge.brand": { name, from, ...Object.keys(anchors).length ? { anchors } : {} } };
1895
2162
  const { $description, $extensions, ...rest } = doc;
@@ -1931,8 +2198,8 @@ function planNewBrand(source, input) {
1931
2198
  try {
1932
2199
  configText = addBrandToConfigText(baseConfigText, slug);
1933
2200
  nextConfig = issues.some((i2) => i2.code.startsWith("slug-")) ? config : loadConfig(configText);
1934
- } catch (e3) {
1935
- issues.push({ level: "error", code: "config", message: e3.message });
2201
+ } catch (e2) {
2202
+ issues.push({ level: "error", code: "config", message: e2.message });
1936
2203
  }
1937
2204
  const after = new LayeredTokenSet(nextConfig, nextFiles);
1938
2205
  const key = (i2) => `${i2.code}|${i2.path ?? ""}|${i2.message}`;
@@ -1946,7 +2213,7 @@ function planNewBrand(source, input) {
1946
2213
  const pairs = parseContrastChecks(source.contrastText);
1947
2214
  const inGate = nextConfig.axes.brand?.values.includes(slug);
1948
2215
  const combos = inGate ? after.combos(nextConfig.contrast?.modes).filter((c10) => c10.brand === slug) : [];
1949
- const results = combos.flatMap((c10) => pairs.map((p2) => checkLayeredPair(after, p2, c10)));
2216
+ const results = combos.flatMap((c10) => pairs.map((p) => checkLayeredPair(after, p, c10)));
1950
2217
  const failing = results.filter((r2) => !r2.pass);
1951
2218
  const themes = [...new Set(combos.map((c10) => c10.theme).filter((t3) => !!t3))];
1952
2219
  const ramps = {};
@@ -1960,7 +2227,7 @@ function planNewBrand(source, input) {
1960
2227
  if (JSON.stringify(r2) !== JSON.stringify(ramps.primary)) ramps[role] = r2;
1961
2228
  }
1962
2229
  }
1963
- const addedTokens = after.defs.filter((d) => created.includes(d.file)).map((d) => ({ kind: "added", path: d.path }));
2230
+ const addedTokens = after.defs.filter((d2) => created.includes(d2.file)).map((d2) => ({ kind: "added", path: d2.path }));
1964
2231
  const risk = classifyRisk({ tokenChanges: addedTokens, files: [{ path: CONFIG_FILE, status: "modified" }], config });
1965
2232
  const planned = [
1966
2233
  ...created.map((f) => ({ path: tokensPath(config, f), action: "create", content: nextFiles.get(f) })),
@@ -2112,21 +2379,21 @@ function cssModuleClasses(css) {
2112
2379
  const cell$1 = (s) => s.replace(/\|/g, "\\|").replace(/\n/g, " ");
2113
2380
  function propsTable(name, props, inherits) {
2114
2381
  if (!props.length) return inherits ? `${name} has no props of its own. It accepts every native <${inherits}> attribute.` : "";
2115
- const rows = props.map((p2) => `| \`${p2.name}\`${p2.required ? " (required)" : ""} | \`${cell$1(p2.type)}\` | ${p2.defaultValue ? `\`${cell$1(p2.defaultValue)}\`` : ""} | ${cell$1(p2.description ?? "")} |`);
2382
+ const rows = props.map((p) => `| \`${p.name}\`${p.required ? " (required)" : ""} | \`${cell$1(p.type)}\` | ${p.defaultValue ? `\`${cell$1(p.defaultValue)}\`` : ""} | ${cell$1(p.description ?? "")} |`);
2116
2383
  const tail = inherits ? `
2117
2384
 
2118
2385
  Also accepts every native <${inherits}> attribute.` : "";
2119
2386
  return ["| Prop | Type | Default | Description |", "| --- | --- | --- | --- |", ...rows].join("\n") + tail;
2120
2387
  }
2121
2388
  const isEmpty = (v2) => v2 === void 0 || v2 === null || typeof v2 === "string" && !v2.trim() || Array.isArray(v2) && v2.length === 0;
2122
- function missingProse(d) {
2123
- return PROSE_KEYS.filter((k3) => isEmpty(d?.[k3]));
2389
+ function missingProse(d2) {
2390
+ return PROSE_KEYS.filter((k3) => isEmpty(d2?.[k3]));
2124
2391
  }
2125
2392
  function prefillDocs(input) {
2126
2393
  const existing = input.existing ?? null;
2127
2394
  const anatomy = {};
2128
2395
  for (const c10 of input.cssClasses) anatomy[c10] = existing?.anatomy?.[c10] ?? anatomyLabel(c10);
2129
- const contrastNotes = (input.contrast ?? []).slice().sort((a, b) => a.ratio - b.ratio).map((p2) => `${p2.foreground} on ${p2.background}: ${p2.ratio.toFixed(2)}:1 at worst over every brand and theme, needs ${p2.min}:1 (${p2.ratio >= p2.min ? "passes" : "fails"}).`);
2396
+ const contrastNotes = (input.contrast ?? []).slice().sort((a, b) => a.ratio - b.ratio).map((p) => `${p.foreground} on ${p.background}: ${p.ratio.toFixed(2)}:1 at worst over every brand and theme, needs ${p.min}:1 (${p.ratio >= p.min ? "passes" : "fails"}).`);
2130
2397
  const missing = missingProse(existing);
2131
2398
  const changelogLine = input.change ? `${input.name}: ${input.change.replace(/\.$/, "")}.` : missing.length === PROSE_KEYS.length ? `${input.name}: usage guidance added.` : `${input.name}: usage guidance updated.`;
2132
2399
  const draft = {
@@ -2194,7 +2461,7 @@ ${text.trim()}
2194
2461
  ] : [],
2195
2462
  ...options.rewrite ? ["Rewrite each one from the facts and the source: keep what is true in the current text, drop what the code does not support."] : []
2196
2463
  ] : [`Write the missing prose of ${prefill.component}.docs.json for the Bridge design system.`];
2197
- const shape = keys ? [
2464
+ const shape2 = keys ? [
2198
2465
  `- ${check.length ? "Return" : "Write"} only these keys: ${keys.join(", ")}${check.length ? ` (the checked ones, ${check.join(", ")}, only when they need a fix)` : ""}. Never return anatomy, preview or any other key: code decides them.`,
2199
2466
  `- Answer with one JSON object holding only those keys, nothing else: ${docsSectionShapes(keys)}.`
2200
2467
  ] : [
@@ -2208,7 +2475,7 @@ ${text.trim()}
2208
2475
  "- Ground every sentence in the facts and the source below. Never invent props, variants, keyboard behavior or tokens that are not there.",
2209
2476
  "- Bridge voice: sentence case, plain words, verbs first, no em dashes, no marketing words.",
2210
2477
  '- Keep the keys and shapes of the example docs.json. dos and donts are { "title", "text" } objects; add an "example" only with components and props that exist.',
2211
- ...shape,
2478
+ ...shape2,
2212
2479
  "",
2213
2480
  "Facts computed from the code:",
2214
2481
  facts.join("\n\n"),
@@ -2223,29 +2490,29 @@ ${JSON.stringify(prefill.draft, null, 2)}`,
2223
2490
  block("example-docs-json", conventions.example)
2224
2491
  ].filter((x, i2, all) => x !== "" || all[i2 - 1] !== "").join("\n");
2225
2492
  }
2226
- function markClaudeDraft(d, sections) {
2493
+ function markClaudeDraft(d2, sections) {
2227
2494
  if (!sections) {
2228
- const { draftedSections: _all, ...rest } = d;
2495
+ const { draftedSections: _all, ...rest } = d2;
2229
2496
  return { ...rest, draftedBy: "claude", needsReview: true };
2230
2497
  }
2231
- const waiting = d.needsReview === true ? d.draftedSections ?? (d.draftedBy ? [...PROSE_KEYS] : []) : [];
2498
+ const waiting = d2.needsReview === true ? d2.draftedSections ?? (d2.draftedBy ? [...PROSE_KEYS] : []) : [];
2232
2499
  const union = PROSE_KEYS.filter((k3) => waiting.includes(k3) || sections.includes(k3));
2233
- return { ...d, draftedBy: "claude", needsReview: true, draftedSections: union };
2500
+ return { ...d2, draftedBy: "claude", needsReview: true, draftedSections: union };
2234
2501
  }
2235
- function sectionsNeedingReview(d) {
2236
- if (!d || d.needsReview !== true) return [];
2237
- return d.draftedSections ? PROSE_KEYS.filter((k3) => d.draftedSections.includes(k3)) : [...PROSE_KEYS];
2502
+ function sectionsNeedingReview(d2) {
2503
+ if (!d2 || d2.needsReview !== true) return [];
2504
+ return d2.draftedSections ? PROSE_KEYS.filter((k3) => d2.draftedSections.includes(k3)) : [...PROSE_KEYS];
2238
2505
  }
2239
- const needsDocsReview = (d) => Boolean(d && d.needsReview === true);
2240
- function acceptDocsDraft(d) {
2241
- const { draftedSections: _done, ...rest } = d;
2506
+ const needsDocsReview = (d2) => Boolean(d2 && d2.needsReview === true);
2507
+ function acceptDocsDraft(d2) {
2508
+ const { draftedSections: _done, ...rest } = d2;
2242
2509
  return { ...rest, needsReview: false };
2243
2510
  }
2244
- function formatDocsJson(d) {
2511
+ function formatDocsJson(d2) {
2245
2512
  const order = ["summary", "category", "status", ...DOCS_KEYS.filter((k3) => k3 !== "summary"), "draftedBy", "draftedSections", "needsReview"];
2246
2513
  const out = {};
2247
- for (const k3 of order) if (d[k3] !== void 0) out[k3] = d[k3];
2248
- for (const [k3, v2] of Object.entries(d)) if (!(k3 in out) && v2 !== void 0) out[k3] = v2;
2514
+ for (const k3 of order) if (d2[k3] !== void 0) out[k3] = d2[k3];
2515
+ for (const [k3, v2] of Object.entries(d2)) if (!(k3 in out) && v2 !== void 0) out[k3] = v2;
2249
2516
  return `${JSON.stringify(out, null, 2)}
2250
2517
  `;
2251
2518
  }
@@ -2253,7 +2520,7 @@ function patchNode(old, next) {
2253
2520
  if (plainEqual(toPlain(old), next)) return old;
2254
2521
  if (old.kind === "object" && next && typeof next === "object" && !Array.isArray(next)) {
2255
2522
  const n2 = next;
2256
- const kept = old.entries.filter((e3) => n2[e3.key] !== void 0).map((e3) => ({ key: e3.key, value: patchNode(e3.value, n2[e3.key]) }));
2523
+ const kept = old.entries.filter((e2) => n2[e2.key] !== void 0).map((e2) => ({ key: e2.key, value: patchNode(e2.value, n2[e2.key]) }));
2257
2524
  const added = Object.keys(n2).filter((k3) => n2[k3] !== void 0 && !getEntry(old, k3)).map((k3) => ({ key: k3, value: fromPlain(n2[k3], void 0, old.inline) }));
2258
2525
  return { kind: "object", inline: old.inline, entries: [...kept, ...added] };
2259
2526
  }
@@ -2293,17 +2560,17 @@ function propShape(s) {
2293
2560
  }
2294
2561
  const VARIANT_FIRST = ["variant", "tone", "intent", "appearance", "kind", "type", "style"];
2295
2562
  function shortVariant(key) {
2296
- const pairs = key.split(", ").map((p2) => {
2297
- const at2 = p2.indexOf("=");
2298
- return at2 < 0 ? { k: "", v: p2.trim() } : { k: p2.slice(0, at2).trim(), v: p2.slice(at2 + 1).trim() };
2563
+ const pairs = key.split(", ").map((p) => {
2564
+ const at2 = p.indexOf("=");
2565
+ return at2 < 0 ? { k: "", v: p.trim() } : { k: p.slice(0, at2).trim(), v: p.slice(at2 + 1).trim() };
2299
2566
  });
2300
- const kept = pairs.filter((p2) => p2.v && !/^default$/i.test(p2.v));
2567
+ const kept = pairs.filter((p) => p.v && !/^default$/i.test(p.v));
2301
2568
  if (!kept.length) return key;
2302
2569
  const rank = (k3) => {
2303
2570
  const i2 = VARIANT_FIRST.indexOf(k3.toLowerCase());
2304
2571
  return i2 < 0 ? VARIANT_FIRST.length : i2;
2305
2572
  };
2306
- return kept.map((p2, i2) => ({ ...p2, i: i2 })).sort((a, b) => rank(a.k) - rank(b.k) || a.i - b.i).map((p2) => p2.v).join(" ");
2573
+ return kept.map((p, i2) => ({ ...p, i: i2 })).sort((a, b) => rank(a.k) - rank(b.k) || a.i - b.i).map((p) => p.v).join(" ");
2307
2574
  }
2308
2575
  const shortVariants = (list) => list ? andList(list.split("; ").map(shortVariant)) : "every variant";
2309
2576
  function parseStructureChange(c10) {
@@ -2312,8 +2579,8 @@ function parseStructureChange(c10) {
2312
2579
  const op = m2[1] === "New" ? "added" : m2[1] === "Removed" ? "removed" : "moved";
2313
2580
  const where = `in ${shortVariants(m2[3])}`;
2314
2581
  if (op === "moved") return { op, name: m2[2], where, at: c10.after, from: c10.before };
2315
- const shape = (op === "added" ? c10.after : c10.before) ?? "";
2316
- const sm = /^(\S+)(?: (.*?))?, ((?:after|before) ".*"|alone)$/.exec(shape);
2582
+ const shape2 = (op === "added" ? c10.after : c10.before) ?? "";
2583
+ const sm = /^(\S+)(?: (.*?))?, ((?:after|before) ".*"|alone)$/.exec(shape2);
2317
2584
  return { op, name: m2[2], where, ...sm ? { type: sm[1], ...sm[2] ? { main: sm[2] } : {}, at: sm[3] } : {} };
2318
2585
  }
2319
2586
  function structurePhrase(r2) {
@@ -2397,10 +2664,10 @@ function firstChange(component, kind, c10, all) {
2397
2664
  function draftRequestText(component, kind, changes) {
2398
2665
  const name = component.trim() || "the component";
2399
2666
  if (!changes.length && kind !== "new-component") return { title: "", summary: "" };
2400
- const d = firstChange(name, kind, changes[0], changes);
2667
+ const d2 = firstChange(name, kind, changes[0], changes);
2401
2668
  const rest = kind === "new-component" ? 0 : changes.length - 1;
2402
- const summary = rest > 0 ? `${d.summary} ${capital(plural(rest, "other change"))} ${rest === 1 ? "is" : "are"} listed below.` : d.summary;
2403
- return { title: cleanDraftText(d.title), summary: cleanDraftText(summary) };
2669
+ const summary = rest > 0 ? `${d2.summary} ${capital(plural(rest, "other change"))} ${rest === 1 ? "is" : "are"} listed below.` : d2.summary;
2670
+ return { title: cleanDraftText(d2.title), summary: cleanDraftText(summary) };
2404
2671
  }
2405
2672
  const DRAFT_LINE_MAX = 120;
2406
2673
  function clipText(text, max) {
@@ -2461,32 +2728,32 @@ function draftChangeLine(kind, changes) {
2461
2728
  const tail = rest ? ` (and ${rest} more)` : "";
2462
2729
  return capital(clipText(cleanDraftText(first), DRAFT_LINE_MAX - tail.length)) + tail;
2463
2730
  }
2464
- const tokenOf = (e3) => e3.figma ?? e3.head ?? e3.base;
2465
- const pathOf = (e3) => tokenOf(e3)?.path ?? e3.path;
2731
+ const tokenOf = (e2) => e2.figma ?? e2.head ?? e2.base;
2732
+ const pathOf = (e2) => tokenOf(e2)?.path ?? e2.path;
2466
2733
  function pushChangeRows(entries) {
2467
- return entries.map((e3) => {
2468
- const before = e3.head ?? e3.base;
2469
- const after = e3.figma;
2734
+ return entries.map((e2) => {
2735
+ const before = e2.head ?? e2.base;
2736
+ const after = e2.figma;
2470
2737
  const show = (t3) => {
2471
2738
  if (!t3) return void 0;
2472
2739
  const modes = Object.keys(t3.values);
2473
2740
  if (modes.length <= 1) return formatValue(t3.type, t3.values[modes[0] ?? ""]);
2474
2741
  return modes.map((m2) => `${modeDisplayName(m2)} ${formatValue(t3.type, t3.values[m2])}`).join("; ");
2475
2742
  };
2476
- const renamed = e3.local?.kind === "renamed" && before && after && before.path !== after.path;
2477
- return { field: renamed ? `${before.path} -> ${after.path}` : pathOf(e3), before: show(before), after: show(after) };
2743
+ const renamed = e2.local?.kind === "renamed" && before && after && before.path !== after.path;
2744
+ return { field: renamed ? `${before.path} -> ${after.path}` : pathOf(e2), before: show(before), after: show(after) };
2478
2745
  });
2479
2746
  }
2480
2747
  function names(paths) {
2481
2748
  if (paths.length <= 3) return andList(paths);
2482
2749
  return `${paths.length} tokens, including ${andList(paths.slice(0, 2))}`;
2483
2750
  }
2484
- function valueModes(e3) {
2485
- return (e3.local?.fields ?? []).filter((f) => f.field === "value" && f.mode && f.mode !== "value").map((f) => modeDisplayName(f.mode));
2751
+ function valueModes(e2) {
2752
+ return (e2.local?.fields ?? []).filter((f) => f.field === "value" && f.mode && f.mode !== "value").map((f) => modeDisplayName(f.mode));
2486
2753
  }
2487
2754
  function draftPushDescription(entries, components = []) {
2488
2755
  const by2 = { changed: [], added: [], renamed: [], removed: [] };
2489
- for (const e3 of entries) by2[e3.local?.kind ?? "changed"].push(e3);
2756
+ for (const e2 of entries) by2[e2.local?.kind ?? "changed"].push(e2);
2490
2757
  const clauses = [];
2491
2758
  if (by2.changed.length) {
2492
2759
  const only = by2.changed.length === 1 ? by2.changed[0] : void 0;
@@ -2718,48 +2985,48 @@ function explorationSlugFromBranch(ref) {
2718
2985
  return isExplorationBranch(ref) ? ref.replace(/^refs\/heads\//, "").slice(EXPLORATION_PREFIX.length) : null;
2719
2986
  }
2720
2987
  const explorationNotePath = (slug) => `${EXPLORATION_NOTES_DIR}/${slug}.md`;
2721
- function explorationProblems(e3) {
2988
+ function explorationProblems(e2) {
2722
2989
  const out = [];
2723
- const name = e3.name.trim();
2724
- const slug = e3.slug?.trim() || explorationSlug(name);
2990
+ const name = e2.name.trim();
2991
+ const slug = e2.slug?.trim() || explorationSlug(name);
2725
2992
  if (!name) out.push('Name the exploration, for example "Denser data tables".');
2726
2993
  else if (name.length > 60) out.push("Keep the name under 60 characters: it becomes the branch name.");
2727
2994
  else if (slug.length < 2 || !SLUG_RE.test(slug)) out.push("Use letters or digits in the name: it becomes the branch explore/<name>.");
2728
- if (!e3.purpose.trim()) out.push("Say what you want to learn, in one sentence.");
2995
+ if (!e2.purpose.trim()) out.push("Say what you want to learn, in one sentence.");
2729
2996
  return out;
2730
2997
  }
2731
2998
  const useCaseLabel = (u2) => EXPLORATION_USE_CASES.find((x) => x.value === u2)?.label;
2732
- function explorationNote(e3) {
2733
- const slug = e3.slug || explorationSlug(e3.name);
2734
- const uc = useCaseLabel(e3.useCase);
2999
+ function explorationNote(e2) {
3000
+ const slug = e2.slug || explorationSlug(e2.name);
3001
+ const uc = useCaseLabel(e2.useCase);
2735
3002
  return [
2736
- `# Exploration: ${e3.name.trim()}`,
3003
+ `# Exploration: ${e2.name.trim()}`,
2737
3004
  "",
2738
- e3.purpose.trim(),
3005
+ e2.purpose.trim(),
2739
3006
  "",
2740
3007
  `- Branch: \`${EXPLORATION_PREFIX}${slug}\``,
2741
3008
  ...uc ? [`- Use case: ${uc}`] : [],
2742
- ...e3.startedAt ? [`- Started: ${e3.startedAt.slice(0, 10)}${e3.author ? ` by @${e3.author}` : ""}`] : [],
3009
+ ...e2.startedAt ? [`- Started: ${e2.startedAt.slice(0, 10)}${e2.author ? ` by @${e2.author}` : ""}`] : [],
2743
3010
  "",
2744
3011
  "This file marks the branch as an exploration. It is never merged as is: promoting the pull request to review removes it.",
2745
3012
  ""
2746
3013
  ].join("\n");
2747
3014
  }
2748
- function explorationPrTitle(e3) {
2749
- const n2 = e3.name.trim().replace(/\.$/, "");
3015
+ function explorationPrTitle(e2) {
3016
+ const n2 = e2.name.trim().replace(/\.$/, "");
2750
3017
  return `Exploration: ${n2.charAt(0).toLowerCase()}${n2.slice(1)}`;
2751
3018
  }
2752
- function explorationPrBody(e3, ctx) {
2753
- const slug = e3.slug || explorationSlug(e3.name);
3019
+ function explorationPrBody(e2, ctx) {
3020
+ const slug = e2.slug || explorationSlug(e2.name);
2754
3021
  const branch = `${EXPLORATION_PREFIX}${slug}`;
2755
- const uc = useCaseLabel(e3.useCase);
2756
- const experimental = (e3.experimental ?? []).map((x) => x.trim()).filter(Boolean);
3022
+ const uc = useCaseLabel(e2.useCase);
3023
+ const experimental = (e2.experimental ?? []).map((x) => x.trim()).filter(Boolean);
2757
3024
  const lines = [
2758
- `## Exploration: ${e3.name.trim()}`,
3025
+ `## Exploration: ${e2.name.trim()}`,
2759
3026
  "",
2760
3027
  `> Not mergeable as is. This draft pull request is a sandbox on \`${branch}\`: promote it to a normal review when the idea is validated, or close it.`,
2761
3028
  "",
2762
- `**Purpose.** ${e3.purpose.trim()}`,
3029
+ `**Purpose.** ${e2.purpose.trim()}`,
2763
3030
  ...uc ? ["", `**Use case.** ${uc}`] : [],
2764
3031
  "",
2765
3032
  "### What is experimental",
@@ -2784,7 +3051,7 @@ function explorationPrBody(e3, ctx) {
2784
3051
  `- **Promote:** in Bridge Studio (Changes, Explorations, Promote to review) or \`bridge explore promote ${slug}\`. Bridge marks the pull request ready for review, removes the \`${EXPLORATION_LABEL}\` label and the exploration note, and adds the tier labels. Then it goes through the usual review.`,
2785
3052
  "- **Close:** close this pull request. The branch stays for reference; the preview prerelease is removed.",
2786
3053
  "",
2787
- `<!-- ${MARK$1} ${JSON.stringify({ name: e3.name.trim(), purpose: e3.purpose.trim(), slug, ...e3.useCase ? { useCase: e3.useCase } : {}, ...experimental.length ? { experimental } : {}, ...e3.author ? { author: e3.author } : {}, ...e3.startedAt ? { startedAt: e3.startedAt } : {} }).replace(/-->/g, "--\\u003e")} -->`
3054
+ `<!-- ${MARK$1} ${JSON.stringify({ name: e2.name.trim(), purpose: e2.purpose.trim(), slug, ...e2.useCase ? { useCase: e2.useCase } : {}, ...experimental.length ? { experimental } : {}, ...e2.author ? { author: e2.author } : {}, ...e2.startedAt ? { startedAt: e2.startedAt } : {}, ...e2.source ? { source: e2.source } : {}, ...e2.agent ? { agent: e2.agent } : {} }).replace(/-->/g, "--\\u003e")} -->`
2788
3055
  );
2789
3056
  return lines.join("\n");
2790
3057
  }
@@ -2793,20 +3060,20 @@ function parseExplorationBody(body) {
2793
3060
  const m2 = new RegExp(`<!-- ${MARK$1} (\\{[\\s\\S]*?\\}) -->`).exec(body);
2794
3061
  if (!m2) return void 0;
2795
3062
  try {
2796
- const e3 = JSON.parse(m2[1]);
2797
- return e3 && typeof e3.name === "string" && typeof e3.purpose === "string" ? e3 : void 0;
3063
+ const e2 = JSON.parse(m2[1]);
3064
+ return e2 && typeof e2.name === "string" && typeof e2.purpose === "string" ? e2 : void 0;
2798
3065
  } catch {
2799
3066
  return void 0;
2800
3067
  }
2801
3068
  }
2802
3069
  const labelNames = (labels) => labels.map((l2) => typeof l2 === "string" ? l2 : l2.name ?? "");
2803
- function isExplorationPull(p2) {
2804
- return isExplorationBranch(p2.headRef) || labelNames(p2.labels).includes(EXPLORATION_LABEL) || Boolean(parseExplorationBody(p2.body));
3070
+ function isExplorationPull(p) {
3071
+ return isExplorationBranch(p.headRef) || labelNames(p.labels).includes(EXPLORATION_LABEL) || Boolean(parseExplorationBody(p.body));
2805
3072
  }
2806
- function explorationStatus(p2) {
2807
- const merged = Boolean(p2.merged || p2.merged_at || p2.state === "merged");
2808
- if (p2.state !== "open" && !merged) return "closed";
2809
- if (p2.state === "open" && labelNames(p2.labels).includes(EXPLORATION_LABEL)) return "active";
3073
+ function explorationStatus(p) {
3074
+ const merged = Boolean(p.merged || p.merged_at || p.state === "merged");
3075
+ if (p.state !== "open" && !merged) return "closed";
3076
+ if (p.state === "open" && labelNames(p.labels).includes(EXPLORATION_LABEL)) return "active";
2810
3077
  return "promoted";
2811
3078
  }
2812
3079
  const isActiveExploration = (labels) => labelNames(labels).includes(EXPLORATION_LABEL);
@@ -2852,7 +3119,7 @@ function explorationTryIt(input) {
2852
3119
  function explorationShareMessage(input) {
2853
3120
  const name = input.name.trim().replace(/"/g, "'");
2854
3121
  const head = input.command ? `Exploration "${name}" (${input.branch}): try it in a staging branch of your product with: ${input.command}.` : `Exploration "${name}" (${input.branch}): its test build is being prepared, the install command for a staging branch of your product will be on the pull request in a few minutes.`;
2855
- const previews = (input.previews ?? []).map((p2) => `${p2.label} ${p2.url}`);
3122
+ const previews = (input.previews ?? []).map((p) => `${p.label} ${p.url}`);
2856
3123
  return [head, previews.length ? `Previews: ${previews.join(", ")}.` : "", `Pull request: ${input.url}.`].filter(Boolean).join(" ");
2857
3124
  }
2858
3125
  function explorationRules(branch) {
@@ -2944,8 +3211,8 @@ function declineComment(reason, by2) {
2944
3211
  }
2945
3212
  function requestStatus(issue) {
2946
3213
  const prs = issue.linkedPrs ?? [];
2947
- if (issue.state === "open") return prs.some((p2) => p2.state === "open") ? "in-progress" : "requested";
2948
- if (prs.some((p2) => p2.merged) || issue.stateReason === "completed") return "done";
3214
+ if (issue.state === "open") return prs.some((p) => p.state === "open") ? "in-progress" : "requested";
3215
+ if (prs.some((p) => p.merged) || issue.stateReason === "completed") return "done";
2949
3216
  return "declined";
2950
3217
  }
2951
3218
  const REQUEST_STATUS_LABEL = { requested: "Requested", "in-progress": "In progress", done: "Done", declined: "Declined" };
@@ -3052,7 +3319,7 @@ function draftImagePath(sessionId, itemId, label) {
3052
3319
  return `${DRAFTS_DIR}/${sessionId}/${item}-${label}.png`;
3053
3320
  }
3054
3321
  function composePendingDrafts(input) {
3055
- const p2 = {
3322
+ const p = {
3056
3323
  version: DRAFT_EXCHANGE_VERSION,
3057
3324
  sessionId: input.sessionId ?? newDraftSessionId(input.random),
3058
3325
  createdAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
@@ -3060,9 +3327,9 @@ function composePendingDrafts(input) {
3060
3327
  source: input.source ?? "figma",
3061
3328
  items: input.items.map((i2) => ({ ...i2, changes: i2.changes ?? [] }))
3062
3329
  };
3063
- const problems = validatePendingDrafts(p2);
3330
+ const problems = validatePendingDrafts(p);
3064
3331
  if (problems.length) throw new Error(problems.join(" "));
3065
- return p2;
3332
+ return p;
3066
3333
  }
3067
3334
  const KINDS = new Set(REQUEST_KINDS.map((k3) => k3.value));
3068
3335
  const str = (x) => typeof x === "string";
@@ -3070,15 +3337,15 @@ const optStr = (x) => x === void 0 || typeof x === "string";
3070
3337
  function validatePendingDrafts(x) {
3071
3338
  const out = [];
3072
3339
  if (!x || typeof x !== "object" || Array.isArray(x)) return ["A draft session is a JSON object."];
3073
- const p2 = x;
3074
- if (p2.version !== DRAFT_EXCHANGE_VERSION) out.push(`Unsupported draft session version ${String(p2.version)}: update Bridge.`);
3075
- if (!isDraftSessionId(p2.sessionId)) out.push("The session id is missing or invalid.");
3076
- if (!str(p2.createdAt) || Number.isNaN(Date.parse(p2.createdAt))) out.push("createdAt must be an ISO date.");
3077
- if (p2.status !== "pending" && p2.status !== "drafted") out.push('status must be "pending" or "drafted".');
3078
- if (p2.source !== "figma" && p2.source !== "studio") out.push('source must be "figma" or "studio".');
3079
- if (!Array.isArray(p2.items) || !p2.items.length) out.push("A draft session needs at least one item.");
3340
+ const p = x;
3341
+ if (p.version !== DRAFT_EXCHANGE_VERSION) out.push(`Unsupported draft session version ${String(p.version)}: update Bridge.`);
3342
+ if (!isDraftSessionId(p.sessionId)) out.push("The session id is missing or invalid.");
3343
+ if (!str(p.createdAt) || Number.isNaN(Date.parse(p.createdAt))) out.push("createdAt must be an ISO date.");
3344
+ if (p.status !== "pending" && p.status !== "drafted") out.push('status must be "pending" or "drafted".');
3345
+ if (p.source !== "figma" && p.source !== "studio") out.push('source must be "figma" or "studio".');
3346
+ if (!Array.isArray(p.items) || !p.items.length) out.push("A draft session needs at least one item.");
3080
3347
  const ids = /* @__PURE__ */ new Set();
3081
- for (const [n2, i2] of (Array.isArray(p2.items) ? p2.items : []).entries()) {
3348
+ for (const [n2, i2] of (Array.isArray(p.items) ? p.items : []).entries()) {
3082
3349
  const at2 = `Item ${n2 + 1}`;
3083
3350
  if (!i2 || typeof i2 !== "object") {
3084
3351
  out.push(`${at2} is not an object.`);
@@ -3089,9 +3356,9 @@ function validatePendingDrafts(x) {
3089
3356
  else ids.add(i2.id);
3090
3357
  if (i2.scope !== "request" && i2.scope !== "push" && i2.scope !== "docs") out.push(`${at2}: scope must be "request", "push" or "docs".`);
3091
3358
  if (i2.scope === "docs") {
3092
- const d = i2.docs;
3093
- if (!d || typeof d !== "object" || !str(d.slug) || !d.slug || !str(d.prompt) || !d.prompt || !optStr(d.path)) out.push(`${at2}: a docs item needs docs {slug, task, prompt}.`);
3094
- else out.push(...validateDocsTask(d.task).map((m2) => `${at2}: ${m2}`));
3359
+ const d2 = i2.docs;
3360
+ if (!d2 || typeof d2 !== "object" || !str(d2.slug) || !d2.slug || !str(d2.prompt) || !d2.prompt || !optStr(d2.path)) out.push(`${at2}: a docs item needs docs {slug, task, prompt}.`);
3361
+ else out.push(...validateDocsTask(d2.task).map((m2) => `${at2}: ${m2}`));
3095
3362
  } else if (i2.docs !== void 0) out.push(`${at2}: only a docs item has docs.`);
3096
3363
  if (!optStr(i2.component)) out.push(`${at2}: component must be text.`);
3097
3364
  if (i2.kind !== void 0 && !KINDS.has(i2.kind)) out.push(`${at2}: unknown kind "${String(i2.kind)}".`);
@@ -3102,10 +3369,10 @@ function validatePendingDrafts(x) {
3102
3369
  if (!i2.draft || !str(i2.draft.title) || !str(i2.draft.summary)) out.push(`${at2}: draft must hold a title and a summary.`);
3103
3370
  if (i2.lines !== void 0 && (!Array.isArray(i2.lines) || i2.lines.some((l2) => !l2 || !str(l2.id) || !l2.id || !str(l2.line) || !optStr(l2.title) || !Array.isArray(l2.changes)))) out.push(`${at2}: lines must be a list of {id, changes, line, title}.`);
3104
3371
  }
3105
- if (p2.results !== void 0) {
3106
- if (!Array.isArray(p2.results)) out.push("results must be a list.");
3372
+ if (p.results !== void 0) {
3373
+ if (!Array.isArray(p.results)) out.push("results must be a list.");
3107
3374
  else
3108
- for (const r2 of p2.results) {
3375
+ for (const r2 of p.results) {
3109
3376
  if (!r2 || !str(r2.id) || !str(r2.title) || !str(r2.summary)) out.push("Each result needs an id, a title and a summary.");
3110
3377
  else if (r2.docs !== void 0 && (!r2.docs || typeof r2.docs !== "object" || Array.isArray(r2.docs))) out.push("Result docs must be an object of sections.");
3111
3378
  else if (!optStr(r2.replacement)) out.push("A result replacement must be text.");
@@ -3124,8 +3391,8 @@ function parsePendingDrafts(text) {
3124
3391
  }
3125
3392
  return validatePendingDrafts(json).length ? void 0 : json;
3126
3393
  }
3127
- function serializePendingDrafts(p2) {
3128
- return `${JSON.stringify(p2, null, 2)}
3394
+ function serializePendingDrafts(p) {
3395
+ return `${JSON.stringify(p, null, 2)}
3129
3396
  `;
3130
3397
  }
3131
3398
  function clip(text, max) {
@@ -3181,12 +3448,12 @@ function sanitizeDraftTitle(raw) {
3181
3448
  const t3 = clip(cleanDraftText(raw.replace(/[\r\n]+/g, " ")), DRAFT_TITLE_MAX);
3182
3449
  return t3.charAt(0).toUpperCase() + t3.slice(1);
3183
3450
  }
3184
- function mergeDraftResults(p2, results, at2 = /* @__PURE__ */ new Date()) {
3185
- const ids = new Set(p2.items.map((i2) => i2.id));
3186
- const next = new Map((p2.results ?? []).map((r2) => [r2.id, r2]));
3451
+ function mergeDraftResults(p, results, at2 = /* @__PURE__ */ new Date()) {
3452
+ const ids = new Set(p.items.map((i2) => i2.id));
3453
+ const next = new Map((p.results ?? []).map((r2) => [r2.id, r2]));
3187
3454
  for (const r2 of results) {
3188
- if (!ids.has(r2.id)) throw new Error(`Session ${p2.sessionId} has no item "${r2.id}". Use the ids from bridge_pending_drafts: ${[...ids].join(", ")}.`);
3189
- const item = p2.items.find((i2) => i2.id === r2.id);
3455
+ if (!ids.has(r2.id)) throw new Error(`Session ${p.sessionId} has no item "${r2.id}". Use the ids from bridge_pending_drafts: ${[...ids].join(", ")}.`);
3456
+ const item = p.items.find((i2) => i2.id === r2.id);
3190
3457
  if (item.scope === "docs") {
3191
3458
  next.set(r2.id, { id: r2.id, title: "", summary: "", ...sanitizeDocsResult(item, r2), by: "claude", at: at2.toISOString() });
3192
3459
  continue;
@@ -3196,8 +3463,8 @@ function mergeDraftResults(p2, results, at2 = /* @__PURE__ */ new Date()) {
3196
3463
  if (!clean.title && !clean.summary && !lines.length) throw new Error(`The result for "${r2.id}" has no title and no summary, and no line.`);
3197
3464
  next.set(r2.id, { id: r2.id, title: clean.title, summary: clean.summary, ...lines.length ? { lines } : {}, by: "claude", at: at2.toISOString() });
3198
3465
  }
3199
- const merged = p2.items.map((i2) => next.get(i2.id)).filter((r2) => !!r2);
3200
- return { ...p2, results: merged, status: merged.length === p2.items.length ? "drafted" : "pending" };
3466
+ const merged = p.items.map((i2) => next.get(i2.id)).filter((r2) => !!r2);
3467
+ return { ...p, results: merged, status: merged.length === p.items.length ? "drafted" : "pending" };
3201
3468
  }
3202
3469
  function draftItemBrief(i2) {
3203
3470
  if (i2.scope === "docs" && i2.docs) {
@@ -3232,11 +3499,11 @@ function draftItemBrief(i2) {
3232
3499
  return lines.join("\n");
3233
3500
  }
3234
3501
  const isConflict = (err) => err instanceof GitHubError ? err.status === 409 || err.status === 422 && /sha/i.test(`${err.detail ?? ""} ${err.message}`) : err?.status === 409;
3235
- async function createPendingDrafts(client, p2, branch = REQUESTS_BRANCH) {
3236
- const problems = validatePendingDrafts(p2);
3502
+ async function createPendingDrafts(client, p, branch = REQUESTS_BRANCH) {
3503
+ const problems = validatePendingDrafts(p);
3237
3504
  if (problems.length) throw new Error(problems.join(" "));
3238
- await client.putFile({ path: draftSessionPath(p2.sessionId), content: serializePendingDrafts(p2), branch, message: `Bridge drafts: ${p2.items.length === 1 ? "1 item" : `${p2.items.length} items`} waiting for Claude` });
3239
- return p2;
3505
+ await client.putFile({ path: draftSessionPath(p.sessionId), content: serializePendingDrafts(p), branch, message: `Bridge drafts: ${p.items.length === 1 ? "1 item" : `${p.items.length} items`} waiting for Claude` });
3506
+ return p;
3240
3507
  }
3241
3508
  async function readPendingDrafts(client, sessionId, branch = REQUESTS_BRANCH) {
3242
3509
  const f = await client.getFile(draftSessionPath(sessionId), branch);
@@ -3245,16 +3512,16 @@ async function readPendingDrafts(client, sessionId, branch = REQUESTS_BRANCH) {
3245
3512
  }
3246
3513
  async function listPendingDrafts(client, opts = {}) {
3247
3514
  const branch = opts.branch ?? REQUESTS_BRANCH;
3248
- const entries = (await client.listDirectory(DRAFTS_DIR, branch)).filter((e3) => e3.type === "file" && /\.json$/.test(e3.name));
3515
+ const entries = (await client.listDirectory(DRAFTS_DIR, branch)).filter((e2) => e2.type === "file" && /\.json$/.test(e2.name));
3249
3516
  const out = [];
3250
- for (const e3 of entries) {
3251
- const id = e3.name.replace(/\.json$/, "");
3517
+ for (const e2 of entries) {
3518
+ const id = e2.name.replace(/\.json$/, "");
3252
3519
  if (!isDraftSessionId(id)) continue;
3253
3520
  const r2 = await readPendingDrafts(client, id, branch).catch(() => void 0);
3254
3521
  if (r2 && r2.drafts.sessionId === id) out.push(r2.drafts);
3255
3522
  }
3256
3523
  const status = opts.status ?? "all";
3257
- return out.filter((p2) => status === "all" || p2.status === status).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
3524
+ return out.filter((p) => status === "all" || p.status === status).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
3258
3525
  }
3259
3526
  async function updatePendingDrafts(client, sessionId, change, opts = {}) {
3260
3527
  const branch = opts.branch ?? REQUESTS_BRANCH;
@@ -3272,7 +3539,7 @@ async function updatePendingDrafts(client, sessionId, change, opts = {}) {
3272
3539
  }
3273
3540
  }
3274
3541
  function writeDraftResults(client, sessionId, results, opts = {}) {
3275
- return updatePendingDrafts(client, sessionId, (p2) => mergeDraftResults(p2, results, opts.now), {
3542
+ return updatePendingDrafts(client, sessionId, (p) => mergeDraftResults(p, results, opts.now), {
3276
3543
  ...opts,
3277
3544
  message: `Bridge drafts: ${results.length === 1 ? "1 text" : `${results.length} texts`} drafted by Claude`
3278
3545
  });
@@ -3284,7 +3551,7 @@ async function deletePendingDrafts(client, sessionId, opts = {}) {
3284
3551
  if (!f) return false;
3285
3552
  await client.deleteFile({ path, branch, message: "Bridge drafts: done", sha: f.sha });
3286
3553
  const images = await client.listDirectory(`${DRAFTS_DIR}/${sessionId}`, branch).catch(() => []);
3287
- for (const img of images.filter((e3) => e3.type === "file")) {
3554
+ for (const img of images.filter((e2) => e2.type === "file")) {
3288
3555
  await client.deleteFile({ path: img.path, branch, message: "Bridge drafts: done", sha: img.sha }).catch(() => void 0);
3289
3556
  }
3290
3557
  return true;
@@ -3378,38 +3645,40 @@ class DraftPoller {
3378
3645
  }
3379
3646
  }
3380
3647
  }
3381
- function explorationSummary(p2, _owner, _repo, s) {
3382
- const e3 = parseExplorationBody(p2.body);
3383
- const slug = p2.headRef?.startsWith(EXPLORATION_PREFIX) ? p2.headRef.slice(EXPLORATION_PREFIX.length) : e3?.slug ?? explorationSlug(p2.title);
3648
+ function explorationSummary(p, _owner, _repo, s) {
3649
+ const e2 = parseExplorationBody(p.body);
3650
+ const slug = p.headRef?.startsWith(EXPLORATION_PREFIX) ? p.headRef.slice(EXPLORATION_PREFIX.length) : e2?.slug ?? explorationSlug(p.title);
3384
3651
  return {
3385
- number: p2.number,
3386
- url: p2.url,
3387
- branch: p2.headRef,
3652
+ number: p.number,
3653
+ url: p.url,
3654
+ branch: p.headRef,
3388
3655
  slug,
3389
- name: e3?.name ?? p2.title.replace(/^Exploration:\s*/i, ""),
3390
- purpose: e3?.purpose ?? "",
3391
- ...e3?.useCase ? { useCase: e3.useCase } : {},
3392
- status: explorationStatus({ state: p2.state, labels: p2.labels, headRef: p2.headRef, body: p2.body }),
3393
- draft: p2.draft,
3394
- author: e3?.author ?? p2.author,
3395
- updatedAt: p2.updatedAt,
3396
- headSha: p2.headSha,
3397
- previews: previewLinks(s.apps, { branch: p2.headRef, pr: p2.number, sha: p2.headSha })
3656
+ name: e2?.name ?? p.title.replace(/^Exploration:\s*/i, ""),
3657
+ purpose: e2?.purpose ?? "",
3658
+ ...e2?.useCase ? { useCase: e2.useCase } : {},
3659
+ status: explorationStatus({ state: p.state, labels: p.labels, headRef: p.headRef, body: p.body }),
3660
+ draft: p.draft,
3661
+ author: e2?.author ?? p.author,
3662
+ ...e2?.source ? { source: e2.source } : {},
3663
+ ...e2?.agent ? { agent: e2.agent } : {},
3664
+ updatedAt: p.updatedAt,
3665
+ headSha: p.headSha,
3666
+ previews: previewLinks(s.apps, { branch: p.headRef, pr: p.number, sha: p.headSha })
3398
3667
  };
3399
3668
  }
3400
3669
  async function listExplorationsOnGitHub(gh, s, opts = {}) {
3401
3670
  const pulls = await gh.listPullRequests(opts.state ?? "open");
3402
- return pulls.filter((p2) => isExplorationPull({ state: p2.state, labels: p2.labels, headRef: p2.headRef, body: p2.body })).map((p2) => explorationSummary(p2, gh.owner, gh.name, s));
3671
+ return pulls.filter((p) => isExplorationPull({ state: p.state, labels: p.labels, headRef: p.headRef, body: p.body })).map((p) => explorationSummary(p, gh.owner, gh.name, s));
3403
3672
  }
3404
- async function startExplorationOnGitHub(gh, e3, s) {
3405
- const problems = explorationProblems(e3);
3673
+ async function startExplorationOnGitHub(gh, e2, s) {
3674
+ const problems = explorationProblems(e2);
3406
3675
  if (problems.length) throw new GitHubError(422, problems.join(" "));
3407
3676
  if (!gh.canWrite) throw new GitHubError(401, "Starting an exploration needs a GitHub token (contents and pull requests, read and write, on this repository only).");
3408
- const slug = e3.slug || explorationSlug(e3.name);
3677
+ const slug = e2.slug || explorationSlug(e2.name);
3409
3678
  const branch = `${EXPLORATION_PREFIX}${slug}`;
3410
3679
  const x = gh.withBranchPrefix(EXPLORATION_PREFIX);
3411
3680
  if (await x.getBranchSha(branch)) throw new GitHubError(422, `An exploration named "${slug}" already exists (${branch}). Pick another name, or continue that one.`);
3412
- const full = { ...e3, slug, startedAt: e3.startedAt ?? (/* @__PURE__ */ new Date()).toISOString() };
3681
+ const full = { ...e2, slug, startedAt: e2.startedAt ?? (/* @__PURE__ */ new Date()).toISOString() };
3413
3682
  const commit = await x.commitToNewBranch({
3414
3683
  base: s.base,
3415
3684
  branch,
@@ -3434,21 +3703,21 @@ Exploration: never merged as is. Promote it to review or close it.`,
3434
3703
  previews: previewLinks(s.apps, { branch, pr: pr.number, sha: commit.sha })
3435
3704
  };
3436
3705
  }
3437
- async function explorationTryItOnGitHub(gh, e3) {
3438
- const [comments, head] = await Promise.all([gh.listIssueComments(e3.number), gh.getBranchSha(e3.branch).catch(() => void 0)]);
3706
+ async function explorationTryItOnGitHub(gh, e2) {
3707
+ const [comments, head] = await Promise.all([gh.listIssueComments(e2.number), gh.getBranchSha(e2.branch).catch(() => void 0)]);
3439
3708
  return explorationTryIt({ comment: findPreviewComment(comments)?.body, headSha: head });
3440
3709
  }
3441
- async function explorationTestBuildOnGitHub(gh, e3, config) {
3442
- const [comments, head] = await Promise.all([gh.listIssueComments(e3.number), gh.getBranchSha(e3.branch).catch(() => void 0)]);
3710
+ async function explorationTestBuildOnGitHub(gh, e2, config) {
3711
+ const [comments, head] = await Promise.all([gh.listIssueComments(e2.number), gh.getBranchSha(e2.branch).catch(() => void 0)]);
3443
3712
  const tryIt = explorationTryIt({ comment: findPreviewComment(comments)?.body, headSha: head });
3444
- const previews = await branchPreviewUrls(gh, e3.number, config, { branch: e3.branch, sha: head, comments }).catch(() => []);
3713
+ const previews = await branchPreviewUrls(gh, e2.number, config, { branch: e2.branch, sha: head, comments }).catch(() => []);
3445
3714
  return { tryIt, previews, settled: tryIt.state !== "building" && previewsSettled(previews) };
3446
3715
  }
3447
3716
  async function findExplorationOnGitHub(gh, ref) {
3448
3717
  if (typeof ref === "number" || /^#?\d+$/.test(String(ref))) {
3449
- const p2 = await gh.getPullRequest(Number(String(ref).replace(/^#/, "")));
3450
- if (!isExplorationPull({ state: p2.state, labels: p2.labels, headRef: p2.headRef, body: p2.body })) throw new GitHubError(422, `Pull request #${p2.number} is not an exploration.`);
3451
- return p2;
3718
+ const p = await gh.getPullRequest(Number(String(ref).replace(/^#/, "")));
3719
+ if (!isExplorationPull({ state: p.state, labels: p.labels, headRef: p.headRef, body: p.body })) throw new GitHubError(422, `Pull request #${p.number} is not an exploration.`);
3720
+ return p;
3452
3721
  }
3453
3722
  const branch = `${EXPLORATION_PREFIX}${explorationSlug(String(ref))}`;
3454
3723
  const open = await gh.findOpenPullRequest(branch);
@@ -3456,36 +3725,36 @@ async function findExplorationOnGitHub(gh, ref) {
3456
3725
  return gh.getPullRequest(open.number);
3457
3726
  }
3458
3727
  async function promoteExplorationOnGitHub(gh, ref, opts = {}) {
3459
- const p2 = await findExplorationOnGitHub(gh, ref);
3460
- const status = explorationStatus({ state: p2.state, labels: p2.labels, headRef: p2.headRef, body: p2.body });
3461
- if (status !== "active") throw new GitHubError(422, status === "closed" ? `Exploration #${p2.number} is closed. Reopen it on GitHub first.` : `#${p2.number} is already promoted to review.`);
3462
- const files = await gh.listPullRequestFiles(p2.number);
3463
- const plan = promotionPlan({ title: p2.title, body: p2.body, labels: p2.labels, files: files.map((f) => ({ path: f.filename, status: f.status })), config: opts.config, requests: opts.requests, date: opts.date });
3464
- const out = { ...plan, number: p2.number, url: p2.url, branch: p2.headRef, warnings: [] };
3728
+ const p = await findExplorationOnGitHub(gh, ref);
3729
+ const status = explorationStatus({ state: p.state, labels: p.labels, headRef: p.headRef, body: p.body });
3730
+ if (status !== "active") throw new GitHubError(422, status === "closed" ? `Exploration #${p.number} is closed. Reopen it on GitHub first.` : `#${p.number} is already promoted to review.`);
3731
+ const files = await gh.listPullRequestFiles(p.number);
3732
+ const plan = promotionPlan({ title: p.title, body: p.body, labels: p.labels, files: files.map((f) => ({ path: f.filename, status: f.status })), config: opts.config, requests: opts.requests, date: opts.date });
3733
+ const out = { ...plan, number: p.number, url: p.url, branch: p.headRef, warnings: [] };
3465
3734
  if (opts.dryRun) return out;
3466
3735
  if (!gh.canWrite) throw new GitHubError(401, "Promoting an exploration needs a GitHub token (contents and pull requests, read and write).");
3467
3736
  const x = gh.withBranchPrefix(EXPLORATION_PREFIX);
3468
3737
  if (plan.removeFiles.length) {
3469
- await x.commitToBranch({ branch: p2.headRef, message: "chore(explore): promote to review, remove the exploration note", files: plan.removeFiles.map((path) => ({ path, content: null })) }).catch((e3) => {
3470
- if (e3 instanceof GitHubError && e3.auth === "rejected") throw e3;
3471
- out.warnings.push(`The exploration note stays on the branch (${e3.message}). Delete ${plan.removeFiles.join(", ")} before merging.`);
3738
+ await x.commitToBranch({ branch: p.headRef, message: "chore(explore): promote to review, remove the exploration note", files: plan.removeFiles.map((path) => ({ path, content: null })) }).catch((e2) => {
3739
+ if (e2 instanceof GitHubError && e2.auth === "rejected") throw e2;
3740
+ out.warnings.push(`The exploration note stays on the branch (${e2.message}). Delete ${plan.removeFiles.join(", ")} before merging.`);
3472
3741
  });
3473
3742
  }
3474
- await x.addLabels(p2.number, plan.addLabels);
3475
- await x.removeLabel(p2.number, EXPLORATION_LABEL).catch((e3) => {
3476
- if (!(e3 instanceof GitHubError && e3.status === 404)) out.warnings.push(`The exploration label is still on (${e3.message}). Remove it on GitHub.`);
3743
+ await x.addLabels(p.number, plan.addLabels);
3744
+ await x.removeLabel(p.number, EXPLORATION_LABEL).catch((e2) => {
3745
+ if (!(e2 instanceof GitHubError && e2.status === 404)) out.warnings.push(`The exploration label is still on (${e2.message}). Remove it on GitHub.`);
3477
3746
  });
3478
- await x.updatePullRequest(p2.number, { title: plan.title, body: plan.body });
3479
- await x.markReadyForReview(p2.number).catch((e3) => {
3480
- out.warnings.push(`Still a draft: ${e3.message}`);
3747
+ await x.updatePullRequest(p.number, { title: plan.title, body: plan.body });
3748
+ await x.markReadyForReview(p.number).catch((e2) => {
3749
+ out.warnings.push(`Still a draft: ${e2.message}`);
3481
3750
  });
3482
3751
  return out;
3483
3752
  }
3484
3753
  async function closeExplorationOnGitHub(gh, ref) {
3485
3754
  if (!gh.canWrite) throw new GitHubError(401, "Closing an exploration needs a GitHub token (pull requests: write).");
3486
- const p2 = await findExplorationOnGitHub(gh, ref);
3487
- await gh.updatePullRequest(p2.number, { state: "closed" });
3488
- return { number: p2.number, url: p2.url, branch: p2.headRef };
3755
+ const p = await findExplorationOnGitHub(gh, ref);
3756
+ await gh.updatePullRequest(p.number, { state: "closed" });
3757
+ return { number: p.number, url: p.url, branch: p.headRef };
3489
3758
  }
3490
3759
  async function linkRequestToExplorationOnGitHub(gh, n2, branch, opts = {}) {
3491
3760
  if (!isExplorationBranch(branch)) throw new GitHubError(422, `"${branch}" is not an exploration branch. Exploration branches are named explore/<name>.`);
@@ -3519,27 +3788,27 @@ async function declineRequestOnGitHub(gh, n2, reason, by2) {
3519
3788
  await gh.updateIssue(n2, { state: "closed", state_reason: "not_planned" });
3520
3789
  }
3521
3790
  export {
3522
- af as AAA_MIN,
3523
- ag as AA_MIN,
3791
+ ai as AAA_MIN,
3792
+ aj as AA_MIN,
3524
3793
  ADMIN_ROLE_ID,
3525
3794
  ANTHROPIC_MESSAGES_URL,
3526
3795
  BELL,
3527
3796
  BRAND_FONTS,
3528
3797
  BRAND_SLUG_RE,
3529
- ah as BULK_LIMIT,
3798
+ ak as BULK_LIMIT,
3530
3799
  k as COLOR_FIELDS,
3531
3800
  C as COMPONENT_SPECS_VERSION,
3532
3801
  CONFIG_FILE,
3533
- ai as CONTRAST_CELL_MAX,
3534
- aj as CONTRAST_CHECKS_FILE,
3802
+ al as CONTRAST_CELL_MAX,
3803
+ am as CONTRAST_CHECKS_FILE,
3535
3804
  ConfigError,
3536
- ak as DEFAULT_COMPONENT_SPECS_FILE,
3537
- al as DEFAULT_GOVERNANCE,
3538
- am as DEFAULT_OVERRIDE,
3805
+ an as DEFAULT_COMPONENT_SPECS_FILE,
3806
+ ao as DEFAULT_GOVERNANCE,
3807
+ ap as DEFAULT_OVERRIDE,
3539
3808
  DEFAULT_PROTECTED_BRANCHES,
3540
- an as DEFAULT_RIGHTS,
3809
+ aq as DEFAULT_RIGHTS,
3541
3810
  DEFAULT_TOKEN_PATHS,
3542
- ao as DEFAULT_VISUAL_IMPACT,
3811
+ ar as DEFAULT_VISUAL_IMPACT,
3543
3812
  DEMO_RELEASES,
3544
3813
  DOCS_CHANGE_BUMP,
3545
3814
  DOCS_DRAFT_MODEL,
@@ -3568,16 +3837,16 @@ export {
3568
3837
  EXT_SCOPES,
3569
3838
  GitHubClient,
3570
3839
  GitHubError,
3571
- ap as JsonParseError,
3840
+ as as JsonParseError,
3572
3841
  LIGHTNESS,
3573
3842
  LayeredTokenSet,
3574
3843
  NEUTRAL_ANCHORS,
3575
- aq as OWNER_GROUPS,
3844
+ at as OWNER_GROUPS,
3576
3845
  PIN_TOLERANCE,
3577
- ar as PREVIEW_APP_LABELS,
3578
- as as PREVIEW_COMMENT_MARKER,
3579
- at as PREVIEW_PLACEHOLDERS,
3580
- au as PRIMITIVE_MODE,
3846
+ au as PREVIEW_APP_LABELS,
3847
+ av as PREVIEW_COMMENT_MARKER,
3848
+ aw as PREVIEW_PLACEHOLDERS,
3849
+ ax as PRIMITIVE_MODE,
3581
3850
  PROSE_KEYS,
3582
3851
  PROTECTION_PARTS,
3583
3852
  PROTECTION_PART_PHRASE,
@@ -3587,111 +3856,120 @@ export {
3587
3856
  REQUEST_KINDS,
3588
3857
  REQUEST_LABEL,
3589
3858
  REQUEST_STATUS_LABEL,
3590
- av as RIGHTS,
3591
- aw as RIGHT_LABEL,
3859
+ ay as RIGHTS,
3860
+ az as RIGHT_LABEL,
3592
3861
  RISK_LABELS,
3593
- ax as RISK_TIER,
3862
+ aA as RISK_TIER,
3594
3863
  SIMILARITY_THRESHOLD,
3595
3864
  SINGLE_MODE,
3596
- ay as SPEC_FIELDS,
3865
+ aB as SPEC_FIELDS,
3597
3866
  STEPS,
3598
3867
  TIER_AXIS,
3599
3868
  TIER_NAMES,
3600
- az as TIER_ORDER,
3869
+ aC as TIER_ORDER,
3601
3870
  TOKEN_REJECTED_MESSAGE,
3602
3871
  TOKEN_SETTINGS_URL,
3603
- aA as TeamDirectory,
3604
- aB as UNRELEASED,
3605
- aC as VISUAL_CHECK_LABEL,
3872
+ aD as TeamDirectory,
3873
+ aE as UNRELEASED,
3874
+ aF as VISUAL_CHECK_LABEL,
3606
3875
  acceptDocsDraft,
3607
3876
  acceptDocsText,
3608
3877
  addBrandToConfigText,
3609
- aD as affectedContrast,
3610
- e2 as aliasOf,
3878
+ aG as affectedContrast,
3879
+ d as aliasOf,
3611
3880
  aliasTarget,
3612
3881
  anatomyLabel,
3613
3882
  anchoredRamp,
3614
3883
  anthropicReplyText,
3615
3884
  anthropicRequest,
3616
- aE as appForProject,
3617
- aF as appUrl,
3885
+ aH as appForProject,
3886
+ aI as appUrl,
3618
3887
  applyConfirmedRenames,
3619
3888
  applyDocsSections,
3620
3889
  applyTokenEdits,
3621
- aG as approverEntries,
3622
- aH as approverLists,
3890
+ applyTokenMerge,
3891
+ aJ as approverEntries,
3892
+ aK as approverLists,
3623
3893
  assertSafeBranch,
3624
3894
  assignRequestOnGitHub,
3625
- aI as assignVersions,
3895
+ aL as assignVersions,
3626
3896
  base64ToUtf8,
3627
- aJ as baseBranchOf,
3897
+ aM as baseBranchOf,
3628
3898
  bellChroma,
3629
- aK as branchName,
3899
+ aN as branchName,
3630
3900
  branchPreviewUrls,
3631
- aL as branchSlug,
3901
+ aO as branchSlug,
3632
3902
  brandDisplayName,
3633
3903
  brandPreviewVariables,
3634
3904
  buildHistoryEntry,
3635
3905
  buildReport,
3636
3906
  i as buildTokenSet,
3637
3907
  buildUsageIndex,
3638
- aM as canShip,
3639
- aN as changeKind,
3640
- aO as changeTable,
3641
- aP as changedModes,
3642
- aQ as changesetBump,
3908
+ aP as canShip,
3909
+ changeEdits,
3910
+ aQ as changeKind,
3911
+ aR as changeTable,
3912
+ aS as changedModes,
3913
+ aT as changesetBump,
3643
3914
  checkBrandSlug,
3644
3915
  checkLayeredPair,
3916
+ choiceFor,
3645
3917
  classifyAuth,
3646
- aR as classifyLayered,
3918
+ aU as classifyLayered,
3647
3919
  classifyRisk,
3648
3920
  cleanDocsText,
3649
3921
  cleanDraftText,
3650
- aS as clearRawDeep,
3922
+ aV as clearRawDeep,
3651
3923
  closeExplorationOnGitHub,
3652
3924
  closingIssueNumbers,
3653
3925
  coerceValue,
3654
3926
  collectHistory,
3655
3927
  collectRefs,
3656
- j2 as colorToCss,
3657
- k2 as colorsEqual,
3928
+ k2 as colorToCss,
3929
+ l as colorsEqual,
3930
+ combineChanges,
3931
+ combineConflicts,
3658
3932
  c as comboKey,
3659
- aT as commitMessage,
3660
- l as compactJson,
3933
+ aW as commitMessage,
3934
+ m as compactJson,
3661
3935
  componentForPath,
3662
- aU as composeChangeset,
3936
+ aX as composeChangeset,
3663
3937
  composeFiles,
3664
3938
  composeNewBrandBody,
3665
3939
  composePendingDrafts,
3666
- aV as composePrBody,
3667
- aW as composeProposalBody,
3940
+ aY as composePrBody,
3941
+ aZ as composeProposalBody,
3668
3942
  composeRequestIssue,
3669
- aX as composite,
3670
- aY as contextFor,
3943
+ a_ as composite,
3944
+ a$ as contextFor,
3671
3945
  contextLabel,
3672
- aZ as contrastDelta,
3673
- a_ as contrastDeltaTable,
3674
- a$ as contrastLevel,
3675
- b0 as contrastPair,
3676
- b1 as contrastRatio,
3946
+ b0 as contrastDelta,
3947
+ b1 as contrastDeltaTable,
3948
+ b2 as contrastLevel,
3949
+ b3 as contrastPair,
3950
+ b4 as contrastRatio,
3677
3951
  contrastScope,
3678
- b2 as countChanges,
3952
+ b5 as countChanges,
3679
3953
  createDocsDraftSession,
3680
3954
  createPendingDrafts,
3681
3955
  cssModuleClasses,
3956
+ cssOf,
3957
+ cssVarOf,
3682
3958
  cssVarsIn,
3683
3959
  declineComment,
3684
3960
  declineReasonProblems,
3685
3961
  declineRequestOnGitHub,
3686
- b3 as defaultContext,
3962
+ decodePicks,
3963
+ defaultChoiceFor,
3964
+ b6 as defaultContext,
3687
3965
  defaultFile,
3688
3966
  defaultScopes,
3689
- b4 as defaultTitle,
3690
- b5 as defineConfig,
3967
+ b7 as defaultTitle,
3968
+ b8 as defineConfig,
3691
3969
  deletePendingDrafts,
3692
3970
  demoHistory,
3693
- b6 as detectLayout,
3694
- b7 as diffLayered,
3971
+ b9 as detectLayout,
3972
+ ba as diffLayered,
3695
3973
  docsPrompt,
3696
3974
  docsSectionShapes,
3697
3975
  docsSectionsAnswer,
@@ -3708,12 +3986,13 @@ export {
3708
3986
  dtcgColor,
3709
3987
  effectiveScopes,
3710
3988
  emptyTokenFile,
3989
+ encodePicks,
3711
3990
  ensureRequestsBranch,
3712
- b8 as entriesFor,
3713
- b9 as entryLabel,
3991
+ bb as entriesFor,
3992
+ bc as entryLabel,
3714
3993
  evaluatePairs,
3715
- ba as expandEntries,
3716
- bb as expandOwners,
3994
+ bd as expandEntries,
3995
+ be as expandOwners,
3717
3996
  explorationBranch,
3718
3997
  explorationNote,
3719
3998
  explorationNotePath,
@@ -3729,62 +4008,62 @@ export {
3729
4008
  explorationTestBuildOnGitHub,
3730
4009
  explorationTryIt,
3731
4010
  explorationTryItOnGitHub,
3732
- bc as fieldChanges,
3733
- bd as fileModes,
3734
- be as filterHistory,
4011
+ bf as fieldChanges,
4012
+ bg as fileModes,
4013
+ bh as filterHistory,
3735
4014
  findExplorationOnGitHub,
3736
4015
  findPreviewComment,
3737
4016
  findReferenceProblems,
3738
- bf as findToken,
3739
- bg as findVercelComment,
3740
- bh as firstParagraph,
3741
- m as flattenLayerFile,
3742
- bi as flattenTokens,
4017
+ bi as findToken,
4018
+ bj as findVercelComment,
4019
+ bk as firstParagraph,
4020
+ n as flattenLayerFile,
4021
+ flattenTokens,
3743
4022
  formatChangeset,
3744
4023
  formatDocsJson,
3745
- bj as formatNumber,
3746
- bk as formatOwnerEntry,
4024
+ bl as formatNumber,
4025
+ bm as formatOwnerEntry,
3747
4026
  formatValue,
3748
4027
  friendlyMessage,
3749
4028
  fromHex,
3750
4029
  fromPlain,
3751
4030
  generateRamp,
3752
- bl as getChild,
4031
+ bn as getChild,
3753
4032
  getEntry,
3754
4033
  gitHubHistoryBackend,
3755
4034
  g2 as globToRegExp,
3756
- bm as groupsPhrase,
4035
+ bo as groupsPhrase,
3757
4036
  h as hashSpec,
3758
4037
  h2 as hexToRgba,
3759
- bn as holdersOf,
4038
+ bp as holdersOf,
3760
4039
  j as iconComponentName,
3761
4040
  idExtensionFor,
3762
4041
  impactedModules,
3763
4042
  importsIn,
3764
- bo as indexByPath,
3765
- bp as inheritedTypeAt,
3766
- bq as installCommand,
3767
- br as installCommandFromPreviewComment,
4043
+ bq as indexByPath,
4044
+ br as inheritedTypeAt,
4045
+ bs as installCommand,
4046
+ bt as installCommandFromPreviewComment,
3768
4047
  isActiveExploration,
3769
4048
  isAlias,
3770
4049
  isDocsSelectionMode,
3771
4050
  isDraftSessionId,
3772
4051
  isExplorationBranch,
3773
4052
  isExplorationPull,
3774
- bs as isGuardrail,
4053
+ bu as isGuardrail,
3775
4054
  isHex,
3776
4055
  isMissingPermission,
3777
4056
  isMultiMode,
3778
4057
  isPlanRefusal,
3779
4058
  isProseKey,
3780
- bt as isTeamEntry,
3781
- bu as isTokenFile,
4059
+ bv as isTeamEntry,
4060
+ bw as isTokenFile,
3782
4061
  isTokenRejected,
3783
- bv as isVercelComment,
4062
+ bx as isVercelComment,
3784
4063
  jiraIssueFields,
3785
- bw as kindForMin,
3786
- bx as layeredImpact,
3787
- n as layeredParityIssues,
4064
+ by as kindForMin,
4065
+ bz as layeredImpact,
4066
+ o as layeredParityIssues,
3788
4067
  g as layoutOptions,
3789
4068
  levenshtein,
3790
4069
  linkRequestToExplorationOnGitHub,
@@ -3796,16 +4075,17 @@ export {
3796
4075
  loadProtection,
3797
4076
  loadRepoFiles,
3798
4077
  loadRequiredChecks,
3799
- by as luminance,
4078
+ bA as luminance,
3800
4079
  markClaudeDraft,
3801
4080
  mergeDocsDraft,
3802
4081
  mergeDraftResults,
3803
4082
  mergeReleases,
4083
+ missingChoices,
3804
4084
  missingPermissionMessage,
3805
4085
  missingProse,
3806
4086
  modeDisplayName,
3807
4087
  modeFile,
3808
- bz as modeLabel,
4088
+ bB as modeLabel,
3809
4089
  modesOf$1 as modesOf,
3810
4090
  moveToken,
3811
4091
  nearestStep,
@@ -3814,83 +4094,88 @@ export {
3814
4094
  neutralOffset,
3815
4095
  newBrandSection,
3816
4096
  newDraftSessionId,
3817
- bA as nodesEqual,
3818
- bB as normalizeRights,
4097
+ bC as nodesEqual,
4098
+ bD as normalizeRights,
3819
4099
  oklch,
3820
4100
  oklchToLinear,
3821
- bC as overrideKey,
3822
- bD as ownerEntryProblems,
4101
+ bE as overrideKey,
4102
+ bF as ownerEntryProblems,
3823
4103
  packageDirCandidates,
3824
- bE as pairKey,
4104
+ bG as pairKey,
3825
4105
  parseChangelog,
3826
- bF as parseChangesetText,
3827
- p as parseColor,
3828
- bG as parseComponentSpecs,
4106
+ bH as parseChangesetText,
4107
+ parseColor,
4108
+ bI as parseComponentSpecs,
3829
4109
  parseContrastChecks,
3830
- o as parseDimension,
4110
+ q as parseDimension,
3831
4111
  parseDocsReply,
3832
4112
  parseDocsTaskAnswer,
3833
4113
  parseExplorationBody,
3834
4114
  parseJson,
3835
- bH as parseOwnerEntry,
4115
+ bJ as parseOwnerEntry,
3836
4116
  parsePendingDrafts,
3837
4117
  parseRepo,
3838
4118
  parseRequestIssue,
3839
4119
  parseStructureChange,
3840
4120
  parseTokenFile,
3841
- bI as parseVercelComment,
4121
+ bK as parseVercelComment,
3842
4122
  patchDocsJson,
3843
4123
  pathId,
3844
4124
  pathSimilarity,
3845
4125
  permissionLabel,
4126
+ pickedOption,
3846
4127
  plainEqual,
3847
4128
  planNewBrand,
3848
- bJ as planRestore,
3849
- bK as planRevert,
3850
- bL as planToJson,
4129
+ bL as planRestore,
4130
+ bM as planRevert,
4131
+ bN as planToJson,
4132
+ planTokenMerge,
3851
4133
  e as prNumberFromSubject,
3852
4134
  prefillDocs,
3853
- bM as previewComment,
4135
+ bO as previewComment,
3854
4136
  previewLinks,
3855
- bN as previewLinksOf,
3856
- bO as previewUrl,
4137
+ bP as previewLinksOf,
4138
+ previewOverrides,
4139
+ bQ as previewUrl,
3857
4140
  previewsSettled,
3858
- bP as projectOfLabel,
4141
+ bR as projectOfLabel,
3859
4142
  promoteExplorationOnGitHub,
3860
4143
  promotionPlan,
3861
4144
  propsTable,
3862
4145
  protectLibrary,
3863
4146
  protectRefusal,
3864
- bQ as protectedBranchesOf,
4147
+ bS as protectedBranchesOf,
3865
4148
  protectionRuleset,
3866
4149
  protectionRulesetName,
3867
4150
  protectionSentence,
3868
4151
  protectionState,
3869
4152
  pushChangeRows,
4153
+ rateLimitMessage,
3870
4154
  readPendingDrafts,
3871
4155
  readPreviewComment,
3872
4156
  readTokenAt,
3873
4157
  reconcileIds,
3874
4158
  releasesFromTags,
3875
4159
  removeToken,
3876
- bR as renderedColor,
4160
+ removedSide,
4161
+ bT as renderedColor,
3877
4162
  requestBrief,
3878
4163
  requestImagePath,
3879
4164
  requestIssueTitle,
3880
4165
  requestStatus,
3881
4166
  requiredCheckNames,
3882
4167
  requiredPermission,
3883
- bS as resolve,
4168
+ resolve,
3884
4169
  resolveBranchPreviews,
3885
4170
  r as rgbaToDtcg,
3886
- q as rgbaToHex,
3887
- bT as rightsProblems,
4171
+ rgbaToHex,
4172
+ bU as rightsProblems,
3888
4173
  round3,
3889
4174
  rulesSettingsUrl,
3890
4175
  rulesetTargetsDefault,
3891
- bU as runLayeredContrast,
4176
+ bV as runLayeredContrast,
3892
4177
  sameScopes,
3893
- bV as sameToken,
4178
+ bW as sameToken,
3894
4179
  sanitizeDocsReplacement,
3895
4180
  sanitizeDocsResult,
3896
4181
  sanitizeDocsSections,
@@ -3904,21 +4189,22 @@ export {
3904
4189
  serializePendingDrafts,
3905
4190
  serializeTokenFile,
3906
4191
  shadowedEdits,
3907
- bW as shipPolicy,
4192
+ bX as shipPolicy,
3908
4193
  shortVariant,
3909
4194
  shortVariants,
3910
4195
  slugify,
3911
- bX as snapshotUrl,
3912
- bY as specHash,
4196
+ bY as snapshotUrl,
4197
+ bZ as specHash,
3913
4198
  startExplorationOnGitHub,
3914
- bZ as summarizeTokenChange,
3915
- b_ as tarballAssetName,
3916
- b$ as tarballUrl,
3917
- c0 as teamKey,
3918
- c1 as teamKeyOf,
3919
- c2 as teamUnreadableMessage,
3920
- c3 as teamsIn,
3921
- c4 as threeWayDiff,
4199
+ b_ as summarizeTokenChange,
4200
+ takeMine,
4201
+ b$ as tarballAssetName,
4202
+ c0 as tarballUrl,
4203
+ c1 as teamKey,
4204
+ c2 as teamKeyOf,
4205
+ c3 as teamUnreadableMessage,
4206
+ c4 as teamsIn,
4207
+ threeWayDiff,
3922
4208
  tintedNeutral,
3923
4209
  c5 as titleOf,
3924
4210
  t2 as toAlias,
@@ -3934,6 +4220,7 @@ export {
3934
4220
  ca as tokenNode,
3935
4221
  tokenUsage,
3936
4222
  tokensPath,
4223
+ unpicked,
3937
4224
  cb as unreadableShipTeams,
3938
4225
  cc as unreadableTeams,
3939
4226
  updatePendingDrafts,