ghostrail 0.15.1 → 0.16.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 +206 -1
- package/dist/agent/claude-code.d.ts.map +1 -1
- package/dist/agent/claude-code.js +4 -1
- package/dist/agent/claude-code.js.map +1 -1
- package/dist/board/page.d.ts +1 -1
- package/dist/board/page.d.ts.map +1 -1
- package/dist/board/page.js +2 -1
- package/dist/board/page.js.map +1 -1
- package/dist/board/server.d.ts +1 -1
- package/dist/board/server.d.ts.map +1 -1
- package/dist/board/server.js +7 -1
- package/dist/board/server.js.map +1 -1
- package/dist/board/stats.d.ts +1 -1
- package/dist/board/stats.d.ts.map +1 -1
- package/dist/board/stats.js +2 -1
- package/dist/board/stats.js.map +1 -1
- package/dist/claude-profile/index.d.ts +1 -1
- package/dist/claude-profile/index.d.ts.map +1 -1
- package/dist/claude-profile/index.js +1 -1
- package/dist/claude-profile/index.js.map +1 -1
- package/dist/claude-profile/setup.d.ts +7 -0
- package/dist/claude-profile/setup.d.ts.map +1 -1
- package/dist/claude-profile/setup.js +7 -0
- package/dist/claude-profile/setup.js.map +1 -1
- package/dist/cli/commands.d.ts +6 -0
- package/dist/cli/commands.d.ts.map +1 -1
- package/dist/cli/commands.js +142 -33
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/update-diagnosis.d.ts +52 -0
- package/dist/cli/update-diagnosis.d.ts.map +1 -0
- package/dist/cli/update-diagnosis.js +87 -0
- package/dist/cli/update-diagnosis.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +3 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +11 -0
- package/dist/commands/help.js.map +1 -1
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +18 -2
- package/dist/config/load.js.map +1 -1
- package/dist/config/schema.d.ts +8 -2
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/dashboard/index.d.ts +1 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +1 -1
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/page.d.ts +7 -1
- package/dist/dashboard/page.d.ts.map +1 -1
- package/dist/dashboard/page.js +204 -39
- package/dist/dashboard/page.js.map +1 -1
- package/dist/dashboard/routes.d.ts +32 -0
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +45 -0
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/dashboard/server.d.ts +55 -10
- package/dist/dashboard/server.d.ts.map +1 -1
- package/dist/dashboard/server.js +91 -14
- package/dist/dashboard/server.js.map +1 -1
- package/dist/doctor/checks.d.ts +87 -0
- package/dist/doctor/checks.d.ts.map +1 -0
- package/dist/doctor/checks.js +414 -0
- package/dist/doctor/checks.js.map +1 -0
- package/dist/doctor/index.d.ts +6 -0
- package/dist/doctor/index.d.ts.map +1 -0
- package/dist/doctor/index.js +5 -0
- package/dist/doctor/index.js.map +1 -0
- package/dist/doctor/probes.d.ts +42 -0
- package/dist/doctor/probes.d.ts.map +1 -0
- package/dist/doctor/probes.js +136 -0
- package/dist/doctor/probes.js.map +1 -0
- package/dist/doctor/report.d.ts +13 -0
- package/dist/doctor/report.d.ts.map +1 -0
- package/dist/doctor/report.js +32 -0
- package/dist/doctor/report.js.map +1 -0
- package/dist/doctor/run.d.ts +48 -0
- package/dist/doctor/run.d.ts.map +1 -0
- package/dist/doctor/run.js +109 -0
- package/dist/doctor/run.js.map +1 -0
- package/dist/doctor/types.d.ts +17 -0
- package/dist/doctor/types.d.ts.map +1 -0
- package/dist/doctor/types.js +6 -0
- package/dist/doctor/types.js.map +1 -0
- package/dist/factory/state.d.ts +1 -0
- package/dist/factory/state.d.ts.map +1 -1
- package/dist/factory/state.js +44 -1
- package/dist/factory/state.js.map +1 -1
- package/dist/loop/budget.d.ts +11 -2
- package/dist/loop/budget.d.ts.map +1 -1
- package/dist/loop/budget.js +13 -3
- package/dist/loop/budget.js.map +1 -1
- package/dist/loop/comments.d.ts +20 -0
- package/dist/loop/comments.d.ts.map +1 -0
- package/dist/loop/comments.js +35 -0
- package/dist/loop/comments.js.map +1 -0
- package/dist/loop/engine.d.ts.map +1 -1
- package/dist/loop/engine.js +18 -0
- package/dist/loop/engine.js.map +1 -1
- package/dist/loop/index.d.ts +1 -0
- package/dist/loop/index.d.ts.map +1 -1
- package/dist/loop/index.js +1 -0
- package/dist/loop/index.js.map +1 -1
- package/dist/source/dependencies.d.ts +81 -0
- package/dist/source/dependencies.d.ts.map +1 -0
- package/dist/source/dependencies.js +218 -0
- package/dist/source/dependencies.js.map +1 -0
- package/dist/source/index.d.ts +1 -0
- package/dist/source/index.d.ts.map +1 -1
- package/dist/source/index.js +1 -0
- package/dist/source/index.js.map +1 -1
- package/dist/source/linear.d.ts +17 -1
- package/dist/source/linear.d.ts.map +1 -1
- package/dist/source/linear.js +75 -9
- package/dist/source/linear.js.map +1 -1
- package/dist/store/events.d.ts +8 -0
- package/dist/store/events.d.ts.map +1 -1
- package/dist/store/events.js +10 -0
- package/dist/store/events.js.map +1 -1
- package/dist/store/file-store.d.ts +1 -1
- package/dist/store/file-store.d.ts.map +1 -1
- package/dist/store/file-store.js +7 -0
- package/dist/store/file-store.js.map +1 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +1 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/port.d.ts +15 -0
- package/dist/store/port.d.ts.map +1 -1
- package/dist/store/port.js +17 -1
- package/dist/store/port.js.map +1 -1
- package/dist/triage/engine.d.ts.map +1 -1
- package/dist/triage/engine.js +2 -0
- package/dist/triage/engine.js.map +1 -1
- package/package.json +3 -1
- package/skill/ghostrail/SKILL.md +30 -29
- package/templates/code/prompts/resolve-issue.md +7 -0
- package/templates/code/prompts/triage.md +7 -0
- package/templates/content/prompts/draft.md +7 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure check functions: each takes already-gathered facts and returns a
|
|
3
|
+
* {@link DoctorCheck} (or one per item, for the checks that repeat per prompt).
|
|
4
|
+
* No I/O here — see probes.ts for that — so every rule is testable without a
|
|
5
|
+
* container, a tracker, or the network. Rules are documented in
|
|
6
|
+
* specs/doctor-command.spec.md.
|
|
7
|
+
*/
|
|
8
|
+
import { DEFAULT_CONTAINER_IMAGE } from "../backend/docker.js";
|
|
9
|
+
export function checkConfig(parsed) {
|
|
10
|
+
const id = "config";
|
|
11
|
+
const label = "config";
|
|
12
|
+
if (parsed.ok) {
|
|
13
|
+
return { id, label, status: "pass", detail: "ghostrail.toml parses" };
|
|
14
|
+
}
|
|
15
|
+
const detail = parsed.errors
|
|
16
|
+
.map((error) => `config error at ${error.path || "(root)"}: ${error.message}`)
|
|
17
|
+
.join("; ");
|
|
18
|
+
return {
|
|
19
|
+
id,
|
|
20
|
+
label,
|
|
21
|
+
status: "fail",
|
|
22
|
+
detail,
|
|
23
|
+
fix: `fix ${parsed.errors.length === 1 ? "the error" : "these errors"} in ghostrail.toml`,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** One check per configured prompt path: exists on disk, and is committed. */
|
|
27
|
+
export function checkPrompt(fact) {
|
|
28
|
+
const id = `prompt:${fact.field}`;
|
|
29
|
+
const label = `prompt (${fact.field})`;
|
|
30
|
+
if (!fact.exists) {
|
|
31
|
+
return {
|
|
32
|
+
id,
|
|
33
|
+
label,
|
|
34
|
+
status: "fail",
|
|
35
|
+
detail: `${fact.path} does not exist`,
|
|
36
|
+
fix: `create ${fact.path}`,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
if (!fact.committed) {
|
|
40
|
+
return {
|
|
41
|
+
id,
|
|
42
|
+
label,
|
|
43
|
+
status: "fail",
|
|
44
|
+
detail: `${fact.path} exists but is not committed; a fresh clone or worktree will not have it`,
|
|
45
|
+
fix: `git add ${fact.path} && git commit`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return { id, label, status: "pass", detail: `${fact.path} exists and is committed` };
|
|
49
|
+
}
|
|
50
|
+
/** Package-manager subcommands that are not a `package.json` script name. */
|
|
51
|
+
const PACKAGE_MANAGER_BUILTINS = new Set([
|
|
52
|
+
"install",
|
|
53
|
+
"ci",
|
|
54
|
+
"add",
|
|
55
|
+
"remove",
|
|
56
|
+
"rm",
|
|
57
|
+
"dlx",
|
|
58
|
+
"exec",
|
|
59
|
+
"create",
|
|
60
|
+
"init",
|
|
61
|
+
"link",
|
|
62
|
+
"unlink",
|
|
63
|
+
"publish",
|
|
64
|
+
"update",
|
|
65
|
+
"outdated",
|
|
66
|
+
"list",
|
|
67
|
+
"ls",
|
|
68
|
+
"why",
|
|
69
|
+
"store",
|
|
70
|
+
"prune",
|
|
71
|
+
"audit",
|
|
72
|
+
"dedupe",
|
|
73
|
+
"pack",
|
|
74
|
+
"patch",
|
|
75
|
+
"rebuild",
|
|
76
|
+
]);
|
|
77
|
+
/**
|
|
78
|
+
* The `package.json` script name a gate command invokes, if it looks like a
|
|
79
|
+
* package-manager script invocation (`pnpm <script>`, `npm run <script>`,
|
|
80
|
+
* `yarn <script>`); undefined for anything else, including a package-manager
|
|
81
|
+
* builtin like `pnpm install`. Best-effort: a command this misses is simply not
|
|
82
|
+
* checked further, never reported as broken on a guess.
|
|
83
|
+
*/
|
|
84
|
+
export function scriptNameOf(command) {
|
|
85
|
+
const [head, ...rest] = command.trim().split(/\s+/);
|
|
86
|
+
const next = rest[0];
|
|
87
|
+
if (head === "pnpm" || head === "yarn") {
|
|
88
|
+
if (next === undefined || next.startsWith("-"))
|
|
89
|
+
return undefined;
|
|
90
|
+
if (next === "run")
|
|
91
|
+
return rest[1];
|
|
92
|
+
if (PACKAGE_MANAGER_BUILTINS.has(next))
|
|
93
|
+
return undefined;
|
|
94
|
+
return next;
|
|
95
|
+
}
|
|
96
|
+
if (head === "npm") {
|
|
97
|
+
if (next !== "run" && next !== "run-script")
|
|
98
|
+
return undefined;
|
|
99
|
+
return rest[1];
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
/** Gate commands that name a `package.json` script the project does not have. */
|
|
104
|
+
export function unresolvedGateCommands(commands, scripts) {
|
|
105
|
+
if (scripts === undefined)
|
|
106
|
+
return [];
|
|
107
|
+
const unresolved = [];
|
|
108
|
+
for (const command of commands) {
|
|
109
|
+
const script = scriptNameOf(command);
|
|
110
|
+
if (script !== undefined && !(script in scripts))
|
|
111
|
+
unresolved.push(command);
|
|
112
|
+
}
|
|
113
|
+
return unresolved;
|
|
114
|
+
}
|
|
115
|
+
export function checkGate(commands, scripts) {
|
|
116
|
+
const id = "gate";
|
|
117
|
+
const label = "gate";
|
|
118
|
+
if (commands.length === 0) {
|
|
119
|
+
return {
|
|
120
|
+
id,
|
|
121
|
+
label,
|
|
122
|
+
status: "fail",
|
|
123
|
+
detail: "[gate].commands is empty; nothing verifies an agent's changes",
|
|
124
|
+
fix: "add CI-mirroring commands to [gate].commands in ghostrail.toml",
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const unresolved = unresolvedGateCommands(commands, scripts);
|
|
128
|
+
if (unresolved.length > 0) {
|
|
129
|
+
return {
|
|
130
|
+
id,
|
|
131
|
+
label,
|
|
132
|
+
status: "warn",
|
|
133
|
+
detail: `no matching package.json script for: ${unresolved.join(", ")}`,
|
|
134
|
+
fix: "add the missing script(s) to package.json, or fix the gate command",
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return { id, label, status: "pass", detail: `${commands.length} gate command(s) configured` };
|
|
138
|
+
}
|
|
139
|
+
export function checkBackend(facts) {
|
|
140
|
+
const id = "backend";
|
|
141
|
+
const label = "backend";
|
|
142
|
+
if (facts.kind !== "container") {
|
|
143
|
+
return { id, label, status: "pass", detail: `${facts.kind} needs no image` };
|
|
144
|
+
}
|
|
145
|
+
if (facts.quick) {
|
|
146
|
+
return { id, label, status: "warn", detail: "skipped docker/image checks (--quick)" };
|
|
147
|
+
}
|
|
148
|
+
if (facts.dockerAvailable === false) {
|
|
149
|
+
return {
|
|
150
|
+
id,
|
|
151
|
+
label,
|
|
152
|
+
status: "fail",
|
|
153
|
+
detail: "docker is not reachable",
|
|
154
|
+
fix: "start Docker; `docker version` should succeed",
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (facts.image === undefined) {
|
|
158
|
+
return {
|
|
159
|
+
id,
|
|
160
|
+
label,
|
|
161
|
+
status: "warn",
|
|
162
|
+
detail: `using the default ${DEFAULT_CONTAINER_IMAGE} image, which has no node, pnpm, git, gh, or claude, so a run will provision and then fail at the gate`,
|
|
163
|
+
fix: "set [backend].image, or build the shipped image with `ghostrail image build`",
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
if (facts.imagePresent === false) {
|
|
167
|
+
return {
|
|
168
|
+
id,
|
|
169
|
+
label,
|
|
170
|
+
status: "fail",
|
|
171
|
+
detail: `image ${facts.image} not found locally`,
|
|
172
|
+
fix: `ghostrail image build --tag ${facts.image}`,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return { id, label, status: "pass", detail: `image ${facts.image} present, docker reachable` };
|
|
176
|
+
}
|
|
177
|
+
export function checkClaudeProfile(facts) {
|
|
178
|
+
const id = "claude-profile";
|
|
179
|
+
const label = "claude profile";
|
|
180
|
+
if (!facts.present) {
|
|
181
|
+
return {
|
|
182
|
+
id,
|
|
183
|
+
label,
|
|
184
|
+
status: "pass",
|
|
185
|
+
detail: "no ghostrail Claude profile in use; runs use your normal ~/.claude",
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const redirectNote = "runs redirect HOME (and pass --settings) at this profile, which carries no " +
|
|
189
|
+
".credentials.json by design, so only ANTHROPIC_API_KEY / CLAUDE_CODE_OAUTH_TOKEN " +
|
|
190
|
+
"survive that redirect; an interactive login in your real home is invisible to the agent";
|
|
191
|
+
if (facts.missingPins.length > 0) {
|
|
192
|
+
return {
|
|
193
|
+
id,
|
|
194
|
+
label,
|
|
195
|
+
status: "warn",
|
|
196
|
+
detail: `${redirectNote}. Requested via --pin but not installed: ${facts.missingPins.join(", ")}`,
|
|
197
|
+
fix: `ghostrail claude-setup --pin ${facts.missingPins.join(" --pin ")} --write`,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return { id, label, status: "pass", detail: redirectNote };
|
|
201
|
+
}
|
|
202
|
+
/** Whether a raw env value is unset, present-but-blank, or a real value. Never returns the value. */
|
|
203
|
+
export function classifyCredential(value) {
|
|
204
|
+
if (value === undefined)
|
|
205
|
+
return "unset";
|
|
206
|
+
return value.trim().length === 0 ? "blank" : "set";
|
|
207
|
+
}
|
|
208
|
+
export function checkClaudeAuthCredential(anthropicApiKey, oauthToken) {
|
|
209
|
+
const id = "credential:claude-auth";
|
|
210
|
+
const label = "credential (claude auth)";
|
|
211
|
+
const apiKey = classifyCredential(anthropicApiKey);
|
|
212
|
+
const oauth = classifyCredential(oauthToken);
|
|
213
|
+
if (apiKey === "blank") {
|
|
214
|
+
return {
|
|
215
|
+
id,
|
|
216
|
+
label,
|
|
217
|
+
status: "fail",
|
|
218
|
+
detail: "ANTHROPIC_API_KEY is set but empty",
|
|
219
|
+
fix: "unset ANTHROPIC_API_KEY or give it a real value",
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
if (oauth === "blank") {
|
|
223
|
+
return {
|
|
224
|
+
id,
|
|
225
|
+
label,
|
|
226
|
+
status: "fail",
|
|
227
|
+
detail: "CLAUDE_CODE_OAUTH_TOKEN is set but empty",
|
|
228
|
+
fix: "unset CLAUDE_CODE_OAUTH_TOKEN, or run `claude setup-token`",
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
if (apiKey === "unset" && oauth === "unset") {
|
|
232
|
+
return {
|
|
233
|
+
id,
|
|
234
|
+
label,
|
|
235
|
+
status: "fail",
|
|
236
|
+
detail: "neither ANTHROPIC_API_KEY nor CLAUDE_CODE_OAUTH_TOKEN is set",
|
|
237
|
+
fix: "run `claude setup-token`, or set ANTHROPIC_API_KEY",
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
if (apiKey === "set" && oauth === "set") {
|
|
241
|
+
return {
|
|
242
|
+
id,
|
|
243
|
+
label,
|
|
244
|
+
status: "warn",
|
|
245
|
+
detail: "ANTHROPIC_API_KEY is set alongside CLAUDE_CODE_OAUTH_TOKEN; the API key wins, so a stale key silently beats a good token",
|
|
246
|
+
fix: "unset ANTHROPIC_API_KEY to bill the Pro/Max subscription via the OAuth token",
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
id,
|
|
251
|
+
label,
|
|
252
|
+
status: "pass",
|
|
253
|
+
detail: `using ${apiKey === "set" ? "ANTHROPIC_API_KEY" : "CLAUDE_CODE_OAUTH_TOKEN"}`,
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
export function checkLinearCredential(linearApiKey) {
|
|
257
|
+
const id = "credential:linear";
|
|
258
|
+
const label = "credential (linear)";
|
|
259
|
+
const shape = classifyCredential(linearApiKey);
|
|
260
|
+
if (shape === "unset") {
|
|
261
|
+
return {
|
|
262
|
+
id,
|
|
263
|
+
label,
|
|
264
|
+
status: "fail",
|
|
265
|
+
detail: "LINEAR_API_KEY is not set; required for every run",
|
|
266
|
+
fix: "ghostrail secrets-setup --write",
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
if (shape === "blank") {
|
|
270
|
+
return {
|
|
271
|
+
id,
|
|
272
|
+
label,
|
|
273
|
+
status: "fail",
|
|
274
|
+
detail: "LINEAR_API_KEY is set but empty",
|
|
275
|
+
fix: "unset LINEAR_API_KEY or give it a real value",
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return { id, label, status: "pass", detail: "LINEAR_API_KEY is set" };
|
|
279
|
+
}
|
|
280
|
+
export function checkGithubCredential(ghToken, githubToken) {
|
|
281
|
+
const id = "credential:github";
|
|
282
|
+
const label = "credential (github)";
|
|
283
|
+
const gh = classifyCredential(ghToken);
|
|
284
|
+
const github = classifyCredential(githubToken);
|
|
285
|
+
if (gh === "blank") {
|
|
286
|
+
return {
|
|
287
|
+
id,
|
|
288
|
+
label,
|
|
289
|
+
status: "fail",
|
|
290
|
+
detail: "GH_TOKEN is set but empty",
|
|
291
|
+
fix: "unset GH_TOKEN or give it a real value",
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
if (github === "blank") {
|
|
295
|
+
return {
|
|
296
|
+
id,
|
|
297
|
+
label,
|
|
298
|
+
status: "fail",
|
|
299
|
+
detail: "GITHUB_TOKEN is set but empty",
|
|
300
|
+
fix: "unset GITHUB_TOKEN or give it a real value",
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
if (gh === "unset" && github === "unset") {
|
|
304
|
+
return {
|
|
305
|
+
id,
|
|
306
|
+
label,
|
|
307
|
+
status: "warn",
|
|
308
|
+
detail: "neither GH_TOKEN nor GITHUB_TOKEN is set; publishing a PR will fail",
|
|
309
|
+
fix: "ghostrail secrets-setup --write",
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
return {
|
|
313
|
+
id,
|
|
314
|
+
label,
|
|
315
|
+
status: "pass",
|
|
316
|
+
detail: `using ${gh === "set" ? "GH_TOKEN" : "GITHUB_TOKEN"}`,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
export function checkClaudeProbe(result, backendKind) {
|
|
320
|
+
const id = "probe:claude-auth";
|
|
321
|
+
const label = "probe (claude auth)";
|
|
322
|
+
switch (result.kind) {
|
|
323
|
+
case "not-run":
|
|
324
|
+
return {
|
|
325
|
+
id,
|
|
326
|
+
label,
|
|
327
|
+
status: "warn",
|
|
328
|
+
detail: "not run: no claude credential is set",
|
|
329
|
+
};
|
|
330
|
+
case "skipped":
|
|
331
|
+
return {
|
|
332
|
+
id,
|
|
333
|
+
label,
|
|
334
|
+
status: "warn",
|
|
335
|
+
detail: "skipped (--quick); presence of a credential does not mean it authenticates",
|
|
336
|
+
};
|
|
337
|
+
case "ok":
|
|
338
|
+
return {
|
|
339
|
+
id,
|
|
340
|
+
label,
|
|
341
|
+
status: "pass",
|
|
342
|
+
detail: `claude -p answered inside the configured backend (${backendKind})`,
|
|
343
|
+
};
|
|
344
|
+
case "invalid-token":
|
|
345
|
+
return {
|
|
346
|
+
id,
|
|
347
|
+
label,
|
|
348
|
+
status: "fail",
|
|
349
|
+
detail: `claude -p failed inside the configured backend (${backendKind}): 401 Invalid bearer token`,
|
|
350
|
+
fix: "the token is expired or revoked; run `claude setup-token`",
|
|
351
|
+
};
|
|
352
|
+
case "error":
|
|
353
|
+
return {
|
|
354
|
+
id,
|
|
355
|
+
label,
|
|
356
|
+
status: "fail",
|
|
357
|
+
detail: `claude -p failed inside the configured backend (${backendKind}): ${result.message}`,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
export function checkLinearProbe(result) {
|
|
362
|
+
const id = "probe:linear-auth";
|
|
363
|
+
const label = "probe (linear auth)";
|
|
364
|
+
switch (result.kind) {
|
|
365
|
+
case "not-run":
|
|
366
|
+
return { id, label, status: "warn", detail: "not run: LINEAR_API_KEY is not usable" };
|
|
367
|
+
case "skipped":
|
|
368
|
+
return { id, label, status: "warn", detail: "skipped (--quick)" };
|
|
369
|
+
case "ok":
|
|
370
|
+
return { id, label, status: "pass", detail: "LINEAR_API_KEY authenticated" };
|
|
371
|
+
case "unauthorized":
|
|
372
|
+
return {
|
|
373
|
+
id,
|
|
374
|
+
label,
|
|
375
|
+
status: "fail",
|
|
376
|
+
detail: "LINEAR_API_KEY was rejected (unauthorized)",
|
|
377
|
+
fix: "generate a new key at Linear Settings > Security & Access",
|
|
378
|
+
};
|
|
379
|
+
case "error":
|
|
380
|
+
return {
|
|
381
|
+
id,
|
|
382
|
+
label,
|
|
383
|
+
status: "fail",
|
|
384
|
+
detail: `LINEAR_API_KEY probe failed: ${result.message}`,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const HISTORY_SAMPLE = 5;
|
|
389
|
+
export function checkHistory(rows) {
|
|
390
|
+
const id = "history";
|
|
391
|
+
const label = "recent history";
|
|
392
|
+
if (rows.length === 0) {
|
|
393
|
+
return {
|
|
394
|
+
id,
|
|
395
|
+
label,
|
|
396
|
+
status: "pass",
|
|
397
|
+
detail: "no run history yet (the store is empty or absent, not evidence of health)",
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
const sample = rows.slice(0, HISTORY_SAMPLE);
|
|
401
|
+
const states = sample.map((row) => row.state ?? "unknown").join(", ");
|
|
402
|
+
const mostRecent = sample[0];
|
|
403
|
+
if (mostRecent?.state === "failed") {
|
|
404
|
+
const error = mostRecent.error ?? "no error was recorded for it";
|
|
405
|
+
return {
|
|
406
|
+
id,
|
|
407
|
+
label,
|
|
408
|
+
status: "warn",
|
|
409
|
+
detail: `recent runs: ${states}. The most recent run failed: ${error}`,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
return { id, label, status: "pass", detail: `recent runs: ${states}` };
|
|
413
|
+
}
|
|
414
|
+
//# sourceMappingURL=checks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.js","sourceRoot":"","sources":["../../src/doctor/checks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { checkBackend, checkClaudeAuthCredential, checkClaudeProbe, checkClaudeProfile, checkConfig, checkGate, checkGithubCredential, checkHistory, checkLinearCredential, checkLinearProbe, checkPrompt, type ClaudeProbeResult, classifyCredential, type CredentialShape, type LinearProbeResult, type PromptField, scriptNameOf, unresolvedGateCommands, } from "./checks.js";
|
|
2
|
+
export { claudeProbeInvocation, isCommitted, isDockerAvailable, isImagePresent, interpretClaudeProbe, probeClaudeAuth, probeLinearAuth, readPackageScripts, } from "./probes.js";
|
|
3
|
+
export { hasFailure, orderedFixes, renderDoctorJson, renderDoctorText } from "./report.js";
|
|
4
|
+
export { type DoctorDeps, type DoctorRunOptions, runDoctor } from "./run.js";
|
|
5
|
+
export type { DoctorCheck, DoctorReport, DoctorStatus } from "./types.js";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/doctor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,KAAK,iBAAiB,EACtB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,YAAY,EACZ,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,gBAAgB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { checkBackend, checkClaudeAuthCredential, checkClaudeProbe, checkClaudeProfile, checkConfig, checkGate, checkGithubCredential, checkHistory, checkLinearCredential, checkLinearProbe, checkPrompt, classifyCredential, scriptNameOf, unresolvedGateCommands, } from "./checks.js";
|
|
2
|
+
export { claudeProbeInvocation, isCommitted, isDockerAvailable, isImagePresent, interpretClaudeProbe, probeClaudeAuth, probeLinearAuth, readPackageScripts, } from "./probes.js";
|
|
3
|
+
export { hasFailure, orderedFixes, renderDoctorJson, renderDoctorText } from "./report.js";
|
|
4
|
+
export { runDoctor } from "./run.js";
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/doctor/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EAEX,kBAAkB,EAIlB,YAAY,EACZ,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,eAAe,EACf,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC3F,OAAO,EAA0C,SAAS,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The I/O doctor's checks are built on: git, docker, a real `claude -p` call,
|
|
3
|
+
* and a Linear GraphQL query. Each is a free function so `run.ts` can swap in a
|
|
4
|
+
* fake for tests — nothing here is ever exercised by the test suite for real.
|
|
5
|
+
*/
|
|
6
|
+
import type { ExecOptions, ExecResult } from "../backend/types.js";
|
|
7
|
+
import type { BackendKind } from "../config/schema.js";
|
|
8
|
+
import type { ClaudeProbeResult, LinearProbeResult } from "./checks.js";
|
|
9
|
+
/** Whether `relPath` is present in the repo's `HEAD` tree (not merely on disk). */
|
|
10
|
+
export declare function isCommitted(repoPath: string, relPath: string): Promise<boolean>;
|
|
11
|
+
/** The repo's `package.json` `scripts` table, or undefined if there is none to read. */
|
|
12
|
+
export declare function readPackageScripts(repoPath: string): Promise<Record<string, unknown> | undefined>;
|
|
13
|
+
/** True if the Docker CLI and daemon are reachable. */
|
|
14
|
+
export declare function isDockerAvailable(): Promise<boolean>;
|
|
15
|
+
/** True if `image` is present in the local Docker image store. */
|
|
16
|
+
export declare function isImagePresent(image: string): Promise<boolean>;
|
|
17
|
+
export interface ClaudeAuthProbeOptions {
|
|
18
|
+
backendKind: BackendKind;
|
|
19
|
+
/** The configured (or default) container image; ignored for a non-container backend. */
|
|
20
|
+
image?: string;
|
|
21
|
+
/** The environment to read ANTHROPIC_API_KEY / CLAUDE_CODE_OAUTH_TOKEN from. */
|
|
22
|
+
env: Record<string, string | undefined>;
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The command (and its exec options) a `claude -p` auth probe would run for the
|
|
27
|
+
* given backend: directly on the host for anything other than `container`,
|
|
28
|
+
* inside a disposable `docker run --rm` for `container` — the whole point being
|
|
29
|
+
* that a container only ever receives forwarded env vars, so a host-side login
|
|
30
|
+
* proves nothing about it. Pure: builds the invocation, never runs it.
|
|
31
|
+
*/
|
|
32
|
+
export declare function claudeProbeInvocation(options: ClaudeAuthProbeOptions): {
|
|
33
|
+
command: string[];
|
|
34
|
+
execOptions: ExecOptions;
|
|
35
|
+
};
|
|
36
|
+
/** Run the probe {@link claudeProbeInvocation} builds, and classify the result. */
|
|
37
|
+
export declare function probeClaudeAuth(options: ClaudeAuthProbeOptions): Promise<ClaudeProbeResult>;
|
|
38
|
+
/** Classify a `claude -p` probe's raw result into a {@link ClaudeProbeResult}. */
|
|
39
|
+
export declare function interpretClaudeProbe(result: ExecResult): ClaudeProbeResult;
|
|
40
|
+
/** Send one cheap authenticated Linear query to check the key actually works. */
|
|
41
|
+
export declare function probeLinearAuth(apiKey: string, fetchImpl?: typeof fetch): Promise<LinearProbeResult>;
|
|
42
|
+
//# sourceMappingURL=probes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../../src/doctor/probes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAExE,mFAAmF;AACnF,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAIrF;AAED,wFAAwF;AACxF,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAW9C;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAEpD;AAED,kEAAkE;AAClE,wBAAsB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGpE;AAKD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,WAAW,CAAC;IACzB,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG;IACtE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;CAC1B,CAmBA;AAED,mFAAmF;AACnF,wBAAsB,eAAe,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAIjG;AAED,kFAAkF;AAClF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,iBAAiB,CAQ1E;AAID,iFAAiF;AACjF,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,OAAO,KAAa,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CA2B5B"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The I/O doctor's checks are built on: git, docker, a real `claude -p` call,
|
|
3
|
+
* and a Linear GraphQL query. Each is a free function so `run.ts` can swap in a
|
|
4
|
+
* fake for tests — nothing here is ever exercised by the test suite for real.
|
|
5
|
+
*/
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
|
+
import { join, sep } from "node:path";
|
|
8
|
+
import { describeAgentFailure } from "../agent/failure.js";
|
|
9
|
+
import { ContainerBackend } from "../backend/container.js";
|
|
10
|
+
import { DEFAULT_CONTAINER_IMAGE } from "../backend/docker.js";
|
|
11
|
+
import { spawnCollect } from "../backend/proc.js";
|
|
12
|
+
/** Whether `relPath` is present in the repo's `HEAD` tree (not merely on disk). */
|
|
13
|
+
export async function isCommitted(repoPath, relPath) {
|
|
14
|
+
const posixPath = relPath.split(sep).join("/");
|
|
15
|
+
const result = await spawnCollect(["git", "-C", repoPath, "cat-file", "-e", `HEAD:${posixPath}`]);
|
|
16
|
+
return result.exitCode === 0;
|
|
17
|
+
}
|
|
18
|
+
/** The repo's `package.json` `scripts` table, or undefined if there is none to read. */
|
|
19
|
+
export async function readPackageScripts(repoPath) {
|
|
20
|
+
try {
|
|
21
|
+
const raw = await readFile(join(repoPath, "package.json"), "utf8");
|
|
22
|
+
const parsed = JSON.parse(raw);
|
|
23
|
+
if (parsed.scripts !== null && typeof parsed.scripts === "object") {
|
|
24
|
+
return parsed.scripts;
|
|
25
|
+
}
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** True if the Docker CLI and daemon are reachable. */
|
|
33
|
+
export function isDockerAvailable() {
|
|
34
|
+
return ContainerBackend.isAvailable();
|
|
35
|
+
}
|
|
36
|
+
/** True if `image` is present in the local Docker image store. */
|
|
37
|
+
export async function isImagePresent(image) {
|
|
38
|
+
const result = await spawnCollect(["docker", "image", "inspect", image]);
|
|
39
|
+
return result.exitCode === 0;
|
|
40
|
+
}
|
|
41
|
+
const PROBE_PROMPT = "Reply with exactly the single word: ok";
|
|
42
|
+
const DEFAULT_PROBE_TIMEOUT_MS = 30_000;
|
|
43
|
+
function forwardedClaudeAuth(env) {
|
|
44
|
+
const out = {};
|
|
45
|
+
for (const key of ["ANTHROPIC_API_KEY", "CLAUDE_CODE_OAUTH_TOKEN"]) {
|
|
46
|
+
const value = env[key];
|
|
47
|
+
if (value !== undefined && value.trim().length > 0)
|
|
48
|
+
out[key] = value;
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/** `-e KEY=VALUE` flags for each forwarded env entry, in insertion order. */
|
|
53
|
+
function dockerEnvFlags(env) {
|
|
54
|
+
const flags = [];
|
|
55
|
+
for (const [key, value] of Object.entries(env))
|
|
56
|
+
flags.push("-e", `${key}=${value}`);
|
|
57
|
+
return flags;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The command (and its exec options) a `claude -p` auth probe would run for the
|
|
61
|
+
* given backend: directly on the host for anything other than `container`,
|
|
62
|
+
* inside a disposable `docker run --rm` for `container` — the whole point being
|
|
63
|
+
* that a container only ever receives forwarded env vars, so a host-side login
|
|
64
|
+
* proves nothing about it. Pure: builds the invocation, never runs it.
|
|
65
|
+
*/
|
|
66
|
+
export function claudeProbeInvocation(options) {
|
|
67
|
+
const forwarded = forwardedClaudeAuth(options.env);
|
|
68
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;
|
|
69
|
+
const claudeArgs = ["claude", "-p", PROBE_PROMPT, "--output-format", "json"];
|
|
70
|
+
if (options.backendKind === "container") {
|
|
71
|
+
return {
|
|
72
|
+
command: [
|
|
73
|
+
"docker",
|
|
74
|
+
"run",
|
|
75
|
+
"--rm",
|
|
76
|
+
...dockerEnvFlags(forwarded),
|
|
77
|
+
options.image ?? DEFAULT_CONTAINER_IMAGE,
|
|
78
|
+
...claudeArgs,
|
|
79
|
+
],
|
|
80
|
+
execOptions: { timeoutMs },
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return { command: claudeArgs, execOptions: { env: forwarded, timeoutMs } };
|
|
84
|
+
}
|
|
85
|
+
/** Run the probe {@link claudeProbeInvocation} builds, and classify the result. */
|
|
86
|
+
export async function probeClaudeAuth(options) {
|
|
87
|
+
const { command, execOptions } = claudeProbeInvocation(options);
|
|
88
|
+
const result = await spawnCollect(command, execOptions);
|
|
89
|
+
return interpretClaudeProbe(result);
|
|
90
|
+
}
|
|
91
|
+
/** Classify a `claude -p` probe's raw result into a {@link ClaudeProbeResult}. */
|
|
92
|
+
export function interpretClaudeProbe(result) {
|
|
93
|
+
if (result.exitCode === 0)
|
|
94
|
+
return { kind: "ok" };
|
|
95
|
+
const text = `${result.stdout}\n${result.stderr}`;
|
|
96
|
+
if (/401/.test(text) && /invalid bearer token/i.test(text))
|
|
97
|
+
return { kind: "invalid-token" };
|
|
98
|
+
return {
|
|
99
|
+
kind: "error",
|
|
100
|
+
message: describeAgentFailure(result.exitCode, result.stdout, result.stderr),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const LINEAR_PROBE_BODY = JSON.stringify({ query: "{ viewer { id } }" });
|
|
104
|
+
/** Send one cheap authenticated Linear query to check the key actually works. */
|
|
105
|
+
export async function probeLinearAuth(apiKey, fetchImpl = fetch) {
|
|
106
|
+
let response;
|
|
107
|
+
try {
|
|
108
|
+
response = await fetchImpl("https://api.linear.app/graphql", {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: { "Content-Type": "application/json", Authorization: apiKey },
|
|
111
|
+
body: LINEAR_PROBE_BODY,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
return { kind: "error", message: error instanceof Error ? error.message : String(error) };
|
|
116
|
+
}
|
|
117
|
+
if (response.status === 401)
|
|
118
|
+
return { kind: "unauthorized" };
|
|
119
|
+
if (!response.ok)
|
|
120
|
+
return { kind: "error", message: `HTTP ${response.status}` };
|
|
121
|
+
let body;
|
|
122
|
+
try {
|
|
123
|
+
body = (await response.json());
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return { kind: "ok" };
|
|
127
|
+
}
|
|
128
|
+
const firstError = body.errors?.[0]?.message;
|
|
129
|
+
if (firstError !== undefined) {
|
|
130
|
+
return /auth/i.test(firstError)
|
|
131
|
+
? { kind: "unauthorized" }
|
|
132
|
+
: { kind: "error", message: firstError };
|
|
133
|
+
}
|
|
134
|
+
return { kind: "ok" };
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=probes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probes.js","sourceRoot":"","sources":["../../src/doctor/probes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAKlD,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe;IACjE,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,SAAS,EAAE,CAAC,CAAC,CAAC;IAClG,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,wFAAwF;AACxF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB;IAEhB,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,EAAE,MAAM,CAAC,CAAC;QACnE,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;QACxD,IAAI,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAClE,OAAO,MAAM,CAAC,OAAkC,CAAC;QACnD,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,iBAAiB;IAC/B,OAAO,gBAAgB,CAAC,WAAW,EAAE,CAAC;AACxC,CAAC;AAED,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAa;IAChD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IACzE,OAAO,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,YAAY,GAAG,wCAAwC,CAAC;AAC9D,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAWxC,SAAS,mBAAmB,CAAC,GAAuC;IAClE,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,GAAG,IAAI,CAAC,mBAAmB,EAAE,yBAAyB,CAAU,EAAE,CAAC;QAC5E,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACvE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6EAA6E;AAC7E,SAAS,cAAc,CAAC,GAA2B;IACjD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAA+B;IAInE,MAAM,SAAS,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACnD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,wBAAwB,CAAC;IAChE,MAAM,UAAU,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAE7E,IAAI,OAAO,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;QACxC,OAAO;YACL,OAAO,EAAE;gBACP,QAAQ;gBACR,KAAK;gBACL,MAAM;gBACN,GAAG,cAAc,CAAC,SAAS,CAAC;gBAC5B,OAAO,CAAC,KAAK,IAAI,uBAAuB;gBACxC,GAAG,UAAU;aACd;YACD,WAAW,EAAE,EAAE,SAAS,EAAE;SAC3B,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC;AAC7E,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAA+B;IACnE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAChE,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IACxD,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;AACtC,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACrD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACjD,MAAM,IAAI,GAAG,GAAG,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;IAClD,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IAC7F,OAAO;QACL,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,oBAAoB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC;KAC7E,CAAC;AACJ,CAAC;AAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;AAEzE,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,MAAc,EACd,YAA0B,KAAK;IAE/B,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,SAAS,CAAC,gCAAgC,EAAE;YAC3D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,EAAE;YACtE,IAAI,EAAE,iBAAiB;SACxB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IAC5F,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;QAAE,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAC7D,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IAE/E,IAAI,IAAyC,CAAC;IAC9C,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAwC,CAAC;IACxE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACxB,CAAC;IACD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;IAC7C,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;YAC7B,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE;YAC1B,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAC7C,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DoctorReport } from "./types.js";
|
|
2
|
+
export declare function hasFailure(report: DoctorReport): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Every check's fix, most blocking first: every `fail` check's fix in check
|
|
5
|
+
* order, then every `warn` check's fix in check order. A check with no `fix`
|
|
6
|
+
* (typically a `pass`) contributes nothing.
|
|
7
|
+
*/
|
|
8
|
+
export declare function orderedFixes(report: DoctorReport): string[];
|
|
9
|
+
/** One line per check, then an ordered "fix this first" list. */
|
|
10
|
+
export declare function renderDoctorText(report: DoctorReport): string;
|
|
11
|
+
/** Machine-readable form, for a wrapper or the board to render. */
|
|
12
|
+
export declare function renderDoctorJson(report: DoctorReport): string;
|
|
13
|
+
//# sourceMappingURL=report.d.ts.map
|