@bridge-ds/core 0.5.0 → 0.6.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 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";
1
+ import { o as modeDisplayName, q as modesOf$1, u as isMultiMode, T as TIER_NAMES, w as TIER_AXIS, x as findReferenceProblems, y as evaluatePairs, z as contrastScope, A as contextLabel, S as SINGLE_MODE, B as pathId, D as flattenTokens, E as serializeTokenFile, F as removeToken, G as upsertToken, H as threeWayDiff, I as emptyTokenFile, J as parseTokenFile, K as EXT_ID, L as EXT_SCOPES, M as resolve, N as moveToken, O as effectiveScopes, P as sameScopes, Q as defaultScopes, R as readTokenAt, U as modeFile, V as defaultFile, W as DEFAULT_PROTECTED_BRANCHES, a as assertSafeBranch, X as ProtectedBranchError, C as CONFIG_FILE, l as loadConfig, Y as ConfigError, Z as DEFAULT_TOKEN_PATHS, c as collectHistory, p as packageDirCandidates, b as parseChangelog, r as releasesFromTags, m as mergeReleases, d as buildReport, _ as applyTokenEdits, $ as buildHistoryEntry, a0 as resolveBranchPreviews, a1 as tokensPath, a2 as coerceValue, a3 as toConfigJson, a4 as parseContrastChecks, a5 as checkLayeredPair, a6 as classifyRisk, a7 as formatChangeset, a8 as RISK_LABELS, a9 as parseJson, aa as serializeJson, ab as plainEqual, ac as toPlain, ad as getEntry, ae as fromPlain, af as previewLinks, ag as slugify, ah as readPreviewComment, ai as findPreviewComment, aj as previewsSettled, f as variantKeyOf } from "./component-spec-GFVEE6Fc.js";
2
+ import { ak, al, am, n, k, 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, aP, aQ, j, 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, bp, bq, br, h, bs, i, bt, bu, bv, bw, bx, by, bz, bA, bB, bC, g, bD, bE, bF, bG, bH, bI, bJ, bK, bL, bM, bN, bO, bP, bQ, e, bR, bS, bT, bU, bV, bW, bX, bY, bZ, b_, b$, s, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, ca, t, cb, cc, cd, ce, v, cf, cg, ch, ci, cj } from "./component-spec-GFVEE6Fc.js";
3
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";
4
+ import { D, d, k as k2, l, c, m, n as n2, 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.");
@@ -236,14 +236,14 @@ function reconcileIds(figma, git) {
236
236
  if (best) suggestions.push(best);
237
237
  }
238
238
  const byGit = /* @__PURE__ */ new Map();
239
- for (const s of suggestions) {
240
- const prev = byGit.get(s.gitId);
241
- if (!prev || s.similarity > prev.similarity) byGit.set(s.gitId, s);
239
+ for (const s2 of suggestions) {
240
+ const prev = byGit.get(s2.gitId);
241
+ if (!prev || s2.similarity > prev.similarity) byGit.set(s2.gitId, s2);
242
242
  }
243
243
  return { tokens, adoptedByName, suggestions: [...byGit.values()] };
244
244
  }
245
245
  function applyConfirmedRenames(tokens, confirmed) {
246
- const map = new Map(confirmed.map((s) => [s.figmaId, s.gitId]));
246
+ const map = new Map(confirmed.map((s2) => [s2.figmaId, s2.gitId]));
247
247
  return tokens.map((t3) => map.has(t3.id) ? { ...t3, id: map.get(t3.id) } : t3);
248
248
  }
249
249
  function idExtensionFor(t3) {
@@ -404,8 +404,8 @@ function combineConflicts(changes) {
404
404
  return out;
405
405
  }
406
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;
407
+ const n3 = picks[c10.key];
408
+ return n3 === void 0 ? null : c10.options.find((o2) => o2.changes.includes(n3)) ?? null;
409
409
  }
410
410
  const unpicked = (conflicts, picks) => conflicts.filter((c10) => !pickedOption(c10, picks));
411
411
  function combineChanges(latest, changes, picks = {}, opts = {}) {
@@ -458,16 +458,16 @@ function combineChanges(latest, changes, picks = {}, opts = {}) {
458
458
  return { files, included: on.map((c10) => c10.number), edits: groups.size, tokens, conflicts, missing, from, problems };
459
459
  }
460
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("~");
461
+ return Object.entries(picks).filter(([, n3]) => Number.isSafeInteger(n3) && n3 > 0).sort(([a], [b]) => a.localeCompare(b)).map(([key, n3]) => `${n3}:${key}`).join("~");
462
462
  }
463
463
  function decodePicks(raw) {
464
464
  const out = {};
465
465
  for (const part of (raw ?? "").split("~")) {
466
466
  const i2 = part.indexOf(":");
467
467
  if (i2 < 1) continue;
468
- const n2 = Number(part.slice(0, i2));
468
+ const n3 = Number(part.slice(0, i2));
469
469
  const key = part.slice(i2 + 1);
470
- if (/^\d{1,7}$/.test(part.slice(0, i2)) && n2 > 0 && key.includes("#")) out[key] = n2;
470
+ if (/^\d{1,7}$/.test(part.slice(0, i2)) && n3 > 0 && key.includes("#")) out[key] = n3;
471
471
  }
472
472
  return out;
473
473
  }
@@ -595,7 +595,7 @@ function requiredCheckNames(defaultBranchRuns, pullRequestRuns) {
595
595
  const names2 = [...new Set(defaultBranchRuns.filter((r2) => !isVercel(r2) && ran(r2)).map((r2) => r2.name))];
596
596
  if (!pullRequestRuns?.length) return names2;
597
597
  const onPulls = new Set(pullRequestRuns.filter((r2) => !isVercel(r2)).map((r2) => r2.name));
598
- return names2.filter((n2) => onPulls.has(n2));
598
+ return names2.filter((n3) => onPulls.has(n3));
599
599
  }
600
600
  function refPattern(pattern) {
601
601
  const src = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "\0").replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]").replace(/\u0000/g, ".*");
@@ -664,8 +664,8 @@ function protectionSentence(state) {
664
664
  case "unprotected":
665
665
  return "Your library can be changed without review.";
666
666
  case "partial": {
667
- const s = joinAnd(state.missing.map((p) => PROTECTION_PART_PHRASE[p]));
668
- return `Partly protected: ${s}.`;
667
+ const s2 = joinAnd(state.missing.map((p) => PROTECTION_PART_PHRASE[p]));
668
+ return `Partly protected: ${s2}.`;
669
669
  }
670
670
  default:
671
671
  return "Protection status unknown: GitHub did not let this token read it.";
@@ -989,37 +989,37 @@ class GitHubClient {
989
989
  * Marks a draft pull request ready for review. REST cannot unset `draft`, so this is the GraphQL mutation
990
990
  * markPullRequestReadyForReview, with the same token (pull requests: write).
991
991
  */
992
- async markReadyForReview(n2) {
992
+ async markReadyForReview(n3) {
993
993
  this.assertToken("Marking a pull request ready for review");
994
- const pr = await this.request("GET", `${this.repoPath}/pulls/${n2}`);
994
+ const pr = await this.request("GET", `${this.repoPath}/pulls/${n3}`);
995
995
  if (pr.draft === false) return;
996
- if (!pr.node_id) throw new GitHubError(422, `Pull request #${n2} has no node id: mark it ready for review on GitHub.`);
996
+ if (!pr.node_id) throw new GitHubError(422, `Pull request #${n3} has no node id: mark it ready for review on GitHub.`);
997
997
  const r2 = await this.request("POST", "/graphql", {
998
998
  query: "mutation($id: ID!) { markPullRequestReadyForReview(input: { pullRequestId: $id }) { pullRequest { number isDraft } } }",
999
999
  variables: { id: pr.node_id }
1000
1000
  });
1001
1001
  if (r2?.errors?.length) {
1002
1002
  const detail = r2.errors.map((e2) => e2.message).filter(Boolean).join(" ");
1003
- throw new GitHubError(422, `GitHub refused to mark #${n2} ready for review${detail ? `: ${detail}` : "."} Use "Ready for review" on GitHub instead.`, detail);
1003
+ throw new GitHubError(422, `GitHub refused to mark #${n3} ready for review${detail ? `: ${detail}` : "."} Use "Ready for review" on GitHub instead.`, detail);
1004
1004
  }
1005
1005
  }
1006
1006
  /**
1007
1007
  * Turns an open pull request back into a draft: the GraphQL mutation convertPullRequestToDraft (REST cannot set
1008
1008
  * `draft` either), same token. No-op when it is already a draft.
1009
1009
  */
1010
- async convertToDraft(n2) {
1010
+ async convertToDraft(n3) {
1011
1011
  this.assertToken("Turning a pull request back into a draft");
1012
- const pr = await this.request("GET", `${this.repoPath}/pulls/${n2}`);
1012
+ const pr = await this.request("GET", `${this.repoPath}/pulls/${n3}`);
1013
1013
  if (pr.draft === true) return;
1014
- if (pr.state && pr.state !== "open") throw new GitHubError(422, `Pull request #${n2} is ${pr.state}: only an open one can go back to draft.`);
1015
- if (!pr.node_id) throw new GitHubError(422, `Pull request #${n2} has no node id: convert it to draft on GitHub.`);
1014
+ if (pr.state && pr.state !== "open") throw new GitHubError(422, `Pull request #${n3} is ${pr.state}: only an open one can go back to draft.`);
1015
+ if (!pr.node_id) throw new GitHubError(422, `Pull request #${n3} has no node id: convert it to draft on GitHub.`);
1016
1016
  const r2 = await this.request("POST", "/graphql", {
1017
1017
  query: "mutation($id: ID!) { convertPullRequestToDraft(input: { pullRequestId: $id }) { pullRequest { number isDraft } } }",
1018
1018
  variables: { id: pr.node_id }
1019
1019
  });
1020
1020
  if (r2?.errors?.length) {
1021
1021
  const detail = r2.errors.map((e2) => e2.message).filter(Boolean).join(" ");
1022
- throw new GitHubError(422, `GitHub refused to turn #${n2} back into a draft${detail ? `: ${detail}` : "."} Use "Convert to draft" on GitHub instead.`, detail);
1022
+ throw new GitHubError(422, `GitHub refused to turn #${n3} back into a draft${detail ? `: ${detail}` : "."} Use "Convert to draft" on GitHub instead.`, detail);
1023
1023
  }
1024
1024
  }
1025
1025
  async createPullRequest(input) {
@@ -1073,18 +1073,18 @@ class GitHubClient {
1073
1073
  const r2 = await this.request("GET", `${this.repoPath}/issues?${q2}`);
1074
1074
  return r2.filter((i2) => !i2.pull_request).map(toIssue);
1075
1075
  }
1076
- async getIssue(n2) {
1077
- return toIssue(await this.request("GET", `${this.repoPath}/issues/${n2}`));
1076
+ async getIssue(n3) {
1077
+ return toIssue(await this.request("GET", `${this.repoPath}/issues/${n3}`));
1078
1078
  }
1079
1079
  /** Edits an issue: its body, or closes it with a reason ("not_planned" for a declined request). */
1080
- async updateIssue(n2, patch) {
1080
+ async updateIssue(n3, patch) {
1081
1081
  this.assertToken("Editing an issue");
1082
- return toIssue(await this.request("PATCH", `${this.repoPath}/issues/${n2}`, patch));
1082
+ return toIssue(await this.request("PATCH", `${this.repoPath}/issues/${n3}`, patch));
1083
1083
  }
1084
1084
  /** Adds people to an issue's assignees (GitHub ignores logins that cannot be assigned: the result says who is). */
1085
- async addAssignees(n2, logins) {
1085
+ async addAssignees(n3, logins) {
1086
1086
  this.assertToken("Assigning an issue");
1087
- const r2 = await this.request("POST", `${this.repoPath}/issues/${n2}/assignees`, { assignees: logins });
1087
+ const r2 = await this.request("POST", `${this.repoPath}/issues/${n3}/assignees`, { assignees: logins });
1088
1088
  return (r2.assignees ?? []).map((a) => a.login);
1089
1089
  }
1090
1090
  /** People with at least `permission` on the repository (reading the list needs push access). First 100. */
@@ -1266,7 +1266,7 @@ class GitHubClient {
1266
1266
  ]);
1267
1267
  const checks = [
1268
1268
  ...runs.map((c10) => ({ name: c10.name, status: c10.status, conclusion: c10.conclusion })),
1269
- ...combined.statuses.map((s) => ({ name: s.context, status: s.state === "pending" ? "in_progress" : "completed", conclusion: s.state === "pending" ? null : s.state }))
1269
+ ...combined.statuses.map((s2) => ({ name: s2.context, status: s2.state === "pending" ? "in_progress" : "completed", conclusion: s2.state === "pending" ? null : s2.state }))
1270
1270
  ];
1271
1271
  const failing = checks.some((c10) => c10.conclusion && !["success", "neutral", "skipped"].includes(c10.conclusion));
1272
1272
  const pending = checks.some((c10) => c10.status !== "completed");
@@ -1275,7 +1275,7 @@ class GitHubClient {
1275
1275
  /** Commit statuses of a commit, newest first (Vercel reports each project as "Vercel – <project>"). */
1276
1276
  async listCommitStatuses(sha) {
1277
1277
  const r2 = await this.request("GET", `${this.repoPath}/commits/${encodeRef(sha)}/statuses?per_page=100`);
1278
- return r2.map((s) => ({ context: s.context, state: s.state, target_url: s.target_url ?? null, description: s.description ?? null }));
1278
+ return r2.map((s2) => ({ context: s2.context, state: s2.state, target_url: s2.target_url ?? null, description: s2.description ?? null }));
1279
1279
  }
1280
1280
  /**
1281
1281
  * GitHub deployments of a commit with their latest status (environment "Preview – <project>", environment_url the
@@ -1288,30 +1288,30 @@ class GitHubClient {
1288
1288
  return Promise.all(
1289
1289
  [...latest.values()].map(async (d2) => {
1290
1290
  const st = await this.request("GET", `${this.repoPath}/deployments/${d2.id}/statuses?per_page=1`).catch(() => []);
1291
- const s = st[0];
1292
- return { id: d2.id, environment: d2.environment, state: s?.state ?? null, environmentUrl: s?.environment_url || null };
1291
+ const s2 = st[0];
1292
+ return { id: d2.id, environment: d2.environment, state: s2?.state ?? null, environmentUrl: s2?.environment_url || null };
1293
1293
  })
1294
1294
  );
1295
1295
  }
1296
- async getPullRequest(n2) {
1297
- const r2 = await this.request("GET", `${this.repoPath}/pulls/${n2}`);
1296
+ async getPullRequest(n3) {
1297
+ const r2 = await this.request("GET", `${this.repoPath}/pulls/${n3}`);
1298
1298
  return { ...toSummary(r2), body: r2.body ?? "", mergeable: r2.mergeable ?? null };
1299
1299
  }
1300
- async listPullRequestFiles(n2) {
1301
- const r2 = await this.request("GET", `${this.repoPath}/pulls/${n2}/files?per_page=100`);
1300
+ async listPullRequestFiles(n3) {
1301
+ const r2 = await this.request("GET", `${this.repoPath}/pulls/${n3}/files?per_page=100`);
1302
1302
  return r2.map((f) => ({ filename: f.filename, status: f.status, additions: f.additions, deletions: f.deletions }));
1303
1303
  }
1304
- async updatePullRequest(n2, patch) {
1305
- await this.request("PATCH", `${this.repoPath}/pulls/${n2}`, patch);
1304
+ async updatePullRequest(n3, patch) {
1305
+ await this.request("PATCH", `${this.repoPath}/pulls/${n3}`, patch);
1306
1306
  }
1307
- async listReviews(n2) {
1308
- const r2 = await this.request("GET", `${this.repoPath}/pulls/${n2}/reviews`);
1307
+ async listReviews(n3) {
1308
+ const r2 = await this.request("GET", `${this.repoPath}/pulls/${n3}/reviews`);
1309
1309
  return r2.map((x) => ({ id: x.id, user: x.user?.login, state: x.state, body: x.body ?? "", ...x.submitted_at ? { submittedAt: x.submitted_at } : {} }));
1310
1310
  }
1311
1311
  /** Submit a review. `COMMENT` works for any collaborator; approving your own PR is refused by GitHub. */
1312
- async createReview(n2, input) {
1312
+ async createReview(n3, input) {
1313
1313
  this.assertToken("Reviewing a pull request");
1314
- const r2 = await this.request("POST", `${this.repoPath}/pulls/${n2}/reviews`, input);
1314
+ const r2 = await this.request("POST", `${this.repoPath}/pulls/${n3}/reviews`, input);
1315
1315
  return { id: r2.id, user: r2.user?.login, state: r2.state, body: r2.body ?? "" };
1316
1316
  }
1317
1317
  async listCheckRuns(ref) {
@@ -1816,19 +1816,19 @@ const LIGHTNESS = { 50: 0.975, 100: 0.952, 200: 0.912, 300: 0.85, 400: 0.735, 50
1816
1816
  const BELL = { 50: 0.12, 100: 0.22, 200: 0.4, 300: 0.62, 400: 0.85, 500: 1, 600: 1, 700: 0.92, 800: 0.8, 900: 0.62, 950: 0.5 };
1817
1817
  const NEUTRAL_ANCHORS = { 200: "#E3E8EE", 600: "#5B6672", 900: "#15202B" };
1818
1818
  const PIN_TOLERANCE = 0.04;
1819
- const bellChroma = (peak) => (s) => peak * BELL[s];
1820
- const neutralChroma = (scale = 1, low = 4e-3, base = 0.01, slope = 0.022) => (s) => (s <= 100 ? low : base + slope * (s / 950)) * scale;
1821
- function oklchToLinear(L, C2, h3) {
1819
+ const bellChroma = (peak) => (s2) => peak * BELL[s2];
1820
+ const neutralChroma = (scale = 1, low = 4e-3, base = 0.01, slope = 0.022) => (s2) => (s2 <= 100 ? low : base + slope * (s2 / 950)) * scale;
1821
+ function oklchToLinear(L, C, h3) {
1822
1822
  const hr = h3 * Math.PI / 180;
1823
- const a = C2 * Math.cos(hr);
1824
- const b = C2 * Math.sin(hr);
1823
+ const a = C * Math.cos(hr);
1824
+ const b = C * Math.sin(hr);
1825
1825
  const l2 = (L + 0.3963377774 * a + 0.2158037573 * b) ** 3;
1826
1826
  const m2 = (L - 0.1055613458 * a - 0.0638541728 * b) ** 3;
1827
- const s = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
1827
+ const s2 = (L - 0.0894841775 * a - 1.291485548 * b) ** 3;
1828
1828
  return [
1829
- 4.0767416621 * l2 - 3.3077115913 * m2 + 0.2309699292 * s,
1830
- -1.2684380046 * l2 + 2.6097574011 * m2 - 0.3413193965 * s,
1831
- -0.0041960863 * l2 - 0.7034186147 * m2 + 1.707614701 * s
1829
+ 4.0767416621 * l2 - 3.3077115913 * m2 + 0.2309699292 * s2,
1830
+ -1.2684380046 * l2 + 2.6097574011 * m2 - 0.3413193965 * s2,
1831
+ -0.0041960863 * l2 - 0.7034186147 * m2 + 1.707614701 * s2
1832
1832
  ];
1833
1833
  }
1834
1834
  const encode = (x) => {
@@ -1836,8 +1836,8 @@ const encode = (x) => {
1836
1836
  return c10 <= 31308e-7 ? 12.92 * c10 : 1.055 * c10 ** (1 / 2.4) - 0.055;
1837
1837
  };
1838
1838
  const decode = (x) => x <= 0.04045 ? x / 12.92 : ((x + 0.055) / 1.055) ** 2.4;
1839
- function oklch(L, C2, h3) {
1840
- let c10 = C2;
1839
+ function oklch(L, C, h3) {
1840
+ let c10 = C;
1841
1841
  let lin = oklchToLinear(L, c10, h3);
1842
1842
  for (let i2 = 0; i2 < 60 && !lin.every((x) => x >= -5e-4 && x <= 1.0005); i2++) {
1843
1843
  c10 *= 0.95;
@@ -1849,15 +1849,15 @@ function toOklch(rgb) {
1849
1849
  const [r2, g3, b] = rgb.map(decode);
1850
1850
  const l2 = Math.cbrt(0.4122214708 * r2 + 0.5363325363 * g3 + 0.0514459929 * b);
1851
1851
  const m2 = Math.cbrt(0.2119034982 * r2 + 0.6806995451 * g3 + 0.1073969566 * b);
1852
- const s = Math.cbrt(0.0883024619 * r2 + 0.2817188376 * g3 + 0.6299787005 * b);
1853
- const L = 0.2104542553 * l2 + 0.793617785 * m2 - 0.0040720468 * s;
1854
- const A = 1.9779984951 * l2 - 2.428592205 * m2 + 0.4505937099 * s;
1855
- const B = 0.0259040371 * l2 + 0.7827717662 * m2 - 0.808675766 * s;
1856
- const C2 = Math.sqrt(A * A + B * B);
1857
- const h3 = C2 < 1e-6 ? 0 : (Math.atan2(B, A) * 180 / Math.PI + 360) % 360;
1858
- return { L, C: C2, h: h3 };
1859
- }
1860
- const isHex = (s) => typeof s === "string" && /^#[0-9a-f]{6}$/i.test(s.trim());
1852
+ const s2 = Math.cbrt(0.0883024619 * r2 + 0.2817188376 * g3 + 0.6299787005 * b);
1853
+ const L = 0.2104542553 * l2 + 0.793617785 * m2 - 0.0040720468 * s2;
1854
+ const A = 1.9779984951 * l2 - 2.428592205 * m2 + 0.4505937099 * s2;
1855
+ const B = 0.0259040371 * l2 + 0.7827717662 * m2 - 0.808675766 * s2;
1856
+ const C = Math.sqrt(A * A + B * B);
1857
+ const h3 = C < 1e-6 ? 0 : (Math.atan2(B, A) * 180 / Math.PI + 360) % 360;
1858
+ return { L, C, h: h3 };
1859
+ }
1860
+ const isHex = (s2) => typeof s2 === "string" && /^#[0-9a-f]{6}$/i.test(s2.trim());
1861
1861
  const fromHex = (hex) => [1, 3, 5].map((i2) => parseInt(hex.slice(i2, i2 + 2), 16) / 255);
1862
1862
  const round3 = (x) => Math.round(x * 1e3) / 1e3;
1863
1863
  const toHex = (rgb) => "#" + rgb.map((x) => Math.round(x * 255).toString(16).padStart(2, "0")).join("");
@@ -1868,35 +1868,35 @@ function dtcgColor(rgb, alpha) {
1868
1868
  }
1869
1869
  function generateRamp({ hue, chroma, offset = () => 0, pins = {} }) {
1870
1870
  const out = {};
1871
- for (const s of STEPS) {
1872
- const pin = pins[s];
1873
- out[s] = pin ? fromHex(pin) : oklch(LIGHTNESS[s] + offset(s), chroma(s), hue);
1871
+ for (const s2 of STEPS) {
1872
+ const pin = pins[s2];
1873
+ out[s2] = pin ? fromHex(pin) : oklch(LIGHTNESS[s2] + offset(s2), chroma(s2), hue);
1874
1874
  }
1875
1875
  return out;
1876
1876
  }
1877
1877
  function nearestStep(rgb) {
1878
1878
  const { L } = toOklch(rgb);
1879
1879
  let best = STEPS[0];
1880
- for (const s of STEPS) if (Math.abs(LIGHTNESS[s] - L) < Math.abs(LIGHTNESS[best] - L)) best = s;
1880
+ for (const s2 of STEPS) if (Math.abs(LIGHTNESS[s2] - L) < Math.abs(LIGHTNESS[best] - L)) best = s2;
1881
1881
  return best;
1882
1882
  }
1883
1883
  function anchoredRamp(hex, pinStep) {
1884
1884
  const rgb = fromHex(hex);
1885
- const { L, C: C2, h: h3 } = toOklch(rgb);
1885
+ const { L, C, h: h3 } = toOklch(rgb);
1886
1886
  const step = pinStep ?? nearestStep(rgb);
1887
- const peak = Math.min(0.24, Math.max(0.02, C2 / BELL[step]));
1887
+ const peak = Math.min(0.24, Math.max(0.02, C / BELL[step]));
1888
1888
  return { hue: h3, peak, step, distance: Math.abs(L - LIGHTNESS[step]), ramp: generateRamp({ hue: h3, chroma: bellChroma(peak), pins: { [step]: hex.toUpperCase() } }) };
1889
1889
  }
1890
1890
  function neutralOffset() {
1891
1891
  const off = {};
1892
- for (const [s, hex] of Object.entries(NEUTRAL_ANCHORS)) off[s] = toOklch(fromHex(hex)).L - LIGHTNESS[s];
1893
- return (s) => off[s] ?? 0;
1892
+ for (const [s2, hex] of Object.entries(NEUTRAL_ANCHORS)) off[s2] = toOklch(fromHex(hex)).L - LIGHTNESS[s2];
1893
+ return (s2) => off[s2] ?? 0;
1894
1894
  }
1895
1895
  function tintedNeutral(hex) {
1896
1896
  const rgb = fromHex(hex);
1897
- const { C: C2, h: h3 } = toOklch(rgb);
1897
+ const { C, h: h3 } = toOklch(rgb);
1898
1898
  const ref = neutralChroma()(nearestStep(rgb));
1899
- const scale = C2 < 4e-3 ? 0 : Math.min(2.5, C2 / ref);
1899
+ const scale = C < 4e-3 ? 0 : Math.min(2.5, C / ref);
1900
1900
  return { hue: h3, scale, ramp: generateRamp({ hue: h3, chroma: neutralChroma(scale), offset: neutralOffset() }) };
1901
1901
  }
1902
1902
  const BRAND_FONTS = [
@@ -1968,8 +1968,8 @@ function rampFor(input, pinStep, kind) {
1968
1968
  const hex = String(input).trim();
1969
1969
  if (!isHex(hex)) throw new Error(`"${hex}" is not a color. Use #rrggbb or a hue in degrees (0 to 360).`);
1970
1970
  if (kind === "neutral") {
1971
- const n2 = tintedNeutral(hex);
1972
- return { ramp: n2.ramp, anchor: `${hex.toUpperCase()} (hue ${Math.round(n2.hue)})` };
1971
+ const n3 = tintedNeutral(hex);
1972
+ return { ramp: n3.ramp, anchor: `${hex.toUpperCase()} (hue ${Math.round(n3.hue)})` };
1973
1973
  }
1974
1974
  const a = anchoredRamp(hex, pinStep);
1975
1975
  const issue = a.distance > PIN_TOLERANCE ? {
@@ -1982,9 +1982,9 @@ function rampFor(input, pinStep, kind) {
1982
1982
  function aliasRamp(doc, role, ramp, description) {
1983
1983
  const group = getAt(doc, `palette.${role}`);
1984
1984
  if (!group) return;
1985
- for (const s of STEPS) {
1986
- if (!(String(s) in group)) continue;
1987
- setAt(doc, `palette.${role}.${s}`, { $value: `{color.${ramp}.${s}}` });
1985
+ for (const s2 of STEPS) {
1986
+ if (!(String(s2) in group)) continue;
1987
+ setAt(doc, `palette.${role}.${s2}`, { $value: `{color.${ramp}.${s2}}` });
1988
1988
  }
1989
1989
  group.$description = description;
1990
1990
  }
@@ -2031,15 +2031,15 @@ function listBrands(source) {
2031
2031
  }
2032
2032
  function checkBrandSlug(config, files, slug) {
2033
2033
  const out = [];
2034
- const s = slug.trim();
2035
- if (!s) return [{ level: "error", code: "slug-empty", message: "Give the brand a name." }];
2036
- if (s.length < 2 || s.length > 24 || !BRAND_SLUG_RE.test(s)) out.push({ level: "error", code: "slug-format", message: 'Use 2 to 24 lowercase letters, digits and single dashes, starting with a letter: "acme" or "north-star".' });
2034
+ const s2 = slug.trim();
2035
+ if (!s2) return [{ level: "error", code: "slug-empty", message: "Give the brand a name." }];
2036
+ if (s2.length < 2 || s2.length > 24 || !BRAND_SLUG_RE.test(s2)) out.push({ level: "error", code: "slug-format", message: 'Use 2 to 24 lowercase letters, digits and single dashes, starting with a letter: "acme" or "north-star".' });
2037
2037
  const taken = Object.values(config.axes).flatMap((a) => a.values);
2038
- if (config.axes.brand?.values.includes(s)) out.push({ level: "error", code: "slug-taken", message: `A brand called "${s}" already exists. Pick another name or edit that brand.` });
2039
- else if (taken.includes(s) || RESERVED.has(s)) out.push({ level: "error", code: "slug-reserved", message: `"${s}" is a reserved mode name. Pick another name.` });
2038
+ if (config.axes.brand?.values.includes(s2)) out.push({ level: "error", code: "slug-taken", message: `A brand called "${s2}" already exists. Pick another name or edit that brand.` });
2039
+ else if (taken.includes(s2) || RESERVED.has(s2)) out.push({ level: "error", code: "slug-reserved", message: `"${s2}" is a reserved mode name. Pick another name.` });
2040
2040
  const layer = brandLayers(config).brand;
2041
2041
  const map = fileMap(files);
2042
- if (layer && !config.axes.brand?.values.includes(s) && map.has(fill(layer, { brand: s }))) out.push({ level: "error", code: "slug-file-exists", message: `${tokensPath(config, fill(layer, { brand: s }))} already exists. Pick another name or add it to bridge.config.json.` });
2042
+ if (layer && !config.axes.brand?.values.includes(s2) && map.has(fill(layer, { brand: s2 }))) out.push({ level: "error", code: "slug-file-exists", message: `${tokensPath(config, fill(layer, { brand: s2 }))} already exists. Pick another name or add it to bridge.config.json.` });
2043
2043
  return out;
2044
2044
  }
2045
2045
  function planNewBrand(source, input) {
@@ -2219,7 +2219,7 @@ function planNewBrand(source, input) {
2219
2219
  const ramps = {};
2220
2220
  if (inGate) {
2221
2221
  const combo = after.normalizeCombo({ brand: slug });
2222
- const read = (role) => STEPS.map((s) => ({ step: s, hex: after.resolve(`palette.${role}.${s}`, combo).css })).filter((x) => /^#[0-9a-f]{6}$/i.test(x.hex));
2222
+ const read = (role) => STEPS.map((s2) => ({ step: s2, hex: after.resolve(`palette.${role}.${s2}`, combo).css })).filter((x) => /^#[0-9a-f]{6}$/i.test(x.hex));
2223
2223
  ramps.primary = read("primary");
2224
2224
  ramps.neutral = read("neutral");
2225
2225
  for (const role of ["accent", "link"]) {
@@ -2281,13 +2281,13 @@ function brandPreviewVariables(source, plan, theme) {
2281
2281
  }
2282
2282
  return out;
2283
2283
  }
2284
- const code = (s) => `\`${s}\``;
2284
+ const code = (s2) => `\`${s2}\``;
2285
2285
  function newBrandSection(plan) {
2286
2286
  const roles = Object.keys(plan.ramps);
2287
2287
  const rampTable = roles.length ? [
2288
2288
  `| Step | ${roles.map((r2) => r2[0].toUpperCase() + r2.slice(1)).join(" | ")} |`,
2289
2289
  `| --- | ${roles.map(() => "---").join(" | ")} |`,
2290
- ...STEPS.map((s) => `| ${s}${s === plan.actionStep ? " (actions)" : ""} | ${roles.map((r2) => code(plan.ramps[r2].find((x) => x.step === s)?.hex ?? "")).join(" | ")} |`)
2290
+ ...STEPS.map((s2) => `| ${s2}${s2 === plan.actionStep ? " (actions)" : ""} | ${roles.map((r2) => code(plan.ramps[r2].find((x) => x.step === s2)?.hex ?? "")).join(" | ")} |`)
2291
2291
  ].join("\n") : "_No ramps resolved._";
2292
2292
  const c10 = plan.contrast;
2293
2293
  const contrastLine = c10.failing.length ? `**${c10.failing.length} of ${c10.checks} pairs fail** for ${plan.name} (${c10.themes.join(" and ")}).` : `All ${c10.checks} contrast checks pass for ${plan.name} in ${c10.themes.join(" and ")}.`;
@@ -2311,7 +2311,7 @@ function newBrandSection(plan) {
2311
2311
  }
2312
2312
  function composeNewBrandBody(plan, opts) {
2313
2313
  const t3 = plan.risk.tier;
2314
- const box = (n2) => `- ${n2 === t3 ? "[x]" : "[ ]"} ${RISK_LABELS[n2]}`;
2314
+ const box = (n3) => `- ${n3 === t3 ? "[x]" : "[ ]"} ${RISK_LABELS[n3]}`;
2315
2315
  const errors = plan.issues.filter((i2) => i2.level === "error");
2316
2316
  const warnings = plan.issues.filter((i2) => i2.level === "warning");
2317
2317
  return [
@@ -2376,7 +2376,7 @@ function cssModuleClasses(css) {
2376
2376
  }
2377
2377
  return out;
2378
2378
  }
2379
- const cell$1 = (s) => s.replace(/\|/g, "\\|").replace(/\n/g, " ");
2379
+ const cell$1 = (s2) => s2.replace(/\|/g, "\\|").replace(/\n/g, " ");
2380
2380
  function propsTable(name, props, inherits) {
2381
2381
  if (!props.length) return inherits ? `${name} has no props of its own. It accepts every native <${inherits}> attribute.` : "";
2382
2382
  const rows = props.map((p) => `| \`${p.name}\`${p.required ? " (required)" : ""} | \`${cell$1(p.type)}\` | ${p.defaultValue ? `\`${cell$1(p.defaultValue)}\`` : ""} | ${cell$1(p.description ?? "")} |`);
@@ -2519,9 +2519,9 @@ function formatDocsJson(d2) {
2519
2519
  function patchNode(old, next) {
2520
2520
  if (plainEqual(toPlain(old), next)) return old;
2521
2521
  if (old.kind === "object" && next && typeof next === "object" && !Array.isArray(next)) {
2522
- const n2 = next;
2523
- const kept = old.entries.filter((e2) => n2[e2.key] !== void 0).map((e2) => ({ key: e2.key, value: patchNode(e2.value, n2[e2.key]) }));
2524
- const added = Object.keys(n2).filter((k3) => n2[k3] !== void 0 && !getEntry(old, k3)).map((k3) => ({ key: k3, value: fromPlain(n2[k3], void 0, old.inline) }));
2522
+ const n3 = next;
2523
+ const kept = old.entries.filter((e2) => n3[e2.key] !== void 0).map((e2) => ({ key: e2.key, value: patchNode(e2.value, n3[e2.key]) }));
2524
+ const added = Object.keys(n3).filter((k3) => n3[k3] !== void 0 && !getEntry(old, k3)).map((k3) => ({ key: k3, value: fromPlain(n3[k3], void 0, old.inline) }));
2525
2525
  return { kind: "object", inline: old.inline, entries: [...kept, ...added] };
2526
2526
  }
2527
2527
  if (old.kind === "array" && Array.isArray(next)) {
@@ -2547,16 +2547,16 @@ const DOCS_CHANGE_BUMP = "patch";
2547
2547
  function cleanDraftText(text) {
2548
2548
  return text.replace(/\s*\u2014\s*/g, ", ").replace(/,\s*,/g, ",").replace(/^,\s*/, "").replace(/[ \t]+/g, " ").trim();
2549
2549
  }
2550
- const values = (s) => (s ?? "").split(", ").map((x) => x.trim()).filter(Boolean);
2550
+ const values = (s2) => (s2 ?? "").split(", ").map((x) => x.trim()).filter(Boolean);
2551
2551
  const article = (word) => /^[aeiou]/i.test(word) ? "an" : "a";
2552
2552
  const andList = (xs) => xs.length <= 1 ? xs[0] ?? "" : `${xs.slice(0, -1).join(", ")} and ${xs[xs.length - 1]}`;
2553
- const plural = (n2, word, many = `${word}s`) => `${n2} ${n2 === 1 ? word : many}`;
2554
- const capital = (s) => s.charAt(0).toUpperCase() + s.slice(1);
2555
- const lower = (s) => s.charAt(0).toLowerCase() + s.slice(1);
2556
- function propShape(s) {
2557
- if (!s) return void 0;
2558
- const m2 = /^(.*?), default (.*)$/.exec(s);
2559
- return m2 ? { type: m2[1], def: m2[2] } : { type: s, def: "" };
2553
+ const plural = (n3, word, many = `${word}s`) => `${n3} ${n3 === 1 ? word : many}`;
2554
+ const capital = (s2) => s2.charAt(0).toUpperCase() + s2.slice(1);
2555
+ const lower = (s2) => s2.charAt(0).toLowerCase() + s2.slice(1);
2556
+ function propShape(s2) {
2557
+ if (!s2) return void 0;
2558
+ const m2 = /^(.*?), default (.*)$/.exec(s2);
2559
+ return m2 ? { type: m2[1], def: m2[2] } : { type: s2, def: "" };
2560
2560
  }
2561
2561
  const VARIANT_FIRST = ["variant", "tone", "intent", "appearance", "kind", "type", "style"];
2562
2562
  function shortVariant(key) {
@@ -2842,19 +2842,19 @@ function parseDocsReply(text) {
2842
2842
  if (!json || typeof json !== "object" || Array.isArray(json)) throw new Error("The reply is not a docs.json object.");
2843
2843
  return json;
2844
2844
  }
2845
- const cleanDocsText = (s) => cleanDraftText(s.replace(/[\r\n]+/g, " "));
2845
+ const cleanDocsText = (s2) => cleanDraftText(s2.replace(/[\r\n]+/g, " "));
2846
2846
  const isExample = (x) => {
2847
2847
  if (typeof x === "string") return true;
2848
2848
  if (!x || typeof x !== "object" || Array.isArray(x)) return false;
2849
- const n2 = x;
2850
- if (typeof n2.c !== "string" || !n2.c) return false;
2851
- if (n2.p !== void 0 && (!n2.p || typeof n2.p !== "object" || Array.isArray(n2.p))) return false;
2852
- return n2.children === void 0 || Array.isArray(n2.children) && n2.children.every(isExample);
2849
+ const n3 = x;
2850
+ if (typeof n3.c !== "string" || !n3.c) return false;
2851
+ if (n3.p !== void 0 && (!n3.p || typeof n3.p !== "object" || Array.isArray(n3.p))) return false;
2852
+ return n3.children === void 0 || Array.isArray(n3.children) && n3.children.every(isExample);
2853
2853
  };
2854
2854
  const textList = (x) => {
2855
2855
  if (typeof x === "string") x = [x];
2856
2856
  if (!Array.isArray(x)) return void 0;
2857
- const out = x.filter((s) => typeof s === "string").map(cleanDocsText).filter(Boolean);
2857
+ const out = x.filter((s2) => typeof s2 === "string").map(cleanDocsText).filter(Boolean);
2858
2858
  return out.length ? out : void 0;
2859
2859
  };
2860
2860
  const guidanceList = (x, examples) => {
@@ -2877,8 +2877,8 @@ function sanitizeDocsSections(raw, keys = PROSE_KEYS, opts = {}) {
2877
2877
  for (const k3 of keys) {
2878
2878
  const v2 = r2[k3];
2879
2879
  if (k3 === "summary") {
2880
- const s = typeof v2 === "string" ? cleanDocsText(v2) : "";
2881
- if (s) out.summary = s;
2880
+ const s2 = typeof v2 === "string" ? cleanDocsText(v2) : "";
2881
+ if (s2) out.summary = s2;
2882
2882
  } else if (k3 === "dos" || k3 === "donts") {
2883
2883
  const g3 = guidanceList(v2, opts.examples ?? false);
2884
2884
  if (g3) out[k3] = g3;
@@ -2970,9 +2970,9 @@ const EXPLORATION_STATUS_LABEL = { active: "Running", promoted: "Promoted to rev
2970
2970
  const MARK$1 = "bridge-exploration";
2971
2971
  const SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
2972
2972
  function explorationSlug(name) {
2973
- const s = name.trim().replace(/^explore\//i, "");
2974
- if (!/[a-z0-9]/i.test(s)) return "";
2975
- return slugify(s, 40);
2973
+ const s2 = name.trim().replace(/^explore\//i, "");
2974
+ if (!/[a-z0-9]/i.test(s2)) return "";
2975
+ return slugify(s2, 40);
2976
2976
  }
2977
2977
  function explorationBranch(nameOrBranch) {
2978
2978
  return `${EXPLORATION_PREFIX}${explorationSlug(nameOrBranch)}`;
@@ -3013,8 +3013,8 @@ function explorationNote(e2) {
3013
3013
  ].join("\n");
3014
3014
  }
3015
3015
  function explorationPrTitle(e2) {
3016
- const n2 = e2.name.trim().replace(/\.$/, "");
3017
- return `Exploration: ${n2.charAt(0).toLowerCase()}${n2.slice(1)}`;
3016
+ const n3 = e2.name.trim().replace(/\.$/, "");
3017
+ return `Exploration: ${n3.charAt(0).toLowerCase()}${n3.slice(1)}`;
3018
3018
  }
3019
3019
  function explorationPrBody(e2, ctx) {
3020
3020
  const slug = e2.slug || explorationSlug(e2.name);
@@ -3079,6 +3079,8 @@ function explorationStatus(p) {
3079
3079
  const isActiveExploration = (labels) => labelNames(labels).includes(EXPLORATION_LABEL);
3080
3080
  function promotionPlan(input) {
3081
3081
  const exploration = parseExplorationBody(input.body);
3082
+ const jira = /^([A-Z][A-Z0-9_]*-\d+)\s+/.exec(input.title)?.[1] ?? null;
3083
+ const title = jira ? input.title.slice(jira.length).trim() : input.title;
3082
3084
  const removeFiles = input.files.filter((f) => f.path.startsWith(`${EXPLORATION_NOTES_DIR}/`) && f.status !== "removed").map((f) => f.path);
3083
3085
  const files = input.files.filter((f) => !f.path.startsWith(`${EXPLORATION_NOTES_DIR}/`));
3084
3086
  const risk = classifyRisk({ files, ...input.config ? { config: input.config } : {} });
@@ -3086,18 +3088,18 @@ function promotionPlan(input) {
3086
3088
  const addLabels = [`tier: ${risk.tier}`, ...risk.tier === 3 && tokens ? ["tokens"] : []];
3087
3089
  const date = (input.date ?? /* @__PURE__ */ new Date()).toISOString().slice(0, 10);
3088
3090
  const existing = new Set(input.body ? [...input.body.matchAll(/\b(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi)].map((m2) => Number(m2[1])) : []);
3089
- const closes = [...new Set(input.requests ?? [])].filter((n2) => !existing.has(n2));
3091
+ const closes = [...new Set(input.requests ?? [])].filter((n3) => !existing.has(n3));
3090
3092
  const kept = (input.body ?? "").replace(/^> Not mergeable as is\..*$\n?\n?/m, "").replace(/### When it is done[\s\S]*?(?=<!-- |$)/, "").replace(/^## Exploration: /m, "## ").trim();
3091
3093
  const body = [
3092
3094
  `**Promoted from an exploration on ${date}.** Review it like any change: the tier below comes from the files it touches.`,
3093
3095
  "",
3094
- kept || `## ${input.title.replace(/^Exploration:\s*/i, "")}`,
3096
+ kept || `## ${title.replace(/^Exploration:\s*/i, "")}`,
3095
3097
  "",
3096
3098
  `**Risk tier:** ${risk.tier}.`,
3097
3099
  ...risk.reasons.slice(0, 8).map((r2) => `- ${r2}`),
3098
- ...closes.length ? ["", ...closes.map((n2) => `Closes #${n2}`)] : []
3100
+ ...closes.length ? ["", ...closes.map((n3) => `Closes #${n3}`)] : []
3099
3101
  ].join("\n");
3100
- const t3 = input.title.replace(/^Exploration:\s*/i, "").trim() || exploration?.name || input.title;
3102
+ const t3 = title.replace(/^Exploration:\s*/i, "").trim() || exploration?.name || title;
3101
3103
  return {
3102
3104
  tier: risk.tier,
3103
3105
  reasons: risk.reasons,
@@ -3105,7 +3107,7 @@ function promotionPlan(input) {
3105
3107
  addLabels,
3106
3108
  removeFiles,
3107
3109
  body,
3108
- title: t3.charAt(0).toUpperCase() + t3.slice(1),
3110
+ title: `${jira ? `${jira} ` : ""}${t3.charAt(0).toUpperCase()}${t3.slice(1)}`,
3109
3111
  markReady: true
3110
3112
  };
3111
3113
  }
@@ -3249,8 +3251,8 @@ function requestBrief(r2, ctx) {
3249
3251
  "- If the request is unclear or conflicts with the guidance, comment on the issue instead of guessing."
3250
3252
  ].join("\n");
3251
3253
  }
3252
- const cell = (s) => s.replace(/\|/g, "\\|").replace(/\n/g, " ");
3253
- const sourceLabel = (s) => s === "figma" ? "Figma" : s === "studio" ? "Bridge Studio" : s === "cli" ? "the CLI" : "Claude (MCP)";
3254
+ const cell = (s2) => s2.replace(/\|/g, "\\|").replace(/\n/g, " ");
3255
+ const sourceLabel = (s2) => s2 === "figma" ? "Figma" : s2 === "studio" ? "Bridge Studio" : s2 === "cli" ? "the CLI" : "Claude (MCP)";
3254
3256
  function validateIntegrations(i2) {
3255
3257
  const out = [];
3256
3258
  if (!i2?.jira) return out;
@@ -3308,7 +3310,7 @@ function newDraftSessionId(random = Math.random) {
3308
3310
  return out;
3309
3311
  }
3310
3312
  const SESSION_RE = /^[a-z0-9-]{6,64}$/;
3311
- const isDraftSessionId = (s) => typeof s === "string" && SESSION_RE.test(s);
3313
+ const isDraftSessionId = (s2) => typeof s2 === "string" && SESSION_RE.test(s2);
3312
3314
  function draftSessionPath(sessionId) {
3313
3315
  if (!isDraftSessionId(sessionId)) throw new Error(`"${sessionId}" is not a draft session id.`);
3314
3316
  return `${DRAFTS_DIR}/${sessionId}.json`;
@@ -3345,8 +3347,8 @@ function validatePendingDrafts(x) {
3345
3347
  if (p.source !== "figma" && p.source !== "studio") out.push('source must be "figma" or "studio".');
3346
3348
  if (!Array.isArray(p.items) || !p.items.length) out.push("A draft session needs at least one item.");
3347
3349
  const ids = /* @__PURE__ */ new Set();
3348
- for (const [n2, i2] of (Array.isArray(p.items) ? p.items : []).entries()) {
3349
- const at2 = `Item ${n2 + 1}`;
3350
+ for (const [n3, i2] of (Array.isArray(p.items) ? p.items : []).entries()) {
3351
+ const at2 = `Item ${n3 + 1}`;
3350
3352
  if (!i2 || typeof i2 !== "object") {
3351
3353
  out.push(`${at2} is not an object.`);
3352
3354
  continue;
@@ -3405,7 +3407,7 @@ function clip(text, max) {
3405
3407
  function sentences(text) {
3406
3408
  const t3 = text.replace(/\s+/g, " ").trim();
3407
3409
  const parts = t3.match(/[^.!?]+(?:[.!?]+(?=\s|$)|$)/g) ?? [t3];
3408
- let out = parts.slice(0, DRAFT_SUMMARY_SENTENCES).map((s) => s.trim()).join(" ");
3410
+ let out = parts.slice(0, DRAFT_SUMMARY_SENTENCES).map((s2) => s2.trim()).join(" ");
3409
3411
  if (out.length > SUMMARY_MAX) out = `${clip(out, SUMMARY_MAX)}.`;
3410
3412
  return out;
3411
3413
  }
@@ -3478,7 +3480,7 @@ function draftItemBrief(i2) {
3478
3480
  return [`Item ${i2.id}: component docs${i2.component ? ` of ${i2.component}` : ""} from Bridge Studio (${i2.docs.path ?? i2.docs.slug}): ${what}.`, "", i2.docs.prompt].join("\n");
3479
3481
  }
3480
3482
  const kind = i2.kind ? REQUEST_KINDS.find((k3) => k3.value === i2.kind)?.label : void 0;
3481
- const cell2 = (s) => (s ?? "").replace(/\|/g, "\\|").replace(/\n/g, " ");
3483
+ const cell2 = (s2) => (s2 ?? "").replace(/\|/g, "\\|").replace(/\n/g, " ");
3482
3484
  const lines = [`Item ${i2.id}: ${i2.scope === "request" ? "a component change request (a GitHub issue developers implement)" : "the description of a pull request with design token (variable) edits from Figma"}.`];
3483
3485
  if (i2.component) lines.push(`Component: ${i2.component}`);
3484
3486
  if (kind) lines.push(`Kind: ${kind}`);
@@ -3645,7 +3647,7 @@ class DraftPoller {
3645
3647
  }
3646
3648
  }
3647
3649
  }
3648
- function explorationSummary(p, _owner, _repo, s) {
3650
+ function explorationSummary(p, _owner, _repo, s2) {
3649
3651
  const e2 = parseExplorationBody(p.body);
3650
3652
  const slug = p.headRef?.startsWith(EXPLORATION_PREFIX) ? p.headRef.slice(EXPLORATION_PREFIX.length) : e2?.slug ?? explorationSlug(p.title);
3651
3653
  return {
@@ -3653,7 +3655,7 @@ function explorationSummary(p, _owner, _repo, s) {
3653
3655
  url: p.url,
3654
3656
  branch: p.headRef,
3655
3657
  slug,
3656
- name: e2?.name ?? p.title.replace(/^Exploration:\s*/i, ""),
3658
+ name: e2?.name ?? p.title.replace(/^[A-Z][A-Z0-9_]*-\d+\s+/, "").replace(/^Exploration:\s*/i, ""),
3657
3659
  purpose: e2?.purpose ?? "",
3658
3660
  ...e2?.useCase ? { useCase: e2.useCase } : {},
3659
3661
  status: explorationStatus({ state: p.state, labels: p.labels, headRef: p.headRef, body: p.body }),
@@ -3663,14 +3665,14 @@ function explorationSummary(p, _owner, _repo, s) {
3663
3665
  ...e2?.agent ? { agent: e2.agent } : {},
3664
3666
  updatedAt: p.updatedAt,
3665
3667
  headSha: p.headSha,
3666
- previews: previewLinks(s.apps, { branch: p.headRef, pr: p.number, sha: p.headSha })
3668
+ previews: previewLinks(s2.apps, { branch: p.headRef, pr: p.number, sha: p.headSha })
3667
3669
  };
3668
3670
  }
3669
- async function listExplorationsOnGitHub(gh, s, opts = {}) {
3671
+ async function listExplorationsOnGitHub(gh, s2, opts = {}) {
3670
3672
  const pulls = await gh.listPullRequests(opts.state ?? "open");
3671
- return pulls.filter((p) => isExplorationPull({ state: p.state, labels: p.labels, headRef: p.headRef, body: p.body })).map((p) => explorationSummary(p, gh.owner, gh.name, s));
3673
+ 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, s2));
3672
3674
  }
3673
- async function startExplorationOnGitHub(gh, e2, s) {
3675
+ async function startExplorationOnGitHub(gh, e2, s2) {
3674
3676
  const problems = explorationProblems(e2);
3675
3677
  if (problems.length) throw new GitHubError(422, problems.join(" "));
3676
3678
  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).");
@@ -3680,7 +3682,7 @@ async function startExplorationOnGitHub(gh, e2, s) {
3680
3682
  if (await x.getBranchSha(branch)) throw new GitHubError(422, `An exploration named "${slug}" already exists (${branch}). Pick another name, or continue that one.`);
3681
3683
  const full = { ...e2, slug, startedAt: e2.startedAt ?? (/* @__PURE__ */ new Date()).toISOString() };
3682
3684
  const commit = await x.commitToNewBranch({
3683
- base: s.base,
3685
+ base: s2.base,
3684
3686
  branch,
3685
3687
  message: `chore(explore): start ${full.name.trim()}
3686
3688
 
@@ -3689,8 +3691,9 @@ ${full.purpose.trim()}
3689
3691
  Exploration: never merged as is. Promote it to review or close it.`,
3690
3692
  files: [{ path: explorationNotePath(slug), content: explorationNote(full) }]
3691
3693
  });
3692
- const ctx = { owner: gh.owner, repo: gh.name, packages: s.packages, apps: s.apps, ...s.requests?.length ? { requests: s.requests } : {} };
3693
- const pr = await x.createPullRequest({ title: explorationPrTitle(full), head: branch, base: s.base, body: explorationPrBody(full, ctx), draft: true });
3694
+ const ctx = { owner: gh.owner, repo: gh.name, packages: s2.packages, apps: s2.apps, ...s2.requests?.length ? { requests: s2.requests } : {} };
3695
+ const title = full.jira ? `${full.jira.trim().toUpperCase()} ${explorationPrTitle(full)}` : explorationPrTitle(full);
3696
+ const pr = await x.createPullRequest({ title, head: branch, base: s2.base, body: explorationPrBody(full, ctx), draft: true });
3694
3697
  await x.addLabels(pr.number, [EXPLORATION_LABEL]);
3695
3698
  await x.updatePullRequest(pr.number, { body: explorationPrBody(full, { ...ctx, pr: pr.number }) }).catch(() => void 0);
3696
3699
  return {
@@ -3700,7 +3703,7 @@ Exploration: never merged as is. Promote it to review or close it.`,
3700
3703
  url: pr.url,
3701
3704
  commit: commit.sha,
3702
3705
  tryIt: { state: "building" },
3703
- previews: previewLinks(s.apps, { branch, pr: pr.number, sha: commit.sha })
3706
+ previews: previewLinks(s2.apps, { branch, pr: pr.number, sha: commit.sha })
3704
3707
  };
3705
3708
  }
3706
3709
  async function explorationTryItOnGitHub(gh, e2) {
@@ -3756,59 +3759,313 @@ async function closeExplorationOnGitHub(gh, ref) {
3756
3759
  await gh.updatePullRequest(p.number, { state: "closed" });
3757
3760
  return { number: p.number, url: p.url, branch: p.headRef };
3758
3761
  }
3759
- async function linkRequestToExplorationOnGitHub(gh, n2, branch, opts = {}) {
3762
+ async function linkRequestToExplorationOnGitHub(gh, n3, branch, opts = {}) {
3760
3763
  if (!isExplorationBranch(branch)) throw new GitHubError(422, `"${branch}" is not an exploration branch. Exploration branches are named explore/<name>.`);
3761
- const issue = await gh.getIssue(n2);
3764
+ const issue = await gh.getIssue(n3);
3762
3765
  const body = withRequestExploration(issue.body, branch);
3763
- if (!body) throw new GitHubError(422, `#${n2} has no Bridge request block, so it cannot be linked. Add "exploration: ${branch}" to it on GitHub.`);
3764
- await gh.updateIssue(n2, { body });
3766
+ if (!body) throw new GitHubError(422, `#${n3} has no Bridge request block, so it cannot be linked. Add "exploration: ${branch}" to it on GitHub.`);
3767
+ await gh.updateIssue(n3, { body });
3765
3768
  const warnings = [];
3766
- if (!await gh.addLabels(n2, [EXPLORATION_LABEL])) warnings.push(`The ${EXPLORATION_LABEL} label could not be added to #${n2}.`);
3769
+ if (!await gh.addLabels(n3, [EXPLORATION_LABEL])) warnings.push(`The ${EXPLORATION_LABEL} label could not be added to #${n3}.`);
3767
3770
  let assignees = [];
3768
3771
  if (opts.assignee) {
3769
3772
  try {
3770
- assignees = await gh.addAssignees(n2, [opts.assignee.replace(/^@/, "")]);
3773
+ assignees = await gh.addAssignees(n3, [opts.assignee.replace(/^@/, "")]);
3771
3774
  } catch {
3772
- warnings.push(`@${opts.assignee.replace(/^@/, "")} could not be assigned to #${n2}.`);
3775
+ warnings.push(`@${opts.assignee.replace(/^@/, "")} could not be assigned to #${n3}.`);
3773
3776
  }
3774
3777
  }
3775
- return { number: n2, branch, assignees, warnings };
3778
+ return { number: n3, branch, assignees, warnings };
3776
3779
  }
3777
- async function assignRequestOnGitHub(gh, n2, login) {
3780
+ async function assignRequestOnGitHub(gh, n3, login) {
3778
3781
  const who = login.trim().replace(/^@/, "");
3779
3782
  if (!who) throw new GitHubError(422, "Pick who should work on it.");
3780
- const assignees = await gh.addAssignees(n2, [who]);
3783
+ const assignees = await gh.addAssignees(n3, [who]);
3781
3784
  if (!assignees.some((a) => a.toLowerCase() === who.toLowerCase())) throw new GitHubError(422, `GitHub did not assign @${who}: they need access to this repository.`);
3782
3785
  return assignees;
3783
3786
  }
3784
- async function declineRequestOnGitHub(gh, n2, reason, by2) {
3787
+ async function declineRequestOnGitHub(gh, n3, reason, by2) {
3785
3788
  const problems = declineReasonProblems(reason);
3786
3789
  if (problems.length) throw new GitHubError(422, problems.join(" "));
3787
- await gh.addComment(n2, declineComment(reason, by2));
3788
- await gh.updateIssue(n2, { state: "closed", state_reason: "not_planned" });
3790
+ await gh.addComment(n3, declineComment(reason, by2));
3791
+ await gh.updateIssue(n3, { state: "closed", state_reason: "not_planned" });
3792
+ }
3793
+ const FIDELITY_DEFAULTS = { scale: 2, threshold: 0.1, maxPercent: 3, sizeTolerance: 1 };
3794
+ const MAX_DELTA = 35215;
3795
+ const STRICT_THRESHOLD = 0.02;
3796
+ function rgbAt(img, x, y) {
3797
+ if (x < 0 || y < 0 || x >= img.width || y >= img.height) return [255, 255, 255];
3798
+ const i2 = (y * img.width + x) * 4;
3799
+ const a = img.data[i2 + 3] / 255;
3800
+ return [255 + (img.data[i2] - 255) * a, 255 + (img.data[i2 + 1] - 255) * a, 255 + (img.data[i2 + 2] - 255) * a];
3801
+ }
3802
+ function colorDelta(a, b) {
3803
+ const dr = a[0] - b[0];
3804
+ const dg = a[1] - b[1];
3805
+ const db = a[2] - b[2];
3806
+ const y = dr * 0.29889531 + dg * 0.58662247 + db * 0.11448223;
3807
+ const i2 = dr * 0.59597799 - dg * 0.2741761 - db * 0.32180189;
3808
+ const q2 = dr * 0.21147017 - dg * 0.52261711 + db * 0.31114694;
3809
+ return 0.5053 * y * y + 0.299 * i2 * i2 + 0.1957 * q2 * q2;
3810
+ }
3811
+ function foundNear(img, x, y, c10, radius, max) {
3812
+ for (let dy = -radius; dy <= radius; dy++) for (let dx = -radius; dx <= radius; dx++) if (colorDelta(c10, rgbAt(img, x + dx, y + dy)) <= max) return true;
3813
+ return false;
3814
+ }
3815
+ function compareImages(figma, code2, options = {}) {
3816
+ const scale = options.scale ?? FIDELITY_DEFAULTS.scale;
3817
+ const radius = Math.max(0, Math.round(options.radius ?? scale));
3818
+ const max = MAX_DELTA * (options.threshold ?? FIDELITY_DEFAULTS.threshold) ** 2;
3819
+ const strict = MAX_DELTA * STRICT_THRESHOLD ** 2;
3820
+ const width = Math.max(figma.width, code2.width);
3821
+ const height = Math.max(figma.height, code2.height);
3822
+ const total = width * height;
3823
+ const wantDiff = options.diffImage !== false;
3824
+ const out = wantDiff ? new Uint8ClampedArray(total * 4) : void 0;
3825
+ let different = 0;
3826
+ for (let y = 0; y < height; y++) {
3827
+ for (let x = 0; x < width; x++) {
3828
+ const a = rgbAt(figma, x, y);
3829
+ const b = rgbAt(code2, x, y);
3830
+ const m2 = x < Math.min(figma.width, code2.width) && y < Math.min(figma.height, code2.height) ? max : strict;
3831
+ const same = colorDelta(a, b) <= m2 || foundNear(code2, x, y, a, radius, m2) && foundNear(figma, x, y, b, radius, m2);
3832
+ if (!same) different++;
3833
+ if (out) {
3834
+ const o2 = (y * width + x) * 4;
3835
+ if (same) {
3836
+ const gray = 255 + (b[0] * 0.299 + b[1] * 0.587 + b[2] * 0.114 - 255) * 0.1;
3837
+ out[o2] = out[o2 + 1] = out[o2 + 2] = gray;
3838
+ } else {
3839
+ out[o2] = 220;
3840
+ out[o2 + 1] = 38;
3841
+ out[o2 + 2] = 38;
3842
+ }
3843
+ out[o2 + 3] = 255;
3844
+ }
3845
+ }
3846
+ }
3847
+ const css = (img) => ({ width: Math.round(img.width / scale), height: Math.round(img.height / scale) });
3848
+ const size = { figma: css(figma), code: css(code2) };
3849
+ const tol = options.sizeTolerance ?? FIDELITY_DEFAULTS.sizeTolerance;
3850
+ const sizeMatches = Math.abs(size.figma.width - size.code.width) <= tol && Math.abs(size.figma.height - size.code.height) <= tol;
3851
+ const percent = total ? Math.round(different / total * 1e4) / 100 : 0;
3852
+ return {
3853
+ matches: sizeMatches && percent <= (options.maxPercent ?? FIDELITY_DEFAULTS.maxPercent),
3854
+ percent,
3855
+ differentPixels: different,
3856
+ totalPixels: total,
3857
+ size,
3858
+ sizeMatches,
3859
+ ...out ? { diff: { width, height, data: out } } : {}
3860
+ };
3861
+ }
3862
+ function summarizeComponent(component, variants, reason) {
3863
+ const compared = variants.filter((v2) => v2.status !== "skipped");
3864
+ const differing = compared.filter((v2) => v2.status === "differs");
3865
+ const rank = (v2) => (v2.status === "differs" ? 1e3 : 0) + (v2.percent ?? 0) + (v2.size && !sameSize(v2.size) ? 500 : 0);
3866
+ const worst = [...compared].sort((a, b) => rank(b) - rank(a))[0];
3867
+ return {
3868
+ component,
3869
+ status: compared.length === 0 ? "not-checked" : differing.length ? "differs" : "matches",
3870
+ checked: compared.length,
3871
+ differing: differing.length,
3872
+ skipped: variants.length - compared.length,
3873
+ ...worst && worst.size ? { worst: { key: worst.key, percent: worst.percent ?? 0, size: worst.size } } : {},
3874
+ ...compared.length === 0 ? { reason: reason ?? variants.find((v2) => v2.reason)?.reason } : {},
3875
+ variants
3876
+ };
3877
+ }
3878
+ const sameSize = (s2) => s2.figma.width === s2.code.width && s2.figma.height === s2.code.height;
3879
+ function buildFidelityReport(input) {
3880
+ const o2 = input.options ?? {};
3881
+ const scale = o2.scale ?? FIDELITY_DEFAULTS.scale;
3882
+ const c10 = input.components;
3883
+ return {
3884
+ version: 1,
3885
+ checkedAt: (input.now ?? /* @__PURE__ */ new Date()).toISOString(),
3886
+ ...input.file ? { file: input.file } : {},
3887
+ reference: input.reference,
3888
+ options: {
3889
+ scale,
3890
+ threshold: o2.threshold ?? FIDELITY_DEFAULTS.threshold,
3891
+ radius: Math.round(o2.radius ?? scale),
3892
+ maxPercent: o2.maxPercent ?? FIDELITY_DEFAULTS.maxPercent,
3893
+ sizeTolerance: o2.sizeTolerance ?? FIDELITY_DEFAULTS.sizeTolerance
3894
+ },
3895
+ components: c10,
3896
+ summary: {
3897
+ components: c10.length,
3898
+ matches: c10.filter((x) => x.status === "matches").length,
3899
+ differs: c10.filter((x) => x.status === "differs").length,
3900
+ notChecked: c10.filter((x) => x.status === "not-checked").length,
3901
+ variantsChecked: c10.reduce((n3, x) => n3 + x.checked, 0),
3902
+ variantsSkipped: c10.reduce((n3, x) => n3 + x.skipped, 0)
3903
+ }
3904
+ };
3905
+ }
3906
+ const fmtPercent = (p) => p >= 10 ? `${Math.round(p)}%` : p >= 1 ? `${Math.round(p * 10) / 10}%` : p > 0 ? "under 1%" : "0%";
3907
+ const fmtSize = (s2) => `${s2.width}x${s2.height}`;
3908
+ function fidelityVerdict(v2) {
3909
+ if (v2.status === "skipped") return `Not compared: ${v2.reason ?? "no image of the code"}`;
3910
+ if (v2.status === "matches") return "Matches the code";
3911
+ const parts = [`${fmtPercent(v2.percent ?? 0)} of pixels`];
3912
+ if (v2.size && !sameSize(v2.size)) parts.push(`size ${fmtSize(v2.size.figma)} vs ${fmtSize(v2.size.code)}`);
3913
+ return `Differs from the code: ${parts.join(", ")}`;
3914
+ }
3915
+ function fidelityComponentLine(c10) {
3916
+ if (c10.status === "not-checked") return `Not compared: ${c10.reason ?? "no image of the code"}`;
3917
+ if (c10.status === "matches") return c10.checked === 1 ? "Matches the code" : `Matches the code (${c10.checked} variants)`;
3918
+ const w = c10.worst;
3919
+ const head = fidelityVerdict({ status: "differs", percent: w.percent, size: w.size });
3920
+ return c10.checked > 1 ? `${head} (${c10.differing} of ${c10.checked} variants)` : head;
3921
+ }
3922
+ const FIGMA_REFERENCES_BRANCH = "bridge-visual";
3923
+ const FIGMA_REFERENCES_DIR = "figma-references";
3924
+ const FIGMA_REFERENCES_MANIFEST = `${FIGMA_REFERENCES_DIR}/manifest.json`;
3925
+ const FIGMA_REFERENCE_STORY = "internal-figma-reference--variant";
3926
+ const FIGMA_FILL_WIDTH_TOKEN = "size.80";
3927
+ const STATE_PSEUDO = {
3928
+ default: "rest",
3929
+ rest: "rest",
3930
+ enabled: "rest",
3931
+ hover: "hover",
3932
+ hovered: "hover",
3933
+ pressed: "active",
3934
+ active: "active",
3935
+ focus: "focus-visible",
3936
+ focused: "focus-visible",
3937
+ "focus visible": "focus-visible",
3938
+ disabled: "disabled"
3939
+ };
3940
+ const iconName = (component) => component.replace(/^Icon\//, "");
3941
+ const exportName = (name) => name.replace(/[^A-Za-z0-9]+/g, "");
3942
+ function planReference(spec, variant, file) {
3943
+ if (spec.view === "popup") return { ok: false, reason: "drawn open in Figma; the code image shows it closed" };
3944
+ const props = { ...spec.fixed ?? {} };
3945
+ let pseudo;
3946
+ for (const axis of spec.axes) {
3947
+ const value = variant.props[axis.name];
3948
+ if (value === void 0) return { ok: false, reason: `the variant has no ${axis.name} value` };
3949
+ if (axis.prop) {
3950
+ props[axis.prop] = value === "true" ? true : value === "false" ? false : value;
3951
+ continue;
3952
+ }
3953
+ if (axis.name === "Checked") {
3954
+ props.checked = value === "true";
3955
+ if (value === "mixed") props.indeterminate = true;
3956
+ continue;
3957
+ }
3958
+ if (axis.name.toLowerCase() !== "state") return { ok: false, reason: `${axis.name} has no matching option in code` };
3959
+ const s2 = STATE_PSEUDO[value.toLowerCase()];
3960
+ if (!s2) return { ok: false, reason: `the ${value} state has no code equivalent to render` };
3961
+ if (s2 === "disabled") props.disabled = true;
3962
+ else if (s2 !== "rest") pseudo = s2;
3963
+ }
3964
+ const root = spec.parts.find((p) => !p.parent);
3965
+ if (!root) return { ok: false, reason: "the spec has no root layer" };
3966
+ const children = (id) => spec.parts.filter((p) => p.parent === id);
3967
+ const textOf = (part) => {
3968
+ const swapTo = variant.slots?.[part.id] ?? part.swap?.default;
3969
+ if (part.swap && swapTo) {
3970
+ const slot = file?.slots?.find((s2) => s2.name === swapTo);
3971
+ if (!slot) return { reason: `${swapTo} is not in the specs` };
3972
+ if (slot.kind !== "text" || !slot.text) return { reason: `Figma shows a placeholder (${swapTo}) that code has no example of` };
3973
+ return slot.text.default;
3974
+ }
3975
+ const prop = spec.properties.find((p) => p.name === part.text && p.type === "TEXT");
3976
+ return typeof prop?.default === "string" ? prop.default : part.name;
3977
+ };
3978
+ let text;
3979
+ const icons = {};
3980
+ for (const prop of spec.properties) {
3981
+ if (prop.type === "TEXT") {
3982
+ const hidden = spec.properties.some((b) => b.type === "BOOLEAN" && b.prop === prop.prop && b.default === false);
3983
+ if (hidden && prop.prop) continue;
3984
+ if (prop.prop === "children") text = String(prop.default);
3985
+ else if (prop.prop) props[prop.prop] = String(prop.default);
3986
+ continue;
3987
+ }
3988
+ const iconPart = spec.parts.find((p) => p.kind === "icon" && p.visible === prop.name);
3989
+ if (prop.default === true && !iconPart && prop.prop && props[prop.prop] === void 0 && spec.example?.p?.[prop.prop] === void 0) props[prop.prop] = true;
3990
+ }
3991
+ for (const part of spec.parts) {
3992
+ if (part.kind !== "icon" || !part.swap) continue;
3993
+ const shown = part.visible ? spec.properties.find((p) => p.name === part.visible)?.default === true : true;
3994
+ if (!shown) continue;
3995
+ if (!part.swap.prop) return { ok: false, reason: `the ${part.name} icon has no matching option in code` };
3996
+ icons[part.swap.prop] = iconName(variant.slots?.[part.id] ?? part.swap.default);
3997
+ }
3998
+ let parts;
3999
+ const loose = spec.properties.filter((p) => p.type === "TEXT" && !p.prop);
4000
+ const frames = children(root.id).filter((p) => p.kind === "frame");
4001
+ const compound = text === void 0 && frames.length > 0 && frames.every((f) => spec.parts.some((p) => p.parent === f.id && p.kind === "text" && (p.swap || p.text === f.name)));
4002
+ if (compound) {
4003
+ parts = [];
4004
+ for (const f of frames) {
4005
+ const t3 = spec.parts.find((p) => p.parent === f.id && p.kind === "text");
4006
+ const value = textOf(t3);
4007
+ if (typeof value !== "string") return { ok: false, reason: value.reason };
4008
+ parts.push({ component: `${exportName(spec.name)}${exportName(f.name)}`, text: value });
4009
+ }
4010
+ }
4011
+ for (const p of loose) {
4012
+ if (p.name === "Value") continue;
4013
+ const part = spec.parts.find((x) => x.text === p.name);
4014
+ if (compound && part && part.parent !== root.id) continue;
4015
+ if (part && /placeholder$/.test(part.id)) {
4016
+ props.placeholder = String(p.default);
4017
+ continue;
4018
+ }
4019
+ return { ok: false, reason: `the ${p.name} text has no matching option in code` };
4020
+ }
4021
+ const example = spec.example;
4022
+ const exampleChildren = example?.children?.length ? example.children : void 0;
4023
+ return {
4024
+ ok: true,
4025
+ render: {
4026
+ component: exportName(spec.view || spec.fixed || example ? example?.c ?? spec.component ?? spec.name : spec.name),
4027
+ props: { ...example?.p ?? {}, ...props },
4028
+ ...exampleChildren ? { children: exampleChildren } : {},
4029
+ ...text !== void 0 && !exampleChildren ? { text } : {},
4030
+ ...parts && !exampleChildren ? { parts } : {},
4031
+ ...Object.keys(icons).length ? { icons } : {},
4032
+ ...pseudo ? { pseudo } : {},
4033
+ ...root.fill ? { width: FIGMA_FILL_WIDTH_TOKEN } : {}
4034
+ }
4035
+ };
4036
+ }
4037
+ function referenceImagePath(component, key) {
4038
+ const slug = (s2) => s2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
4039
+ const file = key.split(",").map((kv) => slug(kv)).filter(Boolean).join("__");
4040
+ return `${slug(component)}/${file || "default"}.png`;
4041
+ }
4042
+ function planReferences(file) {
4043
+ return file.components.flatMap(
4044
+ (spec) => spec.variants.map((v2) => ({ component: spec.name, specHash: spec.hash, key: variantKeyOf(v2.props), plan: planReference(spec, v2, file) }))
4045
+ );
3789
4046
  }
3790
4047
  export {
3791
- ai as AAA_MIN,
3792
- aj as AA_MIN,
4048
+ ak as AAA_MIN,
4049
+ al as AA_MIN,
3793
4050
  ADMIN_ROLE_ID,
3794
4051
  ANTHROPIC_MESSAGES_URL,
3795
4052
  BELL,
3796
4053
  BRAND_FONTS,
3797
4054
  BRAND_SLUG_RE,
3798
- ak as BULK_LIMIT,
3799
- k as COLOR_FIELDS,
3800
- C as COMPONENT_SPECS_VERSION,
4055
+ am as BULK_LIMIT,
4056
+ n as COLOR_FIELDS,
4057
+ k as COMPONENT_SPECS_VERSION,
3801
4058
  CONFIG_FILE,
3802
- al as CONTRAST_CELL_MAX,
3803
- am as CONTRAST_CHECKS_FILE,
4059
+ an as CONTRAST_CELL_MAX,
4060
+ ao as CONTRAST_CHECKS_FILE,
3804
4061
  ConfigError,
3805
- an as DEFAULT_COMPONENT_SPECS_FILE,
3806
- ao as DEFAULT_GOVERNANCE,
3807
- ap as DEFAULT_OVERRIDE,
4062
+ ap as DEFAULT_COMPONENT_SPECS_FILE,
4063
+ aq as DEFAULT_GOVERNANCE,
4064
+ ar as DEFAULT_OVERRIDE,
3808
4065
  DEFAULT_PROTECTED_BRANCHES,
3809
- aq as DEFAULT_RIGHTS,
4066
+ as as DEFAULT_RIGHTS,
3810
4067
  DEFAULT_TOKEN_PATHS,
3811
- ar as DEFAULT_VISUAL_IMPACT,
4068
+ at as DEFAULT_VISUAL_IMPACT,
3812
4069
  DEMO_RELEASES,
3813
4070
  DOCS_CHANGE_BUMP,
3814
4071
  DOCS_DRAFT_MODEL,
@@ -3835,18 +4092,24 @@ export {
3835
4092
  EXPLORATION_USE_CASES,
3836
4093
  EXT_ID,
3837
4094
  EXT_SCOPES,
4095
+ FIDELITY_DEFAULTS,
4096
+ FIGMA_FILL_WIDTH_TOKEN,
4097
+ FIGMA_REFERENCES_BRANCH,
4098
+ FIGMA_REFERENCES_DIR,
4099
+ FIGMA_REFERENCES_MANIFEST,
4100
+ FIGMA_REFERENCE_STORY,
3838
4101
  GitHubClient,
3839
4102
  GitHubError,
3840
- as as JsonParseError,
4103
+ au as JsonParseError,
3841
4104
  LIGHTNESS,
3842
4105
  LayeredTokenSet,
3843
4106
  NEUTRAL_ANCHORS,
3844
- at as OWNER_GROUPS,
4107
+ av as OWNER_GROUPS,
3845
4108
  PIN_TOLERANCE,
3846
- au as PREVIEW_APP_LABELS,
3847
- av as PREVIEW_COMMENT_MARKER,
3848
- aw as PREVIEW_PLACEHOLDERS,
3849
- ax as PRIMITIVE_MODE,
4109
+ aw as PREVIEW_APP_LABELS,
4110
+ ax as PREVIEW_COMMENT_MARKER,
4111
+ ay as PREVIEW_PLACEHOLDERS,
4112
+ az as PRIMITIVE_MODE,
3850
4113
  PROSE_KEYS,
3851
4114
  PROTECTION_PARTS,
3852
4115
  PROTECTION_PART_PHRASE,
@@ -3856,100 +4119,104 @@ export {
3856
4119
  REQUEST_KINDS,
3857
4120
  REQUEST_LABEL,
3858
4121
  REQUEST_STATUS_LABEL,
3859
- ay as RIGHTS,
3860
- az as RIGHT_LABEL,
4122
+ aA as RIGHTS,
4123
+ aB as RIGHT_LABEL,
3861
4124
  RISK_LABELS,
3862
- aA as RISK_TIER,
4125
+ aC as RISK_TIER,
3863
4126
  SIMILARITY_THRESHOLD,
3864
4127
  SINGLE_MODE,
3865
- aB as SPEC_FIELDS,
4128
+ aD as SPEC_FIELDS,
3866
4129
  STEPS,
3867
4130
  TIER_AXIS,
3868
4131
  TIER_NAMES,
3869
- aC as TIER_ORDER,
4132
+ aE as TIER_ORDER,
3870
4133
  TOKEN_REJECTED_MESSAGE,
3871
4134
  TOKEN_SETTINGS_URL,
3872
- aD as TeamDirectory,
3873
- aE as UNRELEASED,
3874
- aF as VISUAL_CHECK_LABEL,
4135
+ aF as TeamDirectory,
4136
+ aG as UNRELEASED,
4137
+ aH as VISUAL_CHECK_LABEL,
3875
4138
  acceptDocsDraft,
3876
4139
  acceptDocsText,
3877
4140
  addBrandToConfigText,
3878
- aG as affectedContrast,
4141
+ aI as affectedContrast,
3879
4142
  d as aliasOf,
3880
4143
  aliasTarget,
3881
4144
  anatomyLabel,
3882
4145
  anchoredRamp,
3883
4146
  anthropicReplyText,
3884
4147
  anthropicRequest,
3885
- aH as appForProject,
3886
- aI as appUrl,
4148
+ aJ as appForProject,
4149
+ aK as appUrl,
3887
4150
  applyConfirmedRenames,
3888
4151
  applyDocsSections,
3889
4152
  applyTokenEdits,
3890
4153
  applyTokenMerge,
3891
- aJ as approverEntries,
3892
- aK as approverLists,
4154
+ aL as approverEntries,
4155
+ aM as approverLists,
3893
4156
  assertSafeBranch,
3894
4157
  assignRequestOnGitHub,
3895
- aL as assignVersions,
4158
+ aN as assignVersions,
3896
4159
  base64ToUtf8,
3897
- aM as baseBranchOf,
4160
+ aO as baseBranchOf,
3898
4161
  bellChroma,
3899
- aN as branchName,
4162
+ aP as branchName,
3900
4163
  branchPreviewUrls,
3901
- aO as branchSlug,
4164
+ aQ as branchSlug,
3902
4165
  brandDisplayName,
3903
4166
  brandPreviewVariables,
4167
+ buildFidelityReport,
3904
4168
  buildHistoryEntry,
3905
4169
  buildReport,
3906
- i as buildTokenSet,
4170
+ j as buildTokenSet,
3907
4171
  buildUsageIndex,
3908
- aP as canShip,
4172
+ aR as canShip,
3909
4173
  changeEdits,
3910
- aQ as changeKind,
3911
- aR as changeTable,
3912
- aS as changedModes,
3913
- aT as changesetBump,
4174
+ aS as changeKind,
4175
+ aT as changeTable,
4176
+ aU as changedModes,
4177
+ aV as changesetBump,
3914
4178
  checkBrandSlug,
3915
4179
  checkLayeredPair,
3916
4180
  choiceFor,
3917
4181
  classifyAuth,
3918
- aU as classifyLayered,
4182
+ aW as classifyLayered,
3919
4183
  classifyRisk,
3920
4184
  cleanDocsText,
3921
4185
  cleanDraftText,
3922
- aV as clearRawDeep,
4186
+ aX as clearRawDeep,
3923
4187
  closeExplorationOnGitHub,
3924
4188
  closingIssueNumbers,
3925
4189
  coerceValue,
3926
4190
  collectHistory,
3927
4191
  collectRefs,
4192
+ colorDelta,
3928
4193
  k2 as colorToCss,
3929
4194
  l as colorsEqual,
3930
4195
  combineChanges,
3931
4196
  combineConflicts,
3932
4197
  c as comboKey,
3933
- aW as commitMessage,
4198
+ aY as commitMessage,
3934
4199
  m as compactJson,
4200
+ compareImages,
3935
4201
  componentForPath,
3936
- aX as composeChangeset,
4202
+ aZ as composeChangeset,
3937
4203
  composeFiles,
3938
4204
  composeNewBrandBody,
3939
4205
  composePendingDrafts,
3940
- aY as composePrBody,
3941
- aZ as composeProposalBody,
4206
+ a_ as composePrBody,
4207
+ a$ as composeProposalBody,
3942
4208
  composeRequestIssue,
3943
- a_ as composite,
3944
- a$ as contextFor,
4209
+ b0 as composite,
4210
+ b1 as contextFor,
3945
4211
  contextLabel,
3946
- b0 as contrastDelta,
3947
- b1 as contrastDeltaTable,
3948
- b2 as contrastLevel,
3949
- b3 as contrastPair,
3950
- b4 as contrastRatio,
4212
+ b2 as contrastDelta,
4213
+ b3 as contrastDeltaTable,
4214
+ b4 as contrastLevel,
4215
+ b5 as contrastPair,
4216
+ b6 as contrastRatio,
3951
4217
  contrastScope,
3952
- b5 as countChanges,
4218
+ b7 as countChanges,
4219
+ b8 as coverageSummary,
3953
4220
  createDocsDraftSession,
3954
4221
  createPendingDrafts,
3955
4222
  cssModuleClasses,
@@ -3961,15 +4228,15 @@ export {
3961
4228
  declineRequestOnGitHub,
3962
4229
  decodePicks,
3963
4230
  defaultChoiceFor,
3964
- b6 as defaultContext,
4231
+ b9 as defaultContext,
3965
4232
  defaultFile,
3966
4233
  defaultScopes,
3967
- b7 as defaultTitle,
3968
- b8 as defineConfig,
4234
+ ba as defaultTitle,
4235
+ bb as defineConfig,
3969
4236
  deletePendingDrafts,
3970
4237
  demoHistory,
3971
- b9 as detectLayout,
3972
- ba as diffLayered,
4238
+ bc as detectLayout,
4239
+ bd as diffLayered,
3973
4240
  docsPrompt,
3974
4241
  docsSectionShapes,
3975
4242
  docsSectionsAnswer,
@@ -3988,11 +4255,11 @@ export {
3988
4255
  emptyTokenFile,
3989
4256
  encodePicks,
3990
4257
  ensureRequestsBranch,
3991
- bb as entriesFor,
3992
- bc as entryLabel,
4258
+ be as entriesFor,
4259
+ bf as entryLabel,
3993
4260
  evaluatePairs,
3994
- bd as expandEntries,
3995
- be as expandOwners,
4261
+ bg as expandEntries,
4262
+ bh as expandOwners,
3996
4263
  explorationBranch,
3997
4264
  explorationNote,
3998
4265
  explorationNotePath,
@@ -4008,61 +4275,63 @@ export {
4008
4275
  explorationTestBuildOnGitHub,
4009
4276
  explorationTryIt,
4010
4277
  explorationTryItOnGitHub,
4011
- bf as fieldChanges,
4012
- bg as fileModes,
4013
- bh as filterHistory,
4278
+ fidelityComponentLine,
4279
+ fidelityVerdict,
4280
+ bi as fieldChanges,
4281
+ bj as fileModes,
4282
+ bk as filterHistory,
4014
4283
  findExplorationOnGitHub,
4015
4284
  findPreviewComment,
4016
4285
  findReferenceProblems,
4017
- bi as findToken,
4018
- bj as findVercelComment,
4019
- bk as firstParagraph,
4020
- n as flattenLayerFile,
4286
+ bl as findToken,
4287
+ bm as findVercelComment,
4288
+ bn as firstParagraph,
4289
+ n2 as flattenLayerFile,
4021
4290
  flattenTokens,
4022
4291
  formatChangeset,
4023
4292
  formatDocsJson,
4024
- bl as formatNumber,
4025
- bm as formatOwnerEntry,
4293
+ bo as formatNumber,
4294
+ bp as formatOwnerEntry,
4026
4295
  formatValue,
4027
4296
  friendlyMessage,
4028
4297
  fromHex,
4029
4298
  fromPlain,
4030
4299
  generateRamp,
4031
- bn as getChild,
4300
+ bq as getChild,
4032
4301
  getEntry,
4033
4302
  gitHubHistoryBackend,
4034
4303
  g2 as globToRegExp,
4035
- bo as groupsPhrase,
4304
+ br as groupsPhrase,
4036
4305
  h as hashSpec,
4037
4306
  h2 as hexToRgba,
4038
- bp as holdersOf,
4039
- j as iconComponentName,
4307
+ bs as holdersOf,
4308
+ i as iconComponentName,
4040
4309
  idExtensionFor,
4041
4310
  impactedModules,
4042
4311
  importsIn,
4043
- bq as indexByPath,
4044
- br as inheritedTypeAt,
4045
- bs as installCommand,
4046
- bt as installCommandFromPreviewComment,
4312
+ bt as indexByPath,
4313
+ bu as inheritedTypeAt,
4314
+ bv as installCommand,
4315
+ bw as installCommandFromPreviewComment,
4047
4316
  isActiveExploration,
4048
4317
  isAlias,
4049
4318
  isDocsSelectionMode,
4050
4319
  isDraftSessionId,
4051
4320
  isExplorationBranch,
4052
4321
  isExplorationPull,
4053
- bu as isGuardrail,
4322
+ bx as isGuardrail,
4054
4323
  isHex,
4055
4324
  isMissingPermission,
4056
4325
  isMultiMode,
4057
4326
  isPlanRefusal,
4058
4327
  isProseKey,
4059
- bv as isTeamEntry,
4060
- bw as isTokenFile,
4328
+ by as isTeamEntry,
4329
+ bz as isTokenFile,
4061
4330
  isTokenRejected,
4062
- bx as isVercelComment,
4331
+ bA as isVercelComment,
4063
4332
  jiraIssueFields,
4064
- by as kindForMin,
4065
- bz as layeredImpact,
4333
+ bB as kindForMin,
4334
+ bC as layeredImpact,
4066
4335
  o as layeredParityIssues,
4067
4336
  g as layoutOptions,
4068
4337
  levenshtein,
@@ -4075,7 +4344,7 @@ export {
4075
4344
  loadProtection,
4076
4345
  loadRepoFiles,
4077
4346
  loadRequiredChecks,
4078
- bA as luminance,
4347
+ bD as luminance,
4079
4348
  markClaudeDraft,
4080
4349
  mergeDocsDraft,
4081
4350
  mergeDraftResults,
@@ -4085,7 +4354,7 @@ export {
4085
4354
  missingProse,
4086
4355
  modeDisplayName,
4087
4356
  modeFile,
4088
- bB as modeLabel,
4357
+ bE as modeLabel,
4089
4358
  modesOf$1 as modesOf,
4090
4359
  moveToken,
4091
4360
  nearestStep,
@@ -4094,31 +4363,31 @@ export {
4094
4363
  neutralOffset,
4095
4364
  newBrandSection,
4096
4365
  newDraftSessionId,
4097
- bC as nodesEqual,
4098
- bD as normalizeRights,
4366
+ bF as nodesEqual,
4367
+ bG as normalizeRights,
4099
4368
  oklch,
4100
4369
  oklchToLinear,
4101
- bE as overrideKey,
4102
- bF as ownerEntryProblems,
4370
+ bH as overrideKey,
4371
+ bI as ownerEntryProblems,
4103
4372
  packageDirCandidates,
4104
- bG as pairKey,
4373
+ bJ as pairKey,
4105
4374
  parseChangelog,
4106
- bH as parseChangesetText,
4375
+ bK as parseChangesetText,
4107
4376
  parseColor,
4108
- bI as parseComponentSpecs,
4377
+ bL as parseComponentSpecs,
4109
4378
  parseContrastChecks,
4110
4379
  q as parseDimension,
4111
4380
  parseDocsReply,
4112
4381
  parseDocsTaskAnswer,
4113
4382
  parseExplorationBody,
4114
4383
  parseJson,
4115
- bJ as parseOwnerEntry,
4384
+ bM as parseOwnerEntry,
4116
4385
  parsePendingDrafts,
4117
4386
  parseRepo,
4118
4387
  parseRequestIssue,
4119
4388
  parseStructureChange,
4120
4389
  parseTokenFile,
4121
- bK as parseVercelComment,
4390
+ bN as parseVercelComment,
4122
4391
  patchDocsJson,
4123
4392
  pathId,
4124
4393
  pathSimilarity,
@@ -4126,25 +4395,27 @@ export {
4126
4395
  pickedOption,
4127
4396
  plainEqual,
4128
4397
  planNewBrand,
4129
- bL as planRestore,
4130
- bM as planRevert,
4131
- bN as planToJson,
4398
+ planReference,
4399
+ planReferences,
4400
+ bO as planRestore,
4401
+ bP as planRevert,
4402
+ bQ as planToJson,
4132
4403
  planTokenMerge,
4133
4404
  e as prNumberFromSubject,
4134
4405
  prefillDocs,
4135
- bO as previewComment,
4406
+ bR as previewComment,
4136
4407
  previewLinks,
4137
- bP as previewLinksOf,
4408
+ bS as previewLinksOf,
4138
4409
  previewOverrides,
4139
- bQ as previewUrl,
4410
+ bT as previewUrl,
4140
4411
  previewsSettled,
4141
- bR as projectOfLabel,
4412
+ bU as projectOfLabel,
4142
4413
  promoteExplorationOnGitHub,
4143
4414
  promotionPlan,
4144
4415
  propsTable,
4145
4416
  protectLibrary,
4146
4417
  protectRefusal,
4147
- bS as protectedBranchesOf,
4418
+ bV as protectedBranchesOf,
4148
4419
  protectionRuleset,
4149
4420
  protectionRulesetName,
4150
4421
  protectionSentence,
@@ -4155,10 +4426,11 @@ export {
4155
4426
  readPreviewComment,
4156
4427
  readTokenAt,
4157
4428
  reconcileIds,
4429
+ referenceImagePath,
4158
4430
  releasesFromTags,
4159
4431
  removeToken,
4160
4432
  removedSide,
4161
- bT as renderedColor,
4433
+ bW as renderedColor,
4162
4434
  requestBrief,
4163
4435
  requestImagePath,
4164
4436
  requestIssueTitle,
@@ -4169,13 +4441,13 @@ export {
4169
4441
  resolveBranchPreviews,
4170
4442
  r as rgbaToDtcg,
4171
4443
  rgbaToHex,
4172
- bU as rightsProblems,
4444
+ bX as rightsProblems,
4173
4445
  round3,
4174
4446
  rulesSettingsUrl,
4175
4447
  rulesetTargetsDefault,
4176
- bV as runLayeredContrast,
4448
+ bY as runLayeredContrast,
4177
4449
  sameScopes,
4178
- bW as sameToken,
4450
+ bZ as sameToken,
4179
4451
  sanitizeDocsReplacement,
4180
4452
  sanitizeDocsResult,
4181
4453
  sanitizeDocsSections,
@@ -4189,57 +4461,59 @@ export {
4189
4461
  serializePendingDrafts,
4190
4462
  serializeTokenFile,
4191
4463
  shadowedEdits,
4192
- bX as shipPolicy,
4464
+ b_ as shipPolicy,
4193
4465
  shortVariant,
4194
4466
  shortVariants,
4195
4467
  slugify,
4196
- bY as snapshotUrl,
4197
- bZ as specHash,
4468
+ b$ as snapshotUrl,
4469
+ s as specHash,
4198
4470
  startExplorationOnGitHub,
4199
- b_ as summarizeTokenChange,
4471
+ summarizeComponent,
4472
+ c0 as summarizeTokenChange,
4200
4473
  takeMine,
4201
- b$ as tarballAssetName,
4202
- c0 as tarballUrl,
4203
- c1 as teamKey,
4204
- c2 as teamKeyOf,
4205
- c3 as teamUnreadableMessage,
4206
- c4 as teamsIn,
4474
+ c1 as tarballAssetName,
4475
+ c2 as tarballUrl,
4476
+ c3 as teamKey,
4477
+ c4 as teamKeyOf,
4478
+ c5 as teamUnreadableMessage,
4479
+ c6 as teamsIn,
4207
4480
  threeWayDiff,
4208
4481
  tintedNeutral,
4209
- c5 as titleOf,
4482
+ c7 as titleOf,
4210
4483
  t2 as toAlias,
4211
- c6 as toChangeSummary,
4484
+ c8 as toChangeSummary,
4212
4485
  toConfigJson,
4213
4486
  toHex,
4214
- c7 as toMap,
4487
+ c9 as toMap,
4215
4488
  toOklch,
4216
4489
  toPlain,
4217
- c8 as tokenBump,
4490
+ ca as tokenBump,
4218
4491
  t as tokenCssVar,
4219
- c9 as tokenHistory,
4220
- ca as tokenNode,
4492
+ cb as tokenHistory,
4493
+ cc as tokenNode,
4221
4494
  tokenUsage,
4222
4495
  tokensPath,
4223
4496
  unpicked,
4224
- cb as unreadableShipTeams,
4225
- cc as unreadableTeams,
4497
+ cd as unreadableShipTeams,
4498
+ ce as unreadableTeams,
4226
4499
  updatePendingDrafts,
4227
4500
  upsertToken,
4228
4501
  utf8ToBase64,
4502
+ v as validateComponentSpec,
4229
4503
  validateDocsTask,
4230
4504
  validateIntegrations,
4231
4505
  validateLayered,
4232
4506
  validatePendingDrafts,
4233
4507
  validateProposal,
4234
4508
  validateSet,
4235
- cd as valueIn,
4509
+ cf as valueIn,
4236
4510
  u as valueToCss,
4237
4511
  valuesEqual,
4238
- v as variantKeyOf,
4239
- ce as variantName,
4240
- cf as versionTimeline,
4241
- cg as visualImpactProblems,
4242
- ch as whoCanShipSentence,
4512
+ variantKeyOf,
4513
+ cg as variantName,
4514
+ ch as versionTimeline,
4515
+ ci as visualImpactProblems,
4516
+ cj as whoCanShipSentence,
4243
4517
  withRequestExploration,
4244
4518
  writeDraftResults
4245
4519
  };