forge-cc 0.1.41 → 1.0.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/README.md +454 -338
- package/dist/cli.js +194 -935
- package/dist/cli.js.map +1 -1
- package/dist/config/loader.d.ts +1 -1
- package/dist/config/loader.js +49 -56
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +37 -125
- package/dist/config/schema.js +13 -28
- package/dist/config/schema.js.map +1 -1
- package/dist/doctor.d.ts +10 -0
- package/dist/doctor.js +148 -0
- package/dist/doctor.js.map +1 -0
- package/dist/gates/index.d.ts +14 -12
- package/dist/gates/index.js +53 -105
- package/dist/gates/index.js.map +1 -1
- package/dist/gates/lint-gate.d.ts +2 -2
- package/dist/gates/lint-gate.js +60 -66
- package/dist/gates/lint-gate.js.map +1 -1
- package/dist/gates/tests-gate.d.ts +2 -4
- package/dist/gates/tests-gate.js +75 -203
- package/dist/gates/tests-gate.js.map +1 -1
- package/dist/gates/types-gate.d.ts +2 -2
- package/dist/gates/types-gate.js +53 -59
- package/dist/gates/types-gate.js.map +1 -1
- package/dist/linear/client.d.ts +31 -108
- package/dist/linear/client.js +88 -388
- package/dist/linear/client.js.map +1 -1
- package/dist/linear/sync.d.ts +15 -0
- package/dist/linear/sync.js +102 -0
- package/dist/linear/sync.js.map +1 -0
- package/dist/runner/loop.d.ts +4 -0
- package/dist/runner/loop.js +168 -0
- package/dist/runner/loop.js.map +1 -0
- package/dist/runner/prompt.d.ts +14 -0
- package/dist/runner/prompt.js +59 -0
- package/dist/runner/prompt.js.map +1 -0
- package/dist/runner/update.d.ts +1 -0
- package/dist/runner/update.js +72 -0
- package/dist/runner/update.js.map +1 -0
- package/dist/server.d.ts +6 -2
- package/dist/server.js +43 -101
- package/dist/server.js.map +1 -1
- package/dist/setup.d.ts +5 -0
- package/dist/setup.js +208 -0
- package/dist/setup.js.map +1 -0
- package/dist/state/cache.d.ts +3 -0
- package/dist/state/cache.js +23 -0
- package/dist/state/cache.js.map +1 -0
- package/dist/state/status.d.ts +66 -0
- package/dist/state/status.js +96 -0
- package/dist/state/status.js.map +1 -0
- package/dist/types.d.ts +46 -114
- package/dist/worktree/manager.d.ts +6 -103
- package/dist/worktree/manager.js +25 -296
- package/dist/worktree/manager.js.map +1 -1
- package/hooks/pre-commit-verify.js +109 -109
- package/package.json +3 -2
- package/skills/forge-go.md +20 -13
- package/skills/forge-setup.md +149 -388
- package/skills/forge-spec.md +367 -342
- package/skills/forge-triage.md +179 -133
- package/skills/forge-update.md +87 -93
package/dist/linear/client.js
CHANGED
|
@@ -1,408 +1,108 @@
|
|
|
1
|
+
import { LinearClient } from "@linear/sdk";
|
|
1
2
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* and the execution engine for programmatic Linear management.
|
|
3
|
+
* Thin wrapper around @linear/sdk's LinearClient, scoped to a team.
|
|
4
|
+
* All public methods degrade gracefully on API errors (warn, don't crash).
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
constructor(apiKey) {
|
|
29
|
-
const key = apiKey ?? process.env.LINEAR_API_KEY;
|
|
30
|
-
if (!key) {
|
|
31
|
-
throw new LinearClientError("Linear API key not found. Set the LINEAR_API_KEY environment variable or pass it to the constructor.");
|
|
32
|
-
}
|
|
33
|
-
this.apiKey = key;
|
|
34
|
-
}
|
|
35
|
-
// -------------------------------------------------------------------------
|
|
36
|
-
// Projects
|
|
37
|
-
// -------------------------------------------------------------------------
|
|
38
|
-
async listProjects(opts) {
|
|
39
|
-
const filter = {};
|
|
40
|
-
if (opts?.query) {
|
|
41
|
-
filter.name = { containsIgnoreCase: opts.query };
|
|
42
|
-
}
|
|
43
|
-
if (opts?.state) {
|
|
44
|
-
filter.state = { eq: opts.state };
|
|
45
|
-
}
|
|
46
|
-
const hasFilter = Object.keys(filter).length > 0;
|
|
47
|
-
const filterVar = hasFilter ? ", $filter: ProjectFilter" : "";
|
|
48
|
-
const filterArg = hasFilter ? ", filter: $filter" : "";
|
|
49
|
-
const query = `
|
|
50
|
-
query ListProjects($after: String${filterVar}) {
|
|
51
|
-
projects(first: 50, after: $after${filterArg}) {
|
|
52
|
-
pageInfo { hasNextPage endCursor }
|
|
53
|
-
nodes {
|
|
54
|
-
id name description state url
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
`;
|
|
59
|
-
return this.paginate(query, "projects", {
|
|
60
|
-
...(hasFilter ? { filter } : {}),
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
async createProject(input) {
|
|
64
|
-
const mutation = `
|
|
65
|
-
mutation CreateProject($input: ProjectCreateInput!) {
|
|
66
|
-
projectCreate(input: $input) {
|
|
67
|
-
success
|
|
68
|
-
project { id name description state url }
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
`;
|
|
72
|
-
const variables = {
|
|
73
|
-
input: {
|
|
74
|
-
name: input.name,
|
|
75
|
-
...(input.description != null && { description: input.description }),
|
|
76
|
-
teamIds: input.teamIds,
|
|
77
|
-
...(input.state != null && { state: input.state }),
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
const data = await this.request(mutation, variables);
|
|
81
|
-
const result = data.projectCreate;
|
|
82
|
-
if (!result?.success) {
|
|
83
|
-
throw new LinearClientError("Failed to create project");
|
|
84
|
-
}
|
|
85
|
-
return result.project;
|
|
86
|
-
}
|
|
87
|
-
async updateProject(id, input) {
|
|
88
|
-
const mutation = `
|
|
89
|
-
mutation UpdateProject($id: String!, $input: ProjectUpdateInput!) {
|
|
90
|
-
projectUpdate(id: $id, input: $input) {
|
|
91
|
-
success
|
|
92
|
-
project { id name description state url }
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
`;
|
|
96
|
-
const data = await this.request(mutation, { id, input });
|
|
97
|
-
const result = data.projectUpdate;
|
|
98
|
-
if (!result?.success) {
|
|
99
|
-
throw new LinearClientError(`Failed to update project ${id}`);
|
|
100
|
-
}
|
|
101
|
-
return result.project;
|
|
102
|
-
}
|
|
103
|
-
// -------------------------------------------------------------------------
|
|
104
|
-
// Milestones (Project Milestones)
|
|
105
|
-
// -------------------------------------------------------------------------
|
|
106
|
-
async listMilestones(projectId) {
|
|
107
|
-
const query = `
|
|
108
|
-
query ListMilestones($projectId: String!, $after: String) {
|
|
109
|
-
project(id: $projectId) {
|
|
110
|
-
projectMilestones(first: 50, after: $after) {
|
|
111
|
-
pageInfo { hasNextPage endCursor }
|
|
112
|
-
nodes {
|
|
113
|
-
id name description progress sortOrder
|
|
6
|
+
export class ForgeLinearClient {
|
|
7
|
+
client;
|
|
8
|
+
teamId;
|
|
9
|
+
constructor(opts) {
|
|
10
|
+
if (!opts.apiKey) {
|
|
11
|
+
throw new Error("LINEAR_API_KEY is required. Set it as an environment variable or pass it to ForgeLinearClient.");
|
|
12
|
+
}
|
|
13
|
+
this.client = new LinearClient({ apiKey: opts.apiKey });
|
|
14
|
+
this.teamId = opts.teamId;
|
|
15
|
+
}
|
|
16
|
+
/** Resolve a workflow state UUID by its display name for a given team. */
|
|
17
|
+
async resolveStateId(teamId, stateName) {
|
|
18
|
+
try {
|
|
19
|
+
const states = await this.client.workflowStates({
|
|
20
|
+
filter: {
|
|
21
|
+
team: { id: { eq: teamId } },
|
|
22
|
+
name: { eq: stateName },
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
const node = states.nodes[0];
|
|
26
|
+
if (!node) {
|
|
27
|
+
throw new Error(`Workflow state "${stateName}" not found for team ${teamId}`);
|
|
114
28
|
}
|
|
115
|
-
|
|
29
|
+
return node.id;
|
|
116
30
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const all = [];
|
|
121
|
-
let after = null;
|
|
122
|
-
for (;;) {
|
|
123
|
-
const data = await this.request(query, { projectId, after });
|
|
124
|
-
const connection = data.project?.projectMilestones;
|
|
125
|
-
if (!connection)
|
|
126
|
-
break;
|
|
127
|
-
all.push(...connection.nodes);
|
|
128
|
-
if (connection.pageInfo.hasNextPage) {
|
|
129
|
-
after = connection.pageInfo.endCursor;
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (err instanceof Error && err.message.includes("not found")) {
|
|
33
|
+
throw err;
|
|
130
34
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return all;
|
|
136
|
-
}
|
|
137
|
-
async createMilestone(input) {
|
|
138
|
-
const mutation = `
|
|
139
|
-
mutation CreateMilestone($input: ProjectMilestoneCreateInput!) {
|
|
140
|
-
projectMilestoneCreate(input: $input) {
|
|
141
|
-
success
|
|
142
|
-
projectMilestone { id name description progress sortOrder }
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
`;
|
|
146
|
-
const variables = {
|
|
147
|
-
input: {
|
|
148
|
-
projectId: input.projectId,
|
|
149
|
-
name: input.name,
|
|
150
|
-
...(input.description != null && { description: input.description }),
|
|
151
|
-
...(input.targetDate != null && { targetDate: input.targetDate }),
|
|
152
|
-
},
|
|
153
|
-
};
|
|
154
|
-
const data = await this.request(mutation, variables);
|
|
155
|
-
const result = data.projectMilestoneCreate;
|
|
156
|
-
if (!result?.success) {
|
|
157
|
-
throw new LinearClientError("Failed to create milestone");
|
|
35
|
+
console.warn(`[forge] Failed to resolve state "${stateName}":`, err);
|
|
36
|
+
throw err;
|
|
158
37
|
}
|
|
159
|
-
return result.projectMilestone;
|
|
160
38
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
const filter = {};
|
|
166
|
-
if (opts?.projectId) {
|
|
167
|
-
filter.project = { id: { eq: opts.projectId } };
|
|
168
|
-
}
|
|
169
|
-
if (opts?.milestoneId) {
|
|
170
|
-
filter.projectMilestone = { id: { eq: opts.milestoneId } };
|
|
39
|
+
/** Update an issue's workflow state. */
|
|
40
|
+
async updateIssueState(issueId, stateId) {
|
|
41
|
+
try {
|
|
42
|
+
await this.client.updateIssue(issueId, { stateId });
|
|
171
43
|
}
|
|
172
|
-
|
|
173
|
-
|
|
44
|
+
catch (err) {
|
|
45
|
+
console.warn(`[forge] Failed to update issue ${issueId}:`, err);
|
|
174
46
|
}
|
|
175
|
-
const hasFilter = Object.keys(filter).length > 0;
|
|
176
|
-
const filterVar = hasFilter ? ", $filter: IssueFilter" : "";
|
|
177
|
-
const filterArg = hasFilter ? ", filter: $filter" : "";
|
|
178
|
-
const query = `
|
|
179
|
-
query ListIssues($after: String${filterVar}) {
|
|
180
|
-
issues(first: 50, after: $after${filterArg}) {
|
|
181
|
-
pageInfo { hasNextPage endCursor }
|
|
182
|
-
nodes {
|
|
183
|
-
id identifier title description url
|
|
184
|
-
state { name }
|
|
185
|
-
project { id }
|
|
186
|
-
projectMilestone { id }
|
|
187
|
-
team { id }
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
`;
|
|
192
|
-
const raw = await this.paginate(query, "issues", hasFilter ? { filter } : {});
|
|
193
|
-
return raw.map((node) => this.mapIssue(node));
|
|
194
47
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
success
|
|
200
|
-
issue {
|
|
201
|
-
id identifier title description url
|
|
202
|
-
state { name }
|
|
203
|
-
project { id }
|
|
204
|
-
projectMilestone { id }
|
|
205
|
-
team { id }
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
`;
|
|
210
|
-
const issueInput = {
|
|
211
|
-
title: input.title,
|
|
212
|
-
teamId: input.teamId,
|
|
213
|
-
...(input.description != null && { description: input.description }),
|
|
214
|
-
...(input.projectId != null && { projectId: input.projectId }),
|
|
215
|
-
...(input.milestoneId != null && {
|
|
216
|
-
projectMilestoneId: input.milestoneId,
|
|
217
|
-
}),
|
|
218
|
-
...(input.priority != null && { priority: input.priority }),
|
|
219
|
-
};
|
|
220
|
-
// state is a name string; Linear expects stateId. The caller should resolve
|
|
221
|
-
// this upstream, but if provided we pass it as-is and let Linear resolve.
|
|
222
|
-
if (input.state != null) {
|
|
223
|
-
issueInput.stateId = input.state;
|
|
48
|
+
/** Update a project's status (state name in Linear projects). */
|
|
49
|
+
async updateProjectState(projectId, stateId) {
|
|
50
|
+
try {
|
|
51
|
+
await this.client.updateProject(projectId, { statusId: stateId });
|
|
224
52
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (!result?.success) {
|
|
228
|
-
throw new LinearClientError("Failed to create issue");
|
|
53
|
+
catch (err) {
|
|
54
|
+
console.warn(`[forge] Failed to update project ${projectId}:`, err);
|
|
229
55
|
}
|
|
230
|
-
return this.mapIssue(result.issue);
|
|
231
56
|
}
|
|
232
|
-
|
|
233
|
-
const mutation = `
|
|
234
|
-
mutation UpdateIssue($id: String!, $input: IssueUpdateInput!) {
|
|
235
|
-
issueUpdate(id: $id, input: $input) {
|
|
236
|
-
success
|
|
237
|
-
issue {
|
|
238
|
-
id identifier title description url
|
|
239
|
-
state { name }
|
|
240
|
-
project { id }
|
|
241
|
-
projectMilestone { id }
|
|
242
|
-
team { id }
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
`;
|
|
247
|
-
const issueInput = {};
|
|
248
|
-
if (input.title != null)
|
|
249
|
-
issueInput.title = input.title;
|
|
250
|
-
if (input.description != null)
|
|
251
|
-
issueInput.description = input.description;
|
|
252
|
-
if (input.stateId != null)
|
|
253
|
-
issueInput.stateId = input.stateId;
|
|
254
|
-
else if (input.state != null)
|
|
255
|
-
issueInput.stateId = input.state;
|
|
256
|
-
if (input.milestoneId != null)
|
|
257
|
-
issueInput.projectMilestoneId = input.milestoneId;
|
|
258
|
-
if (input.priority != null)
|
|
259
|
-
issueInput.priority = input.priority;
|
|
260
|
-
const data = await this.request(mutation, { id, input: issueInput });
|
|
261
|
-
const result = data.issueUpdate;
|
|
262
|
-
if (!result?.success) {
|
|
263
|
-
throw new LinearClientError(`Failed to update issue ${id}`);
|
|
264
|
-
}
|
|
265
|
-
return this.mapIssue(result.issue);
|
|
266
|
-
}
|
|
267
|
-
async createComment(issueId, body) {
|
|
268
|
-
const mutation = `
|
|
269
|
-
mutation CreateComment($input: CommentCreateInput!) {
|
|
270
|
-
commentCreate(input: $input) {
|
|
271
|
-
success
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
`;
|
|
275
|
-
const data = await this.request(mutation, {
|
|
276
|
-
input: { issueId, body },
|
|
277
|
-
});
|
|
278
|
-
if (!data.commentCreate?.success) {
|
|
279
|
-
throw new LinearClientError(`Failed to create comment on issue ${issueId}`);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
// -------------------------------------------------------------------------
|
|
283
|
-
// Teams
|
|
284
|
-
// -------------------------------------------------------------------------
|
|
57
|
+
/** List all teams visible to the authenticated user. */
|
|
285
58
|
async listTeams() {
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
59
|
+
try {
|
|
60
|
+
const result = await this.client.teams();
|
|
61
|
+
return result.nodes.map((t) => ({ id: t.id, name: t.name, key: t.key }));
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.warn("[forge] Failed to list teams:", err);
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** List issues belonging to a project. Returns identifier (e.g. "MSIG-123") and title. */
|
|
69
|
+
async listIssuesByProject(projectId) {
|
|
70
|
+
try {
|
|
71
|
+
const result = await this.client.issues({
|
|
72
|
+
filter: {
|
|
73
|
+
project: { id: { eq: projectId } },
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
return result.nodes.map((i) => ({
|
|
77
|
+
id: i.id,
|
|
78
|
+
identifier: i.identifier,
|
|
79
|
+
title: i.title,
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
console.warn("[forge] Failed to list issues by project:", err);
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** List projects filtered by team. */
|
|
88
|
+
async listProjects(teamId) {
|
|
89
|
+
try {
|
|
90
|
+
const result = await this.client.projects({
|
|
91
|
+
filter: {
|
|
92
|
+
accessibleTeams: { some: { id: { eq: teamId } } },
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
const projects = [];
|
|
96
|
+
for (const p of result.nodes) {
|
|
97
|
+
const status = await p.status;
|
|
98
|
+
projects.push({ id: p.id, name: p.name, state: status?.name ?? "Unknown" });
|
|
322
99
|
}
|
|
323
|
-
|
|
324
|
-
try {
|
|
325
|
-
const controller = new AbortController();
|
|
326
|
-
const timeoutId = globalThis.setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
327
|
-
try {
|
|
328
|
-
res = await fetch(LINEAR_API_URL, {
|
|
329
|
-
method: "POST",
|
|
330
|
-
headers: {
|
|
331
|
-
"Content-Type": "application/json",
|
|
332
|
-
Authorization: this.apiKey,
|
|
333
|
-
},
|
|
334
|
-
body: JSON.stringify({ query, variables }),
|
|
335
|
-
signal: controller.signal,
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
finally {
|
|
339
|
-
clearTimeout(timeoutId);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
catch (err) {
|
|
343
|
-
if (err instanceof DOMException && err.name === "AbortError" || (err instanceof Error && err.name === "AbortError")) {
|
|
344
|
-
lastError = new LinearClientError(`Linear API request timed out after ${REQUEST_TIMEOUT_MS / 1000}s`);
|
|
345
|
-
}
|
|
346
|
-
else {
|
|
347
|
-
lastError =
|
|
348
|
-
err instanceof Error ? err : new Error(String(err));
|
|
349
|
-
}
|
|
350
|
-
continue;
|
|
351
|
-
}
|
|
352
|
-
if (res.status === 429 || res.status >= 500) {
|
|
353
|
-
lastError = new LinearClientError(`Linear API returned ${res.status}`, res.status);
|
|
354
|
-
continue;
|
|
355
|
-
}
|
|
356
|
-
if (!res.ok) {
|
|
357
|
-
const body = await res.text().catch(() => "");
|
|
358
|
-
throw new LinearClientError(`Linear API error ${res.status}: ${body}`, res.status);
|
|
359
|
-
}
|
|
360
|
-
const json = (await res.json());
|
|
361
|
-
if (json.errors?.length) {
|
|
362
|
-
throw new LinearClientError(`GraphQL errors: ${json.errors.map((e) => e.message).join("; ")}`, undefined, json.errors);
|
|
363
|
-
}
|
|
364
|
-
if (!json.data) {
|
|
365
|
-
throw new LinearClientError("No data in Linear API response");
|
|
366
|
-
}
|
|
367
|
-
return json.data;
|
|
100
|
+
return projects;
|
|
368
101
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
* Auto-paginate a connection query. The query MUST accept `$after: String`
|
|
373
|
-
* and the root field must return `{ pageInfo { hasNextPage endCursor } nodes { ... } }`.
|
|
374
|
-
*/
|
|
375
|
-
async paginate(query, rootField, variables) {
|
|
376
|
-
const all = [];
|
|
377
|
-
let after = null;
|
|
378
|
-
for (;;) {
|
|
379
|
-
const data = await this.request(query, { ...variables, after });
|
|
380
|
-
const connection = data[rootField];
|
|
381
|
-
if (!connection)
|
|
382
|
-
break;
|
|
383
|
-
all.push(...connection.nodes);
|
|
384
|
-
if (connection.pageInfo.hasNextPage) {
|
|
385
|
-
after = connection.pageInfo.endCursor;
|
|
386
|
-
}
|
|
387
|
-
else {
|
|
388
|
-
break;
|
|
389
|
-
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.warn("[forge] Failed to list projects:", err);
|
|
104
|
+
return [];
|
|
390
105
|
}
|
|
391
|
-
return all;
|
|
392
|
-
}
|
|
393
|
-
/** Normalize a raw issue node from GraphQL into our flat LinearIssue shape. */
|
|
394
|
-
mapIssue(node) {
|
|
395
|
-
return {
|
|
396
|
-
id: node.id,
|
|
397
|
-
identifier: node.identifier,
|
|
398
|
-
title: node.title,
|
|
399
|
-
description: node.description ?? undefined,
|
|
400
|
-
state: node.state?.name ?? "Unknown",
|
|
401
|
-
projectId: node.project?.id ?? undefined,
|
|
402
|
-
milestoneId: node.projectMilestone?.id ?? undefined,
|
|
403
|
-
teamId: node.team?.id ?? undefined,
|
|
404
|
-
url: node.url,
|
|
405
|
-
};
|
|
406
106
|
}
|
|
407
107
|
}
|
|
408
108
|
//# sourceMappingURL=client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/linear/client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/linear/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ForgeConfig, PRDStatus } from "../types.js";
|
|
2
|
+
import type { ForgeLinearClient } from "./client.js";
|
|
3
|
+
/**
|
|
4
|
+
* Transition milestone issues to inProgress and project to inProgress.
|
|
5
|
+
*/
|
|
6
|
+
export declare function syncMilestoneStart(client: ForgeLinearClient, config: ForgeConfig, status: PRDStatus, milestone: string): Promise<void>;
|
|
7
|
+
/**
|
|
8
|
+
* Transition milestone issues to done.
|
|
9
|
+
* If isLast, transition project to inReview.
|
|
10
|
+
*/
|
|
11
|
+
export declare function syncMilestoneComplete(client: ForgeLinearClient, config: ForgeConfig, status: PRDStatus, milestone: string, isLast: boolean): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Transition all issues across all milestones to done and project to done.
|
|
14
|
+
*/
|
|
15
|
+
export declare function syncProjectDone(client: ForgeLinearClient, config: ForgeConfig, status: PRDStatus): Promise<void>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transition milestone issues to inProgress and project to inProgress.
|
|
3
|
+
*/
|
|
4
|
+
export async function syncMilestoneStart(client, config, status, milestone) {
|
|
5
|
+
const ms = status.milestones[milestone];
|
|
6
|
+
if (!ms) {
|
|
7
|
+
console.warn(`[forge] Milestone "${milestone}" not found in status file`);
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const teamId = status.linearTeamId;
|
|
11
|
+
if (!teamId) {
|
|
12
|
+
console.warn("[forge] No linearTeamId in status file, skipping sync");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
const stateId = await client.resolveStateId(teamId, config.linearStates.inProgress);
|
|
16
|
+
// Transition milestone issues to inProgress
|
|
17
|
+
const issueIds = ms.linearIssueIds ?? [];
|
|
18
|
+
if (issueIds.length === 0) {
|
|
19
|
+
console.warn(`[forge] No linearIssueIds for milestone "${milestone}" — skipping issue transitions`);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
console.log(`[forge] Transitioning ${issueIds.length} issue(s) to "${config.linearStates.inProgress}"`);
|
|
23
|
+
for (const issueId of issueIds) {
|
|
24
|
+
await client.updateIssueState(issueId, stateId);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Transition project to inProgress
|
|
28
|
+
const projectId = status.linearProjectId;
|
|
29
|
+
if (projectId) {
|
|
30
|
+
console.log(`[forge] Updating project ${projectId} to "${config.linearStates.inProgress}"`);
|
|
31
|
+
await client.updateProjectState(projectId, stateId);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Transition milestone issues to done.
|
|
36
|
+
* If isLast, transition project to inReview.
|
|
37
|
+
*/
|
|
38
|
+
export async function syncMilestoneComplete(client, config, status, milestone, isLast) {
|
|
39
|
+
const ms = status.milestones[milestone];
|
|
40
|
+
if (!ms) {
|
|
41
|
+
console.warn(`[forge] Milestone "${milestone}" not found in status file`);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const teamId = status.linearTeamId;
|
|
45
|
+
if (!teamId) {
|
|
46
|
+
console.warn("[forge] No linearTeamId in status file, skipping sync");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const doneStateId = await client.resolveStateId(teamId, config.linearStates.done);
|
|
50
|
+
// Transition milestone issues to done
|
|
51
|
+
const issueIds = ms.linearIssueIds ?? [];
|
|
52
|
+
if (issueIds.length === 0) {
|
|
53
|
+
console.warn(`[forge] No linearIssueIds for milestone "${milestone}" — skipping issue transitions`);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
console.log(`[forge] Transitioning ${issueIds.length} issue(s) to "${config.linearStates.done}"`);
|
|
57
|
+
for (const issueId of issueIds) {
|
|
58
|
+
await client.updateIssueState(issueId, doneStateId);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// If last milestone, transition project to inReview
|
|
62
|
+
if (isLast) {
|
|
63
|
+
const projectId = status.linearProjectId;
|
|
64
|
+
if (projectId) {
|
|
65
|
+
const reviewStateId = await client.resolveStateId(teamId, config.linearStates.inReview);
|
|
66
|
+
console.log(`[forge] Updating project ${projectId} to "${config.linearStates.inReview}" (last milestone)`);
|
|
67
|
+
await client.updateProjectState(projectId, reviewStateId);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Transition all issues across all milestones to done and project to done.
|
|
73
|
+
*/
|
|
74
|
+
export async function syncProjectDone(client, config, status) {
|
|
75
|
+
const teamId = status.linearTeamId;
|
|
76
|
+
if (!teamId) {
|
|
77
|
+
console.warn("[forge] No linearTeamId in status file, skipping sync");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const doneStateId = await client.resolveStateId(teamId, config.linearStates.done);
|
|
81
|
+
// Transition all issues across all milestones to done
|
|
82
|
+
let totalIssues = 0;
|
|
83
|
+
for (const [name, ms] of Object.entries(status.milestones)) {
|
|
84
|
+
const issueIds = ms.linearIssueIds ?? [];
|
|
85
|
+
if (issueIds.length === 0) {
|
|
86
|
+
console.warn(`[forge] No linearIssueIds for milestone "${name}" — skipping issue transitions`);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
totalIssues += issueIds.length;
|
|
90
|
+
for (const issueId of issueIds) {
|
|
91
|
+
await client.updateIssueState(issueId, doneStateId);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
console.log(`[forge] Transitioned ${totalIssues} issue(s) across all milestones to "${config.linearStates.done}"`);
|
|
95
|
+
// Transition project to done
|
|
96
|
+
const projectId = status.linearProjectId;
|
|
97
|
+
if (projectId) {
|
|
98
|
+
console.log(`[forge] Updating project ${projectId} to "${config.linearStates.done}"`);
|
|
99
|
+
await client.updateProjectState(projectId, doneStateId);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/linear/sync.ts"],"names":[],"mappings":"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"}
|