@bridge-ds/core 0.18.0 → 0.19.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 (63) hide show
  1. package/bridge.config.schema.json +16 -0
  2. package/dist/audit/index.js +3 -3
  3. package/dist/audit/report.d.ts +17 -2
  4. package/dist/branch-actions.d.ts +7 -1
  5. package/dist/build-requests-github.d.ts +25 -0
  6. package/dist/build-requests.d.ts +403 -0
  7. package/dist/changelog-model.d.ts +102 -0
  8. package/dist/component-spec.d.ts +3 -1
  9. package/dist/config.d.ts +21 -0
  10. package/dist/css-color.d.ts +25 -0
  11. package/dist/docs-proposal.d.ts +1 -0
  12. package/dist/explorations.d.ts +1 -0
  13. package/dist/fidelity-references.d.ts +12 -0
  14. package/dist/figma-fix-loop.d.ts +153 -0
  15. package/dist/figma-fixes.d.ts +169 -0
  16. package/dist/figma-push-github.d.ts +7 -2
  17. package/dist/figma-push.d.ts +15 -2
  18. package/dist/gap-case.d.ts +144 -0
  19. package/dist/github-client.d.ts +31 -0
  20. package/dist/id-map.d.ts +10 -0
  21. package/dist/index.d.ts +13 -0
  22. package/dist/index.js +3412 -658
  23. package/dist/index.js.map +1 -1
  24. package/dist/layered-review.d.ts +2 -0
  25. package/dist/measure-status.d.ts +127 -0
  26. package/dist/measured-only.d.ts +28 -0
  27. package/dist/measured-spec.d.ts +349 -0
  28. package/dist/measured-tokens.d.ts +25 -0
  29. package/dist/motion-docs.d.ts +51 -0
  30. package/dist/node/audit.d.ts +11 -3
  31. package/dist/node/index.d.ts +1 -0
  32. package/dist/node/index.js +1637 -24
  33. package/dist/node/index.js.map +1 -1
  34. package/dist/node/measure-script.d.ts +1 -0
  35. package/dist/node/measure.d.ts +212 -0
  36. package/dist/node/spec-css.d.ts +9 -1
  37. package/dist/node/tokens-script.d.ts +3 -0
  38. package/dist/pr-composer.d.ts +5 -0
  39. package/dist/previews.d.ts +4 -1
  40. package/dist/{prod-branch-DenQkr_e.js → prod-branch-Bdx_2bRQ.js} +197 -159
  41. package/dist/prod-branch-Bdx_2bRQ.js.map +1 -0
  42. package/dist/prod-branch.d.ts +1 -1
  43. package/dist/repo-model.d.ts +5 -1
  44. package/dist/repo-source-github.d.ts +8 -0
  45. package/dist/{repo-source-CRfhLO87.js → repo-source-m0Tc603o.js} +1406 -629
  46. package/dist/repo-source-m0Tc603o.js.map +1 -0
  47. package/dist/repo-source.d.ts +6 -0
  48. package/dist/{report-DVEmUr0p.js → report-DFPKygfk.js} +17 -6
  49. package/dist/{report-DVEmUr0p.js.map → report-DFPKygfk.js.map} +1 -1
  50. package/dist/requester.d.ts +14 -0
  51. package/dist/requests.d.ts +2 -0
  52. package/dist/review-gate.d.ts +183 -2
  53. package/dist/risk.d.ts +12 -0
  54. package/dist/share-branch.d.ts +1 -1
  55. package/dist/snapshot.d.ts +34 -0
  56. package/dist/suggestion-review.d.ts +2 -0
  57. package/dist/suggestions-github.d.ts +21 -0
  58. package/dist/suggestions.d.ts +6 -0
  59. package/dist/token-proposal.d.ts +7 -0
  60. package/dist/try-in-product.d.ts +9 -0
  61. package/package.json +1 -1
  62. package/dist/prod-branch-DenQkr_e.js.map +0 -1
  63. package/dist/repo-source-CRfhLO87.js.map +0 -1
@@ -0,0 +1,14 @@
1
+ export interface Requester {
2
+ /** The display name, when the line gives one. */
3
+ name: string | null;
4
+ /** The GitHub login, without "@", when the line gives one. */
5
+ login: string | null;
6
+ }
7
+ /** The neutral author of a change whose requester deleted their Bridge account (api/account rewrites the line). */
8
+ export declare const FORMER_MEMBER = "A former member";
9
+ /** How a sentence names a requester by first name ("Waiting for Priya"): the former member stays whole. */
10
+ export declare const requesterFirstName: (name: string) => string;
11
+ /** The requester a body names, null when it names none (or names it in a form Bridge does not write). */
12
+ export declare function requesterOf(body: string | null | undefined): Requester | null;
13
+ /** The line Bridge writes for a requester: "Requested by Ann Leroy (@annleroy)." */
14
+ export declare function requesterLine(r: Requester): string;
@@ -45,6 +45,8 @@ export interface ComponentChangeRequest {
45
45
  * `exploration` label and the brief says to work on that branch (docs/EXPLORATIONS.md).
46
46
  */
47
47
  exploration?: string | undefined;
48
+ /** Build request details (before and after images, props needed, spec path): build-requests.ts. */
49
+ build?: import('./build-requests').BuildRequestExtra | undefined;
48
50
  }
49
51
  export interface RequestIssue {
50
52
  title: string;
@@ -1,3 +1,4 @@
1
+ import type { FigmaPush } from './build-requests';
1
2
  import type { OverridePolicy } from './config';
2
3
  import { type ShipPolicy } from './rights';
3
4
  import { type RiskTier } from './risk';
@@ -12,8 +13,22 @@ export interface PullStateLike {
12
13
  draft?: boolean;
13
14
  merged?: boolean;
14
15
  merged_at?: string | null;
16
+ /** GitHub labels (objects or names): `drafted-by-claude` makes a draft ready for review (isDraft). */
17
+ labels?: readonly ({
18
+ name?: string;
19
+ } | string)[] | null | undefined;
15
20
  }
16
21
  export type PullState = 'merged' | 'closed' | 'draft' | 'open';
22
+ /**
23
+ * Where Claude stands on a library branch opened from Figma (figma-push labels): `waiting` while it carries the spec
24
+ * only (a developer builds it with Claude), `drafted` once the code is written. Null on any other branch.
25
+ */
26
+ export declare function claudeStage(labels: PullStateLike['labels']): 'waiting' | 'drafted' | null;
27
+ /**
28
+ * A draft on GitHub that still reads as one. Decision RT-1: once Claude drafted the code (`drafted-by-claude`), the
29
+ * branch is ready for review even while GitHub still calls it a draft; the merge marks it ready first (branch-actions).
30
+ */
31
+ export declare const isDraft: (p: Pick<PullStateLike, "draft" | "labels">) => boolean;
17
32
  /** Merged wins over closed (GitHub reports merged pull requests as closed), closed over draft, draft over open. */
18
33
  export declare function pullState(p: PullStateLike): PullState;
19
34
  /** Label and pill tone of each state, for list and detail views. */
@@ -33,7 +48,13 @@ export interface CiStatusLike {
33
48
  context: string;
34
49
  state: 'success' | 'failure' | 'error' | 'pending' | string;
35
50
  target_url?: string | null;
51
+ description?: string | null;
36
52
  }
53
+ /**
54
+ * A status the hosting platform posts when it refused to run at all (Vercel "Deployment rate limited"): it says nothing
55
+ * about the change, and GitHub does not require it, so it never counts as a failed check.
56
+ */
57
+ export declare function isPlatformRefusal(s: Pick<CiStatusLike, 'state' | 'description'>): boolean;
37
58
  export type CiState = 'pass' | 'fail' | 'pending' | 'none';
38
59
  export interface CiSummary {
39
60
  state: CiState;
@@ -56,13 +77,29 @@ export interface ReviewLike {
56
77
  } | null;
57
78
  state: 'APPROVED' | 'CHANGES_REQUESTED' | 'COMMENTED' | 'DISMISSED' | 'PENDING' | string;
58
79
  submitted_at?: string | null;
80
+ /** The commit the review was given on (GitHub `commit_id`): tells whether the branch moved on since. */
81
+ commit_id?: string | null;
59
82
  }
60
83
  export interface ApprovalSummary {
61
84
  approvers: string[];
62
85
  changesRequested: string[];
63
86
  design: boolean;
64
87
  tech: boolean;
88
+ /**
89
+ * One owner approved (design or tech list, teams expanded): the Tier 1 rule of docs/GOVERNANCE.md, "1 code owner",
90
+ * the same as Settings says ("one owner"). With no owner configured, any approval counts. Absent (a summary built by
91
+ * hand): any approval counts.
92
+ */
93
+ owner?: boolean;
94
+ /**
95
+ * A token value change (withTokenValueApprovals, decision TV-1 in docs/BUILD-REQUESTS.md): token values changed or
96
+ * tokens added, nothing renamed or removed, no code. The design approval is all it needs: once it is in, `tech` counts
97
+ * as given and the change ships after the automatic checks. mergeGate never asks for the tech approval then.
98
+ */
99
+ valuesOnly?: boolean;
65
100
  }
101
+ /** Whether the Tier 1 approval is in: one owner approved (GOVERNANCE.md "1 code owner"), else any approval without owners. */
102
+ export declare const hasOwnerApproval: (a: ApprovalSummary) => boolean;
66
103
  export interface ApprovalRules {
67
104
  /**
68
105
  * `governance.soloOwnerCanApproveBoth`: when the owners resolve to one person holding both roles, that person's
@@ -75,6 +112,41 @@ export declare function summarizeApprovals(reviews: ReviewLike[], owners: {
75
112
  design: string[];
76
113
  tech: string[];
77
114
  }, author?: string, rules?: ApprovalRules): ApprovalSummary;
115
+ /**
116
+ * The reviewers to look again: the author updated the branch after every changes request that still counts (the
117
+ * latest decisive review of each of those reviewers was given on a commit other than `headSha`). Then it is the
118
+ * reviewers' turn, not the author's, like GitHub's re-request but read from what happened (an email member cannot
119
+ * request reviewers). Empty while one request was given on the current head, or a review does not say its commit.
120
+ * The merge gate is unchanged: the changes request still blocks until that reviewer approves.
121
+ */
122
+ export declare function lookAgainReviewers(reviews: ReviewLike[], headSha: string | null | undefined, author?: string): string[];
123
+ /**
124
+ * The approvals a pull request carries from the Bridge suggestion it applies (its body says "Closes #n"): the owners
125
+ * approved that exact change on the suggestion, so the pull request that applies it is not gated a second time for the
126
+ * same approval (docs/GOVERNANCE.md, Suggestions). Only when the suggestion is approved (every approval its tier needs,
127
+ * no changes requested) and the pull request's tier is not higher than the tier it was approved at. Changes requested
128
+ * on the pull request itself still block, and CI, conflicts and the ship right gate the merge as before.
129
+ */
130
+ export declare function withSuggestionApprovals(pr: ApprovalSummary, suggestion: {
131
+ approvals: ApprovalSummary;
132
+ tier: RiskTier;
133
+ } | null | undefined, prTier: RiskTier | null | undefined): ApprovalSummary;
134
+ /**
135
+ * The approvals a push from the Figma plugin carries (docs/BUILD-REQUESTS.md): a push counts as design-approved, since
136
+ * keeping unvalidated work out of Figma main is the team's discipline. Token values only (scope `token-values`) also
137
+ * count as tech-approved: they ship after the automatic checks. A rename or removal, code, or unread token changes still
138
+ * need the tech approval. A guardrail file (`outside`) gets no credit. Changes requested on the pull request, CI, a
139
+ * conflict and the ship right gate the merge as before.
140
+ */
141
+ export declare function withFigmaPushApprovals(pr: ApprovalSummary, push: FigmaPush | null | undefined): ApprovalSummary;
142
+ /**
143
+ * Decision TV-1 (docs/BUILD-REQUESTS.md, "Token values from Studio"): a token value change follows the rule of a push
144
+ * from Figma, whoever opened it (Studio, the CLI, the MCP server, an agent). Once the design approval is given, it
145
+ * ships after the automatic checks with no developer code OK: the tech approval counts as given. A rename or removal,
146
+ * unread token changes, code or a guardrail file is not a value change (isTokenValueChange) and still needs it. Changes
147
+ * requested, CI, a conflict and the ship right gate the merge as before.
148
+ */
149
+ export declare function withTokenValueApprovals(pr: ApprovalSummary, valuesOnly: boolean | null | undefined): ApprovalSummary;
78
150
  export type MissingApproval = 'design approval' | 'tech approval' | 'approval';
79
151
  export interface MergeGate {
80
152
  allowed: boolean;
@@ -88,6 +160,21 @@ export interface MergeGate {
88
160
  }
89
161
  /** Whether `login` may use the owner override. Case-insensitive, a leading @ is ignored. */
90
162
  export declare function canOverride(login: string | null | undefined, policy: OverridePolicy | null | undefined): boolean;
163
+ /**
164
+ * Who may use the owner override: the logins `governance.override.allowed` names that are also owners (design or
165
+ * tech lists, teams expanded). docs/GOVERNANCE.md: "A listed owner may merge past missing approvals only". Settings,
166
+ * the Home and the branch page read this one list, so the override is never offered to someone who is not an owner.
167
+ * When an owner entry is a team whose members are not known (a "/" entry), the allowed list stands as it is.
168
+ */
169
+ export declare function overrideHolders(policy: OverridePolicy | null | undefined, owners: {
170
+ design: string[];
171
+ tech: string[];
172
+ }): string[];
173
+ /** The override policy limited to its holders (overrideHolders): what the gate and the who-acts rules read. */
174
+ export declare const ownerOverridePolicy: (policy: OverridePolicy | null | undefined, owners: {
175
+ design: string[];
176
+ tech: string[];
177
+ }) => OverridePolicy | null;
91
178
  /**
92
179
  * Whether the Merge button is enabled, and why not. Mirrors docs/GOVERNANCE.md.
93
180
  * The owner override only ever covers missing approvals: CI failing or running, changes requested, a draft,
@@ -110,8 +197,90 @@ export declare function mergeGate(input: {
110
197
  ship?: ShipPolicy | null;
111
198
  }): MergeGate;
112
199
  /** The gate reason of a conflict, in the words a designer reads. Detected by identity, never by regex. */
200
+ /**
201
+ * The verdict on one pull request, assembled once for every surface: Studio's branch page and row status, the MCP
202
+ * tools (bridge_branch_status, bridge_merge_branch, bridge_what_needs_me) and the CLI (`bridge branch status`,
203
+ * `bridge branch merge`). One composition of the rules of docs/GOVERNANCE.md, so a branch never reads ready in one
204
+ * place and blocked in another:
205
+ * - the pull request that applies an approved suggestion ("Closes #n") carries its approvals (withSuggestionApprovals);
206
+ * - the owner override is limited to the owners `governance.override.allowed` names (ownerOverridePolicy);
207
+ * - Tier 1 needs one owner approval (hasOwnerApproval, inside mergeGate and reviewStatusKind).
208
+ * `gate` is null while the tests or the reviews could not be read: an unknown read never reads as mergeable.
209
+ */
210
+ export interface BranchVerdictInput {
211
+ tier: RiskTier | null;
212
+ ci: CiSummary | null;
213
+ /** The pull request's own approvals (summarizeApprovals); null when its reviews could not be read. */
214
+ approvals: ApprovalSummary | null;
215
+ /** The approved Bridge suggestion the pull request applies (approvedSuggestionOnGitHub), or null. */
216
+ suggestion?: {
217
+ approvals: ApprovalSummary;
218
+ tier: RiskTier;
219
+ } | null | undefined;
220
+ /** The approver lists (approverLists: rights applied, teams expanded). */
221
+ owners: {
222
+ design: string[];
223
+ tech: string[];
224
+ };
225
+ /** `governance.override` as configured; the verdict limits it to its owner holders. */
226
+ override?: OverridePolicy | null | undefined;
227
+ draft?: boolean | undefined;
228
+ /** The pull request's labels: `drafted-by-claude` reads a draft as ready for review (isDraft). */
229
+ labels?: PullStateLike['labels'];
230
+ mergeable?: boolean | null | undefined;
231
+ state?: string | undefined;
232
+ merged_at?: string | null | undefined;
233
+ /** Login of the viewer; null or absent leaves out who may ship and the override (signed out, no token). */
234
+ viewer?: string | null | undefined;
235
+ exploration?: boolean | undefined;
236
+ ship?: ShipPolicy | null | undefined;
237
+ /** Pushed from the Figma plugin (figmaPushOf): design approved by the push, tech too for token values only. */
238
+ figmaPush?: FigmaPush | null | undefined;
239
+ /**
240
+ * The pull request only changes token values (isTokenValueChange over its real files and token changes), whoever
241
+ * opened it: the design approval is all it needs (withTokenValueApprovals, decision TV-1). Absent: not known, the
242
+ * tech approval is still asked.
243
+ */
244
+ tokenValues?: boolean | null | undefined;
245
+ /**
246
+ * Auto-merge is armed on the pull request (GitHub `auto_merge` set): Bridge armed a token value change once its design
247
+ * approval was in (/api/ship, decision TV-1). With `tokenValues` and the design approval, it reads `autoShip`.
248
+ */
249
+ autoMerge?: boolean | null | undefined;
250
+ /**
251
+ * The reviewers to look again (lookAgainReviewers over the reviews and the head sha): the author updated the branch
252
+ * after every changes request. The status stays `changes-requested` and the merge stays blocked; only its words say
253
+ * "Updated, look again".
254
+ */
255
+ lookAgain?: readonly string[] | null | undefined;
256
+ }
257
+ export interface BranchVerdict {
258
+ /** The approvals the gate counts: the pull request's own plus the ones carried from its approved suggestion. */
259
+ approvals: ApprovalSummary | null;
260
+ /** The owner override as the gate reads it: its holders only. Null when none is configured. */
261
+ override: OverridePolicy | null;
262
+ gate: MergeGate | null;
263
+ status: ReviewStatusKind;
264
+ /** The words of the status, the same in Studio, the MCP server and the CLI (reviewStatusLabel). */
265
+ label: string;
266
+ /** Reviewers to look again (the input's lookAgain while changes are requested), else empty. */
267
+ lookAgain: string[];
268
+ /**
269
+ * A token push from Figma with values only, still open: Bridge merges it once the automatic checks pass, nobody
270
+ * reviews it. Also a token value change whose design approval is in and whose merge Bridge armed (`autoMerge`,
271
+ * decision TV-1). Review queues and "Needs you" leave it out; Studio shows "On its way to the library".
272
+ */
273
+ autoShip: boolean;
274
+ }
275
+ export declare function branchVerdict(input: BranchVerdictInput): BranchVerdict;
113
276
  export declare const CONFLICT_REASON = "It conflicts with main: resolve it with Update from main on the branch.";
114
277
  export declare const OVERRIDE_HEADING = "**Bridge owner override**";
278
+ /**
279
+ * The shortest override reason accepted. docs/GOVERNANCE.md: the reason is always required, at least
280
+ * `minReasonLength` characters (20 by default). `requireReason: false` no longer waives it: an override without a
281
+ * reason would leave the audit trail empty.
282
+ */
283
+ export declare function overrideReasonMin(policy: Pick<OverridePolicy, 'minReasonLength'>): number;
115
284
  /** Problem with an override reason, or null when it is accepted. */
116
285
  export declare function overrideReasonProblem(reason: string, policy: OverridePolicy): string | null;
117
286
  /**
@@ -163,6 +332,7 @@ export declare const REVIEW_STATUS_ORDER: Record<ReviewStatusKind, number>;
163
332
  export declare function reviewStatusKind(input: {
164
333
  state?: string;
165
334
  draft?: boolean;
335
+ labels?: PullStateLike['labels'];
166
336
  merged_at?: string | null;
167
337
  ci: CiSummary | null;
168
338
  approvals: ApprovalSummary | null;
@@ -174,6 +344,14 @@ export declare function reviewStatusKind(input: {
174
344
  * working out whether an approved branch merges cleanly; it never stands for missing tests.
175
345
  */
176
346
  export declare const REVIEW_STATUS_LABEL: Record<ReviewStatusKind, string>;
347
+ /** The words of a branch the author updated after every changes request: the reviewers who asked look again. */
348
+ export declare const LOOK_AGAIN_STATUS_LABEL = "Updated, look again";
349
+ /**
350
+ * The words of a status. Changes requested on a branch the author updated since (lookAgainReviewers not empty) reads
351
+ * "Updated, look again", never the stale "Changes requested": the merge gate is the same, the next step is the
352
+ * reviewers'.
353
+ */
354
+ export declare function reviewStatusLabel(kind: ReviewStatusKind, lookAgain?: readonly string[] | null): string;
177
355
  /** The words of a CI summary. A repo without automated checks reads as that, calmly, never as pending or unknown. */
178
356
  export declare const CI_STATE_LABEL: Record<CiState, string>;
179
357
  export interface QueuePull extends PullStateLike {
@@ -233,8 +411,11 @@ export declare function reopenEligibility(x: {
233
411
  branch: 'exists' | 'gone' | 'unknown';
234
412
  }): ReopenEligibility;
235
413
  export type ApprovalRole = 'design' | 'tech' | 'approval';
236
- /** The approvals a tier needs, as mergeGate counts them (Tier 2 and 3: design and tech; Tier 1: one approval). */
237
- export declare function requiredApprovals(tier: RiskTier | null): ApprovalRole[];
414
+ /**
415
+ * The approvals a tier needs, as mergeGate counts them (Tier 2 and 3: design and tech; Tier 1: one approval). A token
416
+ * value change (`valuesOnly`, withTokenValueApprovals) needs the design approval only.
417
+ */
418
+ export declare function requiredApprovals(tier: RiskTier | null, valuesOnly?: boolean | null): ApprovalRole[];
238
419
  /** The approvals still missing on a branch, from its tier and the reviews read (empty when either is unknown). */
239
420
  export declare function pendingApprovals(tier: RiskTier | null | undefined, approvals: ApprovalSummary | null | undefined): ApprovalRole[];
240
421
  /**
package/dist/risk.d.ts CHANGED
@@ -32,6 +32,18 @@ export interface RiskResult {
32
32
  bump?: SemverBump | undefined;
33
33
  }
34
34
  export declare const RISK_LABELS: Record<RiskTier, string>;
35
+ /**
36
+ * The tier line of a token change pushed from the Figma plugin (docs/BUILD-REQUESTS.md): a push is design-approved, so
37
+ * the approvals part of RISK_LABELS would mislead. Token values ship once the checks pass; a rename or a removal waits for
38
+ * a developer OK. Keeps "Tier N" first so parseTier reads it. Same rule as branchVerdict `autoShip`.
39
+ */
40
+ export declare function figmaPushTierLabel(tier: RiskTier, changes: readonly {
41
+ kind: TokenChangeKind | string;
42
+ }[]): string;
43
+ /** The sentence after it: what happens next to a token change pushed from Figma. */
44
+ export declare const figmaPushNextLine: (changes: readonly {
45
+ kind: TokenChangeKind | string;
46
+ }[]) => string;
35
47
  /** Kind and description-only flag of any token change. */
36
48
  export declare function summarizeTokenChange(c: AcceptedChange | TokenChangeSummary): TokenChangeSummary;
37
49
  /** Semver bump of a set of token changes: renames and removals major, other changes minor, descriptions patch. */
@@ -1,5 +1,5 @@
1
1
  /** The dialog's explanation, in designer words. */
2
- export declare const SHARE_EXPLAIN = "Product teams can install this branch in their app before it is merged, and remove it any time.";
2
+ export declare const SHARE_EXPLAIN = "Product teams can install this change in their app before it is in the library, and remove it any time.";
3
3
  export type ChangeLifecycle = 'open' | 'draft' | 'merged' | 'closed';
4
4
  type Source = 'pkg.pr.new' | 'release' | 'other';
5
5
  export type ShareState =
@@ -1,6 +1,8 @@
1
1
  import type { AuditMetrics, AuditReport } from './audit/types';
2
+ import type { ChangelogReleaseRow } from './changelog-model';
2
3
  import type { ContrastPairResult } from './contrast-model';
3
4
  import type { SpecCoverage } from './component-spec';
5
+ import { type MotionDocs } from './motion-docs';
4
6
  import { type RepoSource } from './repo-source';
5
7
  import type { RepoModel } from './repo-model';
6
8
  export declare const SNAPSHOT_SCHEMA_VERSION = 1;
@@ -10,6 +12,17 @@ export declare const SNAPSHOT_FILE = "snapshot.json";
10
12
  export declare const SNAPSHOT_AUDITS_DIR = "audits";
11
13
  /** Above this, a snapshot is refused (a published file the browser downloads whole). */
12
14
  export declare const SNAPSHOT_MAX_BYTES = 5000000;
15
+ /** Releases a snapshot keeps, newest first (the pending one counts); older ones stay in the CHANGELOG.md files. */
16
+ export declare const SNAPSHOT_MAX_RELEASES = 60;
17
+ /** A workspace package of the repository, for the Library's Install page. */
18
+ export interface SnapshotPackage {
19
+ name: string;
20
+ version: string;
21
+ /** Not published to npm. */
22
+ private: boolean;
23
+ /** Repo-relative folder ("." for the root package). */
24
+ dir: string;
25
+ }
13
26
  /** One adoption audit: the summary lives in snapshot.json, the full report in audits/<id>.json next to it. */
14
27
  export interface SnapshotAudit {
15
28
  id: string;
@@ -85,6 +98,19 @@ export interface RepoSnapshot {
85
98
  * written before Bridge read global stylesheets: a reader then reads those files from the repository.
86
99
  */
87
100
  styles?: string[];
101
+ /**
102
+ * Releases from the packages' CHANGELOG.md files and the pending changesets, newest first, at most
103
+ * SNAPSHOT_MAX_RELEASES. Dates come from release tags or git history, absent when the clone has neither. Absent from
104
+ * a snapshot written before Bridge read releases, or when the repository has no changelog.
105
+ */
106
+ releases?: ChangelogReleaseRow[];
107
+ /** Workspace packages (name, version, private, folder). Absent from a snapshot written before Bridge read them. */
108
+ packages?: SnapshotPackage[];
109
+ /**
110
+ * Motion and interaction docs per component (motionDocs), keyed by component name, computed from the specs file the
111
+ * snapshot does not carry. Absent without a readable specs file or a component scan.
112
+ */
113
+ motion?: Record<string, MotionDocs>;
88
114
  }
89
115
  export declare class SnapshotError extends Error {
90
116
  }
@@ -120,7 +146,15 @@ export interface BuildSnapshotInput {
120
146
  committedAt?: string;
121
147
  generatedAt?: string;
122
148
  audits?: SnapshotAudit[];
149
+ /** collectReleases() of the repository; kept to the newest SNAPSHOT_MAX_RELEASES. */
150
+ releases?: ChangelogReleaseRow[];
151
+ packages?: SnapshotPackage[];
123
152
  }
153
+ /**
154
+ * Motion docs of every scanned component, from the parsed specs file: what the Library's motion section shows. Null
155
+ * without a specs file or a component scan.
156
+ */
157
+ export declare function snapshotMotion(model: Pick<RepoModel, 'components' | 'specs'>): Record<string, MotionDocs> | null;
124
158
  /** Counts of a model for the snapshot summary. */
125
159
  export declare function snapshotSummary(model: RepoModel): SnapshotSummary;
126
160
  /** Assembles the snapshot from a model and the files it was read from. The specs file becomes the coverage list. */
@@ -68,6 +68,8 @@ export interface SuggestionApprovals extends ApprovalSummary {
68
68
  export declare function summarizeSuggestionApprovals(comments: readonly SuggestionCommentLike[], gov: SuggestionGovernance, opts: {
69
69
  payloadSha: string;
70
70
  author?: string | null | undefined;
71
+ /** A token value suggestion (suggestionIsTokenValues): the design approval is all it needs (decision TV-1). */
72
+ valuesOnly?: boolean | undefined;
71
73
  }): SuggestionApprovals;
72
74
  /** The review state for the status machine: changes requested beats approved; approved when no approval is missing. */
73
75
  export declare function suggestionReviewState(tier: RiskTier, approvals: ApprovalSummary): 'needs-review' | 'changes-requested' | 'approved';
@@ -1,4 +1,5 @@
1
1
  import { GitHubClient, type IssueSummary, type PullRequestSummary } from './github-client';
2
+ import { type Requester } from './requester';
2
3
  import { type SuggestionAppliedRecord, type SuggestionApprovals, type SuggestionCommentLike, type SuggestionGovernance, type SuggestionReviewEvent } from './suggestion-review';
3
4
  import { type ComposeSuggestionOptions, type ParsedSuggestion, type SuggestionKind, type SuggestionPayloadV1, type SuggestionStatus } from './suggestions';
4
5
  import type { ApprovalRole } from './review-gate';
@@ -32,6 +33,11 @@ export interface SuggestionListItem {
32
33
  title: string;
33
34
  url: string;
34
35
  author: string;
36
+ /**
37
+ * Who asked for it, as Bridge records it in the body ("Requested by Ann Leroy."): the person to show, since the
38
+ * GitHub author is often a lead or an agent acting for them. Null when the body names nobody.
39
+ */
40
+ requester: Requester | null;
35
41
  createdAt: string;
36
42
  state: 'open' | 'closed';
37
43
  stateReason: string | null;
@@ -86,6 +92,21 @@ export declare function getSuggestionOnGitHub(gh: GitHubClient, n: number, gov:
86
92
  pulls?: PullRequestSummary[] | undefined;
87
93
  outdated?: boolean | undefined;
88
94
  }): Promise<SuggestionDetail>;
95
+ /** An approved Bridge suggestion a pull request applies: its number, approvals and the tier they were given at. */
96
+ export interface ApprovedSuggestion {
97
+ number: number;
98
+ approvals: SuggestionApprovals;
99
+ tier: 1 | 2 | 3;
100
+ }
101
+ /**
102
+ * The approved Bridge suggestion a pull request applies, from the issues its body closes ("Closes #n", the first three):
103
+ * its approvals and the tier they were given at, for branchVerdict (withSuggestionApprovals). Null when it closes
104
+ * none, or none is an approved suggestion. Studio, the MCP server and the CLI read it through this one call. A read
105
+ * that fails counts as no suggestion: the pull request then needs its own approvals, never fewer.
106
+ */
107
+ export declare function approvedSuggestionOnGitHub(gh: GitHubClient, body: string | null | undefined, gov: SuggestionGovernance): Promise<ApprovedSuggestion | null>;
108
+ /** One issue: the approved suggestion it holds, or null (not a suggestion, not approved). Throws when it cannot be read. */
109
+ export declare function approvedSuggestionNumber(gh: GitHubClient, n: number, gov: SuggestionGovernance): Promise<ApprovedSuggestion | null>;
89
110
  /**
90
111
  * Keeps exactly one status label on the issue, the one the status calls for (suggestionLabelChanges): an open state
91
112
  * label while open, the final label ("suggestion: applied", "suggestion: declined") once closed, the old ones removed.
@@ -173,6 +173,12 @@ export interface SuggestionStatusInput {
173
173
  /** The dry-run apply found a conflict with the current default branch. */
174
174
  outdated?: boolean | undefined;
175
175
  }
176
+ /**
177
+ * Decision TV-1 (docs/BUILD-REQUESTS.md, "Token values from Studio"): a token suggestion that only changes values or
178
+ * adds tokens (every edit a `set` or an `add`, no file beside its changeset) needs the design approval only, the same
179
+ * rule as a pull request (isTokenValueChange). A rename, a removal or any other kind still needs the tech approval.
180
+ */
181
+ export declare function suggestionIsTokenValues(p: Pick<SuggestionPayloadV1, 'kind' | 'tokens' | 'files' | 'docs' | 'componentSpec'>): boolean;
176
182
  /**
177
183
  * Where a suggestion stands. Closed: applied when a linked pull request merged or the issue was closed as completed,
178
184
  * declined otherwise. Open: applying when a linked pull request is open or an applied marker exists; outdated when the
@@ -52,6 +52,8 @@ export declare function planTokenProposal(input: {
52
52
  tool?: string | undefined;
53
53
  /** More body paragraphs, after the generated body (the product line, "Needed by"). */
54
54
  bodyExtra?: string[] | undefined;
55
+ /** Pushed from the Figma plugin: the body says design-approved and what happens next (docs/BUILD-REQUESTS.md). */
56
+ fromFigma?: boolean | undefined;
55
57
  }): TokenProposalPlan | null;
56
58
  export interface OpenedTokenProposal {
57
59
  branch: string;
@@ -74,6 +76,11 @@ export declare function writeTokenProposalOnGitHub(gh: GitHubClient, plan: Token
74
76
  labelsAfter?: string[] | undefined;
75
77
  /** Who proposes it, in the commit message: "Bridge MCP (source: mcp)". */
76
78
  tool?: string | undefined;
79
+ /**
80
+ * Open it as a draft or not. Default: a draft from tier 2, until design review. A token push from Figma with values
81
+ * only opens ready (false): it ships after the automatic checks (docs/BUILD-REQUESTS.md).
82
+ */
83
+ draft?: boolean | undefined;
77
84
  }): Promise<OpenedTokenProposal>;
78
85
  export interface SuggestedTokenProposal {
79
86
  status: 'suggested';
@@ -17,3 +17,12 @@ export declare function productPreview(apps: PreviewApps, ctx: {
17
17
  * Only http(s) previews: anything else (a javascript: or data: URL in a hostile comment) gives ''.
18
18
  */
19
19
  export declare function tryInProductUrl(preview: string, pr: number, screen: ProductScreen | null): string;
20
+ /**
21
+ * True when nothing reported an online preview of the branch (no Vercel status, deployment or comment, only config
22
+ * templates): explorations and library branches are not deployed, a developer tries them on their machine.
23
+ */
24
+ export declare function noOnlinePreview(previews: readonly {
25
+ source: string | null;
26
+ }[]): boolean;
27
+ /** The command that puts a branch on a developer's machine, quoted when the name has shell characters. */
28
+ export declare function localTryCommand(branch: string): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bridge-ds/core",
3
- "version": "0.18.0",
3
+ "version": "0.19.0",
4
4
  "type": "module",
5
5
  "description": "Bridge core: bridge.config.json, DTCG token loading (tiers and layered modes), alias resolution, WCAG contrast, diffs, minimal-diff edits, PR body, the shared risk tier classifier, changesets and a fetch-based GitHub client. No Figma API, no DOM; Node-only helpers (git, reading a product folder) under @bridge-ds/core/node; the adoption audit under @bridge-ds/core/audit.",
6
6
  "license": "MIT",