@bridge-ds/cli 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.
Files changed (2) hide show
  1. package/dist/index.js +193 -92
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -2158,57 +2158,6 @@ function planCssFixes(text, lang, ds) {
2158
2158
  return { edits: edits.map(({ start: _s, end: _e, ...e }) => e), output };
2159
2159
  }
2160
2160
 
2161
- // ../core/src/node/git-local.ts
2162
- import { execFile } from "node:child_process";
2163
-
2164
- // ../core/src/governance.ts
2165
- var DEFAULT_PROTECTED_BRANCHES = ["main", "master"];
2166
- var ProtectedBranchError = class extends Error {
2167
- constructor(message) {
2168
- super(message);
2169
- this.name = "ProtectedBranchError";
2170
- }
2171
- };
2172
- function assertSafeBranch(branch, rules = {}) {
2173
- const name = branch.replace(/^refs\/heads\//, "").trim();
2174
- const blocked = /* @__PURE__ */ new Set([...rules.protectedBranches ?? DEFAULT_PROTECTED_BRANCHES, ...rules.base ? [rules.base] : []]);
2175
- if (!name || blocked.has(name)) {
2176
- throw new ProtectedBranchError(`Refusing to write to protected branch "${name}". Bridge only creates new branches and pull requests.`);
2177
- }
2178
- if (rules.branchPrefix && !name.startsWith(rules.branchPrefix)) {
2179
- throw new ProtectedBranchError(`Branch "${name}" must start with "${rules.branchPrefix}".`);
2180
- }
2181
- }
2182
-
2183
- // ../core/src/node/git-local.ts
2184
- function git(root, args, opts = {}) {
2185
- return new Promise((resolve5, reject) => {
2186
- const child = execFile("git", args, { cwd: root, env: { ...process.env, ...opts.env }, maxBuffer: 32 * 1024 * 1024 }, (err, stdout, stderr) => {
2187
- if (err) reject(new Error(`git ${args.join(" ")}: ${stderr || err.message}`.trim()));
2188
- else resolve5(stdout);
2189
- });
2190
- if (opts.input !== void 0) child.stdin.end(opts.input);
2191
- });
2192
- }
2193
- async function showFile(root, ref, path) {
2194
- try {
2195
- return await git(root, ["show", `${ref}:${path}`]);
2196
- } catch {
2197
- return null;
2198
- }
2199
- }
2200
- async function listFilesAt(root, ref) {
2201
- return (await git(root, ["ls-tree", "-r", "--name-only", ref])).split("\n").filter(Boolean);
2202
- }
2203
- async function originRepo(root) {
2204
- try {
2205
- const url = (await git(root, ["remote", "get-url", "origin"])).trim();
2206
- return /github\.com[:/]([\w.-]+\/[\w.-]+?)(\.git)?$/.exec(url)?.[1];
2207
- } catch {
2208
- return void 0;
2209
- }
2210
- }
2211
-
2212
2161
  // ../core/src/previews.ts
2213
2162
  var PREVIEW_APP_LABELS = { docs: "Docs", storybook: "Storybook", admin: "Admin demo" };
2214
2163
 
@@ -2766,6 +2715,57 @@ function loadConfig(source) {
2766
2715
  return defineConfig(d);
2767
2716
  }
2768
2717
 
2718
+ // ../core/src/node/git-local.ts
2719
+ import { execFile } from "node:child_process";
2720
+
2721
+ // ../core/src/governance.ts
2722
+ var DEFAULT_PROTECTED_BRANCHES = ["main", "master"];
2723
+ var ProtectedBranchError = class extends Error {
2724
+ constructor(message) {
2725
+ super(message);
2726
+ this.name = "ProtectedBranchError";
2727
+ }
2728
+ };
2729
+ function assertSafeBranch(branch, rules = {}) {
2730
+ const name = branch.replace(/^refs\/heads\//, "").trim();
2731
+ const blocked = /* @__PURE__ */ new Set([...rules.protectedBranches ?? DEFAULT_PROTECTED_BRANCHES, ...rules.base ? [rules.base] : []]);
2732
+ if (!name || blocked.has(name)) {
2733
+ throw new ProtectedBranchError(`Refusing to write to protected branch "${name}". Bridge only creates new branches and pull requests.`);
2734
+ }
2735
+ if (rules.branchPrefix && !name.startsWith(rules.branchPrefix)) {
2736
+ throw new ProtectedBranchError(`Branch "${name}" must start with "${rules.branchPrefix}".`);
2737
+ }
2738
+ }
2739
+
2740
+ // ../core/src/node/git-local.ts
2741
+ function git(root, args, opts = {}) {
2742
+ return new Promise((resolve5, reject) => {
2743
+ const child = execFile("git", args, { cwd: root, env: { ...process.env, ...opts.env }, maxBuffer: 32 * 1024 * 1024 }, (err, stdout, stderr) => {
2744
+ if (err) reject(new Error(`git ${args.join(" ")}: ${stderr || err.message}`.trim()));
2745
+ else resolve5(stdout);
2746
+ });
2747
+ if (opts.input !== void 0) child.stdin.end(opts.input);
2748
+ });
2749
+ }
2750
+ async function showFile(root, ref, path) {
2751
+ try {
2752
+ return await git(root, ["show", `${ref}:${path}`]);
2753
+ } catch {
2754
+ return null;
2755
+ }
2756
+ }
2757
+ async function listFilesAt(root, ref) {
2758
+ return (await git(root, ["ls-tree", "-r", "--name-only", ref])).split("\n").filter(Boolean);
2759
+ }
2760
+ async function originRepo(root) {
2761
+ try {
2762
+ const url = (await git(root, ["remote", "get-url", "origin"])).trim();
2763
+ return /github\.com[:/]([\w.-]+\/[\w.-]+?)(\.git)?$/.exec(url)?.[1];
2764
+ } catch {
2765
+ return void 0;
2766
+ }
2767
+ }
2768
+
2769
2769
  // ../core/src/layered-review.ts
2770
2770
  var same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
2771
2771
  function diffLayered(before, after) {
@@ -3773,6 +3773,17 @@ var GitHubClient = class _GitHubClient {
3773
3773
  this.assertToken("Updating a branch from main");
3774
3774
  await this.request("PUT", `${this.repoPath}/pulls/${n}/update-branch`, { expected_head_sha: expectedHeadSha });
3775
3775
  }
3776
+ /**
3777
+ * Merges the branch `head` into the branch `base` (GitHub's merges API): a merge commit on `base`, or nothing when
3778
+ * `base` already has every commit of `head`. A conflict throws a GitHubError with status 409. Refuses protected
3779
+ * branches and, with a branch prefix, a `base` without it.
3780
+ */
3781
+ async mergeIntoBranch(base, head, message) {
3782
+ this.assertToken("Merging a branch into another");
3783
+ this.assertWritableBranch(base);
3784
+ const r = await this.request("POST", `${this.repoPath}/merges`, { base, head, commit_message: message });
3785
+ return r?.sha ? { status: "merged", sha: r.sha } : { status: "up-to-date", sha: null };
3786
+ }
3776
3787
  /** Posts a comment on an issue or pull request and returns its id and link. */
3777
3788
  async createIssueComment(n, body) {
3778
3789
  this.assertToken("Commenting");
@@ -5904,6 +5915,91 @@ ${r.content}` : String(r.said));
5904
5915
  return 0;
5905
5916
  }
5906
5917
 
5918
+ // src/pieces.ts
5919
+ import { BridgeContext as BridgeContext5, branches as branches2, pieces } from "@bridge-ds/mcp";
5920
+ var PIECES_HELP = `bridge pieces: a product branch and the library
5921
+
5922
+ Usage:
5923
+ bridge pieces <n> [--record] [--json] what the product branch adds that the library lacks (the audit
5924
+ on its diff against main); --record saves it in the branch,
5925
+ where Bridge Studio shows it
5926
+ bridge pieces status <n> [--json] each linked library branch: status, reviewers, preview, next step
5927
+ bridge pieces open <n> <piece> [--no-preview] [--dry-run] [--json]
5928
+ open the library side of a piece, linked both ways: a token
5929
+ change, a library exploration (variant) or a request (component)
5930
+ bridge pieces preview <n> <piece> the product branch takes the latest library branch (merged in)
5931
+ bridge pieces switch <n> once the library shipped: main into the product branch
5932
+
5933
+ GitHub token: GITHUB_TOKEN or BRIDGE_GITHUB_TOKEN, else \`gh auth token\`. Exit codes: 0 ok, 2 usage or setup error.`;
5934
+ var has4 = (a, k) => Boolean(a.flags[k]);
5935
+ async function context4(root, io) {
5936
+ const token = io.env.BRIDGE_GITHUB_TOKEN || io.env.GITHUB_TOKEN || io.ghToken();
5937
+ return BridgeContext5.create({ root, ...token ? { token } : {}, ...io.fetch ? { fetch: io.fetch } : {} });
5938
+ }
5939
+ function number2(a, at, usage) {
5940
+ const raw = a._[at];
5941
+ if (!raw) throw new RequestUsageError(`Usage: ${usage}`);
5942
+ return branches2.branchNumber(raw);
5943
+ }
5944
+ function piece(a, at, usage) {
5945
+ const raw = a._[at];
5946
+ if (!raw) throw new RequestUsageError(`Usage: ${usage}. \`bridge pieces <n>\` lists the piece ids.`);
5947
+ return raw;
5948
+ }
5949
+ async function runPieces(a, root, io = defaultIO()) {
5950
+ const sub = a._[1];
5951
+ if (!sub || sub === "help" || has4(a, "help")) {
5952
+ io.print(PIECES_HELP);
5953
+ return sub || has4(a, "help") ? 0 : 2;
5954
+ }
5955
+ const json = has4(a, "json");
5956
+ const ctx = await context4(root, io);
5957
+ const out = (r, text) => (json ? io.print(JSON.stringify(r, null, 2)) : text(), 0);
5958
+ switch (sub) {
5959
+ case "status": {
5960
+ const r = await pieces.productBranchOp(ctx, { pr: number2(a, 2, "bridge pieces status <n>") });
5961
+ return out(r, () => {
5962
+ io.print(`#${r.pr} ${r.title} (${r.product})`);
5963
+ io.print(r.said);
5964
+ for (const l of r.linked) io.print(` ${l.piece}: #${l.library.number} ${l.status}. ${l.preview}${l.action ? ` Next: ${l.action}.` : ""}`);
5965
+ for (const p of r.notLinked) io.print(` ${p.title} (${p.id}): no library branch yet. bridge pieces open ${r.pr} ${p.id}`);
5966
+ if (r.next) io.print(r.next);
5967
+ });
5968
+ }
5969
+ case "open": {
5970
+ const usage = "bridge pieces open <n> <piece>";
5971
+ const r = await pieces.openLibraryBranchOp(ctx, { pr: number2(a, 2, usage), piece: piece(a, 3, usage), usePreview: !has4(a, "no-preview"), dryRun: has4(a, "dry-run"), source: "cli" });
5972
+ return out(r, () => {
5973
+ io.print(`${r.status === "dry-run" ? "Would open" : r.status === "already-linked" ? "Already linked" : "Opened"} a ${r.opens}: ${r.title}, needed by ${r.neededBy}.`);
5974
+ if (r.library) io.print(` #${r.library.number} ${r.library.url}`);
5975
+ if (r.preview) io.print(` ${r.preview.said}`);
5976
+ for (const w of r.warnings ?? []) io.print(` ${w}`);
5977
+ io.print(`Next: ${r.next}`);
5978
+ });
5979
+ }
5980
+ case "preview": {
5981
+ const usage = "bridge pieces preview <n> <piece>";
5982
+ const r = await pieces.useLibraryPreviewOp(ctx, { pr: number2(a, 2, usage), piece: piece(a, 3, usage) });
5983
+ return out(r, () => io.print(r.said));
5984
+ }
5985
+ case "switch": {
5986
+ const r = await pieces.switchToPublishedOp(ctx, { pr: number2(a, 2, "bridge pieces switch <n>") });
5987
+ return out(r, () => io.print(r.said));
5988
+ }
5989
+ default: {
5990
+ const r = await pieces.missingPiecesOp(ctx, { pr: number2(a, 1, "bridge pieces <n> [--record]"), record: has4(a, "record") });
5991
+ return out(r, () => {
5992
+ io.print(`#${r.pr} ${r.branch} (${r.product}): ${r.pieces.length ? `${r.pieces.length} ${r.pieces.length === 1 ? "piece is" : "pieces are"} missing from the library` : "nothing is missing from the library"}, ${r.files} files read.`);
5993
+ for (const p of r.pieces) io.print(` ${p.id} ${p.title}: ${p.summary} Opens ${p.opens}.${"linked" in p ? ` Linked: #${p.linked}.` : ""}`);
5994
+ if (r.fixes.count) io.print(`${r.fixes.count} value${r.fixes.count === 1 ? "" : "s"} the library already has (use them instead):
5995
+ ${r.fixes.sample.map((s) => ` ${s}`).join("\n")}`);
5996
+ if (r.skipped) io.print(r.skipped);
5997
+ io.print(`Next: ${r.next}`);
5998
+ });
5999
+ }
6000
+ }
6001
+ }
6002
+
5907
6003
  // src/protection.ts
5908
6004
  var UNKNOWN = { kind: "unknown", missing: ["review", "checks", "history", "deletion"] };
5909
6005
  async function protectionReport(opts) {
@@ -5936,7 +6032,7 @@ async function rolesReport(opts) {
5936
6032
  }
5937
6033
 
5938
6034
  // src/index.ts
5939
- import { brand, BridgeContext as BridgeContext5, CONFIG_FILE as CONFIG_FILE2, core, detectConfig, GitRefSource, history as hist, LocalSource, ops, optionsFromArgv, serveStdio, toConfigJson, VERSION } from "@bridge-ds/mcp";
6035
+ import { brand, BridgeContext as BridgeContext6, CONFIG_FILE as CONFIG_FILE2, core, detectConfig, GitRefSource, history as hist, LocalSource, ops, optionsFromArgv, serveStdio, toConfigJson, VERSION } from "@bridge-ds/mcp";
5940
6036
  var MCP_PACKAGE = "@bridge-ds/mcp";
5941
6037
  var HELP = `bridge ${VERSION}: design system as code, for you and your Claude
5942
6038
 
@@ -6018,6 +6114,10 @@ Usage:
6018
6114
  (\`bridge branch help\`): what needs me, send for review, review,
6019
6115
  merge through the same gate (owner override with a reason), update
6020
6116
  from main with token conflicts, try it in a product, try together
6117
+ bridge pieces <n> [--record] | status <n> | open <n> <piece> | preview <n> <piece> | switch <n>
6118
+ a product branch and the library (\`bridge pieces help\`): what it adds
6119
+ that the library lacks, the library branch each piece opens (linked
6120
+ both ways), its preview in the product branch, the published version
6021
6121
  bridge products | bridge settings | bridge coverage [Component]
6022
6122
  products (and this folder's), Studio settings safe to read, which
6023
6123
  components are in Figma
@@ -6046,16 +6146,16 @@ function parse(argv) {
6046
6146
  return out;
6047
6147
  }
6048
6148
  var flag4 = (a, k) => a.flags[k]?.[a.flags[k].length - 1];
6049
- var has4 = (a, k) => Boolean(a.flags[k]);
6149
+ var has5 = (a, k) => Boolean(a.flags[k]);
6050
6150
  var print = (s) => process.stdout.write(`${s}
6051
6151
  `);
6052
6152
  var modeArg = (s) => s ? Object.fromEntries(s.split(",").map((kv) => kv.split("="))) : void 0;
6053
6153
  async function init(a, root) {
6054
6154
  const cfgPath = join6(root, CONFIG_FILE2);
6055
6155
  let config;
6056
- if (existsSync6(cfgPath) && !has4(a, "force")) {
6156
+ if (existsSync6(cfgPath) && !has5(a, "force")) {
6057
6157
  print(`${CONFIG_FILE2} exists, keeping it (--force to regenerate).`);
6058
- config = (await (await BridgeContext5.create({ root })).config()).config;
6158
+ config = (await (await BridgeContext6.create({ root })).config()).config;
6059
6159
  } else {
6060
6160
  const src = new LocalSource(root);
6061
6161
  const files = await src.list("");
@@ -6083,14 +6183,14 @@ async function init(a, root) {
6083
6183
  print(` claude mcp add bridge -- ${desktop.command} ${desktop.args.join(" ")}`);
6084
6184
  }
6085
6185
  async function check(a, root) {
6086
- const ctx = await BridgeContext5.create({ root });
6186
+ const ctx = await BridgeContext6.create({ root });
6087
6187
  const v = await ops.validateTokens(ctx, { includeWarnings: true });
6088
6188
  const c = await ops.checkContrast(ctx, {});
6089
6189
  const warnings = "warnings" in v ? v.warnings ?? [] : [];
6090
- const failed = !v.valid || "failing" in c && (c.failing ?? 0) > 0 || has4(a, "strict") && warnings.length > 0;
6190
+ const failed = !v.valid || "failing" in c && (c.failing ?? 0) > 0 || has5(a, "strict") && warnings.length > 0;
6091
6191
  const protection = await protectionOf(a, root, ctx);
6092
6192
  const roles = await rolesOf(a, root, ctx);
6093
- if (has4(a, "json")) {
6193
+ if (has5(a, "json")) {
6094
6194
  print(JSON.stringify({ ok: !failed, validation: v, contrast: c, ...protection ? { protection: protection.state } : {}, ...roles?.teams.length ? { teams: roles.teams } : {} }, null, 2));
6095
6195
  return failed ? 1 : 0;
6096
6196
  }
@@ -6109,7 +6209,7 @@ async function check(a, root) {
6109
6209
  return failed ? 1 : 0;
6110
6210
  }
6111
6211
  async function protectionOf(a, root, ctx) {
6112
- if (has4(a, "offline") || process.env.BRIDGE_OFFLINE === "1") return void 0;
6212
+ if (has5(a, "offline") || process.env.BRIDGE_OFFLINE === "1") return void 0;
6113
6213
  const { config } = await ctx.config();
6114
6214
  const repo = config.repo ? `${config.repo.owner}/${config.repo.name}` : await originRepo(root);
6115
6215
  if (!repo) return void 0;
@@ -6117,7 +6217,7 @@ async function protectionOf(a, root, ctx) {
6117
6217
  return protectionReport({ repo, defaultBranch: config.repo?.defaultBranch ?? "main", token });
6118
6218
  }
6119
6219
  async function rolesOf(a, root, ctx) {
6120
- if (has4(a, "offline") || process.env.BRIDGE_OFFLINE === "1") return void 0;
6220
+ if (has5(a, "offline") || process.env.BRIDGE_OFFLINE === "1") return void 0;
6121
6221
  const { config } = await ctx.config();
6122
6222
  const repo = config.repo ? `${config.repo.owner}/${config.repo.name}` : await originRepo(root);
6123
6223
  if (!repo) return void 0;
@@ -6127,9 +6227,9 @@ async function rolesOf(a, root, ctx) {
6127
6227
  async function tokens(a, root) {
6128
6228
  const q = a._.slice(1).join(" ");
6129
6229
  if (!q) throw new UsageError("bridge tokens <query>");
6130
- const ctx = await BridgeContext5.create({ root });
6230
+ const ctx = await BridgeContext6.create({ root });
6131
6231
  const r = await ops.searchTokens(ctx, { query: q, limit: Number(flag4(a, "limit") ?? 20) });
6132
- if (has4(a, "json")) return print(JSON.stringify(r, null, 2));
6232
+ if (has5(a, "json")) return print(JSON.stringify(r, null, 2));
6133
6233
  if (!r.results.length) return print(`No token matches "${q}".`);
6134
6234
  const w = Math.max(...r.results.map((x) => x.path.length));
6135
6235
  for (const t of r.results) print(`${t.path.padEnd(w)} ${String(t.value).padEnd(10)} ${(t.tier ?? "").padEnd(9)} ${t.description ?? ""}`);
@@ -6137,7 +6237,7 @@ async function tokens(a, root) {
6137
6237
  async function diff(a, root) {
6138
6238
  const base = a._[1];
6139
6239
  if (!base) throw new UsageError("bridge diff <base> (a git ref: main, HEAD~1, a sha)");
6140
- const ctx = await BridgeContext5.create({ root });
6240
+ const ctx = await BridgeContext6.create({ root });
6141
6241
  const { config } = await ctx.config();
6142
6242
  const before = await core.loadTokenSet(new GitRefSource(root, base), config);
6143
6243
  const after = await ctx.tokens();
@@ -6146,11 +6246,11 @@ async function diff(a, root) {
6146
6246
  const delta2 = pairs2.length ? core.contrastDelta(core.runContrast(before, pairs2, config.contrast?.modes), core.runContrast(after, pairs2, config.contrast?.modes)) : [];
6147
6247
  const tier = core.classify(changes, [], config);
6148
6248
  const imp = core.impact(before, after, changes, 30);
6149
- if (has4(a, "json")) {
6249
+ if (has5(a, "json")) {
6150
6250
  print(JSON.stringify({ base, changes, contrast: delta2, tier, impact: imp }, null, 2));
6151
6251
  return 0;
6152
6252
  }
6153
- if (has4(a, "md")) {
6253
+ if (has5(a, "md")) {
6154
6254
  print(`## Token changes since \`${base}\`
6155
6255
 
6156
6256
  ${core.tokenTable(changes)}
@@ -6200,7 +6300,7 @@ async function propose(a, root) {
6200
6300
  if (!edits.length) throw new UsageError("Give at least one --set path=value or --edits file.json");
6201
6301
  const pr = flag4(a, "pr");
6202
6302
  const token = pr ? process.env.BRIDGE_GITHUB_TOKEN || process.env.GITHUB_TOKEN || defaultIO().ghToken() : void 0;
6203
- const ctx = await BridgeContext5.create({ root, ...token ? { token } : {} });
6303
+ const ctx = await BridgeContext6.create({ root, ...token ? { token } : {} });
6204
6304
  const summary = flag4(a, "summary");
6205
6305
  const branch = flag4(a, "branch");
6206
6306
  const jira = flag4(a, "jira");
@@ -6213,9 +6313,9 @@ async function propose(a, root) {
6213
6313
  ...pr ? { pr } : {},
6214
6314
  ...jira ? { jira } : {},
6215
6315
  ...product ? { product } : {},
6216
- dryRun: has4(a, "dry-run")
6316
+ dryRun: has5(a, "dry-run")
6217
6317
  });
6218
- if (has4(a, "json")) print(JSON.stringify(r, null, 2));
6318
+ if (has5(a, "json")) print(JSON.stringify(r, null, 2));
6219
6319
  else {
6220
6320
  print(`status: ${r.status}${r.why ? ` (${r.why})` : ""}`);
6221
6321
  if (r.tier) print(`tier ${r.tier}, ${r.bump}`);
@@ -6230,10 +6330,10 @@ ${r.prBody}`);
6230
6330
  }
6231
6331
  async function brandCmd(a, root) {
6232
6332
  const sub = a._[1];
6233
- const ctx = await BridgeContext5.create({ root });
6333
+ const ctx = await BridgeContext6.create({ root });
6234
6334
  if (sub === "list") {
6235
6335
  const r2 = await brand.listBrands(ctx);
6236
- if (has4(a, "json")) print(JSON.stringify(r2.brands, null, 2));
6336
+ if (has5(a, "json")) print(JSON.stringify(r2.brands, null, 2));
6237
6337
  else for (const b of r2.brands) print(`${b.default ? "*" : " "} ${b.slug.padEnd(14)} ${b.name.padEnd(18)} ${b.primary ?? ""}${b.overrides.length ? ` overrides: ${b.overrides.join(", ")}` : ""}`);
6238
6338
  return 0;
6239
6339
  }
@@ -6253,9 +6353,9 @@ async function brandCmd(a, root) {
6253
6353
  ...opt("radius") ? { radius: opt("radius") } : {},
6254
6354
  ...Object.keys(fonts).length ? { fonts } : {},
6255
6355
  ...opt("notes") ? { notes: opt("notes") } : {},
6256
- dryRun: has4(a, "dry-run")
6356
+ dryRun: has5(a, "dry-run")
6257
6357
  });
6258
- if (has4(a, "json")) {
6358
+ if (has5(a, "json")) {
6259
6359
  const { fileContents: _f, ...rest } = r;
6260
6360
  print(JSON.stringify(rest, null, 2));
6261
6361
  return r.status === "blocked" ? 1 : 0;
@@ -6291,9 +6391,9 @@ async function figmaReferences(a, root) {
6291
6391
  out: resolve4(root, flag4(a, "out") ?? "figma-references"),
6292
6392
  sha,
6293
6393
  ...only.length ? { only } : {},
6294
- log: has4(a, "json") ? void 0 : (line) => print(line)
6394
+ log: has5(a, "json") ? void 0 : (line) => print(line)
6295
6395
  });
6296
- if (has4(a, "json")) print(JSON.stringify({ manifest: r.manifestPath, captured: r.captured, skipped: r.skipped }, null, 2));
6396
+ if (has5(a, "json")) print(JSON.stringify({ manifest: r.manifestPath, captured: r.captured, skipped: r.skipped }, null, 2));
6297
6397
  return 0;
6298
6398
  }
6299
6399
  async function impact(a, root) {
@@ -6318,15 +6418,15 @@ async function impact(a, root) {
6318
6418
  ...maxStories ? { maxStoriesPerComponent: maxStories } : {},
6319
6419
  ...imageBase !== void 0 ? { imageBase } : {},
6320
6420
  ...artifactUrl ? { artifactUrl } : {},
6321
- plan: has4(a, "plan"),
6322
- keepUnchanged: has4(a, "keep-unchanged")
6421
+ plan: has5(a, "plan"),
6422
+ keepUnchanged: has5(a, "keep-unchanged")
6323
6423
  });
6324
- if (has4(a, "json")) {
6424
+ if (has5(a, "json")) {
6325
6425
  print(JSON.stringify({ summary: r.summary, manifest: r.manifestPath, comment: r.commentPath ?? null, ...r.manifest.summary, selection: r.manifest.selection }, null, 2));
6326
6426
  return 0;
6327
6427
  }
6328
6428
  const sel = r.manifest.selection;
6329
- if (has4(a, "plan")) {
6429
+ if (has5(a, "plan")) {
6330
6430
  print(`Plan ${r.manifest.base.ref} (${r.manifest.base.sha.slice(0, 7)}) -> ${r.manifest.head.ref} (${r.manifest.head.sha.slice(0, 7)})`);
6331
6431
  print(` tokens changing value: ${sel.tokens.length}${sel.tokens.length ? ` (${sel.tokens.filter((t) => t.kind === "direct").map((t) => t.path).slice(0, 6).join(", ")})` : ""}`);
6332
6432
  print(` components: ${sel.components.map((c) => c.id).join(", ") || "none"}`);
@@ -6342,12 +6442,12 @@ async function impact(a, root) {
6342
6442
  }
6343
6443
  var day = (iso) => iso.slice(0, 10);
6344
6444
  async function historyCmd(a, root) {
6345
- const ctx = await BridgeContext5.create({ root });
6445
+ const ctx = await BridgeContext6.create({ root });
6346
6446
  const token = a._[1];
6347
6447
  const limit = Number(flag4(a, "limit") ?? 20);
6348
6448
  if (token) {
6349
6449
  const r2 = await hist.getTokenHistory(ctx, { path: token, limit });
6350
- if (has4(a, "json")) return print(JSON.stringify(r2, null, 2)), 0;
6450
+ if (has5(a, "json")) return print(JSON.stringify(r2, null, 2)), 0;
6351
6451
  if (!r2.total) return print(`No recorded change of ${r2.path} in ${r2.source}.`), 0;
6352
6452
  print(`${r2.path}: ${r2.total} change(s) (${r2.source})
6353
6453
  `);
@@ -6359,8 +6459,8 @@ async function historyCmd(a, root) {
6359
6459
  return 0;
6360
6460
  }
6361
6461
  const tier = flag4(a, "tier");
6362
- const r = await hist.getHistory(ctx, { limit, ...flag4(a, "author") ? { author: flag4(a, "author") } : {}, ...tier ? { tier: Number(tier) } : {}, ...flag4(a, "version") ? { version: flag4(a, "version") } : {}, ...has4(a, "breaking") ? { breaking: true } : {} });
6363
- if (has4(a, "json")) return print(JSON.stringify(r, null, 2)), 0;
6462
+ const r = await hist.getHistory(ctx, { limit, ...flag4(a, "author") ? { author: flag4(a, "author") } : {}, ...tier ? { tier: Number(tier) } : {}, ...flag4(a, "version") ? { version: flag4(a, "version") } : {}, ...has5(a, "breaking") ? { breaking: true } : {} });
6463
+ if (has5(a, "json")) return print(JSON.stringify(r, null, 2)), 0;
6364
6464
  print(`${r.source}${r.currentVersion ? `, package version ${r.currentVersion}` : ""}`);
6365
6465
  if (!r.total) return print(r.note ?? "No token change matches."), 0;
6366
6466
  for (const v of r.versions) print(` ${v.version.padEnd(11)} ${day(v.date)} ${v.entries} change(s), ${v.tokenChanges} token edit(s)${v.breaking ? ", breaking" : ""}`);
@@ -6378,10 +6478,10 @@ ${r.truncated}`);
6378
6478
  async function revertCmd(a, root) {
6379
6479
  const target = a._[1];
6380
6480
  if (!target) throw new UsageError("bridge revert <pr|commit|id> [--dry-run] (ids from `bridge history`)");
6381
- const ctx = await BridgeContext5.create({ root });
6481
+ const ctx = await BridgeContext6.create({ root });
6382
6482
  const resolutions = Object.fromEntries((a.flags["use-before"] ?? []).map((k) => [k, "use-before"]));
6383
- const r = await hist.proposeRevert(ctx, { target, resolutions, restoreConflicts: has4(a, "restore-conflicts"), dryRun: has4(a, "dry-run") });
6384
- if (has4(a, "json")) {
6483
+ const r = await hist.proposeRevert(ctx, { target, resolutions, restoreConflicts: has5(a, "restore-conflicts"), dryRun: has5(a, "dry-run") });
6484
+ if (has5(a, "json")) {
6385
6485
  print(JSON.stringify(r, null, 2));
6386
6486
  return r.status === "blocked" ? 1 : 0;
6387
6487
  }
@@ -6409,8 +6509,8 @@ async function audit(a, root) {
6409
6509
  const dsRoot = flag4(a, "ds") ? resolve4(flag4(a, "ds")) : existsSync6(join6(root, CONFIG_FILE2)) ? root : findDesignSystemRoot(root);
6410
6510
  if (!dsRoot) throw new UsageError(`No ${CONFIG_FILE2} found: run bridge audit from the design system repo or pass --ds <dir>.`);
6411
6511
  const ds = loadDesignSystem(dsRoot);
6412
- if (has4(a, "fix")) {
6413
- const write = has4(a, "write");
6512
+ if (has5(a, "fix")) {
6513
+ const write = has5(a, "write");
6414
6514
  const changes = fixCss(target, ds.index, write);
6415
6515
  const n = changes.reduce((acc, c) => acc + c.edits.length, 0);
6416
6516
  for (const c of changes) for (const e of c.edits) print(`${c.file}:${e.line}:${e.column} ${e.from} -> ${e.to}`);
@@ -6486,7 +6586,7 @@ async function audit(a, root) {
6486
6586
  code = 1;
6487
6587
  }
6488
6588
  }
6489
- if (has4(a, "no-regress") && report.baseline) {
6589
+ if (has5(a, "no-regress") && report.baseline) {
6490
6590
  const b = report.baseline;
6491
6591
  if ((b.tokenAdoption.delta ?? 0) < 0 || (b.componentAdoption.delta ?? 0) < 0 || b.hardcoded.delta > 0) {
6492
6592
  process.stderr.write("bridge audit: adoption regressed since the baseline\n");
@@ -6498,9 +6598,9 @@ async function audit(a, root) {
6498
6598
  async function docsCmd(a, root) {
6499
6599
  const [, sub, name] = a._;
6500
6600
  if (sub !== "draft" || !name) throw new UsageError("Usage: bridge docs draft <Component> [--json]");
6501
- const ctx = await BridgeContext5.create({ root });
6601
+ const ctx = await BridgeContext6.create({ root });
6502
6602
  const d = await ops.draftDocsOp(ctx, { name });
6503
- if (has4(a, "json")) {
6603
+ if (has5(a, "json")) {
6504
6604
  print(JSON.stringify({ component: d.component, path: d.path, exists: d.exists, prefill: d.prefill, prompt: d.prompt }, null, 2));
6505
6605
  return 0;
6506
6606
  }
@@ -6535,11 +6635,12 @@ async function main() {
6535
6635
  if (cmd === "request") return runRequest(a, root);
6536
6636
  if (cmd === "explore") return runExplore(a, root);
6537
6637
  if (cmd === "branch") return runBranch(a, root);
6638
+ if (cmd === "pieces") return runPieces(a, root);
6538
6639
  if (cmd === "products" || cmd === "settings" || cmd === "coverage") return runStudioRead(cmd, a, root);
6539
6640
  if (cmd === "docs" && a._[1] === "save") return runDocsSave(a, root);
6540
- if (!cmd || has4(a, "help") || cmd === "help") {
6641
+ if (!cmd || has5(a, "help") || cmd === "help") {
6541
6642
  print(HELP);
6542
- return cmd || has4(a, "help") ? 0 : 2;
6643
+ return cmd || has5(a, "help") ? 0 : 2;
6543
6644
  }
6544
6645
  if (cmd === "--version" || cmd === "version") return print(VERSION), 0;
6545
6646
  switch (cmd) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bridge-ds/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "type": "module",
5
5
  "description": "bridge CLI: set up Bridge in a design system repo, check tokens in CI, search and diff tokens, propose changes, start the MCP server.",
6
6
  "license": "MIT",
@@ -43,8 +43,8 @@
43
43
  "build:package": "node ../../scripts/build-packages.mjs cli"
44
44
  },
45
45
  "dependencies": {
46
- "@bridge-ds/mcp": "^0.4.0",
47
- "@bridge-ds/visual": "^0.3.1",
46
+ "@bridge-ds/mcp": "^0.5.0",
47
+ "@bridge-ds/visual": "^0.3.3",
48
48
  "typescript": "5.9.3"
49
49
  },
50
50
  "devDependencies": {