litmus-cli 1.4.32 → 1.4.33

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.
@@ -0,0 +1,492 @@
1
+ /**
2
+ * Post-init capture self-test (ENG-2477).
3
+ *
4
+ * WHY THIS EXISTS. A candidate ran Cursor for a full hour on the CLI lane,
5
+ * produced zero captured prompts, and the report told the judge the tool was
6
+ * not used. Every safeguard `init` had for that was a config validator or a
7
+ * sentence: the hook entry is present, the logger file exists, "restart your
8
+ * editor". None of them asks the only question that matters, which is whether
9
+ * a prompt typed into the tool would reach Litmus. Checked on a real
10
+ * engineer's machine on 2026-09-22, `~/.cursor/hooks.json` pointed at a
11
+ * leftover debugging probe: valid JSON, executable, exits 0, returns a
12
+ * well-formed verdict, sends nothing. Every shape-check passes on that file
13
+ * and it captures nothing. There will be a third cause with the same symptom.
14
+ *
15
+ * WHAT IT DOES. For each tool `init` configures, read the command string back
16
+ * out of the file the TOOL reads, run it the way the tool would (through the
17
+ * shell, the tool's own payload shape on stdin), and then ask the backend
18
+ * whether the resulting event landed in `candidate_activity_logs`. The payload
19
+ * carries a nonce; the read-back matches on it. Same reasoning as the
20
+ * Codespaces image's build-time hook self-test (`install-cursor-hook.sh` §4:
21
+ * a synthetic payload on stdin, asserted rather than assumed), one step
22
+ * further: that test asserts the hook exits 0 with parseable stdout, this one
23
+ * asserts an event ARRIVED, because exit 0 and a parseable verdict is exactly
24
+ * what the leftover probe produced.
25
+ *
26
+ * WHAT IT PROVES AND WHAT IT DOES NOT. Arrival proves the whole chain from the
27
+ * config file's command string to a row in the database: the entry is ours,
28
+ * the path resolves, node runs, the logger finds the assessment, reads the
29
+ * token, and the upload reaches the backend. It does NOT prove the tool will
30
+ * invoke that command. Cursor and Codex read their hook config once at launch,
31
+ * so a tool that was already open when `init` wrote the file fires nothing
32
+ * until it is restarted; and Codex, Gemini and Copilot skip untrusted hooks in
33
+ * silence. Those cannot be probed from outside the tool, which is why the pass
34
+ * message still carries the restart instruction, sharpened by a process scan
35
+ * to name the tool that is open right now. The probe also runs with THIS
36
+ * terminal's environment, not the editor's: a `node` that resolves here and
37
+ * not inside a Dock-launched Cursor is a gap this check cannot see.
38
+ *
39
+ * WARN, NOT GATE — and why. A failing self-test prints a red block as the last
40
+ * thing `init` outputs, records the verdict in `.litmus/` and uploads it as a
41
+ * `capture_selftest` event so the report and the admin monitor can see it,
42
+ * and then lets the candidate proceed. It does not refuse to finish. Three
43
+ * reasons, in order of weight:
44
+ *
45
+ * 1. The candidate may use none of these tools. A Cursor hook that cannot
46
+ * reach Litmus is no reason to block someone about to work with a web
47
+ * chat or no AI at all, and `init` cannot tell which candidate it has.
48
+ * 2. The check depends on things outside the candidate's control — the
49
+ * backend, their network, a corporate proxy. A gate turns a transient
50
+ * outage of ours into a candidate locked out minutes before a live
51
+ * interview, which is a worse harm than the one being prevented.
52
+ * 3. What a missed capture now costs the candidate is bounded. ENG-2476
53
+ * makes a zero-prompt Cursor session read as unmeasurable rather than as
54
+ * "did not use AI", so proceeding with a known gap yields a report that
55
+ * names the gap, not a wrong score. A gate would also need an escape
56
+ * hatch, and a candidate on a clock reaches for escape hatches blindly.
57
+ *
58
+ * The failure is made impossible to miss by placement and by record rather
59
+ * than by refusal: last block printed, coloured, actionable (`litmus doctor`
60
+ * repairs the hook files and re-runs this same check), and stored on both
61
+ * sides so nobody has to have been watching the terminal.
62
+ *
63
+ * Pure decisions live in exported functions so tests can drive them against a
64
+ * fake backend and a deliberately broken hook without going through `init`.
65
+ */
66
+ import { spawn, spawnSync } from "child_process";
67
+ import { randomUUID } from "crypto";
68
+ import { existsSync, mkdirSync, writeFileSync } from "fs";
69
+ import os from "os";
70
+ import path from "path";
71
+ import chalk from "chalk";
72
+ import { installedHookCommands, } from "./ai-tracking.js";
73
+ import { fetchCaptureSelftest, isNetworkError, ServerError } from "./api.js";
74
+ import { classifyClaudeProcesses } from "./detection.js";
75
+ import { getProcessList } from "./platform.js";
76
+ /** The event the logger records for a probe. Not a prompt; no reader counts it. */
77
+ export const PROBE_EVENT_TYPE = "capture_selftest_probe";
78
+ /** The CLI's own verdict, uploaded so the report and the monitor can see it. */
79
+ export const RESULT_EVENT_TYPE = "capture_selftest";
80
+ /** Where the verdict is kept locally, under `.litmus/`. */
81
+ export const SELFTEST_RECORD_FILE = "capture-selftest.json";
82
+ /**
83
+ * Per-hook budget. The logger waits up to 5s for a complete payload on stdin
84
+ * (STDIN_TIMEOUT_MS) and up to 2s for the upload (UPLOAD_TIMEOUT_MS); the
85
+ * hook runners themselves allow 10-30s. Generous on purpose: a probe that is
86
+ * killed early would report "no event" for a hook that was about to deliver.
87
+ */
88
+ export const HOOK_TIMEOUT_MS = 15000;
89
+ export const TOOL_LABELS = {
90
+ claude: "Claude Code",
91
+ codex: "Codex",
92
+ cursor: "Cursor",
93
+ gemini: "the Gemini CLI",
94
+ copilot: "Copilot",
95
+ };
96
+ // ── Probe payloads ────────────────────────────────────────────────
97
+ /** The prompt text a probe carries. Carries the nonce so a pre-ENG-2477 logger's
98
+ * `ai_prompt` record of it is still recognisable on the read-back. */
99
+ export function probePromptText(nonce) {
100
+ return `Litmus capture self-test ${nonce}. Not a candidate prompt.`;
101
+ }
102
+ /**
103
+ * The payload each tool's prompt hook would deliver, in that tool's shape, so
104
+ * the logger's real per-tool branch runs. Field sets are the ones the logger's
105
+ * extractPrompt documents per tool. `litmus_selftest` is the marker.
106
+ */
107
+ export function probePayload(tool, nonce, assessmentDir) {
108
+ const prompt = probePromptText(nonce);
109
+ const sessionId = `litmus-selftest-${nonce}`;
110
+ switch (tool) {
111
+ case "cursor":
112
+ return {
113
+ hook_event_name: "beforeSubmitPrompt",
114
+ conversation_id: sessionId,
115
+ generation_id: `${sessionId}-gen`,
116
+ cursor_version: "litmus-selftest",
117
+ prompt,
118
+ workspace_roots: [assessmentDir],
119
+ litmus_selftest: nonce,
120
+ };
121
+ case "claude":
122
+ return {
123
+ hook_event_name: "UserPromptSubmit",
124
+ session_id: sessionId,
125
+ transcript_path: "",
126
+ cwd: assessmentDir,
127
+ prompt,
128
+ litmus_selftest: nonce,
129
+ };
130
+ case "codex":
131
+ return {
132
+ hook_event_name: "UserPromptSubmit",
133
+ session_id: sessionId,
134
+ turn_id: `${sessionId}-turn`,
135
+ cwd: assessmentDir,
136
+ prompt,
137
+ litmus_selftest: nonce,
138
+ };
139
+ case "gemini":
140
+ return {
141
+ hook_event_name: "BeforeAgent",
142
+ session_id: sessionId,
143
+ cwd: assessmentDir,
144
+ prompt,
145
+ litmus_selftest: nonce,
146
+ };
147
+ case "copilot":
148
+ return {
149
+ hook_event_name: "UserPromptSubmit",
150
+ session_id: sessionId,
151
+ cwd: assessmentDir,
152
+ timestamp: new Date().toISOString(),
153
+ prompt,
154
+ litmus_selftest: nonce,
155
+ };
156
+ }
157
+ }
158
+ const TAIL_CHARS = 200;
159
+ /**
160
+ * The one line of a hook's stderr worth showing. Node prints a location, a
161
+ * caret and a stack around the line that names the cause, so the LAST lines
162
+ * are the least useful ("} | Node.js v24.11.0", measured on the live run);
163
+ * prefer the first line that reads like an error, fall back to the last one.
164
+ */
165
+ function tail(s) {
166
+ const lines = s.trim().split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
167
+ if (lines.length === 0)
168
+ return "";
169
+ const cause = lines.find((l) => /\b(error|cannot|denied|not found|no such|not recognized)\b/i.test(l)) ?? lines[lines.length - 1];
170
+ return cause.length > TAIL_CHARS ? cause.slice(0, TAIL_CHARS) + "..." : cause;
171
+ }
172
+ /**
173
+ * Run one hook command the way its tool would: handed to the platform shell
174
+ * (`/bin/sh -c` on POSIX, `cmd.exe /c` on Windows, which is what the command's
175
+ * quoting was written for — see quoteForShell), payload on stdin, then stdin
176
+ * closed. The command string is not parsed or rebuilt here; whatever the
177
+ * candidate's file says is what runs.
178
+ *
179
+ * THE TIMEOUT IS AUTHORITATIVE. A hook is a candidate-controlled command, and
180
+ * it can start something that outlives it while holding the stdout/stderr
181
+ * pipes it inherited. Waiting for `close` would then wait for that grandchild,
182
+ * and neither `init` nor `doctor` has an outer deadline, so the candidate
183
+ * would sit at a spinner, blocked by the check meant to protect them, at the
184
+ * worst possible moment (Greptile on #2600). So on the deadline this settles
185
+ * with what it has, destroys its ends of the pipes, and kills the whole
186
+ * process group (the shell is spawned as a group leader for exactly that), or
187
+ * the tree on Windows. A hook that has not delivered inside HOOK_TIMEOUT_MS
188
+ * has not delivered; nothing it does afterwards changes the verdict.
189
+ */
190
+ export function runHookCommand(command, payload, opts = { cwd: process.cwd() }) {
191
+ const timeoutMs = opts.timeoutMs ?? HOOK_TIMEOUT_MS;
192
+ return new Promise((resolve) => {
193
+ let stdout = "";
194
+ let stderr = "";
195
+ let settled = false;
196
+ const finish = (run) => {
197
+ if (settled)
198
+ return;
199
+ settled = true;
200
+ clearTimeout(timer);
201
+ resolve(run);
202
+ };
203
+ let child;
204
+ try {
205
+ child = spawn(command, {
206
+ shell: true,
207
+ cwd: opts.cwd,
208
+ env: opts.env ?? process.env,
209
+ stdio: ["pipe", "pipe", "pipe"],
210
+ windowsHide: true,
211
+ // Own process group on POSIX, so the deadline can kill everything the
212
+ // hook started and not just the shell. No effect on Windows.
213
+ detached: process.platform !== "win32",
214
+ });
215
+ }
216
+ catch (err) {
217
+ resolve({ exitCode: null, stdout: "", stderr: "", timedOut: false, spawnError: err instanceof Error ? err.message : String(err) });
218
+ return;
219
+ }
220
+ const timer = setTimeout(() => {
221
+ killTree(child);
222
+ // Stop holding the pipes: a surviving grandchild may never close them.
223
+ try {
224
+ child.stdout?.destroy();
225
+ }
226
+ catch { /* already closed */ }
227
+ try {
228
+ child.stderr?.destroy();
229
+ }
230
+ catch { /* already closed */ }
231
+ try {
232
+ child.unref();
233
+ }
234
+ catch { /* nothing to release */ }
235
+ finish({ exitCode: null, stdout, stderr, timedOut: true });
236
+ }, timeoutMs);
237
+ child.stdout?.on("data", (d) => { stdout += d.toString("utf8"); });
238
+ child.stderr?.on("data", (d) => { stderr += d.toString("utf8"); });
239
+ child.on("error", (err) => finish({ exitCode: null, stdout, stderr, timedOut: false, spawnError: err.message }));
240
+ child.on("close", (code) => finish({ exitCode: code, stdout, stderr, timedOut: false }));
241
+ try {
242
+ child.stdin?.on("error", () => { });
243
+ child.stdin?.end(JSON.stringify(payload));
244
+ }
245
+ catch { /* the command exited before stdin opened */ }
246
+ });
247
+ }
248
+ /** Kill the hook's whole process tree: the group on POSIX, `taskkill /T` on Windows. */
249
+ function killTree(child) {
250
+ const pid = child.pid;
251
+ if (!pid)
252
+ return;
253
+ if (process.platform === "win32") {
254
+ try {
255
+ spawnSync("taskkill", ["/pid", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true, timeout: 5000 });
256
+ }
257
+ catch { /* best effort */ }
258
+ try {
259
+ child.kill();
260
+ }
261
+ catch { /* already gone */ }
262
+ return;
263
+ }
264
+ try {
265
+ process.kill(-pid, "SIGKILL");
266
+ }
267
+ catch {
268
+ try {
269
+ child.kill("SIGKILL");
270
+ }
271
+ catch { /* already gone */ }
272
+ }
273
+ }
274
+ function describeRun(run) {
275
+ if (run.spawnError)
276
+ return `the hook command could not be started (${run.spawnError})`;
277
+ if (run.timedOut)
278
+ return `the hook command did not finish within ${Math.round(HOOK_TIMEOUT_MS / 1000)}s`;
279
+ const err = tail(run.stderr);
280
+ const exit = run.exitCode === null ? "no exit code" : `exit ${run.exitCode}`;
281
+ return err
282
+ ? `the hook ran (${exit}) but nothing reached Litmus: ${err}`
283
+ : `the hook ran (${exit}) but nothing reached Litmus`;
284
+ }
285
+ function describeMissing(h) {
286
+ switch (h.problem) {
287
+ case "file_missing": return `no hook config at ${h.file}`;
288
+ case "unparseable": return `${h.file} is not valid JSON, so the tool loads no hooks from it`;
289
+ default: return `no Litmus entry under ${h.event} in ${h.file}`;
290
+ }
291
+ }
292
+ /**
293
+ * Fire one probe per tool through its installed command(s), in parallel, then
294
+ * ask the backend which arrived. Never throws; every failure becomes a status
295
+ * on the tool it belongs to, and a read-back failure becomes "unverified"
296
+ * rather than "broken", because those call for different fixes.
297
+ */
298
+ export async function runCaptureSelfTest(opts) {
299
+ const started = Date.now();
300
+ const hooks = opts.hooks ?? installedHookCommands(opts.assessmentDir);
301
+ const confirm = opts.confirm ?? ((nonces) => fetchCaptureSelftest(opts.backendUrl, opts.token, nonces));
302
+ // The hook runners' cwd is not the assessment: Cursor's hooks service runs
303
+ // from its own process, Claude Code from wherever it was launched. Running
304
+ // from HOME makes the logger place the session from the payload, the way it
305
+ // has to for a real prompt; the assessment dir is only the fallback for a
306
+ // machine whose HOME does not resolve.
307
+ const home = os.homedir();
308
+ const cwd = home && existsSync(home) ? home : opts.assessmentDir;
309
+ const fired = await Promise.all(hooks.map(async (h) => {
310
+ if (h.commands.length === 0)
311
+ return { hook: h, nonce: null, runs: [] };
312
+ const nonce = randomUUID();
313
+ const payload = probePayload(h.tool, nonce, opts.assessmentDir);
314
+ const runs = await Promise.all(h.commands.map((cmd) => runHookCommand(cmd, payload, { cwd, timeoutMs: opts.timeoutMs, env: opts.env })));
315
+ return { hook: h, nonce, runs };
316
+ }));
317
+ const nonces = fired.map((f) => f.nonce).filter((n) => n !== null);
318
+ let arrived = null;
319
+ let readBackFailure = null;
320
+ if (nonces.length > 0) {
321
+ try {
322
+ arrived = new Set((await confirm(nonces)).arrived.map((n) => n.toLowerCase()));
323
+ }
324
+ catch (err) {
325
+ readBackFailure = err instanceof ServerError
326
+ ? `Litmus answered ${err.statusCode ?? "an error"}: ${err.message}`
327
+ : isNetworkError(err)
328
+ ? "Litmus could not be reached"
329
+ : (err instanceof Error ? err.message : String(err));
330
+ }
331
+ }
332
+ const tools = fired.map(({ hook, nonce, runs }) => {
333
+ const label = TOOL_LABELS[hook.tool];
334
+ if (nonce === null) {
335
+ return { tool: hook.tool, label, status: "not_installed", file: hook.file, detail: describeMissing(hook) };
336
+ }
337
+ if (arrived === null) {
338
+ return {
339
+ tool: hook.tool, label, status: "unverified", file: hook.file,
340
+ detail: `the hook ran, but whether its event arrived could not be checked (${readBackFailure})`,
341
+ exitCode: runs[0]?.exitCode ?? null,
342
+ };
343
+ }
344
+ if (arrived.has(nonce)) {
345
+ return { tool: hook.tool, label, status: "arrived", file: hook.file, detail: "a test prompt reached Litmus", exitCode: runs[0]?.exitCode ?? null };
346
+ }
347
+ // Several commands under one event would be several of our entries; the
348
+ // first is representative, and the tail names the real cause when there is one.
349
+ const run = runs[0];
350
+ return {
351
+ tool: hook.tool, label, status: "no_event", file: hook.file,
352
+ detail: describeRun(run),
353
+ exitCode: run.exitCode,
354
+ stderrTail: tail(run.stderr) || undefined,
355
+ };
356
+ });
357
+ const verdict = tools.some((t) => t.status === "not_installed" || t.status === "no_event")
358
+ ? "fail"
359
+ : tools.some((t) => t.status === "unverified") ? "unverified" : "pass";
360
+ return { verdict, at: new Date(started).toISOString(), durationMs: Date.now() - started, tools };
361
+ }
362
+ // ── Recording the verdict ─────────────────────────────────────────
363
+ export function writeSelfTestRecord(assessmentDir, report) {
364
+ const litmusDir = path.join(assessmentDir, ".litmus");
365
+ mkdirSync(litmusDir, { recursive: true });
366
+ writeFileSync(path.join(litmusDir, SELFTEST_RECORD_FILE), JSON.stringify(report, null, 2) + "\n");
367
+ }
368
+ /**
369
+ * The event `init` uploads with the verdict. Typed `capture_selftest`, which
370
+ * every reader treats as ours-not-theirs (cli-tracking.ts channel map); it
371
+ * exists so a failed check is visible on the report and the admin monitor,
372
+ * not only in a terminal nobody is watching. Paths are dropped: a home
373
+ * directory is a name.
374
+ */
375
+ export function selfTestResultEvent(report, source) {
376
+ return {
377
+ ts: report.at,
378
+ type: RESULT_EVENT_TYPE,
379
+ source,
380
+ verdict: report.verdict,
381
+ durationMs: report.durationMs,
382
+ tools: Object.fromEntries(report.tools.map((t) => [t.tool, t.status])),
383
+ failures: report.tools
384
+ .filter((t) => t.status !== "arrived")
385
+ .map((t) => ({ tool: t.tool, status: t.status, exitCode: t.exitCode ?? null, stderrTail: t.stderrTail ? withoutHome(t.stderrTail) : null })),
386
+ };
387
+ }
388
+ /** Node's error lines quote absolute paths, and the logger lives under HOME. */
389
+ function withoutHome(s) {
390
+ const home = os.homedir();
391
+ return home ? s.split(home).join("~") : s;
392
+ }
393
+ // ── Which tools are open right now ────────────────────────────────
394
+ /**
395
+ * Tools that read hook config only at launch and are running at this moment,
396
+ * from a process listing (lowercased `ps aux` / `tasklist`). This is the one
397
+ * cause the probe cannot see, so the pass message names the tool by name
398
+ * instead of saying "any tool". Path-anchored patterns, like detection.ts:
399
+ * the word inside a config-directory path is not the tool running.
400
+ */
401
+ export function detectRunningHookTools(ps = safeProcessList()) {
402
+ const found = new Set();
403
+ if (classifyClaudeProcesses(ps).includes("claude_code"))
404
+ found.add("claude");
405
+ for (const line of ps.split("\n")) {
406
+ if (/cursor\.app\/contents\/macos\/cursor|[/\\]cursor(?:\.exe)?(?:\s|$)|cursor-agent/.test(line))
407
+ found.add("cursor");
408
+ if (/[/\\]codex(?:\.exe|\.js)?(?:\s|$)|@openai[/\\]codex/.test(line))
409
+ found.add("codex");
410
+ if (/[/\\]gemini(?:\.exe|\.js)?(?:\s|$)|@google[/\\]gemini-cli/.test(line))
411
+ found.add("gemini");
412
+ if (/[/\\]copilot(?:\.exe|\.js)?(?:\s|$)|@github[/\\]copilot/.test(line))
413
+ found.add("copilot");
414
+ }
415
+ return [...found];
416
+ }
417
+ function safeProcessList() {
418
+ try {
419
+ return getProcessList();
420
+ }
421
+ catch {
422
+ return "";
423
+ }
424
+ }
425
+ // ── Rendering ─────────────────────────────────────────────────────
426
+ function joinLabels(labels) {
427
+ if (labels.length <= 1)
428
+ return labels[0] ?? "";
429
+ return `${labels.slice(0, -1).join(", ")} and ${labels[labels.length - 1]}`;
430
+ }
431
+ /**
432
+ * Lines for the terminal. A failure is a coloured block meant to be the LAST
433
+ * thing `init` prints; a pass is one green line, plus a yellow one naming any
434
+ * tool that is open right now and needs a restart before it will fire.
435
+ */
436
+ export function renderCaptureSelfTest(report, opts) {
437
+ const lines = [];
438
+ const broken = report.tools.filter((t) => t.status === "not_installed" || t.status === "no_event");
439
+ const unverified = report.tools.filter((t) => t.status === "unverified");
440
+ const ok = report.tools.filter((t) => t.status === "arrived");
441
+ const restart = opts.runningTools
442
+ .filter((tool) => report.tools.some((t) => t.tool === tool && t.status !== "not_installed"))
443
+ .map((tool) => TOOL_LABELS[tool]);
444
+ if (report.verdict === "fail") {
445
+ lines.push("");
446
+ lines.push(chalk.bgRed.white.bold(" AI CAPTURE CHECK FAILED: prompts to the tools below will NOT reach Litmus "));
447
+ lines.push("");
448
+ for (const t of broken)
449
+ lines.push(chalk.red(` x ${t.label}: ${t.detail}`));
450
+ if (unverified.length)
451
+ lines.push(chalk.yellow(` ? ${joinLabels(unverified.map((t) => t.label))}: ${unverified[0].detail}`));
452
+ if (ok.length)
453
+ lines.push(chalk.green(` + ${joinLabels(ok.map((t) => t.label))}: a test prompt reached Litmus`));
454
+ lines.push("");
455
+ lines.push(chalk.red.bold(" If you use a tool marked x, nothing you ask it will be recorded, and the hiring"));
456
+ lines.push(chalk.red.bold(" company will see no AI use from you. Fix it before you start:"));
457
+ lines.push(chalk.red(` 1. cd ${opts.folderName} && litmus doctor ${chalk.dim("(repairs the hook files and re-runs this check)")}`));
458
+ lines.push(chalk.red(` 2. quit and reopen ${broken.length === 1 ? broken[0].label : "the tool"} if it is open: it reads its hook config once, at launch`));
459
+ lines.push(chalk.red(" Still failing? Contact the company for help, or visit https://litmushiring.com."));
460
+ return lines;
461
+ }
462
+ if (report.verdict === "unverified") {
463
+ lines.push("");
464
+ lines.push(chalk.yellow.bold(" AI capture could not be verified."));
465
+ lines.push(chalk.yellow(` The hooks ran, but ${unverified[0]?.detail ?? "the check did not complete"}.`));
466
+ lines.push(chalk.yellow(` Once you are online, run ${chalk.bold("litmus doctor")} inside ${opts.folderName} to re-check.`));
467
+ if (restart.length)
468
+ lines.push(...restartLines(restart));
469
+ return lines;
470
+ }
471
+ lines.push("");
472
+ lines.push(chalk.green(` AI capture verified: a test prompt through the ${joinLabels(ok.map((t) => t.label))} hooks reached Litmus.`));
473
+ if (restart.length)
474
+ lines.push(...restartLines(restart));
475
+ return lines;
476
+ }
477
+ /**
478
+ * The restart notice for tools that are open right now, shared by init's
479
+ * verdict block and doctor's failure lines so the two never disagree on the
480
+ * grammar or the claim.
481
+ */
482
+ export function renderRestartNotice(tools, opts = { then: "before you start" }) {
483
+ return restartLines(tools.map((t) => TOOL_LABELS[t]), opts.then);
484
+ }
485
+ function restartLines(labels, then = "before you start") {
486
+ const one = labels.length === 1;
487
+ return [
488
+ chalk.yellow.bold(` ${joinLabels(labels)} ${one ? "is" : "are"} open right now and ${one ? "reads" : "read"} hook config only at launch.`),
489
+ chalk.yellow.bold(` Quit and reopen ${one ? "it" : "them"} ${then}, or ${one ? "its" : "their"} prompts will not be captured.`),
490
+ ];
491
+ }
492
+ //# sourceMappingURL=capture-selftest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-selftest.js","sourceRoot":"","sources":["../../src/lib/capture-selftest.ts"],"names":[],"mappings":"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"}