forge-cc 0.1.40 → 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 -906
- 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/go/linear-sync-cli.js +13 -4
- package/dist/go/linear-sync-cli.js.map +1 -1
- package/dist/go/linear-sync.d.ts +1 -0
- package/dist/go/linear-sync.js +67 -4
- package/dist/go/linear-sync.js.map +1 -1
- package/dist/linear/client.d.ts +34 -105
- package/dist/linear/client.js +85 -365
- package/dist/linear/client.js.map +1 -1
- package/dist/linear/issues.d.ts +3 -1
- package/dist/linear/issues.js +14 -2
- package/dist/linear/issues.js.map +1 -1
- package/dist/linear/projects.js +3 -2
- package/dist/linear/projects.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 +583 -575
- 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/gates/tests-gate.js
CHANGED
|
@@ -1,219 +1,91 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
* Common test failure patterns with file/line info:
|
|
7
|
-
* FAIL src/foo.test.ts > suite > test name
|
|
8
|
-
* at src/foo.test.ts:42:10
|
|
9
|
-
*/
|
|
10
|
-
const TEST_FILE_RE = /^FAIL\s+(.+?)(?:\s+>|$)/;
|
|
11
|
-
const STACKTRACE_RE = /at\s+.*?([^\s(]+):(\d+):\d+/;
|
|
12
|
-
export async function verifyTests(projectDir, options) {
|
|
13
|
-
const start = Date.now();
|
|
14
|
-
const errors = [];
|
|
15
|
-
const warnings = [];
|
|
16
|
-
// Load config and run test analysis
|
|
17
|
-
const config = loadConfig(options?.configRoot ?? projectDir);
|
|
18
|
-
const testingConfig = config.testing;
|
|
19
|
-
const analysis = await analyzeTestCoverage(projectDir);
|
|
20
|
-
// Detect whether a test script exists in package.json
|
|
21
|
-
let hasTestScript = false;
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
/** Detect test runner from package.json dependencies. */
|
|
5
|
+
async function detectRunner(projectDir) {
|
|
22
6
|
try {
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
7
|
+
const content = await readFile(join(projectDir, "package.json"), "utf-8");
|
|
8
|
+
const pkg = JSON.parse(content);
|
|
9
|
+
const deps = {
|
|
10
|
+
...pkg.dependencies,
|
|
11
|
+
...pkg.devDependencies,
|
|
12
|
+
};
|
|
13
|
+
if ("vitest" in deps)
|
|
14
|
+
return "vitest";
|
|
15
|
+
if ("jest" in deps)
|
|
16
|
+
return "jest";
|
|
30
17
|
}
|
|
31
18
|
catch {
|
|
32
|
-
// No package.json
|
|
33
|
-
}
|
|
34
|
-
// -----------------------------------------------------------------------
|
|
35
|
-
// Baseline check: If zero test files AND no test script, FAIL immediately
|
|
36
|
-
// -----------------------------------------------------------------------
|
|
37
|
-
if (analysis.coverage.testFiles === 0 && !hasTestScript) {
|
|
38
|
-
const categoryNames = analysis.categories.map(c => c.name).join(", ");
|
|
39
|
-
const msg = `No tests found. ${analysis.coverage.sourceFiles} source file${analysis.coverage.sourceFiles === 1 ? "" : "s"} across ${analysis.categories.length} categor${analysis.categories.length === 1 ? "y" : "ies"} (${categoryNames || "none"}) have no test coverage. Run \`/forge:setup\` to scaffold tests.`;
|
|
40
|
-
const error = { message: msg };
|
|
41
|
-
error.remediation = buildTestCoverageRemediation(error);
|
|
42
|
-
errors.push(error);
|
|
43
|
-
return {
|
|
44
|
-
gate: "tests",
|
|
45
|
-
passed: false,
|
|
46
|
-
errors,
|
|
47
|
-
warnings,
|
|
48
|
-
duration_ms: Date.now() - start,
|
|
49
|
-
};
|
|
19
|
+
// No package.json — fall through
|
|
50
20
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
errors.push(error);
|
|
21
|
+
return "unknown";
|
|
22
|
+
}
|
|
23
|
+
async function runTestRunner(projectDir) {
|
|
24
|
+
const start = Date.now();
|
|
25
|
+
const runner = await detectRunner(projectDir);
|
|
26
|
+
if (runner === "unknown") {
|
|
58
27
|
return {
|
|
59
28
|
gate: "tests",
|
|
60
29
|
passed: false,
|
|
61
|
-
errors,
|
|
62
|
-
|
|
63
|
-
duration_ms: Date.now() - start,
|
|
30
|
+
errors: [{ file: "", line: 0, message: "No test runner detected (install vitest or jest)" }],
|
|
31
|
+
durationMs: Date.now() - start,
|
|
64
32
|
};
|
|
65
33
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
const stdout = err instanceof Error && "stdout" in err
|
|
89
|
-
? String(err.stdout)
|
|
90
|
-
: "";
|
|
91
|
-
const stderr = err instanceof Error && "stderr" in err
|
|
92
|
-
? String(err.stderr)
|
|
93
|
-
: "";
|
|
94
|
-
const output = `${stdout}\n${stderr}`;
|
|
95
|
-
let lastFailFile;
|
|
96
|
-
for (const line of output.split("\n")) {
|
|
97
|
-
const trimmed = line.trim();
|
|
98
|
-
if (!trimmed)
|
|
99
|
-
continue;
|
|
100
|
-
// Track which test file we're in
|
|
101
|
-
const failMatch = TEST_FILE_RE.exec(trimmed);
|
|
102
|
-
if (failMatch) {
|
|
103
|
-
lastFailFile = failMatch[1];
|
|
104
|
-
}
|
|
105
|
-
// Try to extract stack trace location
|
|
106
|
-
const stackMatch = STACKTRACE_RE.exec(trimmed);
|
|
107
|
-
if (stackMatch) {
|
|
108
|
-
lastFailFile = stackMatch[1];
|
|
109
|
-
}
|
|
110
|
-
if (trimmed.includes("FAIL") ||
|
|
111
|
-
trimmed.includes("AssertionError") ||
|
|
112
|
-
trimmed.includes("AssertionError") ||
|
|
113
|
-
trimmed.includes("Expected") ||
|
|
114
|
-
trimmed.includes("Received")) {
|
|
34
|
+
const cmd = runner === "vitest" ? ["vitest", "run"] : ["jest", "--ci"];
|
|
35
|
+
return new Promise((resolve) => {
|
|
36
|
+
const child = spawn("npx", cmd, {
|
|
37
|
+
cwd: projectDir,
|
|
38
|
+
shell: true,
|
|
39
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
40
|
+
});
|
|
41
|
+
let stdout = "";
|
|
42
|
+
let stderr = "";
|
|
43
|
+
child.stdout.on("data", (data) => {
|
|
44
|
+
stdout += data.toString();
|
|
45
|
+
});
|
|
46
|
+
child.stderr.on("data", (data) => {
|
|
47
|
+
stderr += data.toString();
|
|
48
|
+
});
|
|
49
|
+
child.on("close", (code) => {
|
|
50
|
+
const errors = [];
|
|
51
|
+
if (code !== 0) {
|
|
52
|
+
const output = stdout + stderr;
|
|
53
|
+
const failRegex = /FAIL\s+(.+)/g;
|
|
54
|
+
let match;
|
|
55
|
+
while ((match = failRegex.exec(output)) !== null) {
|
|
115
56
|
errors.push({
|
|
116
|
-
file:
|
|
117
|
-
line:
|
|
118
|
-
message:
|
|
57
|
+
file: match[1].trim(),
|
|
58
|
+
line: 0,
|
|
59
|
+
message: `Test suite failed: ${match[1].trim()}`,
|
|
119
60
|
});
|
|
120
61
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
warnings.push(`${passed} passed, ${failed} failed`);
|
|
128
|
-
}
|
|
129
|
-
if (errors.length === 0) {
|
|
130
|
-
errors.push({ message: "Test runner exited with non-zero status" });
|
|
131
|
-
}
|
|
132
|
-
// Enrich errors with remediation hints
|
|
133
|
-
for (const error of errors) {
|
|
134
|
-
error.remediation = buildTestRemediation(error);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
// -----------------------------------------------------------------------
|
|
139
|
-
// Enforcement check: Verify changed files have corresponding tests
|
|
140
|
-
// -----------------------------------------------------------------------
|
|
141
|
-
if (testingConfig?.enforce) {
|
|
142
|
-
const changedSourceFiles = getChangedSourceFiles(projectDir);
|
|
143
|
-
if (changedSourceFiles.length > 0) {
|
|
144
|
-
const untestedSet = new Set(analysis.coverage.untestedFiles);
|
|
145
|
-
for (const file of changedSourceFiles) {
|
|
146
|
-
const normalized = file.replace(/\\/g, "/");
|
|
147
|
-
if (untestedSet.has(normalized)) {
|
|
148
|
-
const error = {
|
|
149
|
-
file: normalized,
|
|
150
|
-
message: `Missing test file for changed source: ${normalized}`,
|
|
151
|
-
};
|
|
152
|
-
error.remediation = buildTestCoverageRemediation(error);
|
|
153
|
-
errors.push(error);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
// -----------------------------------------------------------------------
|
|
159
|
-
// Thin coverage advisory
|
|
160
|
-
// -----------------------------------------------------------------------
|
|
161
|
-
if (analysis.coverage.testFiles > 0 && analysis.coverage.ratio < 0.3) {
|
|
162
|
-
warnings.push(`Thin test coverage: ratio ${analysis.coverage.ratio} (${analysis.coverage.testFiles} test file${analysis.coverage.testFiles === 1 ? "" : "s"} for ${analysis.coverage.sourceFiles} source file${analysis.coverage.sourceFiles === 1 ? "" : "s"}). Consider adding tests for untested files.`);
|
|
163
|
-
}
|
|
164
|
-
const passed = testsRanSuccessfully && errors.length === 0;
|
|
165
|
-
return {
|
|
166
|
-
gate: "tests",
|
|
167
|
-
passed,
|
|
168
|
-
errors,
|
|
169
|
-
warnings,
|
|
170
|
-
duration_ms: Date.now() - start,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Get source files changed relative to HEAD~1 or the staging area.
|
|
175
|
-
* Returns paths relative to projectDir, normalized with forward slashes.
|
|
176
|
-
*/
|
|
177
|
-
function getChangedSourceFiles(projectDir) {
|
|
178
|
-
const files = [];
|
|
179
|
-
// Try git diff against HEAD~1 first, fall back to cached diff
|
|
180
|
-
for (const cmd of [
|
|
181
|
-
"git diff --name-only HEAD~1",
|
|
182
|
-
"git diff --cached --name-only",
|
|
183
|
-
]) {
|
|
184
|
-
try {
|
|
185
|
-
const output = execSync(cmd, {
|
|
186
|
-
cwd: projectDir,
|
|
187
|
-
stdio: "pipe",
|
|
188
|
-
timeout: 10_000,
|
|
189
|
-
}).toString().trim();
|
|
190
|
-
if (output) {
|
|
191
|
-
for (const line of output.split("\n")) {
|
|
192
|
-
const trimmed = line.trim();
|
|
193
|
-
if (!trimmed)
|
|
194
|
-
continue;
|
|
195
|
-
// Only include source files (not test files, not configs)
|
|
196
|
-
if (isSourceFilePath(trimmed)) {
|
|
197
|
-
files.push(trimmed.replace(/\\/g, "/"));
|
|
198
|
-
}
|
|
62
|
+
if (errors.length === 0) {
|
|
63
|
+
errors.push({
|
|
64
|
+
file: "",
|
|
65
|
+
line: 0,
|
|
66
|
+
message: `Test runner exited with code ${code}`,
|
|
67
|
+
});
|
|
199
68
|
}
|
|
200
|
-
break; // Use the first successful command
|
|
201
69
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
70
|
+
resolve({
|
|
71
|
+
gate: "tests",
|
|
72
|
+
passed: code === 0,
|
|
73
|
+
errors,
|
|
74
|
+
durationMs: Date.now() - start,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
child.on("error", (err) => {
|
|
78
|
+
resolve({
|
|
79
|
+
gate: "tests",
|
|
80
|
+
passed: false,
|
|
81
|
+
errors: [{ file: "", line: 0, message: err.message }],
|
|
82
|
+
durationMs: Date.now() - start,
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
});
|
|
218
86
|
}
|
|
87
|
+
export const testsGate = {
|
|
88
|
+
name: "tests",
|
|
89
|
+
run: runTestRunner,
|
|
90
|
+
};
|
|
219
91
|
//# sourceMappingURL=tests-gate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tests-gate.js","sourceRoot":"","sources":["../../src/gates/tests-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"tests-gate.js","sourceRoot":"","sources":["../../src/gates/tests-gate.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare
|
|
1
|
+
import type { Gate } from "./index.js";
|
|
2
|
+
export declare const typesGate: Gate;
|
package/dist/gates/types-gate.js
CHANGED
|
@@ -1,64 +1,58 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const TSC_ERROR_RE = /^(.+?)\((\d+),\d+\):\s*(.+)$/;
|
|
5
|
-
export async function verifyTypes(projectDir) {
|
|
6
|
-
const start = Date.now();
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
/** Parse tsc output lines into structured errors. */
|
|
3
|
+
function parseTscOutput(output) {
|
|
7
4
|
const errors = [];
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
// tsc error format: file(line,col): error TSxxxx: message
|
|
6
|
+
const regex = /^(.+?)\((\d+),(\d+)\):\s+error\s+TS\d+:\s+(.+)$/gm;
|
|
7
|
+
let match;
|
|
8
|
+
while ((match = regex.exec(output)) !== null) {
|
|
9
|
+
errors.push({
|
|
10
|
+
file: match[1],
|
|
11
|
+
line: parseInt(match[2], 10),
|
|
12
|
+
column: parseInt(match[3], 10),
|
|
13
|
+
message: match[4],
|
|
14
14
|
});
|
|
15
|
-
return {
|
|
16
|
-
gate: "types",
|
|
17
|
-
passed: true,
|
|
18
|
-
errors,
|
|
19
|
-
warnings,
|
|
20
|
-
duration_ms: Date.now() - start,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
catch (err) {
|
|
24
|
-
const output = err instanceof Error && "stdout" in err
|
|
25
|
-
? String(err.stdout)
|
|
26
|
-
: "";
|
|
27
|
-
for (const line of output.split("\n")) {
|
|
28
|
-
const trimmed = line.trim();
|
|
29
|
-
if (!trimmed)
|
|
30
|
-
continue;
|
|
31
|
-
if (trimmed.toLowerCase().includes("warning")) {
|
|
32
|
-
warnings.push(trimmed);
|
|
33
|
-
}
|
|
34
|
-
else if (trimmed.includes("error TS")) {
|
|
35
|
-
const match = TSC_ERROR_RE.exec(trimmed);
|
|
36
|
-
if (match) {
|
|
37
|
-
errors.push({
|
|
38
|
-
file: match[1],
|
|
39
|
-
line: Number.parseInt(match[2], 10),
|
|
40
|
-
message: match[3],
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
errors.push({ message: trimmed });
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (errors.length === 0) {
|
|
49
|
-
errors.push({ message: "tsc exited with non-zero status but no TS errors were parsed" });
|
|
50
|
-
}
|
|
51
|
-
// Enrich errors with remediation hints
|
|
52
|
-
for (const error of errors) {
|
|
53
|
-
error.remediation = buildTypeRemediation(error);
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
gate: "types",
|
|
57
|
-
passed: false,
|
|
58
|
-
errors,
|
|
59
|
-
warnings,
|
|
60
|
-
duration_ms: Date.now() - start,
|
|
61
|
-
};
|
|
62
15
|
}
|
|
16
|
+
return errors;
|
|
17
|
+
}
|
|
18
|
+
function runTsc(projectDir) {
|
|
19
|
+
return new Promise((resolve) => {
|
|
20
|
+
const start = Date.now();
|
|
21
|
+
const child = spawn("npx", ["tsc", "--noEmit"], {
|
|
22
|
+
cwd: projectDir,
|
|
23
|
+
shell: true,
|
|
24
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
25
|
+
});
|
|
26
|
+
let stdout = "";
|
|
27
|
+
let stderr = "";
|
|
28
|
+
child.stdout.on("data", (data) => {
|
|
29
|
+
stdout += data.toString();
|
|
30
|
+
});
|
|
31
|
+
child.stderr.on("data", (data) => {
|
|
32
|
+
stderr += data.toString();
|
|
33
|
+
});
|
|
34
|
+
child.on("close", (code) => {
|
|
35
|
+
const output = stdout + stderr;
|
|
36
|
+
const errors = parseTscOutput(output);
|
|
37
|
+
resolve({
|
|
38
|
+
gate: "types",
|
|
39
|
+
passed: code === 0,
|
|
40
|
+
errors,
|
|
41
|
+
durationMs: Date.now() - start,
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
child.on("error", (err) => {
|
|
45
|
+
resolve({
|
|
46
|
+
gate: "types",
|
|
47
|
+
passed: false,
|
|
48
|
+
errors: [{ file: "", line: 0, message: err.message }],
|
|
49
|
+
durationMs: Date.now() - start,
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
63
53
|
}
|
|
54
|
+
export const typesGate = {
|
|
55
|
+
name: "types",
|
|
56
|
+
run: runTsc,
|
|
57
|
+
};
|
|
64
58
|
//# sourceMappingURL=types-gate.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-gate.js","sourceRoot":"","sources":["../../src/gates/types-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"types-gate.js","sourceRoot":"","sources":["../../src/gates/types-gate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAI3C,qDAAqD;AACrD,SAAS,cAAc,CAAC,MAAc;IACpC,MAAM,MAAM,GAAgB,EAAE,CAAC;IAC/B,0DAA0D;IAC1D,MAAM,KAAK,GAAG,mDAAmD,CAAC;IAClE,IAAI,KAA6B,CAAC;IAClC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACd,IAAI,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;YAC9B,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;SAClB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,MAAM,CAAC,UAAkB;IAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE;YAC9C,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;SAClC,CAAC,CAAC;QAEH,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACvC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE;YACvC,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;YAC/B,MAAM,MAAM,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YACtC,OAAO,CAAC;gBACN,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,IAAI,KAAK,CAAC;gBAClB,MAAM;gBACN,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;aAC/B,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC;gBACN,IAAI,EAAE,OAAO;gBACb,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;gBACrD,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK;aAC/B,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,SAAS,GAAS;IAC7B,IAAI,EAAE,OAAO;IACb,GAAG,EAAE,MAAM;CACZ,CAAC"}
|
|
@@ -42,6 +42,7 @@ export async function resolveLinearProjectId(projectDir, slug) {
|
|
|
42
42
|
}
|
|
43
43
|
catch (error) {
|
|
44
44
|
if (error instanceof LinearClientError) {
|
|
45
|
+
console.warn("[linear-sync] WARN: LINEAR_API_KEY not set — skipping Linear sync");
|
|
45
46
|
return null;
|
|
46
47
|
}
|
|
47
48
|
throw error;
|
|
@@ -92,8 +93,10 @@ export async function cliSyncStart(projectDir, slug, milestoneNumber) {
|
|
|
92
93
|
new LinearClient();
|
|
93
94
|
}
|
|
94
95
|
catch (error) {
|
|
95
|
-
if (error instanceof LinearClientError)
|
|
96
|
+
if (error instanceof LinearClientError) {
|
|
97
|
+
console.warn("[linear-sync] WARN: LINEAR_API_KEY not set — skipping Linear sync");
|
|
96
98
|
return null;
|
|
99
|
+
}
|
|
97
100
|
throw error;
|
|
98
101
|
}
|
|
99
102
|
const milestoneName = await resolveMilestoneName(projectDir, slug, milestoneNumber);
|
|
@@ -121,8 +124,10 @@ export async function cliSyncComplete(projectDir, slug, milestoneNumber, isLastM
|
|
|
121
124
|
new LinearClient();
|
|
122
125
|
}
|
|
123
126
|
catch (error) {
|
|
124
|
-
if (error instanceof LinearClientError)
|
|
127
|
+
if (error instanceof LinearClientError) {
|
|
128
|
+
console.warn("[linear-sync] WARN: LINEAR_API_KEY not set — skipping Linear sync");
|
|
125
129
|
return null;
|
|
130
|
+
}
|
|
126
131
|
throw error;
|
|
127
132
|
}
|
|
128
133
|
const milestoneName = await resolveMilestoneName(projectDir, slug, milestoneNumber);
|
|
@@ -151,8 +156,10 @@ export async function cliFetchIssueIdentifiers(projectDir, slug) {
|
|
|
151
156
|
new LinearClient();
|
|
152
157
|
}
|
|
153
158
|
catch (error) {
|
|
154
|
-
if (error instanceof LinearClientError)
|
|
159
|
+
if (error instanceof LinearClientError) {
|
|
160
|
+
console.warn("[linear-sync] WARN: LINEAR_API_KEY not set — skipping Linear sync");
|
|
155
161
|
return null;
|
|
162
|
+
}
|
|
156
163
|
throw error;
|
|
157
164
|
}
|
|
158
165
|
return fetchProjectIssueIdentifiers({ projectId });
|
|
@@ -174,8 +181,10 @@ export async function cliSyncDone(projectDir, slug) {
|
|
|
174
181
|
new LinearClient();
|
|
175
182
|
}
|
|
176
183
|
catch (error) {
|
|
177
|
-
if (error instanceof LinearClientError)
|
|
184
|
+
if (error instanceof LinearClientError) {
|
|
185
|
+
console.warn("[linear-sync] WARN: LINEAR_API_KEY not set — skipping Linear sync");
|
|
178
186
|
return null;
|
|
187
|
+
}
|
|
179
188
|
throw error;
|
|
180
189
|
}
|
|
181
190
|
return syncProjectDone({ projectId });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linear-sync-cli.js","sourceRoot":"","sources":["../../src/go/linear-sync-cli.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"linear-sync-cli.js","sourceRoot":"","sources":["../../src/go/linear-sync-cli.ts"],"names":[],"mappings":"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"}
|