@bridge-ds/core 0.3.0 → 0.4.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;
@@ -562,8 +808,8 @@ class GitHubClient {
562
808
  try {
563
809
  return await this.once(method, path, body);
564
810
  } catch (err) {
565
- const e3 = err;
566
- if (attempt >= attempts || !(e3 instanceof GitHubError) || !isTransient(e3.status, e3.detail ?? "")) throw err;
811
+ const e2 = err;
812
+ if (attempt >= attempts || !(e2 instanceof GitHubError) || !isTransient(e2.status, e2.detail ?? "")) throw err;
567
813
  await this.retry.sleep(this.retry.baseDelayMs * 2 ** (attempt - 1));
568
814
  }
569
815
  }
@@ -586,7 +832,7 @@ class GitHubClient {
586
832
  let detail = "";
587
833
  try {
588
834
  const data = await res.json();
589
- detail = [data.message, ...(data.errors ?? []).map((e3) => typeof e3 === "string" ? e3 : e3.message)].filter(Boolean).join(" ");
835
+ detail = [data.message, ...(data.errors ?? []).map((e2) => typeof e2 === "string" ? e2 : e2.message)].filter(Boolean).join(" ");
590
836
  } catch {
591
837
  detail = "";
592
838
  }
@@ -670,7 +916,7 @@ class GitHubClient {
670
916
  /** Pull requests a commit belongs to (merged ones first): how a commit on main finds its PR. */
671
917
  async listPullRequestsForCommit(sha) {
672
918
  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)));
919
+ 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
920
  }
675
921
  /** Tags with the commit they point to, newest first as GitHub lists them. */
676
922
  async listTags(perPage = 30) {
@@ -751,10 +997,29 @@ class GitHubClient {
751
997
  variables: { id: pr.node_id }
752
998
  });
753
999
  if (r2?.errors?.length) {
754
- const detail = r2.errors.map((e3) => e3.message).filter(Boolean).join(" ");
1000
+ const detail = r2.errors.map((e2) => e2.message).filter(Boolean).join(" ");
755
1001
  throw new GitHubError(422, `GitHub refused to mark #${n2} ready for review${detail ? `: ${detail}` : "."} Use "Ready for review" on GitHub instead.`, detail);
756
1002
  }
757
1003
  }
1004
+ /**
1005
+ * Turns an open pull request back into a draft: the GraphQL mutation convertPullRequestToDraft (REST cannot set
1006
+ * `draft` either), same token. No-op when it is already a draft.
1007
+ */
1008
+ async convertToDraft(n2) {
1009
+ this.assertToken("Turning a pull request back into a draft");
1010
+ const pr = await this.request("GET", `${this.repoPath}/pulls/${n2}`);
1011
+ if (pr.draft === true) return;
1012
+ 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.`);
1013
+ if (!pr.node_id) throw new GitHubError(422, `Pull request #${n2} has no node id: convert it to draft on GitHub.`);
1014
+ const r2 = await this.request("POST", "/graphql", {
1015
+ query: "mutation($id: ID!) { convertPullRequestToDraft(input: { pullRequestId: $id }) { pullRequest { number isDraft } } }",
1016
+ variables: { id: pr.node_id }
1017
+ });
1018
+ if (r2?.errors?.length) {
1019
+ const detail = r2.errors.map((e2) => e2.message).filter(Boolean).join(" ");
1020
+ throw new GitHubError(422, `GitHub refused to turn #${n2} back into a draft${detail ? `: ${detail}` : "."} Use "Convert to draft" on GitHub instead.`, detail);
1021
+ }
1022
+ }
758
1023
  async createPullRequest(input) {
759
1024
  this.assertWritableBranch(input.head, input.base);
760
1025
  const r2 = await this.request(
@@ -931,7 +1196,7 @@ class GitHubClient {
931
1196
  const q2 = ref ? `?ref=${encodeURIComponent(ref)}` : "";
932
1197
  const r2 = await this.request("GET", `${this.repoPath}/contents/${encodeRef(path)}${q2}`);
933
1198
  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 }));
1199
+ return r2.map((e2) => ({ name: e2.name, path: e2.path, type: e2.type, sha: e2.sha, size: e2.size ?? 0 }));
935
1200
  } catch (err) {
936
1201
  if (err instanceof GitHubError && err.status === 404) return [];
937
1202
  throw err;
@@ -984,7 +1249,7 @@ class GitHubClient {
984
1249
  async listFiles(ref) {
985
1250
  const r2 = await this.request("GET", `${this.repoPath}/git/trees/${encodeRef(ref)}?recursive=1`);
986
1251
  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);
1252
+ return r2.tree.filter((e2) => e2.type === "blob").map((e2) => e2.path);
988
1253
  }
989
1254
  // --- Pull requests, reviews, checks ---------------------------------------------------------
990
1255
  async listPullRequests(state = "open") {
@@ -1017,12 +1282,12 @@ class GitHubClient {
1017
1282
  async listDeployments(sha) {
1018
1283
  const list = await this.request("GET", `${this.repoPath}/deployments?sha=${encodeURIComponent(sha)}&per_page=30`);
1019
1284
  const latest = /* @__PURE__ */ new Map();
1020
- for (const d of list) if (!latest.has(d.environment)) latest.set(d.environment, d);
1285
+ for (const d2 of list) if (!latest.has(d2.environment)) latest.set(d2.environment, d2);
1021
1286
  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(() => []);
1287
+ [...latest.values()].map(async (d2) => {
1288
+ const st = await this.request("GET", `${this.repoPath}/deployments/${d2.id}/statuses?per_page=1`).catch(() => []);
1024
1289
  const s = st[0];
1025
- return { id: d.id, environment: d.environment, state: s?.state ?? null, environmentUrl: s?.environment_url || null };
1290
+ return { id: d2.id, environment: d2.environment, state: s?.state ?? null, environmentUrl: s?.environment_url || null };
1026
1291
  })
1027
1292
  );
1028
1293
  }
@@ -1109,7 +1374,7 @@ class GitHubClient {
1109
1374
  function toCommitSummary(c10) {
1110
1375
  return {
1111
1376
  sha: c10.sha,
1112
- parents: (c10.parents ?? []).map((p2) => p2.sha),
1377
+ parents: (c10.parents ?? []).map((p) => p.sha),
1113
1378
  date: c10.commit?.committer?.date ?? c10.commit?.author?.date ?? "",
1114
1379
  author: c10.author?.login ?? c10.commit?.author?.name ?? "unknown",
1115
1380
  message: c10.commit?.message ?? ""
@@ -1160,7 +1425,7 @@ async function loadRepoFiles(client, commitSha, fallbackTokensPath) {
1160
1425
  const warnings = [];
1161
1426
  let config;
1162
1427
  let configText;
1163
- const configEntry = entries.find((e3) => e3.type === "blob" && e3.path === CONFIG_FILE);
1428
+ const configEntry = entries.find((e2) => e2.type === "blob" && e2.path === CONFIG_FILE);
1164
1429
  if (configEntry) {
1165
1430
  try {
1166
1431
  configText = await client.getBlobText(configEntry.sha);
@@ -1173,16 +1438,16 @@ async function loadRepoFiles(client, commitSha, fallbackTokensPath) {
1173
1438
  const checksFile = config?.tokens.contrastChecks ?? DEFAULT_TOKEN_PATHS.contrastChecks;
1174
1439
  const prefix = tokensPath2 + "/";
1175
1440
  const wanted = entries.filter(
1176
- (e3) => e3.type === "blob" && e3.path.startsWith(prefix) && (e3.path.endsWith(".tokens.json") || e3.path === prefix + checksFile)
1441
+ (e2) => e2.type === "blob" && e2.path.startsWith(prefix) && (e2.path.endsWith(".tokens.json") || e2.path === prefix + checksFile)
1177
1442
  );
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)}.`);
1443
+ 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
1444
  const files = {};
1180
1445
  let contrastChecks;
1181
1446
  const queue = [...wanted];
1182
1447
  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);
1448
+ for (let e2 = queue.shift(); e2; e2 = queue.shift()) {
1449
+ const text = await client.getBlobText(e2.sha);
1450
+ const rel = e2.path.slice(prefix.length);
1186
1451
  if (rel === checksFile) contrastChecks = text;
1187
1452
  else files[rel] = text;
1188
1453
  }
@@ -1215,7 +1480,7 @@ async function loadProtection(client, defaultBranch) {
1215
1480
  }
1216
1481
  async function loadRequiredChecks(client, defaultBranch) {
1217
1482
  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);
1483
+ const merged = await client.listPullRequests("closed").then((prs) => prs.find((p) => p.state === "merged" && p.baseRef === defaultBranch)).catch(() => void 0);
1219
1484
  const onPull = merged?.headSha ? await client.listCheckRuns(merged.headSha).catch(() => []) : [];
1220
1485
  return requiredCheckNames(onDefault, onPull);
1221
1486
  }
@@ -1248,11 +1513,11 @@ function importsIn(text) {
1248
1513
  for (const m2 of text.matchAll(IMPORT_RE)) out.add(m2[1] ?? m2[2]);
1249
1514
  return [...out];
1250
1515
  }
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);
1516
+ const norm = (p) => p.replace(/\\/g, "/").replace(/\/+$/, "");
1517
+ const isStory = (p) => /\.stories\.[cm]?[jt]sx?$/.test(p);
1518
+ const isTest = (p) => /\.(test|spec)\.[cm]?[jt]sx?$/.test(p);
1519
+ const isCss = (p) => /\.(css|scss|less)$/.test(p);
1520
+ const isScript = (p) => /\.[cm]?[jt]sx?$/.test(p);
1256
1521
  function componentOf(from, spec, componentsDir) {
1257
1522
  if (!spec.startsWith(".")) return null;
1258
1523
  const parts = from.split("/").slice(0, -1);
@@ -1267,9 +1532,9 @@ function componentOf(from, spec, componentsDir) {
1267
1532
  }
1268
1533
  function componentForPath(path, componentsDir) {
1269
1534
  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("/");
1535
+ const p = norm(path);
1536
+ if (!p.startsWith(`${dir}/`)) return null;
1537
+ const rest = p.slice(dir.length + 1).split("/");
1273
1538
  return rest.length >= 2 ? rest[0] : null;
1274
1539
  }
1275
1540
  function buildUsageIndex(files, componentsDir) {
@@ -1306,7 +1571,7 @@ function buildUsageIndex(files, componentsDir) {
1306
1571
  mod.files.sort();
1307
1572
  mod.vars = [...vars.get(mod.id) ?? []].sort();
1308
1573
  mod.imports = [...imports.get(mod.id) ?? []].sort();
1309
- mod.storyImports = [...storyImports.get(mod.id) ?? []].filter((d) => !mod.imports.includes(d)).sort();
1574
+ mod.storyImports = [...storyImports.get(mod.id) ?? []].filter((d2) => !mod.imports.includes(d2)).sort();
1310
1575
  for (const v2 of mod.vars) (byVar[v2] ??= []).push(mod.id);
1311
1576
  }
1312
1577
  for (const k3 of Object.keys(byVar)) byVar[k3].sort();
@@ -1328,7 +1593,7 @@ function impactedModules(index, input) {
1328
1593
  if (id && index.modules[id]) add(id, `file changed: ${norm(f)}`, false);
1329
1594
  }
1330
1595
  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);
1596
+ 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
1597
  const queue = [...reasons.keys()];
1333
1598
  while (queue.length) {
1334
1599
  const id = queue.shift();
@@ -1351,10 +1616,10 @@ function tokenUsage(tokens, reads) {
1351
1616
  const used = /* @__PURE__ */ new Set();
1352
1617
  const queue = [...direct];
1353
1618
  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);
1619
+ const p = queue.pop();
1620
+ if (used.has(p)) continue;
1621
+ used.add(p);
1622
+ for (const r2 of byPath.get(p)?.refs ?? []) if (!used.has(r2) && byPath.has(r2)) queue.push(r2);
1358
1623
  }
1359
1624
  return { used, direct };
1360
1625
  }
@@ -1395,7 +1660,7 @@ function gitHubHistoryBackend(client, config, opts = {}) {
1395
1660
  const merges = /* @__PURE__ */ new Map();
1396
1661
  const enriched = await pool(list, async (c10) => {
1397
1662
  const prs = await client.listPullRequestsForCommit(c10.sha).catch(() => []);
1398
- const pr = prs.find((p2) => p2.mergedAt && p2.baseRef === ref) ?? prs.find((p2) => p2.mergedAt);
1663
+ const pr = prs.find((p) => p.mergedAt && p.baseRef === ref) ?? prs.find((p) => p.mergedAt);
1399
1664
  if (!pr) return c10;
1400
1665
  const prInfo = { number: pr.number, title: pr.title, url: pr.url, author: pr.author, ...pr.mergedAt ? { mergedAt: pr.mergedAt } : {}, body: pr.body };
1401
1666
  if (pr.mergeCommitSha && pr.mergeCommitSha !== c10.sha) {
@@ -1419,20 +1684,20 @@ function gitHubHistoryBackend(client, config, opts = {}) {
1419
1684
  },
1420
1685
  async tokenFiles(sha) {
1421
1686
  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)]);
1687
+ const blobs = entries.filter((e2) => e2.type === "blob" && e2.path.startsWith(prefix));
1688
+ const picked = new Set(selectTokenFiles(config, blobs.map((e2) => e2.path)));
1689
+ const wanted = blobs.filter((e2) => picked.has(prefix ? e2.path.slice(prefix.length) : e2.path));
1690
+ const texts = await pool(wanted, async (e2) => [prefix ? e2.path.slice(prefix.length) : e2.path, await client.getBlobText(e2.sha)]);
1426
1691
  return new Map(texts);
1427
1692
  },
1428
1693
  async changesetPaths(sha) {
1429
1694
  const dir = config.changesets?.dir.replace(/\/$/, "");
1430
1695
  if (!dir) return [];
1431
- return (await tree(sha)).filter((e3) => e3.type === "blob" && e3.path.startsWith(`${dir}/`)).map((e3) => e3.path);
1696
+ return (await tree(sha)).filter((e2) => e2.type === "blob" && e2.path.startsWith(`${dir}/`)).map((e2) => e2.path);
1432
1697
  },
1433
1698
  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;
1699
+ const e2 = (await tree(sha)).find((x) => x.type === "blob" && x.path === path);
1700
+ return e2 ? client.getBlobText(e2.sha) : null;
1436
1701
  }
1437
1702
  };
1438
1703
  }
@@ -1453,9 +1718,9 @@ async function loadGitHubHistory(client, config, opts = {}) {
1453
1718
  if (head) {
1454
1719
  const files = await backend.tree(head).catch(() => []);
1455
1720
  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"));
1721
+ const p = (f) => dir ? `${dir}/${f}` : f;
1722
+ const cl = files.find((e2) => e2.path === p("CHANGELOG.md"));
1723
+ const pkg = files.find((e2) => e2.path === p("package.json"));
1459
1724
  if (!cl && !pkg) continue;
1460
1725
  if (cl) changelog = parseChangelog(await client.getBlobText(cl.sha));
1461
1726
  if (pkg) {
@@ -1503,14 +1768,14 @@ function demoHistory(config, current) {
1503
1768
  }
1504
1769
  const entries = [];
1505
1770
  kept.forEach((step, i2) => {
1506
- const e3 = buildHistoryEntry({
1771
+ const e2 = buildHistoryEntry({
1507
1772
  config,
1508
1773
  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
1774
  before: states[i2],
1510
1775
  after: states[i2 + 1],
1511
1776
  demo: true
1512
1777
  });
1513
- if (e3) entries.push(e3);
1778
+ if (e2) entries.push(e2);
1514
1779
  });
1515
1780
  return { ...buildReport({ source: "demo", label: "Demo history (fixture data)", ref: "demo", entries, releases: DEMO_RELEASES, truncated: false }), demo: true };
1516
1781
  }
@@ -1523,14 +1788,14 @@ async function branchPreviewUrls(gh, ref, config, opts = {}) {
1523
1788
  if (typeof ref === "number") {
1524
1789
  pr = ref;
1525
1790
  if (!branch || !sha) {
1526
- const p2 = await gh.getPullRequest(ref);
1527
- branch ??= p2.headRef;
1528
- sha ??= p2.headSha;
1791
+ const p = await gh.getPullRequest(ref);
1792
+ branch ??= p.headRef;
1793
+ sha ??= p.headSha;
1529
1794
  }
1530
1795
  } else {
1531
1796
  sha = ref;
1532
1797
  if (!branch || !opts.comments) {
1533
- const open = (await gh.listPullRequestsForCommit(ref).catch(() => [])).find((p2) => p2.state === "open");
1798
+ const open = (await gh.listPullRequestsForCommit(ref).catch(() => [])).find((p) => p.state === "open");
1534
1799
  if (open) {
1535
1800
  pr = open.number;
1536
1801
  branch ??= open.headRef;
@@ -1655,12 +1920,12 @@ const brandDisplayName = (slug) => slug.split("-").filter(Boolean).map((w) => w[
1655
1920
  function brandLayers(config) {
1656
1921
  const out = {};
1657
1922
  for (const l2 of config.tokens.layers) {
1658
- const ph = (l2.files.match(/\{([^}]+)\}/g) ?? []).map((p2) => p2.slice(1, -1));
1923
+ const ph = (l2.files.match(/\{([^}]+)\}/g) ?? []).map((p) => p.slice(1, -1));
1659
1924
  if (!ph.includes("brand")) continue;
1660
1925
  if (ph.length === 1 && !out.brand) out.brand = l2.files;
1661
1926
  else if (ph.length === 2 && !out.override) {
1662
1927
  out.override = l2.files;
1663
- out.overrideAxis = ph.find((p2) => p2 !== "brand");
1928
+ out.overrideAxis = ph.find((p) => p !== "brand");
1664
1929
  }
1665
1930
  }
1666
1931
  return out;
@@ -1803,8 +2068,8 @@ function planNewBrand(source, input) {
1803
2068
  if (r2.issue) issues.push({ ...r2.issue, path: `palette.${role}` });
1804
2069
  anchors[role] = r2.anchor;
1805
2070
  return r2.ramp;
1806
- } catch (e3) {
1807
- issues.push({ level: "error", code: "invalid-color", message: e3.message, path: `palette.${role}` });
2071
+ } catch (e2) {
2072
+ issues.push({ level: "error", code: "invalid-color", message: e2.message, path: `palette.${role}` });
1808
2073
  return void 0;
1809
2074
  }
1810
2075
  };
@@ -1889,7 +2154,7 @@ function planNewBrand(source, input) {
1889
2154
  const primDir = config.tokens.tiers.primitive?.[0]?.replace(/\/$/, "") ?? config.tokens.primitives;
1890
2155
  const primFile = `${primDir}/${slug}.tokens.json`;
1891
2156
  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.` });
2157
+ 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
2158
  doc.$description = `${name}: created with Bridge, started from ${blank ? "a blank brand" : brandDisplayName(from)}.`;
1894
2159
  doc.$extensions = { ...isObj(doc.$extensions) ? doc.$extensions : {}, "dev.bridge.brand": { name, from, ...Object.keys(anchors).length ? { anchors } : {} } };
1895
2160
  const { $description, $extensions, ...rest } = doc;
@@ -1931,8 +2196,8 @@ function planNewBrand(source, input) {
1931
2196
  try {
1932
2197
  configText = addBrandToConfigText(baseConfigText, slug);
1933
2198
  nextConfig = issues.some((i2) => i2.code.startsWith("slug-")) ? config : loadConfig(configText);
1934
- } catch (e3) {
1935
- issues.push({ level: "error", code: "config", message: e3.message });
2199
+ } catch (e2) {
2200
+ issues.push({ level: "error", code: "config", message: e2.message });
1936
2201
  }
1937
2202
  const after = new LayeredTokenSet(nextConfig, nextFiles);
1938
2203
  const key = (i2) => `${i2.code}|${i2.path ?? ""}|${i2.message}`;
@@ -1946,7 +2211,7 @@ function planNewBrand(source, input) {
1946
2211
  const pairs = parseContrastChecks(source.contrastText);
1947
2212
  const inGate = nextConfig.axes.brand?.values.includes(slug);
1948
2213
  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)));
2214
+ const results = combos.flatMap((c10) => pairs.map((p) => checkLayeredPair(after, p, c10)));
1950
2215
  const failing = results.filter((r2) => !r2.pass);
1951
2216
  const themes = [...new Set(combos.map((c10) => c10.theme).filter((t3) => !!t3))];
1952
2217
  const ramps = {};
@@ -1960,7 +2225,7 @@ function planNewBrand(source, input) {
1960
2225
  if (JSON.stringify(r2) !== JSON.stringify(ramps.primary)) ramps[role] = r2;
1961
2226
  }
1962
2227
  }
1963
- const addedTokens = after.defs.filter((d) => created.includes(d.file)).map((d) => ({ kind: "added", path: d.path }));
2228
+ const addedTokens = after.defs.filter((d2) => created.includes(d2.file)).map((d2) => ({ kind: "added", path: d2.path }));
1964
2229
  const risk = classifyRisk({ tokenChanges: addedTokens, files: [{ path: CONFIG_FILE, status: "modified" }], config });
1965
2230
  const planned = [
1966
2231
  ...created.map((f) => ({ path: tokensPath(config, f), action: "create", content: nextFiles.get(f) })),
@@ -2112,21 +2377,21 @@ function cssModuleClasses(css) {
2112
2377
  const cell$1 = (s) => s.replace(/\|/g, "\\|").replace(/\n/g, " ");
2113
2378
  function propsTable(name, props, inherits) {
2114
2379
  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 ?? "")} |`);
2380
+ 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
2381
  const tail = inherits ? `
2117
2382
 
2118
2383
  Also accepts every native <${inherits}> attribute.` : "";
2119
2384
  return ["| Prop | Type | Default | Description |", "| --- | --- | --- | --- |", ...rows].join("\n") + tail;
2120
2385
  }
2121
2386
  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]));
2387
+ function missingProse(d2) {
2388
+ return PROSE_KEYS.filter((k3) => isEmpty(d2?.[k3]));
2124
2389
  }
2125
2390
  function prefillDocs(input) {
2126
2391
  const existing = input.existing ?? null;
2127
2392
  const anatomy = {};
2128
2393
  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"}).`);
2394
+ 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
2395
  const missing = missingProse(existing);
2131
2396
  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
2397
  const draft = {
@@ -2194,7 +2459,7 @@ ${text.trim()}
2194
2459
  ] : [],
2195
2460
  ...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
2461
  ] : [`Write the missing prose of ${prefill.component}.docs.json for the Bridge design system.`];
2197
- const shape = keys ? [
2462
+ const shape2 = keys ? [
2198
2463
  `- ${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
2464
  `- Answer with one JSON object holding only those keys, nothing else: ${docsSectionShapes(keys)}.`
2200
2465
  ] : [
@@ -2208,7 +2473,7 @@ ${text.trim()}
2208
2473
  "- Ground every sentence in the facts and the source below. Never invent props, variants, keyboard behavior or tokens that are not there.",
2209
2474
  "- Bridge voice: sentence case, plain words, verbs first, no em dashes, no marketing words.",
2210
2475
  '- 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,
2476
+ ...shape2,
2212
2477
  "",
2213
2478
  "Facts computed from the code:",
2214
2479
  facts.join("\n\n"),
@@ -2223,29 +2488,29 @@ ${JSON.stringify(prefill.draft, null, 2)}`,
2223
2488
  block("example-docs-json", conventions.example)
2224
2489
  ].filter((x, i2, all) => x !== "" || all[i2 - 1] !== "").join("\n");
2225
2490
  }
2226
- function markClaudeDraft(d, sections) {
2491
+ function markClaudeDraft(d2, sections) {
2227
2492
  if (!sections) {
2228
- const { draftedSections: _all, ...rest } = d;
2493
+ const { draftedSections: _all, ...rest } = d2;
2229
2494
  return { ...rest, draftedBy: "claude", needsReview: true };
2230
2495
  }
2231
- const waiting = d.needsReview === true ? d.draftedSections ?? (d.draftedBy ? [...PROSE_KEYS] : []) : [];
2496
+ const waiting = d2.needsReview === true ? d2.draftedSections ?? (d2.draftedBy ? [...PROSE_KEYS] : []) : [];
2232
2497
  const union = PROSE_KEYS.filter((k3) => waiting.includes(k3) || sections.includes(k3));
2233
- return { ...d, draftedBy: "claude", needsReview: true, draftedSections: union };
2498
+ return { ...d2, draftedBy: "claude", needsReview: true, draftedSections: union };
2234
2499
  }
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];
2500
+ function sectionsNeedingReview(d2) {
2501
+ if (!d2 || d2.needsReview !== true) return [];
2502
+ return d2.draftedSections ? PROSE_KEYS.filter((k3) => d2.draftedSections.includes(k3)) : [...PROSE_KEYS];
2238
2503
  }
2239
- const needsDocsReview = (d) => Boolean(d && d.needsReview === true);
2240
- function acceptDocsDraft(d) {
2241
- const { draftedSections: _done, ...rest } = d;
2504
+ const needsDocsReview = (d2) => Boolean(d2 && d2.needsReview === true);
2505
+ function acceptDocsDraft(d2) {
2506
+ const { draftedSections: _done, ...rest } = d2;
2242
2507
  return { ...rest, needsReview: false };
2243
2508
  }
2244
- function formatDocsJson(d) {
2509
+ function formatDocsJson(d2) {
2245
2510
  const order = ["summary", "category", "status", ...DOCS_KEYS.filter((k3) => k3 !== "summary"), "draftedBy", "draftedSections", "needsReview"];
2246
2511
  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;
2512
+ for (const k3 of order) if (d2[k3] !== void 0) out[k3] = d2[k3];
2513
+ for (const [k3, v2] of Object.entries(d2)) if (!(k3 in out) && v2 !== void 0) out[k3] = v2;
2249
2514
  return `${JSON.stringify(out, null, 2)}
2250
2515
  `;
2251
2516
  }
@@ -2253,7 +2518,7 @@ function patchNode(old, next) {
2253
2518
  if (plainEqual(toPlain(old), next)) return old;
2254
2519
  if (old.kind === "object" && next && typeof next === "object" && !Array.isArray(next)) {
2255
2520
  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]) }));
2521
+ const kept = old.entries.filter((e2) => n2[e2.key] !== void 0).map((e2) => ({ key: e2.key, value: patchNode(e2.value, n2[e2.key]) }));
2257
2522
  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
2523
  return { kind: "object", inline: old.inline, entries: [...kept, ...added] };
2259
2524
  }
@@ -2293,17 +2558,17 @@ function propShape(s) {
2293
2558
  }
2294
2559
  const VARIANT_FIRST = ["variant", "tone", "intent", "appearance", "kind", "type", "style"];
2295
2560
  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() };
2561
+ const pairs = key.split(", ").map((p) => {
2562
+ const at2 = p.indexOf("=");
2563
+ return at2 < 0 ? { k: "", v: p.trim() } : { k: p.slice(0, at2).trim(), v: p.slice(at2 + 1).trim() };
2299
2564
  });
2300
- const kept = pairs.filter((p2) => p2.v && !/^default$/i.test(p2.v));
2565
+ const kept = pairs.filter((p) => p.v && !/^default$/i.test(p.v));
2301
2566
  if (!kept.length) return key;
2302
2567
  const rank = (k3) => {
2303
2568
  const i2 = VARIANT_FIRST.indexOf(k3.toLowerCase());
2304
2569
  return i2 < 0 ? VARIANT_FIRST.length : i2;
2305
2570
  };
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(" ");
2571
+ 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
2572
  }
2308
2573
  const shortVariants = (list) => list ? andList(list.split("; ").map(shortVariant)) : "every variant";
2309
2574
  function parseStructureChange(c10) {
@@ -2312,8 +2577,8 @@ function parseStructureChange(c10) {
2312
2577
  const op = m2[1] === "New" ? "added" : m2[1] === "Removed" ? "removed" : "moved";
2313
2578
  const where = `in ${shortVariants(m2[3])}`;
2314
2579
  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);
2580
+ const shape2 = (op === "added" ? c10.after : c10.before) ?? "";
2581
+ const sm = /^(\S+)(?: (.*?))?, ((?:after|before) ".*"|alone)$/.exec(shape2);
2317
2582
  return { op, name: m2[2], where, ...sm ? { type: sm[1], ...sm[2] ? { main: sm[2] } : {}, at: sm[3] } : {} };
2318
2583
  }
2319
2584
  function structurePhrase(r2) {
@@ -2397,10 +2662,10 @@ function firstChange(component, kind, c10, all) {
2397
2662
  function draftRequestText(component, kind, changes) {
2398
2663
  const name = component.trim() || "the component";
2399
2664
  if (!changes.length && kind !== "new-component") return { title: "", summary: "" };
2400
- const d = firstChange(name, kind, changes[0], changes);
2665
+ const d2 = firstChange(name, kind, changes[0], changes);
2401
2666
  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) };
2667
+ const summary = rest > 0 ? `${d2.summary} ${capital(plural(rest, "other change"))} ${rest === 1 ? "is" : "are"} listed below.` : d2.summary;
2668
+ return { title: cleanDraftText(d2.title), summary: cleanDraftText(summary) };
2404
2669
  }
2405
2670
  const DRAFT_LINE_MAX = 120;
2406
2671
  function clipText(text, max) {
@@ -2461,32 +2726,32 @@ function draftChangeLine(kind, changes) {
2461
2726
  const tail = rest ? ` (and ${rest} more)` : "";
2462
2727
  return capital(clipText(cleanDraftText(first), DRAFT_LINE_MAX - tail.length)) + tail;
2463
2728
  }
2464
- const tokenOf = (e3) => e3.figma ?? e3.head ?? e3.base;
2465
- const pathOf = (e3) => tokenOf(e3)?.path ?? e3.path;
2729
+ const tokenOf = (e2) => e2.figma ?? e2.head ?? e2.base;
2730
+ const pathOf = (e2) => tokenOf(e2)?.path ?? e2.path;
2466
2731
  function pushChangeRows(entries) {
2467
- return entries.map((e3) => {
2468
- const before = e3.head ?? e3.base;
2469
- const after = e3.figma;
2732
+ return entries.map((e2) => {
2733
+ const before = e2.head ?? e2.base;
2734
+ const after = e2.figma;
2470
2735
  const show = (t3) => {
2471
2736
  if (!t3) return void 0;
2472
2737
  const modes = Object.keys(t3.values);
2473
2738
  if (modes.length <= 1) return formatValue(t3.type, t3.values[modes[0] ?? ""]);
2474
2739
  return modes.map((m2) => `${modeDisplayName(m2)} ${formatValue(t3.type, t3.values[m2])}`).join("; ");
2475
2740
  };
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) };
2741
+ const renamed = e2.local?.kind === "renamed" && before && after && before.path !== after.path;
2742
+ return { field: renamed ? `${before.path} -> ${after.path}` : pathOf(e2), before: show(before), after: show(after) };
2478
2743
  });
2479
2744
  }
2480
2745
  function names(paths) {
2481
2746
  if (paths.length <= 3) return andList(paths);
2482
2747
  return `${paths.length} tokens, including ${andList(paths.slice(0, 2))}`;
2483
2748
  }
2484
- function valueModes(e3) {
2485
- return (e3.local?.fields ?? []).filter((f) => f.field === "value" && f.mode && f.mode !== "value").map((f) => modeDisplayName(f.mode));
2749
+ function valueModes(e2) {
2750
+ return (e2.local?.fields ?? []).filter((f) => f.field === "value" && f.mode && f.mode !== "value").map((f) => modeDisplayName(f.mode));
2486
2751
  }
2487
2752
  function draftPushDescription(entries, components = []) {
2488
2753
  const by2 = { changed: [], added: [], renamed: [], removed: [] };
2489
- for (const e3 of entries) by2[e3.local?.kind ?? "changed"].push(e3);
2754
+ for (const e2 of entries) by2[e2.local?.kind ?? "changed"].push(e2);
2490
2755
  const clauses = [];
2491
2756
  if (by2.changed.length) {
2492
2757
  const only = by2.changed.length === 1 ? by2.changed[0] : void 0;
@@ -2718,48 +2983,48 @@ function explorationSlugFromBranch(ref) {
2718
2983
  return isExplorationBranch(ref) ? ref.replace(/^refs\/heads\//, "").slice(EXPLORATION_PREFIX.length) : null;
2719
2984
  }
2720
2985
  const explorationNotePath = (slug) => `${EXPLORATION_NOTES_DIR}/${slug}.md`;
2721
- function explorationProblems(e3) {
2986
+ function explorationProblems(e2) {
2722
2987
  const out = [];
2723
- const name = e3.name.trim();
2724
- const slug = e3.slug?.trim() || explorationSlug(name);
2988
+ const name = e2.name.trim();
2989
+ const slug = e2.slug?.trim() || explorationSlug(name);
2725
2990
  if (!name) out.push('Name the exploration, for example "Denser data tables".');
2726
2991
  else if (name.length > 60) out.push("Keep the name under 60 characters: it becomes the branch name.");
2727
2992
  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.");
2993
+ if (!e2.purpose.trim()) out.push("Say what you want to learn, in one sentence.");
2729
2994
  return out;
2730
2995
  }
2731
2996
  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);
2997
+ function explorationNote(e2) {
2998
+ const slug = e2.slug || explorationSlug(e2.name);
2999
+ const uc = useCaseLabel(e2.useCase);
2735
3000
  return [
2736
- `# Exploration: ${e3.name.trim()}`,
3001
+ `# Exploration: ${e2.name.trim()}`,
2737
3002
  "",
2738
- e3.purpose.trim(),
3003
+ e2.purpose.trim(),
2739
3004
  "",
2740
3005
  `- Branch: \`${EXPLORATION_PREFIX}${slug}\``,
2741
3006
  ...uc ? [`- Use case: ${uc}`] : [],
2742
- ...e3.startedAt ? [`- Started: ${e3.startedAt.slice(0, 10)}${e3.author ? ` by @${e3.author}` : ""}`] : [],
3007
+ ...e2.startedAt ? [`- Started: ${e2.startedAt.slice(0, 10)}${e2.author ? ` by @${e2.author}` : ""}`] : [],
2743
3008
  "",
2744
3009
  "This file marks the branch as an exploration. It is never merged as is: promoting the pull request to review removes it.",
2745
3010
  ""
2746
3011
  ].join("\n");
2747
3012
  }
2748
- function explorationPrTitle(e3) {
2749
- const n2 = e3.name.trim().replace(/\.$/, "");
3013
+ function explorationPrTitle(e2) {
3014
+ const n2 = e2.name.trim().replace(/\.$/, "");
2750
3015
  return `Exploration: ${n2.charAt(0).toLowerCase()}${n2.slice(1)}`;
2751
3016
  }
2752
- function explorationPrBody(e3, ctx) {
2753
- const slug = e3.slug || explorationSlug(e3.name);
3017
+ function explorationPrBody(e2, ctx) {
3018
+ const slug = e2.slug || explorationSlug(e2.name);
2754
3019
  const branch = `${EXPLORATION_PREFIX}${slug}`;
2755
- const uc = useCaseLabel(e3.useCase);
2756
- const experimental = (e3.experimental ?? []).map((x) => x.trim()).filter(Boolean);
3020
+ const uc = useCaseLabel(e2.useCase);
3021
+ const experimental = (e2.experimental ?? []).map((x) => x.trim()).filter(Boolean);
2757
3022
  const lines = [
2758
- `## Exploration: ${e3.name.trim()}`,
3023
+ `## Exploration: ${e2.name.trim()}`,
2759
3024
  "",
2760
3025
  `> 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
3026
  "",
2762
- `**Purpose.** ${e3.purpose.trim()}`,
3027
+ `**Purpose.** ${e2.purpose.trim()}`,
2763
3028
  ...uc ? ["", `**Use case.** ${uc}`] : [],
2764
3029
  "",
2765
3030
  "### What is experimental",
@@ -2784,7 +3049,7 @@ function explorationPrBody(e3, ctx) {
2784
3049
  `- **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
3050
  "- **Close:** close this pull request. The branch stays for reference; the preview prerelease is removed.",
2786
3051
  "",
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")} -->`
3052
+ `<!-- ${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
3053
  );
2789
3054
  return lines.join("\n");
2790
3055
  }
@@ -2793,20 +3058,20 @@ function parseExplorationBody(body) {
2793
3058
  const m2 = new RegExp(`<!-- ${MARK$1} (\\{[\\s\\S]*?\\}) -->`).exec(body);
2794
3059
  if (!m2) return void 0;
2795
3060
  try {
2796
- const e3 = JSON.parse(m2[1]);
2797
- return e3 && typeof e3.name === "string" && typeof e3.purpose === "string" ? e3 : void 0;
3061
+ const e2 = JSON.parse(m2[1]);
3062
+ return e2 && typeof e2.name === "string" && typeof e2.purpose === "string" ? e2 : void 0;
2798
3063
  } catch {
2799
3064
  return void 0;
2800
3065
  }
2801
3066
  }
2802
3067
  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));
3068
+ function isExplorationPull(p) {
3069
+ return isExplorationBranch(p.headRef) || labelNames(p.labels).includes(EXPLORATION_LABEL) || Boolean(parseExplorationBody(p.body));
2805
3070
  }
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";
3071
+ function explorationStatus(p) {
3072
+ const merged = Boolean(p.merged || p.merged_at || p.state === "merged");
3073
+ if (p.state !== "open" && !merged) return "closed";
3074
+ if (p.state === "open" && labelNames(p.labels).includes(EXPLORATION_LABEL)) return "active";
2810
3075
  return "promoted";
2811
3076
  }
2812
3077
  const isActiveExploration = (labels) => labelNames(labels).includes(EXPLORATION_LABEL);
@@ -2852,7 +3117,7 @@ function explorationTryIt(input) {
2852
3117
  function explorationShareMessage(input) {
2853
3118
  const name = input.name.trim().replace(/"/g, "'");
2854
3119
  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}`);
3120
+ const previews = (input.previews ?? []).map((p) => `${p.label} ${p.url}`);
2856
3121
  return [head, previews.length ? `Previews: ${previews.join(", ")}.` : "", `Pull request: ${input.url}.`].filter(Boolean).join(" ");
2857
3122
  }
2858
3123
  function explorationRules(branch) {
@@ -2944,8 +3209,8 @@ function declineComment(reason, by2) {
2944
3209
  }
2945
3210
  function requestStatus(issue) {
2946
3211
  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";
3212
+ if (issue.state === "open") return prs.some((p) => p.state === "open") ? "in-progress" : "requested";
3213
+ if (prs.some((p) => p.merged) || issue.stateReason === "completed") return "done";
2949
3214
  return "declined";
2950
3215
  }
2951
3216
  const REQUEST_STATUS_LABEL = { requested: "Requested", "in-progress": "In progress", done: "Done", declined: "Declined" };
@@ -3052,7 +3317,7 @@ function draftImagePath(sessionId, itemId, label) {
3052
3317
  return `${DRAFTS_DIR}/${sessionId}/${item}-${label}.png`;
3053
3318
  }
3054
3319
  function composePendingDrafts(input) {
3055
- const p2 = {
3320
+ const p = {
3056
3321
  version: DRAFT_EXCHANGE_VERSION,
3057
3322
  sessionId: input.sessionId ?? newDraftSessionId(input.random),
3058
3323
  createdAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
@@ -3060,9 +3325,9 @@ function composePendingDrafts(input) {
3060
3325
  source: input.source ?? "figma",
3061
3326
  items: input.items.map((i2) => ({ ...i2, changes: i2.changes ?? [] }))
3062
3327
  };
3063
- const problems = validatePendingDrafts(p2);
3328
+ const problems = validatePendingDrafts(p);
3064
3329
  if (problems.length) throw new Error(problems.join(" "));
3065
- return p2;
3330
+ return p;
3066
3331
  }
3067
3332
  const KINDS = new Set(REQUEST_KINDS.map((k3) => k3.value));
3068
3333
  const str = (x) => typeof x === "string";
@@ -3070,15 +3335,15 @@ const optStr = (x) => x === void 0 || typeof x === "string";
3070
3335
  function validatePendingDrafts(x) {
3071
3336
  const out = [];
3072
3337
  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.");
3338
+ const p = x;
3339
+ if (p.version !== DRAFT_EXCHANGE_VERSION) out.push(`Unsupported draft session version ${String(p.version)}: update Bridge.`);
3340
+ if (!isDraftSessionId(p.sessionId)) out.push("The session id is missing or invalid.");
3341
+ if (!str(p.createdAt) || Number.isNaN(Date.parse(p.createdAt))) out.push("createdAt must be an ISO date.");
3342
+ if (p.status !== "pending" && p.status !== "drafted") out.push('status must be "pending" or "drafted".');
3343
+ if (p.source !== "figma" && p.source !== "studio") out.push('source must be "figma" or "studio".');
3344
+ if (!Array.isArray(p.items) || !p.items.length) out.push("A draft session needs at least one item.");
3080
3345
  const ids = /* @__PURE__ */ new Set();
3081
- for (const [n2, i2] of (Array.isArray(p2.items) ? p2.items : []).entries()) {
3346
+ for (const [n2, i2] of (Array.isArray(p.items) ? p.items : []).entries()) {
3082
3347
  const at2 = `Item ${n2 + 1}`;
3083
3348
  if (!i2 || typeof i2 !== "object") {
3084
3349
  out.push(`${at2} is not an object.`);
@@ -3089,9 +3354,9 @@ function validatePendingDrafts(x) {
3089
3354
  else ids.add(i2.id);
3090
3355
  if (i2.scope !== "request" && i2.scope !== "push" && i2.scope !== "docs") out.push(`${at2}: scope must be "request", "push" or "docs".`);
3091
3356
  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}`));
3357
+ const d2 = i2.docs;
3358
+ 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}.`);
3359
+ else out.push(...validateDocsTask(d2.task).map((m2) => `${at2}: ${m2}`));
3095
3360
  } else if (i2.docs !== void 0) out.push(`${at2}: only a docs item has docs.`);
3096
3361
  if (!optStr(i2.component)) out.push(`${at2}: component must be text.`);
3097
3362
  if (i2.kind !== void 0 && !KINDS.has(i2.kind)) out.push(`${at2}: unknown kind "${String(i2.kind)}".`);
@@ -3102,10 +3367,10 @@ function validatePendingDrafts(x) {
3102
3367
  if (!i2.draft || !str(i2.draft.title) || !str(i2.draft.summary)) out.push(`${at2}: draft must hold a title and a summary.`);
3103
3368
  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
3369
  }
3105
- if (p2.results !== void 0) {
3106
- if (!Array.isArray(p2.results)) out.push("results must be a list.");
3370
+ if (p.results !== void 0) {
3371
+ if (!Array.isArray(p.results)) out.push("results must be a list.");
3107
3372
  else
3108
- for (const r2 of p2.results) {
3373
+ for (const r2 of p.results) {
3109
3374
  if (!r2 || !str(r2.id) || !str(r2.title) || !str(r2.summary)) out.push("Each result needs an id, a title and a summary.");
3110
3375
  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
3376
  else if (!optStr(r2.replacement)) out.push("A result replacement must be text.");
@@ -3124,8 +3389,8 @@ function parsePendingDrafts(text) {
3124
3389
  }
3125
3390
  return validatePendingDrafts(json).length ? void 0 : json;
3126
3391
  }
3127
- function serializePendingDrafts(p2) {
3128
- return `${JSON.stringify(p2, null, 2)}
3392
+ function serializePendingDrafts(p) {
3393
+ return `${JSON.stringify(p, null, 2)}
3129
3394
  `;
3130
3395
  }
3131
3396
  function clip(text, max) {
@@ -3181,12 +3446,12 @@ function sanitizeDraftTitle(raw) {
3181
3446
  const t3 = clip(cleanDraftText(raw.replace(/[\r\n]+/g, " ")), DRAFT_TITLE_MAX);
3182
3447
  return t3.charAt(0).toUpperCase() + t3.slice(1);
3183
3448
  }
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]));
3449
+ function mergeDraftResults(p, results, at2 = /* @__PURE__ */ new Date()) {
3450
+ const ids = new Set(p.items.map((i2) => i2.id));
3451
+ const next = new Map((p.results ?? []).map((r2) => [r2.id, r2]));
3187
3452
  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);
3453
+ 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(", ")}.`);
3454
+ const item = p.items.find((i2) => i2.id === r2.id);
3190
3455
  if (item.scope === "docs") {
3191
3456
  next.set(r2.id, { id: r2.id, title: "", summary: "", ...sanitizeDocsResult(item, r2), by: "claude", at: at2.toISOString() });
3192
3457
  continue;
@@ -3196,8 +3461,8 @@ function mergeDraftResults(p2, results, at2 = /* @__PURE__ */ new Date()) {
3196
3461
  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
3462
  next.set(r2.id, { id: r2.id, title: clean.title, summary: clean.summary, ...lines.length ? { lines } : {}, by: "claude", at: at2.toISOString() });
3198
3463
  }
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" };
3464
+ const merged = p.items.map((i2) => next.get(i2.id)).filter((r2) => !!r2);
3465
+ return { ...p, results: merged, status: merged.length === p.items.length ? "drafted" : "pending" };
3201
3466
  }
3202
3467
  function draftItemBrief(i2) {
3203
3468
  if (i2.scope === "docs" && i2.docs) {
@@ -3232,11 +3497,11 @@ function draftItemBrief(i2) {
3232
3497
  return lines.join("\n");
3233
3498
  }
3234
3499
  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);
3500
+ async function createPendingDrafts(client, p, branch = REQUESTS_BRANCH) {
3501
+ const problems = validatePendingDrafts(p);
3237
3502
  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;
3503
+ 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` });
3504
+ return p;
3240
3505
  }
3241
3506
  async function readPendingDrafts(client, sessionId, branch = REQUESTS_BRANCH) {
3242
3507
  const f = await client.getFile(draftSessionPath(sessionId), branch);
@@ -3245,16 +3510,16 @@ async function readPendingDrafts(client, sessionId, branch = REQUESTS_BRANCH) {
3245
3510
  }
3246
3511
  async function listPendingDrafts(client, opts = {}) {
3247
3512
  const branch = opts.branch ?? REQUESTS_BRANCH;
3248
- const entries = (await client.listDirectory(DRAFTS_DIR, branch)).filter((e3) => e3.type === "file" && /\.json$/.test(e3.name));
3513
+ const entries = (await client.listDirectory(DRAFTS_DIR, branch)).filter((e2) => e2.type === "file" && /\.json$/.test(e2.name));
3249
3514
  const out = [];
3250
- for (const e3 of entries) {
3251
- const id = e3.name.replace(/\.json$/, "");
3515
+ for (const e2 of entries) {
3516
+ const id = e2.name.replace(/\.json$/, "");
3252
3517
  if (!isDraftSessionId(id)) continue;
3253
3518
  const r2 = await readPendingDrafts(client, id, branch).catch(() => void 0);
3254
3519
  if (r2 && r2.drafts.sessionId === id) out.push(r2.drafts);
3255
3520
  }
3256
3521
  const status = opts.status ?? "all";
3257
- return out.filter((p2) => status === "all" || p2.status === status).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
3522
+ return out.filter((p) => status === "all" || p.status === status).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
3258
3523
  }
3259
3524
  async function updatePendingDrafts(client, sessionId, change, opts = {}) {
3260
3525
  const branch = opts.branch ?? REQUESTS_BRANCH;
@@ -3272,7 +3537,7 @@ async function updatePendingDrafts(client, sessionId, change, opts = {}) {
3272
3537
  }
3273
3538
  }
3274
3539
  function writeDraftResults(client, sessionId, results, opts = {}) {
3275
- return updatePendingDrafts(client, sessionId, (p2) => mergeDraftResults(p2, results, opts.now), {
3540
+ return updatePendingDrafts(client, sessionId, (p) => mergeDraftResults(p, results, opts.now), {
3276
3541
  ...opts,
3277
3542
  message: `Bridge drafts: ${results.length === 1 ? "1 text" : `${results.length} texts`} drafted by Claude`
3278
3543
  });
@@ -3284,7 +3549,7 @@ async function deletePendingDrafts(client, sessionId, opts = {}) {
3284
3549
  if (!f) return false;
3285
3550
  await client.deleteFile({ path, branch, message: "Bridge drafts: done", sha: f.sha });
3286
3551
  const images = await client.listDirectory(`${DRAFTS_DIR}/${sessionId}`, branch).catch(() => []);
3287
- for (const img of images.filter((e3) => e3.type === "file")) {
3552
+ for (const img of images.filter((e2) => e2.type === "file")) {
3288
3553
  await client.deleteFile({ path: img.path, branch, message: "Bridge drafts: done", sha: img.sha }).catch(() => void 0);
3289
3554
  }
3290
3555
  return true;
@@ -3378,38 +3643,40 @@ class DraftPoller {
3378
3643
  }
3379
3644
  }
3380
3645
  }
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);
3646
+ function explorationSummary(p, _owner, _repo, s) {
3647
+ const e2 = parseExplorationBody(p.body);
3648
+ const slug = p.headRef?.startsWith(EXPLORATION_PREFIX) ? p.headRef.slice(EXPLORATION_PREFIX.length) : e2?.slug ?? explorationSlug(p.title);
3384
3649
  return {
3385
- number: p2.number,
3386
- url: p2.url,
3387
- branch: p2.headRef,
3650
+ number: p.number,
3651
+ url: p.url,
3652
+ branch: p.headRef,
3388
3653
  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 })
3654
+ name: e2?.name ?? p.title.replace(/^Exploration:\s*/i, ""),
3655
+ purpose: e2?.purpose ?? "",
3656
+ ...e2?.useCase ? { useCase: e2.useCase } : {},
3657
+ status: explorationStatus({ state: p.state, labels: p.labels, headRef: p.headRef, body: p.body }),
3658
+ draft: p.draft,
3659
+ author: e2?.author ?? p.author,
3660
+ ...e2?.source ? { source: e2.source } : {},
3661
+ ...e2?.agent ? { agent: e2.agent } : {},
3662
+ updatedAt: p.updatedAt,
3663
+ headSha: p.headSha,
3664
+ previews: previewLinks(s.apps, { branch: p.headRef, pr: p.number, sha: p.headSha })
3398
3665
  };
3399
3666
  }
3400
3667
  async function listExplorationsOnGitHub(gh, s, opts = {}) {
3401
3668
  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));
3669
+ 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
3670
  }
3404
- async function startExplorationOnGitHub(gh, e3, s) {
3405
- const problems = explorationProblems(e3);
3671
+ async function startExplorationOnGitHub(gh, e2, s) {
3672
+ const problems = explorationProblems(e2);
3406
3673
  if (problems.length) throw new GitHubError(422, problems.join(" "));
3407
3674
  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);
3675
+ const slug = e2.slug || explorationSlug(e2.name);
3409
3676
  const branch = `${EXPLORATION_PREFIX}${slug}`;
3410
3677
  const x = gh.withBranchPrefix(EXPLORATION_PREFIX);
3411
3678
  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() };
3679
+ const full = { ...e2, slug, startedAt: e2.startedAt ?? (/* @__PURE__ */ new Date()).toISOString() };
3413
3680
  const commit = await x.commitToNewBranch({
3414
3681
  base: s.base,
3415
3682
  branch,
@@ -3434,21 +3701,21 @@ Exploration: never merged as is. Promote it to review or close it.`,
3434
3701
  previews: previewLinks(s.apps, { branch, pr: pr.number, sha: commit.sha })
3435
3702
  };
3436
3703
  }
3437
- async function explorationTryItOnGitHub(gh, e3) {
3438
- const [comments, head] = await Promise.all([gh.listIssueComments(e3.number), gh.getBranchSha(e3.branch).catch(() => void 0)]);
3704
+ async function explorationTryItOnGitHub(gh, e2) {
3705
+ const [comments, head] = await Promise.all([gh.listIssueComments(e2.number), gh.getBranchSha(e2.branch).catch(() => void 0)]);
3439
3706
  return explorationTryIt({ comment: findPreviewComment(comments)?.body, headSha: head });
3440
3707
  }
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)]);
3708
+ async function explorationTestBuildOnGitHub(gh, e2, config) {
3709
+ const [comments, head] = await Promise.all([gh.listIssueComments(e2.number), gh.getBranchSha(e2.branch).catch(() => void 0)]);
3443
3710
  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(() => []);
3711
+ const previews = await branchPreviewUrls(gh, e2.number, config, { branch: e2.branch, sha: head, comments }).catch(() => []);
3445
3712
  return { tryIt, previews, settled: tryIt.state !== "building" && previewsSettled(previews) };
3446
3713
  }
3447
3714
  async function findExplorationOnGitHub(gh, ref) {
3448
3715
  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;
3716
+ const p = await gh.getPullRequest(Number(String(ref).replace(/^#/, "")));
3717
+ 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.`);
3718
+ return p;
3452
3719
  }
3453
3720
  const branch = `${EXPLORATION_PREFIX}${explorationSlug(String(ref))}`;
3454
3721
  const open = await gh.findOpenPullRequest(branch);
@@ -3456,36 +3723,36 @@ async function findExplorationOnGitHub(gh, ref) {
3456
3723
  return gh.getPullRequest(open.number);
3457
3724
  }
3458
3725
  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: [] };
3726
+ const p = await findExplorationOnGitHub(gh, ref);
3727
+ const status = explorationStatus({ state: p.state, labels: p.labels, headRef: p.headRef, body: p.body });
3728
+ 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.`);
3729
+ const files = await gh.listPullRequestFiles(p.number);
3730
+ 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 });
3731
+ const out = { ...plan, number: p.number, url: p.url, branch: p.headRef, warnings: [] };
3465
3732
  if (opts.dryRun) return out;
3466
3733
  if (!gh.canWrite) throw new GitHubError(401, "Promoting an exploration needs a GitHub token (contents and pull requests, read and write).");
3467
3734
  const x = gh.withBranchPrefix(EXPLORATION_PREFIX);
3468
3735
  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.`);
3736
+ 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) => {
3737
+ if (e2 instanceof GitHubError && e2.auth === "rejected") throw e2;
3738
+ out.warnings.push(`The exploration note stays on the branch (${e2.message}). Delete ${plan.removeFiles.join(", ")} before merging.`);
3472
3739
  });
3473
3740
  }
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.`);
3741
+ await x.addLabels(p.number, plan.addLabels);
3742
+ await x.removeLabel(p.number, EXPLORATION_LABEL).catch((e2) => {
3743
+ if (!(e2 instanceof GitHubError && e2.status === 404)) out.warnings.push(`The exploration label is still on (${e2.message}). Remove it on GitHub.`);
3477
3744
  });
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}`);
3745
+ await x.updatePullRequest(p.number, { title: plan.title, body: plan.body });
3746
+ await x.markReadyForReview(p.number).catch((e2) => {
3747
+ out.warnings.push(`Still a draft: ${e2.message}`);
3481
3748
  });
3482
3749
  return out;
3483
3750
  }
3484
3751
  async function closeExplorationOnGitHub(gh, ref) {
3485
3752
  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 };
3753
+ const p = await findExplorationOnGitHub(gh, ref);
3754
+ await gh.updatePullRequest(p.number, { state: "closed" });
3755
+ return { number: p.number, url: p.url, branch: p.headRef };
3489
3756
  }
3490
3757
  async function linkRequestToExplorationOnGitHub(gh, n2, branch, opts = {}) {
3491
3758
  if (!isExplorationBranch(branch)) throw new GitHubError(422, `"${branch}" is not an exploration branch. Exploration branches are named explore/<name>.`);
@@ -3519,27 +3786,27 @@ async function declineRequestOnGitHub(gh, n2, reason, by2) {
3519
3786
  await gh.updateIssue(n2, { state: "closed", state_reason: "not_planned" });
3520
3787
  }
3521
3788
  export {
3522
- af as AAA_MIN,
3523
- ag as AA_MIN,
3789
+ ai as AAA_MIN,
3790
+ aj as AA_MIN,
3524
3791
  ADMIN_ROLE_ID,
3525
3792
  ANTHROPIC_MESSAGES_URL,
3526
3793
  BELL,
3527
3794
  BRAND_FONTS,
3528
3795
  BRAND_SLUG_RE,
3529
- ah as BULK_LIMIT,
3796
+ ak as BULK_LIMIT,
3530
3797
  k as COLOR_FIELDS,
3531
3798
  C as COMPONENT_SPECS_VERSION,
3532
3799
  CONFIG_FILE,
3533
- ai as CONTRAST_CELL_MAX,
3534
- aj as CONTRAST_CHECKS_FILE,
3800
+ al as CONTRAST_CELL_MAX,
3801
+ am as CONTRAST_CHECKS_FILE,
3535
3802
  ConfigError,
3536
- ak as DEFAULT_COMPONENT_SPECS_FILE,
3537
- al as DEFAULT_GOVERNANCE,
3538
- am as DEFAULT_OVERRIDE,
3803
+ an as DEFAULT_COMPONENT_SPECS_FILE,
3804
+ ao as DEFAULT_GOVERNANCE,
3805
+ ap as DEFAULT_OVERRIDE,
3539
3806
  DEFAULT_PROTECTED_BRANCHES,
3540
- an as DEFAULT_RIGHTS,
3807
+ aq as DEFAULT_RIGHTS,
3541
3808
  DEFAULT_TOKEN_PATHS,
3542
- ao as DEFAULT_VISUAL_IMPACT,
3809
+ ar as DEFAULT_VISUAL_IMPACT,
3543
3810
  DEMO_RELEASES,
3544
3811
  DOCS_CHANGE_BUMP,
3545
3812
  DOCS_DRAFT_MODEL,
@@ -3568,16 +3835,16 @@ export {
3568
3835
  EXT_SCOPES,
3569
3836
  GitHubClient,
3570
3837
  GitHubError,
3571
- ap as JsonParseError,
3838
+ as as JsonParseError,
3572
3839
  LIGHTNESS,
3573
3840
  LayeredTokenSet,
3574
3841
  NEUTRAL_ANCHORS,
3575
- aq as OWNER_GROUPS,
3842
+ at as OWNER_GROUPS,
3576
3843
  PIN_TOLERANCE,
3577
- ar as PREVIEW_APP_LABELS,
3578
- as as PREVIEW_COMMENT_MARKER,
3579
- at as PREVIEW_PLACEHOLDERS,
3580
- au as PRIMITIVE_MODE,
3844
+ au as PREVIEW_APP_LABELS,
3845
+ av as PREVIEW_COMMENT_MARKER,
3846
+ aw as PREVIEW_PLACEHOLDERS,
3847
+ ax as PRIMITIVE_MODE,
3581
3848
  PROSE_KEYS,
3582
3849
  PROTECTION_PARTS,
3583
3850
  PROTECTION_PART_PHRASE,
@@ -3587,111 +3854,120 @@ export {
3587
3854
  REQUEST_KINDS,
3588
3855
  REQUEST_LABEL,
3589
3856
  REQUEST_STATUS_LABEL,
3590
- av as RIGHTS,
3591
- aw as RIGHT_LABEL,
3857
+ ay as RIGHTS,
3858
+ az as RIGHT_LABEL,
3592
3859
  RISK_LABELS,
3593
- ax as RISK_TIER,
3860
+ aA as RISK_TIER,
3594
3861
  SIMILARITY_THRESHOLD,
3595
3862
  SINGLE_MODE,
3596
- ay as SPEC_FIELDS,
3863
+ aB as SPEC_FIELDS,
3597
3864
  STEPS,
3598
3865
  TIER_AXIS,
3599
3866
  TIER_NAMES,
3600
- az as TIER_ORDER,
3867
+ aC as TIER_ORDER,
3601
3868
  TOKEN_REJECTED_MESSAGE,
3602
3869
  TOKEN_SETTINGS_URL,
3603
- aA as TeamDirectory,
3604
- aB as UNRELEASED,
3605
- aC as VISUAL_CHECK_LABEL,
3870
+ aD as TeamDirectory,
3871
+ aE as UNRELEASED,
3872
+ aF as VISUAL_CHECK_LABEL,
3606
3873
  acceptDocsDraft,
3607
3874
  acceptDocsText,
3608
3875
  addBrandToConfigText,
3609
- aD as affectedContrast,
3610
- e2 as aliasOf,
3876
+ aG as affectedContrast,
3877
+ d as aliasOf,
3611
3878
  aliasTarget,
3612
3879
  anatomyLabel,
3613
3880
  anchoredRamp,
3614
3881
  anthropicReplyText,
3615
3882
  anthropicRequest,
3616
- aE as appForProject,
3617
- aF as appUrl,
3883
+ aH as appForProject,
3884
+ aI as appUrl,
3618
3885
  applyConfirmedRenames,
3619
3886
  applyDocsSections,
3620
3887
  applyTokenEdits,
3621
- aG as approverEntries,
3622
- aH as approverLists,
3888
+ applyTokenMerge,
3889
+ aJ as approverEntries,
3890
+ aK as approverLists,
3623
3891
  assertSafeBranch,
3624
3892
  assignRequestOnGitHub,
3625
- aI as assignVersions,
3893
+ aL as assignVersions,
3626
3894
  base64ToUtf8,
3627
- aJ as baseBranchOf,
3895
+ aM as baseBranchOf,
3628
3896
  bellChroma,
3629
- aK as branchName,
3897
+ aN as branchName,
3630
3898
  branchPreviewUrls,
3631
- aL as branchSlug,
3899
+ aO as branchSlug,
3632
3900
  brandDisplayName,
3633
3901
  brandPreviewVariables,
3634
3902
  buildHistoryEntry,
3635
3903
  buildReport,
3636
3904
  i as buildTokenSet,
3637
3905
  buildUsageIndex,
3638
- aM as canShip,
3639
- aN as changeKind,
3640
- aO as changeTable,
3641
- aP as changedModes,
3642
- aQ as changesetBump,
3906
+ aP as canShip,
3907
+ changeEdits,
3908
+ aQ as changeKind,
3909
+ aR as changeTable,
3910
+ aS as changedModes,
3911
+ aT as changesetBump,
3643
3912
  checkBrandSlug,
3644
3913
  checkLayeredPair,
3914
+ choiceFor,
3645
3915
  classifyAuth,
3646
- aR as classifyLayered,
3916
+ aU as classifyLayered,
3647
3917
  classifyRisk,
3648
3918
  cleanDocsText,
3649
3919
  cleanDraftText,
3650
- aS as clearRawDeep,
3920
+ aV as clearRawDeep,
3651
3921
  closeExplorationOnGitHub,
3652
3922
  closingIssueNumbers,
3653
3923
  coerceValue,
3654
3924
  collectHistory,
3655
3925
  collectRefs,
3656
- j2 as colorToCss,
3657
- k2 as colorsEqual,
3926
+ k2 as colorToCss,
3927
+ l as colorsEqual,
3928
+ combineChanges,
3929
+ combineConflicts,
3658
3930
  c as comboKey,
3659
- aT as commitMessage,
3660
- l as compactJson,
3931
+ aW as commitMessage,
3932
+ m as compactJson,
3661
3933
  componentForPath,
3662
- aU as composeChangeset,
3934
+ aX as composeChangeset,
3663
3935
  composeFiles,
3664
3936
  composeNewBrandBody,
3665
3937
  composePendingDrafts,
3666
- aV as composePrBody,
3667
- aW as composeProposalBody,
3938
+ aY as composePrBody,
3939
+ aZ as composeProposalBody,
3668
3940
  composeRequestIssue,
3669
- aX as composite,
3670
- aY as contextFor,
3941
+ a_ as composite,
3942
+ a$ as contextFor,
3671
3943
  contextLabel,
3672
- aZ as contrastDelta,
3673
- a_ as contrastDeltaTable,
3674
- a$ as contrastLevel,
3675
- b0 as contrastPair,
3676
- b1 as contrastRatio,
3944
+ b0 as contrastDelta,
3945
+ b1 as contrastDeltaTable,
3946
+ b2 as contrastLevel,
3947
+ b3 as contrastPair,
3948
+ b4 as contrastRatio,
3677
3949
  contrastScope,
3678
- b2 as countChanges,
3950
+ b5 as countChanges,
3679
3951
  createDocsDraftSession,
3680
3952
  createPendingDrafts,
3681
3953
  cssModuleClasses,
3954
+ cssOf,
3955
+ cssVarOf,
3682
3956
  cssVarsIn,
3683
3957
  declineComment,
3684
3958
  declineReasonProblems,
3685
3959
  declineRequestOnGitHub,
3686
- b3 as defaultContext,
3960
+ decodePicks,
3961
+ defaultChoiceFor,
3962
+ b6 as defaultContext,
3687
3963
  defaultFile,
3688
3964
  defaultScopes,
3689
- b4 as defaultTitle,
3690
- b5 as defineConfig,
3965
+ b7 as defaultTitle,
3966
+ b8 as defineConfig,
3691
3967
  deletePendingDrafts,
3692
3968
  demoHistory,
3693
- b6 as detectLayout,
3694
- b7 as diffLayered,
3969
+ b9 as detectLayout,
3970
+ ba as diffLayered,
3695
3971
  docsPrompt,
3696
3972
  docsSectionShapes,
3697
3973
  docsSectionsAnswer,
@@ -3708,12 +3984,13 @@ export {
3708
3984
  dtcgColor,
3709
3985
  effectiveScopes,
3710
3986
  emptyTokenFile,
3987
+ encodePicks,
3711
3988
  ensureRequestsBranch,
3712
- b8 as entriesFor,
3713
- b9 as entryLabel,
3989
+ bb as entriesFor,
3990
+ bc as entryLabel,
3714
3991
  evaluatePairs,
3715
- ba as expandEntries,
3716
- bb as expandOwners,
3992
+ bd as expandEntries,
3993
+ be as expandOwners,
3717
3994
  explorationBranch,
3718
3995
  explorationNote,
3719
3996
  explorationNotePath,
@@ -3729,62 +4006,62 @@ export {
3729
4006
  explorationTestBuildOnGitHub,
3730
4007
  explorationTryIt,
3731
4008
  explorationTryItOnGitHub,
3732
- bc as fieldChanges,
3733
- bd as fileModes,
3734
- be as filterHistory,
4009
+ bf as fieldChanges,
4010
+ bg as fileModes,
4011
+ bh as filterHistory,
3735
4012
  findExplorationOnGitHub,
3736
4013
  findPreviewComment,
3737
4014
  findReferenceProblems,
3738
- bf as findToken,
3739
- bg as findVercelComment,
3740
- bh as firstParagraph,
3741
- m as flattenLayerFile,
3742
- bi as flattenTokens,
4015
+ bi as findToken,
4016
+ bj as findVercelComment,
4017
+ bk as firstParagraph,
4018
+ n as flattenLayerFile,
4019
+ flattenTokens,
3743
4020
  formatChangeset,
3744
4021
  formatDocsJson,
3745
- bj as formatNumber,
3746
- bk as formatOwnerEntry,
4022
+ bl as formatNumber,
4023
+ bm as formatOwnerEntry,
3747
4024
  formatValue,
3748
4025
  friendlyMessage,
3749
4026
  fromHex,
3750
4027
  fromPlain,
3751
4028
  generateRamp,
3752
- bl as getChild,
4029
+ bn as getChild,
3753
4030
  getEntry,
3754
4031
  gitHubHistoryBackend,
3755
4032
  g2 as globToRegExp,
3756
- bm as groupsPhrase,
4033
+ bo as groupsPhrase,
3757
4034
  h as hashSpec,
3758
4035
  h2 as hexToRgba,
3759
- bn as holdersOf,
4036
+ bp as holdersOf,
3760
4037
  j as iconComponentName,
3761
4038
  idExtensionFor,
3762
4039
  impactedModules,
3763
4040
  importsIn,
3764
- bo as indexByPath,
3765
- bp as inheritedTypeAt,
3766
- bq as installCommand,
3767
- br as installCommandFromPreviewComment,
4041
+ bq as indexByPath,
4042
+ br as inheritedTypeAt,
4043
+ bs as installCommand,
4044
+ bt as installCommandFromPreviewComment,
3768
4045
  isActiveExploration,
3769
4046
  isAlias,
3770
4047
  isDocsSelectionMode,
3771
4048
  isDraftSessionId,
3772
4049
  isExplorationBranch,
3773
4050
  isExplorationPull,
3774
- bs as isGuardrail,
4051
+ bu as isGuardrail,
3775
4052
  isHex,
3776
4053
  isMissingPermission,
3777
4054
  isMultiMode,
3778
4055
  isPlanRefusal,
3779
4056
  isProseKey,
3780
- bt as isTeamEntry,
3781
- bu as isTokenFile,
4057
+ bv as isTeamEntry,
4058
+ bw as isTokenFile,
3782
4059
  isTokenRejected,
3783
- bv as isVercelComment,
4060
+ bx as isVercelComment,
3784
4061
  jiraIssueFields,
3785
- bw as kindForMin,
3786
- bx as layeredImpact,
3787
- n as layeredParityIssues,
4062
+ by as kindForMin,
4063
+ bz as layeredImpact,
4064
+ o as layeredParityIssues,
3788
4065
  g as layoutOptions,
3789
4066
  levenshtein,
3790
4067
  linkRequestToExplorationOnGitHub,
@@ -3796,16 +4073,17 @@ export {
3796
4073
  loadProtection,
3797
4074
  loadRepoFiles,
3798
4075
  loadRequiredChecks,
3799
- by as luminance,
4076
+ bA as luminance,
3800
4077
  markClaudeDraft,
3801
4078
  mergeDocsDraft,
3802
4079
  mergeDraftResults,
3803
4080
  mergeReleases,
4081
+ missingChoices,
3804
4082
  missingPermissionMessage,
3805
4083
  missingProse,
3806
4084
  modeDisplayName,
3807
4085
  modeFile,
3808
- bz as modeLabel,
4086
+ bB as modeLabel,
3809
4087
  modesOf$1 as modesOf,
3810
4088
  moveToken,
3811
4089
  nearestStep,
@@ -3814,54 +4092,57 @@ export {
3814
4092
  neutralOffset,
3815
4093
  newBrandSection,
3816
4094
  newDraftSessionId,
3817
- bA as nodesEqual,
3818
- bB as normalizeRights,
4095
+ bC as nodesEqual,
4096
+ bD as normalizeRights,
3819
4097
  oklch,
3820
4098
  oklchToLinear,
3821
- bC as overrideKey,
3822
- bD as ownerEntryProblems,
4099
+ bE as overrideKey,
4100
+ bF as ownerEntryProblems,
3823
4101
  packageDirCandidates,
3824
- bE as pairKey,
4102
+ bG as pairKey,
3825
4103
  parseChangelog,
3826
- bF as parseChangesetText,
3827
- p as parseColor,
3828
- bG as parseComponentSpecs,
4104
+ bH as parseChangesetText,
4105
+ parseColor,
4106
+ bI as parseComponentSpecs,
3829
4107
  parseContrastChecks,
3830
- o as parseDimension,
4108
+ q as parseDimension,
3831
4109
  parseDocsReply,
3832
4110
  parseDocsTaskAnswer,
3833
4111
  parseExplorationBody,
3834
4112
  parseJson,
3835
- bH as parseOwnerEntry,
4113
+ bJ as parseOwnerEntry,
3836
4114
  parsePendingDrafts,
3837
4115
  parseRepo,
3838
4116
  parseRequestIssue,
3839
4117
  parseStructureChange,
3840
4118
  parseTokenFile,
3841
- bI as parseVercelComment,
4119
+ bK as parseVercelComment,
3842
4120
  patchDocsJson,
3843
4121
  pathId,
3844
4122
  pathSimilarity,
3845
4123
  permissionLabel,
4124
+ pickedOption,
3846
4125
  plainEqual,
3847
4126
  planNewBrand,
3848
- bJ as planRestore,
3849
- bK as planRevert,
3850
- bL as planToJson,
4127
+ bL as planRestore,
4128
+ bM as planRevert,
4129
+ bN as planToJson,
4130
+ planTokenMerge,
3851
4131
  e as prNumberFromSubject,
3852
4132
  prefillDocs,
3853
- bM as previewComment,
4133
+ bO as previewComment,
3854
4134
  previewLinks,
3855
- bN as previewLinksOf,
3856
- bO as previewUrl,
4135
+ bP as previewLinksOf,
4136
+ previewOverrides,
4137
+ bQ as previewUrl,
3857
4138
  previewsSettled,
3858
- bP as projectOfLabel,
4139
+ bR as projectOfLabel,
3859
4140
  promoteExplorationOnGitHub,
3860
4141
  promotionPlan,
3861
4142
  propsTable,
3862
4143
  protectLibrary,
3863
4144
  protectRefusal,
3864
- bQ as protectedBranchesOf,
4145
+ bS as protectedBranchesOf,
3865
4146
  protectionRuleset,
3866
4147
  protectionRulesetName,
3867
4148
  protectionSentence,
@@ -3873,24 +4154,25 @@ export {
3873
4154
  reconcileIds,
3874
4155
  releasesFromTags,
3875
4156
  removeToken,
3876
- bR as renderedColor,
4157
+ removedSide,
4158
+ bT as renderedColor,
3877
4159
  requestBrief,
3878
4160
  requestImagePath,
3879
4161
  requestIssueTitle,
3880
4162
  requestStatus,
3881
4163
  requiredCheckNames,
3882
4164
  requiredPermission,
3883
- bS as resolve,
4165
+ resolve,
3884
4166
  resolveBranchPreviews,
3885
4167
  r as rgbaToDtcg,
3886
- q as rgbaToHex,
3887
- bT as rightsProblems,
4168
+ rgbaToHex,
4169
+ bU as rightsProblems,
3888
4170
  round3,
3889
4171
  rulesSettingsUrl,
3890
4172
  rulesetTargetsDefault,
3891
- bU as runLayeredContrast,
4173
+ bV as runLayeredContrast,
3892
4174
  sameScopes,
3893
- bV as sameToken,
4175
+ bW as sameToken,
3894
4176
  sanitizeDocsReplacement,
3895
4177
  sanitizeDocsResult,
3896
4178
  sanitizeDocsSections,
@@ -3904,21 +4186,22 @@ export {
3904
4186
  serializePendingDrafts,
3905
4187
  serializeTokenFile,
3906
4188
  shadowedEdits,
3907
- bW as shipPolicy,
4189
+ bX as shipPolicy,
3908
4190
  shortVariant,
3909
4191
  shortVariants,
3910
4192
  slugify,
3911
- bX as snapshotUrl,
3912
- bY as specHash,
4193
+ bY as snapshotUrl,
4194
+ bZ as specHash,
3913
4195
  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,
4196
+ b_ as summarizeTokenChange,
4197
+ takeMine,
4198
+ b$ as tarballAssetName,
4199
+ c0 as tarballUrl,
4200
+ c1 as teamKey,
4201
+ c2 as teamKeyOf,
4202
+ c3 as teamUnreadableMessage,
4203
+ c4 as teamsIn,
4204
+ threeWayDiff,
3922
4205
  tintedNeutral,
3923
4206
  c5 as titleOf,
3924
4207
  t2 as toAlias,
@@ -3934,6 +4217,7 @@ export {
3934
4217
  ca as tokenNode,
3935
4218
  tokenUsage,
3936
4219
  tokensPath,
4220
+ unpicked,
3937
4221
  cb as unreadableShipTeams,
3938
4222
  cc as unreadableTeams,
3939
4223
  updatePendingDrafts,