@bridge-ds/core 0.20.0 → 0.21.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/audit/index.js +275 -52
- package/dist/audit/index.js.map +1 -1
- package/dist/audit/missing-pieces.d.ts +4 -0
- package/dist/component-spec.d.ts +13 -0
- package/dist/exploration-done-github.d.ts +50 -0
- package/dist/exploration-resume.d.ts +136 -0
- package/dist/explorations-github.d.ts +75 -3
- package/dist/explorations.d.ts +137 -8
- package/dist/figma-fix-loop.d.ts +1 -1
- package/dist/figma-fixes.d.ts +14 -2
- package/dist/github-client.d.ts +17 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1708 -1283
- package/dist/index.js.map +1 -1
- package/dist/measured-only.d.ts +13 -1
- package/dist/node/index.js +11 -11
- package/dist/previews-github.d.ts +13 -0
- package/dist/previews.d.ts +8 -1
- package/dist/{prod-branch-CJZwMfVD.js → prod-branch-C7tphFAA.js} +255 -192
- package/dist/prod-branch-C7tphFAA.js.map +1 -0
- package/dist/prod-branch-github.d.ts +54 -4
- package/dist/prod-branch.d.ts +42 -1
- package/dist/products.d.ts +17 -0
- package/dist/{repo-source-CshjjC7x.js → repo-source-CEBBBtm1.js} +2165 -1998
- package/dist/repo-source-CEBBBtm1.js.map +1 -0
- package/dist/{report-CE-jHAuw.js → report-B7wNAnSu.js} +38 -38
- package/dist/{report-CE-jHAuw.js.map → report-B7wNAnSu.js.map} +1 -1
- package/dist/review-gate.d.ts +1 -1
- package/dist/try-in-product.d.ts +4 -1
- package/package.json +1 -1
- package/dist/prod-branch-CJZwMfVD.js.map +0 -1
- package/dist/repo-source-CshjjC7x.js.map +0 -1
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type DoneExploringPlan, type ExplorationChecks, type ExplorationStatus } from './explorations';
|
|
2
|
+
import { type GitHubClient } from './github-client';
|
|
3
|
+
import { type ProposedPieces } from './prod-branch-github';
|
|
4
|
+
import type { ProductConfig } from './products';
|
|
5
|
+
import type { RequestSource } from './requests';
|
|
6
|
+
export interface DoneExploringInput {
|
|
7
|
+
/** Piece ids the designer ticked: each becomes a request for the DS lead. Unticked ones are not proposed. */
|
|
8
|
+
pieces?: readonly string[] | undefined;
|
|
9
|
+
/** bridge.config.json products, to name the product the pieces are needed by. */
|
|
10
|
+
products?: readonly ProductConfig[] | undefined;
|
|
11
|
+
/** The exploration's preview, linked from each request so the DS lead sees the piece in context. */
|
|
12
|
+
previewUrl?: string | null | undefined;
|
|
13
|
+
/** Who said it, and the AI agent behind it ("claude"). */
|
|
14
|
+
openedBy?: string | undefined;
|
|
15
|
+
agent?: string | undefined;
|
|
16
|
+
source?: RequestSource | undefined;
|
|
17
|
+
date?: Date | undefined;
|
|
18
|
+
dryRun?: boolean | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* The design system repository, when the exploration lives in a product's own repository (`gh` reads that one): the
|
|
21
|
+
* requests for the ticked pieces are filed there, where the DS lead works, linking back to the product pull request.
|
|
22
|
+
*/
|
|
23
|
+
library?: GitHubClient | undefined;
|
|
24
|
+
}
|
|
25
|
+
export interface DoneExploring {
|
|
26
|
+
number: number;
|
|
27
|
+
url: string;
|
|
28
|
+
branch: string;
|
|
29
|
+
/** Where it stands after: ready (waiting for code), or what it already was when said again. */
|
|
30
|
+
status: ExplorationStatus;
|
|
31
|
+
/** False when it was already done exploring: only the newly ticked pieces were sent. */
|
|
32
|
+
handedOff: boolean;
|
|
33
|
+
plan: DoneExploringPlan | null;
|
|
34
|
+
pieces: ProposedPieces;
|
|
35
|
+
/** The two commands a developer runs to take it. */
|
|
36
|
+
take: [string, string];
|
|
37
|
+
/** The branch checks at the head developers start from, when GitHub said; null when it could not be read. */
|
|
38
|
+
checks: ExplorationChecks | null;
|
|
39
|
+
/** What developers read next to the commands, true to those checks. */
|
|
40
|
+
note: string;
|
|
41
|
+
/** Steps that did not go through, with what to do on GitHub instead. */
|
|
42
|
+
warnings: string[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Says "Done exploring" on an exploration: requests for the ticked pieces first, then the note removed, the labels
|
|
46
|
+
* swapped and the body rewritten for developers (with the head they start from, so their pushes read "Being built").
|
|
47
|
+
* Said again on an exploration already handed off, it only sends the newly ticked pieces. Refused on a closed or
|
|
48
|
+
* shipped one. Never closes, merges or marks the draft ready.
|
|
49
|
+
*/
|
|
50
|
+
export declare function doneExploringOnGitHub(gh: GitHubClient, ref: string | number, input?: DoneExploringInput): Promise<DoneExploring>;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { type ExplorationStatus } from './explorations';
|
|
2
|
+
/** The phrase Claude recognizes to resume an exploration ("Continue Bridge exploration #12"). */
|
|
3
|
+
export declare const CONTINUE_PHRASE = "Continue Bridge exploration";
|
|
4
|
+
/** True when every changed file is a Bridge note (.bridge/): nothing the product is built from changed yet. */
|
|
5
|
+
export declare const onlyNotes: (files: readonly string[] | null | undefined) => boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Where a running exploration stands: not started (nothing beyond the Bridge notes), exploring (something changed),
|
|
8
|
+
* or handed on (done exploring, being built, shipped, closed, archived: the pages keep their own layout). Files
|
|
9
|
+
* unknown (null): exploring, so a failed read never hides work behind "Nothing built yet".
|
|
10
|
+
*/
|
|
11
|
+
export declare function explorationStage(x: {
|
|
12
|
+
status: ExplorationStatus;
|
|
13
|
+
archived?: boolean | null | undefined;
|
|
14
|
+
files: readonly string[] | null | undefined;
|
|
15
|
+
}): 'not-started' | 'exploring' | 'handed';
|
|
16
|
+
export interface ContinueRef {
|
|
17
|
+
number: number;
|
|
18
|
+
name: string;
|
|
19
|
+
/** The product's display name ("Admin demo"). */
|
|
20
|
+
productName: string;
|
|
21
|
+
/** Set when the exploration lives in a product's own repository: its key ("shop") and that repository. */
|
|
22
|
+
product?: string | null | undefined;
|
|
23
|
+
repo?: string | null | undefined;
|
|
24
|
+
}
|
|
25
|
+
/** The ref Claude resolves: "#12", or "shop#12" in a product's own repository. */
|
|
26
|
+
export declare const continueRef: (x: Pick<ContinueRef, "number" | "product" | "repo">) => string;
|
|
27
|
+
/**
|
|
28
|
+
* The two lines a designer pastes to continue: in the Claude app, a sentence; in a terminal, the claude command.
|
|
29
|
+
* No em dash: the line is copied as is.
|
|
30
|
+
*/
|
|
31
|
+
export declare function continueLines(x: ContinueRef): {
|
|
32
|
+
app: string;
|
|
33
|
+
terminal: string;
|
|
34
|
+
};
|
|
35
|
+
/** Reads "Continue Bridge exploration #12" or "... shop#12" back into a ref ("#12", "shop#12"); null otherwise. */
|
|
36
|
+
export declare function parseContinueLine(text: string): string | null;
|
|
37
|
+
/** "BulkActionsBar" -> "Bulk actions bar", "DSBridgePanel" -> "DS bridge panel". */
|
|
38
|
+
export declare function wordsOf(name: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* What one file is, for a designer: a component ("Bulk actions bar"), a screen ("Orders screen"), the tokens
|
|
41
|
+
* ("Tokens"), or null when it says nothing to them (helpers, config, tests, notes).
|
|
42
|
+
*/
|
|
43
|
+
export declare function thingOf(path: string): string | null;
|
|
44
|
+
/** The distinct things the files are, in file order. */
|
|
45
|
+
export declare function changedThings(files: readonly string[]): string[];
|
|
46
|
+
/** "A", "A and B", "A, B and 3 more". */
|
|
47
|
+
export declare function listThings(things: readonly string[], max?: number): string;
|
|
48
|
+
/** A commit on the branch, as GitHub lists them (GET /pulls/{n}/commits). */
|
|
49
|
+
export interface BranchCommitLike {
|
|
50
|
+
sha: string;
|
|
51
|
+
commit: {
|
|
52
|
+
message: string;
|
|
53
|
+
author?: {
|
|
54
|
+
name?: string | null;
|
|
55
|
+
date?: string | null;
|
|
56
|
+
} | null;
|
|
57
|
+
committer?: {
|
|
58
|
+
date?: string | null;
|
|
59
|
+
} | null;
|
|
60
|
+
};
|
|
61
|
+
author?: {
|
|
62
|
+
login?: string | null;
|
|
63
|
+
} | null;
|
|
64
|
+
}
|
|
65
|
+
export interface ActivityEvent {
|
|
66
|
+
/** "claude" for Claude's work, else the person's login (or git name). */
|
|
67
|
+
who: string;
|
|
68
|
+
/** Claude alone: a Claude account, or Claude's trailer with no person as the author (a bot or none). */
|
|
69
|
+
claude: boolean;
|
|
70
|
+
/** A person's commit Claude co-wrote (its co-author trailer or footer): shown as "Florian with Claude". */
|
|
71
|
+
withClaude?: boolean;
|
|
72
|
+
/** After the actor: "added row selection to the Orders table". */
|
|
73
|
+
text: string;
|
|
74
|
+
at: string;
|
|
75
|
+
sha?: string;
|
|
76
|
+
}
|
|
77
|
+
/** True when the commit carries Claude's co-author trailer or the Claude Code footer. */
|
|
78
|
+
export declare function isClaudeAssisted(c: BranchCommitLike): boolean;
|
|
79
|
+
/** The person who authored the commit (GitHub login, else git name), or null for a bot, Claude or nobody. */
|
|
80
|
+
export declare function humanAuthorOf(c: BranchCommitLike): string | null;
|
|
81
|
+
/**
|
|
82
|
+
* True when Claude alone wrote the commit: a Claude account, or Claude's trailer on a commit no person authored (a
|
|
83
|
+
* bot, or no author). A person's commit with Claude's trailer is theirs, made with Claude (isClaudeAssisted).
|
|
84
|
+
*/
|
|
85
|
+
export declare function isClaudeCommit(c: BranchCommitLike): boolean;
|
|
86
|
+
/** True for the commit Bridge writes when it starts an exploration (only the note file). */
|
|
87
|
+
export declare const isStartCommit: (c: BranchCommitLike) => boolean;
|
|
88
|
+
/**
|
|
89
|
+
* A commit subject in words after the actor: "feat(orders): add row selection" -> "added row selection". Conventional
|
|
90
|
+
* prefixes go, an imperative first verb turns past, em dashes become commas. Other subjects: "changed things: <subject>".
|
|
91
|
+
*/
|
|
92
|
+
export declare function subjectWords(subject: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* The branch's activity, newest first: one event per commit (Bridge's start commit left out), then "started the
|
|
95
|
+
* exploration". `limit` keeps the newest ones, the start event included when it fits.
|
|
96
|
+
*/
|
|
97
|
+
export declare function explorationActivity(input: {
|
|
98
|
+
commits: readonly BranchCommitLike[];
|
|
99
|
+
author: string;
|
|
100
|
+
startedAt?: string | null | undefined;
|
|
101
|
+
limit?: number;
|
|
102
|
+
}): ActivityEvent[];
|
|
103
|
+
/**
|
|
104
|
+
* The line under the title once something changed: who changed what, from the branch files when they name screens
|
|
105
|
+
* or components ("changed Orders table and Bulk actions bar"), else the latest commit in words. Null before any change.
|
|
106
|
+
*/
|
|
107
|
+
export declare function lastActivity(input: {
|
|
108
|
+
commits: readonly BranchCommitLike[];
|
|
109
|
+
files: readonly string[] | null | undefined;
|
|
110
|
+
author: string;
|
|
111
|
+
}): {
|
|
112
|
+
who: string;
|
|
113
|
+
claude: boolean;
|
|
114
|
+
withClaude?: boolean;
|
|
115
|
+
text: string;
|
|
116
|
+
at: string;
|
|
117
|
+
} | null;
|
|
118
|
+
/** "just now", "5 min ago", "2 h ago", "Yesterday", "3 days ago", then the date ("Oct 12"). */
|
|
119
|
+
export declare function shortAgo(iso: string, now?: Date): string;
|
|
120
|
+
/** "today", "yesterday", "3 days ago", "Oct 12": when it was started, after "Started by Ann · Admin demo ·". */
|
|
121
|
+
export declare function startedWhen(iso: string, now?: Date): string;
|
|
122
|
+
/** The actor in words: "Claude", "Florian", or "Florian with Claude" when Claude co-wrote a person's change. */
|
|
123
|
+
export declare function actorName(e: Pick<ActivityEvent, 'who' | 'claude' | 'withClaude'>, names?: Record<string, string>): string;
|
|
124
|
+
/**
|
|
125
|
+
* Where it stands, in one or two plain sentences, for Claude to say first when the designer continues it. No
|
|
126
|
+
* technical words: no branch, commit or pull request.
|
|
127
|
+
*/
|
|
128
|
+
export declare function whereItStands(input: {
|
|
129
|
+
name: string;
|
|
130
|
+
stage: 'not-started' | 'exploring' | 'handed';
|
|
131
|
+
statusLabel?: string;
|
|
132
|
+
events: readonly ActivityEvent[];
|
|
133
|
+
files: readonly string[] | null | undefined;
|
|
134
|
+
names?: Record<string, string>;
|
|
135
|
+
now?: Date;
|
|
136
|
+
}): string;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { BridgeConfig } from './config';
|
|
2
|
-
import { type Exploration, type ExplorationSource, type ExplorationStatus, type ExplorationTryIt, type PromotionPlan } from './explorations';
|
|
2
|
+
import { type Exploration, type ExplorationSource, type ExplorationStatus, type ExplorationPrContext, type ExplorationTryIt, type PromotionPlan } from './explorations';
|
|
3
3
|
import { type GitHubClient, type PullRequestSummary } from './github-client';
|
|
4
4
|
import { type BranchPreview, type PreviewApps } from './previews';
|
|
5
|
+
import { type ProductConfig } from './products';
|
|
5
6
|
export interface ExplorationSettings {
|
|
6
7
|
/** Branch explorations start from and pull requests target (the default branch). */
|
|
7
8
|
base: string;
|
|
@@ -16,7 +17,11 @@ export interface ExplorationSettings {
|
|
|
16
17
|
}[] | undefined;
|
|
17
18
|
/** More labels for the draft pull request, such as the product ones (productMarks). */
|
|
18
19
|
labels?: string[] | undefined;
|
|
20
|
+
/** Started in a product's own repository (productRepoOf): what its draft pull request body says instead of the library's. */
|
|
21
|
+
inProduct?: ExplorationPrContext['inProduct'];
|
|
19
22
|
}
|
|
23
|
+
/** The first commit message of an exploration branch: the purpose only when one was given. */
|
|
24
|
+
export declare const explorationStartMessage: (e: Pick<Exploration, "name" | "purpose">) => string;
|
|
20
25
|
export interface ExplorationSummary {
|
|
21
26
|
number: number;
|
|
22
27
|
url: string;
|
|
@@ -26,6 +31,8 @@ export interface ExplorationSummary {
|
|
|
26
31
|
purpose: string;
|
|
27
32
|
useCase?: string | undefined;
|
|
28
33
|
status: ExplorationStatus;
|
|
34
|
+
/** Archived (the `archived` label): hidden from the default lists, its pull request and preview still open. */
|
|
35
|
+
archived: boolean;
|
|
29
36
|
draft: boolean;
|
|
30
37
|
author: string;
|
|
31
38
|
/** Where it was started and the AI agent that started it, when the exploration block says so. */
|
|
@@ -43,13 +50,49 @@ export interface ExplorationSummary {
|
|
|
43
50
|
label: string;
|
|
44
51
|
url: string;
|
|
45
52
|
}[];
|
|
53
|
+
/**
|
|
54
|
+
* Set when the exploration lives in a product's own repository (productRepoOf): that repository ("owner/name") and
|
|
55
|
+
* the product key. Tools name it "<product>#<number>" (explorationRefLabel); absent in the design system repository.
|
|
56
|
+
*/
|
|
57
|
+
repo?: string | undefined;
|
|
58
|
+
product?: string | undefined;
|
|
46
59
|
}
|
|
47
60
|
/** One exploration from a pull request summary. */
|
|
48
61
|
export declare function explorationSummary(p: PullRequestSummary, _owner: string, _repo: string, s: Pick<ExplorationSettings, 'packages' | 'apps'>): ExplorationSummary;
|
|
49
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Explorations of the repo, newest activity first. `state: 'open'` lists the running ones and the open ones handed to
|
|
64
|
+
* developers. Archived ones are left out unless `archived` is 'include' (all) or 'only' (the Archived filter).
|
|
65
|
+
*/
|
|
50
66
|
export declare function listExplorationsOnGitHub(gh: GitHubClient, s: Pick<ExplorationSettings, 'packages' | 'apps'>, opts?: {
|
|
51
67
|
state?: 'open' | 'closed' | 'all';
|
|
68
|
+
archived?: 'exclude' | 'include' | 'only';
|
|
52
69
|
}): Promise<ExplorationSummary[]>;
|
|
70
|
+
/** A product repository Bridge could not read while listing: left out of the lists, said only where connections live. */
|
|
71
|
+
export interface UnreachableProductRepo {
|
|
72
|
+
product: string;
|
|
73
|
+
name: string;
|
|
74
|
+
repo: string;
|
|
75
|
+
/** not-connected: GitHub hides it (Bridge not installed there, or the token does not reach it); unavailable: any other failure. */
|
|
76
|
+
reason: 'not-connected' | 'unavailable';
|
|
77
|
+
}
|
|
78
|
+
/** GitHub hides the repository from this token, or Bridge's proxy says its app is not there. */
|
|
79
|
+
export declare const isHiddenRepoError: (err: unknown) => boolean;
|
|
80
|
+
/**
|
|
81
|
+
* The explorations of every product that has its own repository (bridge.config.json products[].repo): one read of
|
|
82
|
+
* the open (or `state`) pull requests per repository, all in parallel. Each one carries its `repo` and `product`, and
|
|
83
|
+
* the product's preview template as its preview. A repository Bridge cannot read is skipped and reported in
|
|
84
|
+
* `unreachable`, never thrown: designers never see it in a list, Settings says it. `clientFor` gives a client for
|
|
85
|
+
* "owner/name" with the same token (or proxy) as the design system repository.
|
|
86
|
+
*/
|
|
87
|
+
export declare function listProductExplorationsOnGitHub(clientFor: (repo: string) => GitHubClient, products: readonly ProductConfig[], designSystemRepo: string | null | undefined, opts?: {
|
|
88
|
+
state?: 'open' | 'closed' | 'all';
|
|
89
|
+
archived?: 'exclude' | 'include' | 'only';
|
|
90
|
+
}): Promise<{
|
|
91
|
+
explorations: ExplorationSummary[];
|
|
92
|
+
unreachable: UnreachableProductRepo[];
|
|
93
|
+
}>;
|
|
94
|
+
/** An exploration read in a product's own repository: its repository, its product and the product's preview. */
|
|
95
|
+
export declare function inProductRepo(x: ExplorationSummary, product: ProductConfig, repo: string): ExplorationSummary;
|
|
53
96
|
export interface StartedExploration {
|
|
54
97
|
branch: string;
|
|
55
98
|
slug: string;
|
|
@@ -70,6 +113,20 @@ export interface StartedExploration {
|
|
|
70
113
|
* install command. Refuses an exploration whose branch already exists.
|
|
71
114
|
*/
|
|
72
115
|
export declare function startExplorationOnGitHub(gh: GitHubClient, e: Exploration, s: ExplorationSettings): Promise<StartedExploration>;
|
|
116
|
+
/** Whether Bridge can open an exploration in a product's own repository with this token, and from which branch. */
|
|
117
|
+
export type ProductRepoAccess = {
|
|
118
|
+
ok: true;
|
|
119
|
+
base: string;
|
|
120
|
+
} | {
|
|
121
|
+
ok: false;
|
|
122
|
+
reason: 'not-connected' | 'read-only';
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* One read of a product's own repository before an exploration starts there: its default branch when the token may
|
|
126
|
+
* push to it; `not-connected` when GitHub hides it (Bridge is not installed on it, or the token does not reach it);
|
|
127
|
+
* `read-only` when the person may only read it. A rejected token or a GitHub outage still throws.
|
|
128
|
+
*/
|
|
129
|
+
export declare function productRepoAccess(gh: GitHubClient): Promise<ProductRepoAccess>;
|
|
73
130
|
/**
|
|
74
131
|
* Where the test build of an exploration stands: the install command from its sticky preview comment when it matches
|
|
75
132
|
* the branch head, "building" while the workflow has not caught up, "failed" when the publish failed. Two reads.
|
|
@@ -116,7 +173,22 @@ export declare function promoteExplorationOnGitHub(gh: GitHubClient, ref: string
|
|
|
116
173
|
date?: Date | undefined;
|
|
117
174
|
dryRun?: boolean | undefined;
|
|
118
175
|
}): Promise<PromotedExploration>;
|
|
119
|
-
/**
|
|
176
|
+
/**
|
|
177
|
+
* Archives an exploration (the `archived` label), or brings it back with `archived: false`. The pull request stays
|
|
178
|
+
* open, so its preview link keeps working: archiving only hides it from the default lists.
|
|
179
|
+
*/
|
|
180
|
+
export declare function archiveExplorationOnGitHub(gh: GitHubClient, ref: string | number, opts?: {
|
|
181
|
+
archived?: boolean;
|
|
182
|
+
}): Promise<{
|
|
183
|
+
number: number;
|
|
184
|
+
url: string;
|
|
185
|
+
branch: string;
|
|
186
|
+
archived: boolean;
|
|
187
|
+
}>;
|
|
188
|
+
/**
|
|
189
|
+
* Closes an exploration without merging. The branch stays for reference, but the workflows remove its preview
|
|
190
|
+
* prerelease and visual images: archiving (archiveExplorationOnGitHub) keeps the link alive instead.
|
|
191
|
+
*/
|
|
120
192
|
export declare function closeExplorationOnGitHub(gh: GitHubClient, ref: string | number): Promise<{
|
|
121
193
|
number: number;
|
|
122
194
|
url: string;
|
package/dist/explorations.d.ts
CHANGED
|
@@ -11,8 +11,17 @@ export declare const EXPLORATION_NOTES_DIR = ".bridge/explorations";
|
|
|
11
11
|
export declare const EXPLORATION_TIER_LABEL = "Exploration (not mergeable)";
|
|
12
12
|
/** Name of the CI job that fails while the label is on. */
|
|
13
13
|
export declare const EXPLORATION_CHECK = "Exploration not merged as is";
|
|
14
|
+
/** Done exploring: the exploration label gives way to this one. Developers take the branch from there. */
|
|
15
|
+
export declare const EXPLORATION_READY_LABEL = "ready-for-devs";
|
|
16
|
+
/** An archived exploration: hidden from the default lists, its pull request and preview still open. */
|
|
17
|
+
export declare const EXPLORATION_ARCHIVED_LABEL = "archived";
|
|
14
18
|
export type ExplorationUseCase = 'user-test' | 'stakeholder-demo' | 'ab-idea' | 'terminal' | 'other';
|
|
15
|
-
|
|
19
|
+
/**
|
|
20
|
+
* active: running (the exploration label is on). ready: done exploring, waiting for developers to take it. building:
|
|
21
|
+
* developers pushed to it (or marked it ready for review) since. shipped: merged after done exploring. promoted: sent
|
|
22
|
+
* to review the older way (label removed without done exploring), open or merged. closed: closed without merging.
|
|
23
|
+
*/
|
|
24
|
+
export type ExplorationStatus = 'active' | 'ready' | 'building' | 'shipped' | 'promoted' | 'closed';
|
|
16
25
|
/** Where an exploration was started: Bridge Studio, the Figma plugin, the CLI or the MCP server (an AI agent). */
|
|
17
26
|
export type ExplorationSource = 'studio' | 'figma' | 'cli' | 'mcp';
|
|
18
27
|
export declare const EXPLORATION_USE_CASES: {
|
|
@@ -24,7 +33,10 @@ export declare const EXPLORATION_STATUS_LABEL: Record<ExplorationStatus, string>
|
|
|
24
33
|
export interface Exploration {
|
|
25
34
|
/** Display name, sentence case: "Denser data tables". */
|
|
26
35
|
name: string;
|
|
27
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* What the team wants to learn, in one or two sentences, or empty: designers explore freely and nobody is asked
|
|
38
|
+
* for a brief (Claude passes the designer's first sentence when it has one).
|
|
39
|
+
*/
|
|
28
40
|
purpose: string;
|
|
29
41
|
/** Branch slug: `explore/<slug>`. Derived from the name when missing. */
|
|
30
42
|
slug?: string | undefined;
|
|
@@ -41,8 +53,14 @@ export interface Exploration {
|
|
|
41
53
|
agent?: string | undefined;
|
|
42
54
|
/** A Jira ticket key ("DS-42"), first in the pull request title so Jira's GitHub integration links it. */
|
|
43
55
|
jira?: string | undefined;
|
|
56
|
+
/** ISO date someone said "Done exploring". */
|
|
57
|
+
doneAt?: string | undefined;
|
|
58
|
+
/** The branch head at that moment: a newer head means developers are building on it. */
|
|
59
|
+
doneSha?: string | undefined;
|
|
44
60
|
}
|
|
45
|
-
/**
|
|
61
|
+
/** Longest slug: a name is under 60 characters (explorationProblems), so a valid name is never cut mid-phrase. */
|
|
62
|
+
export declare const EXPLORATION_SLUG_MAX = 60;
|
|
63
|
+
/** "Denser data tables!" -> "denser-data-tables". Up to 60 characters, cut at a word boundary. Empty when nothing is left. */
|
|
46
64
|
export declare function explorationSlug(name: string): string;
|
|
47
65
|
/** `explore/<slug>` for a name, a slug or a branch name. */
|
|
48
66
|
export declare function explorationBranch(nameOrBranch: string): string;
|
|
@@ -50,10 +68,35 @@ export declare function explorationBranch(nameOrBranch: string): string;
|
|
|
50
68
|
export declare function isExplorationBranch(ref: string | null | undefined): boolean;
|
|
51
69
|
/** The slug of an exploration branch, or null. */
|
|
52
70
|
export declare function explorationSlugFromBranch(ref: string): string | null;
|
|
71
|
+
/**
|
|
72
|
+
* Which exploration a person or a tool means, wherever it lives. In the design system repository: its number ("12",
|
|
73
|
+
* "#12") or its name ("pill-buttons", "explore/pill-buttons"). In a product's own repository, the product key or the
|
|
74
|
+
* repository goes first: "shop#12", "peterbono/bridge-demo-shop#12", "shop:checkout-flow", or the pull request link.
|
|
75
|
+
*/
|
|
76
|
+
export interface ExplorationRef {
|
|
77
|
+
/** A product key ("shop"), when the reference names one. */
|
|
78
|
+
product?: string | undefined;
|
|
79
|
+
/** "owner/name", when the reference names the repository (a link or owner/name#12). */
|
|
80
|
+
repo?: string | undefined;
|
|
81
|
+
/** The pull request number, or the exploration's name or branch. */
|
|
82
|
+
ref: number | string;
|
|
83
|
+
}
|
|
84
|
+
/** Reads an exploration reference (ExplorationRef). Anything else is taken as a name in the design system repository. */
|
|
85
|
+
export declare function parseExplorationRef(input: string | number): ExplorationRef;
|
|
86
|
+
/** How tools name an exploration back: "#12" in the design system repository, "shop#12" in a product's own one. */
|
|
87
|
+
export declare const explorationRefLabel: (x: {
|
|
88
|
+
number: number;
|
|
89
|
+
product?: string | null | undefined;
|
|
90
|
+
repo?: string | null | undefined;
|
|
91
|
+
}) => string;
|
|
53
92
|
/** Path of the note that starts an exploration branch. */
|
|
54
93
|
export declare const explorationNotePath: (slug: string) => string;
|
|
55
|
-
/**
|
|
56
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Problems with a new exploration, as sentences that say how to fix them. Empty when it can start. Only the name is
|
|
96
|
+
* needed: the purpose is optional, nobody has to write a brief to explore.
|
|
97
|
+
*/
|
|
98
|
+
export declare function explorationProblems(e: Pick<Exploration, 'name'> & {
|
|
99
|
+
purpose?: string | undefined;
|
|
57
100
|
slug?: string | undefined;
|
|
58
101
|
}): string[];
|
|
59
102
|
/** The note committed as the first commit of the branch (`.bridge/explorations/<slug>.md`). */
|
|
@@ -70,12 +113,26 @@ export interface ExplorationPrContext {
|
|
|
70
113
|
number: number;
|
|
71
114
|
title: string;
|
|
72
115
|
}[] | undefined;
|
|
116
|
+
/**
|
|
117
|
+
* Set when the exploration lives in a product's own repository (productRepoOf): the body says to check the branch
|
|
118
|
+
* out there and to get the library from npm (`library`: the design system repository), with the product's preview
|
|
119
|
+
* template instead of the library's apps.
|
|
120
|
+
*/
|
|
121
|
+
inProduct?: {
|
|
122
|
+
name: string;
|
|
123
|
+
library: string;
|
|
124
|
+
preview?: string | undefined;
|
|
125
|
+
} | undefined;
|
|
73
126
|
}
|
|
74
|
-
/**
|
|
127
|
+
/**
|
|
128
|
+
* Draft pull request title: "Exploration: Denser data tables". The name keeps its casing as typed; a name that already
|
|
129
|
+
* starts with "Exploration:" is not prefixed twice, and a colon inside the name becomes a comma so the title has one
|
|
130
|
+
* ("Exploration page: pick up" -> "Exploration: Exploration page, pick up").
|
|
131
|
+
*/
|
|
75
132
|
export declare function explorationPrTitle(e: Pick<Exploration, 'name'>): string;
|
|
76
133
|
/**
|
|
77
134
|
* The draft pull request body: purpose, what is experimental, how a product staging branch installs it, the
|
|
78
|
-
* previews, and how
|
|
135
|
+
* previews, and how it ends (Done exploring, Archive). Markdown for people plus one hidden JSON block for tools.
|
|
79
136
|
*/
|
|
80
137
|
export declare function explorationPrBody(e: Exploration, ctx: ExplorationPrContext): string;
|
|
81
138
|
/** The exploration inside a pull request body, or undefined when it has no valid Bridge block. */
|
|
@@ -89,16 +146,88 @@ export interface ExplorationPullLike {
|
|
|
89
146
|
})[];
|
|
90
147
|
headRef?: string | undefined;
|
|
91
148
|
body?: string | null | undefined;
|
|
149
|
+
/** Head commit and draft flag: after "Done exploring", a newer head or a ready pull request reads "Being built". */
|
|
150
|
+
headSha?: string | undefined;
|
|
151
|
+
draft?: boolean | undefined;
|
|
92
152
|
}
|
|
93
153
|
/** True for a pull request that is or was an exploration: an `explore/*` branch, the label, or the Bridge block. */
|
|
94
154
|
export declare function isExplorationPull(p: ExplorationPullLike): boolean;
|
|
155
|
+
/** "Done exploring" was said: the `ready-for-devs` label, or the date in the exploration block. */
|
|
156
|
+
export declare function isHandedOff(p: Pick<ExplorationPullLike, 'labels' | 'body'>): boolean;
|
|
95
157
|
/**
|
|
96
158
|
* Where an exploration stands: closed without merging = closed; open with the `exploration` label = active
|
|
97
|
-
* (running)
|
|
159
|
+
* (running). After "Done exploring": merged = shipped; marked ready for review, or a head newer than the one done
|
|
160
|
+
* exploring left = building (developers work on it); otherwise ready (waiting for code). The label removed without
|
|
161
|
+
* done exploring is the older promotion: promoted, open or merged.
|
|
98
162
|
*/
|
|
99
163
|
export declare function explorationStatus(p: ExplorationPullLike): ExplorationStatus;
|
|
100
164
|
/** True while the label is on: the pull request must not merge (the CI check fails, Studio blocks the merge). */
|
|
101
165
|
export declare const isActiveExploration: (labels: ExplorationPullLike["labels"]) => boolean;
|
|
166
|
+
/** True for an archived exploration: hidden from the default lists, reachable from the Archived filter. */
|
|
167
|
+
export declare const isArchivedExploration: (labels: readonly (string | {
|
|
168
|
+
name?: string;
|
|
169
|
+
})[] | null | undefined) => boolean;
|
|
170
|
+
/**
|
|
171
|
+
* Open explorations that stay out of the review queue: running, archived, or handed to developers while still a
|
|
172
|
+
* draft. Once developers mark it ready for review it is a change like any other.
|
|
173
|
+
*/
|
|
174
|
+
export declare function isHeldExploration(p: {
|
|
175
|
+
state?: string | undefined;
|
|
176
|
+
draft?: boolean | undefined;
|
|
177
|
+
labels?: readonly (string | {
|
|
178
|
+
name?: string;
|
|
179
|
+
})[] | null | undefined;
|
|
180
|
+
}): boolean;
|
|
181
|
+
/** How a developer takes an exploration: fetch, then check out its branch. */
|
|
182
|
+
export declare const explorationTakeCommands: (branch: string) => [string, string];
|
|
183
|
+
/** What developers read next to those commands, when nothing is known about the branch checks: a starting point. */
|
|
184
|
+
export declare const EXPLORATION_STARTING_POINT = "A starting point, not ready to ship: nobody has reviewed Claude's prototype code yet. Continue on this branch: its pull request already exists, so Bridge follows your pushes, and the merge reads as shipped.";
|
|
185
|
+
/** The branch checks at its head, folded into one state (GitHubClient.getChecks). */
|
|
186
|
+
export type ExplorationChecks = 'success' | 'failure' | 'pending' | 'none';
|
|
187
|
+
/**
|
|
188
|
+
* The starting point note, true to the branch checks: passing checks are said as such (the code is still not
|
|
189
|
+
* reviewed), failing or missing checks too. Without a state it is EXPLORATION_STARTING_POINT.
|
|
190
|
+
*/
|
|
191
|
+
export declare function explorationStartingPoint(checks?: ExplorationChecks | null | undefined): string;
|
|
192
|
+
export interface DoneExploringPlan {
|
|
193
|
+
/** Labels to remove (the exploration label) and to add (ready-for-devs). */
|
|
194
|
+
removeLabels: string[];
|
|
195
|
+
addLabels: string[];
|
|
196
|
+
/** Files to delete on the branch first: the exploration note, so main never gets it. */
|
|
197
|
+
removeFiles: string[];
|
|
198
|
+
/** The body once done: the developer section in place of the sandbox note and the "When it is done" part. */
|
|
199
|
+
body: string;
|
|
200
|
+
/** The two commands a developer runs to take it. */
|
|
201
|
+
take: [string, string];
|
|
202
|
+
/** Done exploring never merges, closes or marks the draft ready. */
|
|
203
|
+
markReady: false;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* What "Done exploring" does to the pull request: the exploration label gives way to `ready-for-devs` (the merge
|
|
207
|
+
* guard stops failing, so developers can ship it once the code is theirs), the exploration note leaves the branch, and
|
|
208
|
+
* the body says how developers take it. The draft stays a draft and the pull request stays open, so its preview lives
|
|
209
|
+
* on. The caller records the head once the note is gone (withDoneExploring with `doneSha`).
|
|
210
|
+
*/
|
|
211
|
+
export declare function doneExploringPlan(input: {
|
|
212
|
+
body: string | null | undefined;
|
|
213
|
+
branch: string;
|
|
214
|
+
files: {
|
|
215
|
+
path: string;
|
|
216
|
+
status?: string | undefined;
|
|
217
|
+
}[];
|
|
218
|
+
date?: Date | undefined;
|
|
219
|
+
}): DoneExploringPlan;
|
|
220
|
+
/**
|
|
221
|
+
* The body after "Done exploring": the sandbox warning and the "When it is done" part give way to the developer
|
|
222
|
+
* section (the two commands and the starting point note), and the hidden block records when, and on which head once
|
|
223
|
+
* known. Calling it again replaces the section and the block.
|
|
224
|
+
*/
|
|
225
|
+
export declare function withDoneExploring(body: string | null | undefined, done: {
|
|
226
|
+
branch: string;
|
|
227
|
+
doneAt: string;
|
|
228
|
+
doneSha?: string | undefined;
|
|
229
|
+
checks?: ExplorationChecks | null | undefined;
|
|
230
|
+
}): string;
|
|
102
231
|
export interface PromotionPlan {
|
|
103
232
|
tier: RiskTier;
|
|
104
233
|
reasons: string[];
|
package/dist/figma-fix-loop.d.ts
CHANGED
|
@@ -68,7 +68,7 @@ export interface GapCaseFor {
|
|
|
68
68
|
}
|
|
69
69
|
/** The gap case of one component, built the way the plugin pulls it: fixes applied, set rebuilt, the run's verdicts. */
|
|
70
70
|
export declare function gapCaseFor(input: GapCaseForInput): GapCaseFor;
|
|
71
|
-
export declare const FIX_SCHEMA_SUMMARY = "figma-fixes.json fixes (version 1). Each fix is one JSON object:\n- Every fix: \"id\" (lower case, digits, dashes, unique), \"kind\", \"component\" (the Figma set, e.g. \"TextInput\"), \"reason\" (one plain sentence, no em dash), optional \"by\": \"claude\", optional \"where\": { \"args\": { \"<arg>\": value }, \"state\": \"rest\" | \"hover\" | \"active\" | \"focus-visible\" | \"disabled\" } (absent: every variant).\n- kind \"part\": \"part\" is a part id from the gap case (\"root\", \"cds--text-input-label-wrapper\") or \".class\". At least one of: \"set\" { field: token path | px number | null (colors only) | \"full\" (cornerRadius only) }, \"width\" / \"height\": \"fixed\" (
|
|
71
|
+
export declare const FIX_SCHEMA_SUMMARY = "figma-fixes.json fixes (version 1). Each fix is one JSON object:\n- Every fix: \"id\" (lower case, digits, dashes, unique), \"kind\", \"component\" (the Figma set, e.g. \"TextInput\"), \"reason\" (one plain sentence, no em dash), optional \"by\": \"claude\", optional \"where\": { \"args\": { \"<arg>\": value }, \"state\": \"rest\" | \"hover\" | \"active\" | \"focus-visible\" | \"disabled\" } (absent: every variant).\n- kind \"part\": \"part\" is a part id from the gap case (\"root\", \"cds--text-input-label-wrapper\") or \".class\". At least one of: \"set\" { field: token path | px number | null (colors only) | \"full\" (cornerRadius only) }, \"width\" / \"height\": \"fixed\" (each story's own measured size; a width that only hugs text in code is skipped, since it is the story's words) | px number | \"hug\" | \"fill\", \"direction\": \"HORIZONTAL\" | \"VERTICAL\", \"align\": { \"primary\": MIN|CENTER|MAX|SPACE_BETWEEN, \"counter\": MIN|CENTER|MAX|STRETCH }, \"overlay\": true | false | { \"top\": 3, \"left\": 3 }, \"hide\": true (alone; never the root). Fields: fill, stroke, strokeWeight, strokeTopWeight, strokeRightWeight, strokeBottomWeight, strokeLeftWeight, cornerRadius, paddingTop, paddingRight, paddingBottom, paddingLeft, itemSpacing, counterAxisSpacing, width, height, minWidth, minHeight, opacity, textFill, fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, textDecoration.\n- kind \"axis\": \"action\" \"map\" (\"arg\", \"property\" and/or \"values\" { code value: Figma value }), \"ignore\" (\"arg\"), or \"prune\" (\"where\" names the variants to drop).\n- kind \"story\": \"where\" names the variant, \"use\": { \"story\": \"<story id>\", \"args\"?, \"state\"? } is the measured render to draw it from.\n- kind \"status\": \"status\": \"differs\" | \"cant-check\" with the reason; never \"matches\" (only the shots say a component matches). Without \"status\": a note.\nRules: fix only the component you were given; prefer the smallest fix that explains the differences (a part's size \"fixed\" when Figma hugs what code fixes, a missing padding, a hidden part); never invent a part id or a token: use the ones in the gap case.";
|
|
72
72
|
export type FixDiffResult = 'resolved' | 'closer' | 'same' | 'worse' | 'unknown';
|
|
73
73
|
export type FixVerdict = 'closer' | 'same' | 'worse';
|
|
74
74
|
export interface TriedDifference {
|
package/dist/figma-fixes.d.ts
CHANGED
|
@@ -134,8 +134,12 @@ export interface AppliedFix {
|
|
|
134
134
|
id: string;
|
|
135
135
|
kind: FigmaFix['kind'];
|
|
136
136
|
component: string;
|
|
137
|
-
/**
|
|
138
|
-
|
|
137
|
+
/**
|
|
138
|
+
* applied: it changed what the pull draws. not-found: nothing matched (the code or the measure moved: re-check it).
|
|
139
|
+
* skipped: it matched, but the measure has no size of the part's own to pin there (the detail says why). already:
|
|
140
|
+
* the input had it.
|
|
141
|
+
*/
|
|
142
|
+
result: 'applied' | 'not-found' | 'skipped' | 'already';
|
|
139
143
|
/** Story entries it changed. */
|
|
140
144
|
stories: number;
|
|
141
145
|
/** Plain words: what it did, or what it did not find. */
|
|
@@ -152,6 +156,14 @@ export type FixedMeasuredSpecsFile = Omit<MeasuredSpecsFile, 'stories' | 'compon
|
|
|
152
156
|
};
|
|
153
157
|
/** A story is one of `where`'s variants: every arg it names, at that value, and the state. */
|
|
154
158
|
export declare function storyMatchesWhere(s: MeasuredSpecsStory, where: FixWhere | undefined): boolean;
|
|
159
|
+
/** Why a `fixed` size was not laid on one part of one story: the measure has no size of the part's own there. */
|
|
160
|
+
export interface SkippedSize {
|
|
161
|
+
part: string;
|
|
162
|
+
side: 'width' | 'height';
|
|
163
|
+
why: 'words' | 'fills' | 'unmeasured';
|
|
164
|
+
/** The measured px it did not pin (words, fills). */
|
|
165
|
+
measured?: number | undefined;
|
|
166
|
+
}
|
|
155
167
|
/**
|
|
156
168
|
* The measured specs the pull reads, with the fixes laid on, and one provenance record per fix. Pure: the input is not
|
|
157
169
|
* changed. Fixes run in file order; a fix whose component, part or story is not in this measure is reported
|
package/dist/github-client.d.ts
CHANGED
|
@@ -638,6 +638,23 @@ export declare class GitHubClient {
|
|
|
638
638
|
autoMerge: boolean;
|
|
639
639
|
}>;
|
|
640
640
|
listPullRequestFiles(n: number): Promise<PullRequestFile[]>;
|
|
641
|
+
/** The commits of a pull request, oldest first, as GitHub lists them (one read, up to 100). */
|
|
642
|
+
listPullRequestCommits(n: number): Promise<{
|
|
643
|
+
sha: string;
|
|
644
|
+
commit: {
|
|
645
|
+
message: string;
|
|
646
|
+
author?: {
|
|
647
|
+
name?: string | null;
|
|
648
|
+
date?: string | null;
|
|
649
|
+
} | null;
|
|
650
|
+
committer?: {
|
|
651
|
+
date?: string | null;
|
|
652
|
+
} | null;
|
|
653
|
+
};
|
|
654
|
+
author?: {
|
|
655
|
+
login?: string | null;
|
|
656
|
+
} | null;
|
|
657
|
+
}[]>;
|
|
641
658
|
updatePullRequest(n: number, patch: {
|
|
642
659
|
title?: string;
|
|
643
660
|
body?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -41,6 +41,8 @@ export * from './change-drafts';
|
|
|
41
41
|
export * from './draft-exchange';
|
|
42
42
|
export * from './explorations';
|
|
43
43
|
export * from './explorations-github';
|
|
44
|
+
export * from './exploration-done-github';
|
|
45
|
+
export * from './exploration-resume';
|
|
44
46
|
export * from './requests-github';
|
|
45
47
|
export * from './component-spec';
|
|
46
48
|
export * from './measured-spec';
|