lacuna-cli 0.1.1

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.
Files changed (144) hide show
  1. package/README.md +451 -0
  2. package/bin/run.js +5 -0
  3. package/dist/agent/context.d.ts +25 -0
  4. package/dist/agent/context.d.ts.map +1 -0
  5. package/dist/agent/context.js +366 -0
  6. package/dist/agent/context.js.map +1 -0
  7. package/dist/agent/fix-loop.d.ts +20 -0
  8. package/dist/agent/fix-loop.d.ts.map +1 -0
  9. package/dist/agent/fix-loop.js +466 -0
  10. package/dist/agent/fix-loop.js.map +1 -0
  11. package/dist/agent/generator.d.ts +35 -0
  12. package/dist/agent/generator.d.ts.map +1 -0
  13. package/dist/agent/generator.js +220 -0
  14. package/dist/agent/generator.js.map +1 -0
  15. package/dist/agent/loop.d.ts +23 -0
  16. package/dist/agent/loop.d.ts.map +1 -0
  17. package/dist/agent/loop.js +394 -0
  18. package/dist/agent/loop.js.map +1 -0
  19. package/dist/agent/project-memory.d.ts +10 -0
  20. package/dist/agent/project-memory.d.ts.map +1 -0
  21. package/dist/agent/project-memory.js +57 -0
  22. package/dist/agent/project-memory.js.map +1 -0
  23. package/dist/agent/prompts.d.ts +44 -0
  24. package/dist/agent/prompts.d.ts.map +1 -0
  25. package/dist/agent/prompts.js +377 -0
  26. package/dist/agent/prompts.js.map +1 -0
  27. package/dist/ci/comment.d.ts +2 -0
  28. package/dist/ci/comment.d.ts.map +1 -0
  29. package/dist/ci/comment.js +97 -0
  30. package/dist/ci/comment.js.map +1 -0
  31. package/dist/ci/parse-outputs.d.ts +2 -0
  32. package/dist/ci/parse-outputs.d.ts.map +1 -0
  33. package/dist/ci/parse-outputs.js +30 -0
  34. package/dist/ci/parse-outputs.js.map +1 -0
  35. package/dist/commands/analyze.d.ts +13 -0
  36. package/dist/commands/analyze.d.ts.map +1 -0
  37. package/dist/commands/analyze.js +151 -0
  38. package/dist/commands/analyze.js.map +1 -0
  39. package/dist/commands/fix.d.ts +15 -0
  40. package/dist/commands/fix.d.ts.map +1 -0
  41. package/dist/commands/fix.js +106 -0
  42. package/dist/commands/fix.js.map +1 -0
  43. package/dist/commands/generate.d.ts +18 -0
  44. package/dist/commands/generate.d.ts.map +1 -0
  45. package/dist/commands/generate.js +129 -0
  46. package/dist/commands/generate.js.map +1 -0
  47. package/dist/commands/init.d.ts +7 -0
  48. package/dist/commands/init.d.ts.map +1 -0
  49. package/dist/commands/init.js +131 -0
  50. package/dist/commands/init.js.map +1 -0
  51. package/dist/commands/run.d.ts +10 -0
  52. package/dist/commands/run.d.ts.map +1 -0
  53. package/dist/commands/run.js +45 -0
  54. package/dist/commands/run.js.map +1 -0
  55. package/dist/lib/config.d.ts +58 -0
  56. package/dist/lib/config.d.ts.map +1 -0
  57. package/dist/lib/config.js +68 -0
  58. package/dist/lib/config.js.map +1 -0
  59. package/dist/lib/coverage/gaps.d.ts +12 -0
  60. package/dist/lib/coverage/gaps.d.ts.map +1 -0
  61. package/dist/lib/coverage/gaps.js +186 -0
  62. package/dist/lib/coverage/gaps.js.map +1 -0
  63. package/dist/lib/coverage/index.d.ts +7 -0
  64. package/dist/lib/coverage/index.d.ts.map +1 -0
  65. package/dist/lib/coverage/index.js +24 -0
  66. package/dist/lib/coverage/index.js.map +1 -0
  67. package/dist/lib/coverage/json.d.ts +3 -0
  68. package/dist/lib/coverage/json.d.ts.map +1 -0
  69. package/dist/lib/coverage/json.js +24 -0
  70. package/dist/lib/coverage/json.js.map +1 -0
  71. package/dist/lib/coverage/lcov.d.ts +3 -0
  72. package/dist/lib/coverage/lcov.d.ts.map +1 -0
  73. package/dist/lib/coverage/lcov.js +58 -0
  74. package/dist/lib/coverage/lcov.js.map +1 -0
  75. package/dist/lib/coverage/types.d.ts +27 -0
  76. package/dist/lib/coverage/types.d.ts.map +1 -0
  77. package/dist/lib/coverage/types.js +2 -0
  78. package/dist/lib/coverage/types.js.map +1 -0
  79. package/dist/lib/coverage-spinner.d.ts +6 -0
  80. package/dist/lib/coverage-spinner.d.ts.map +1 -0
  81. package/dist/lib/coverage-spinner.js +101 -0
  82. package/dist/lib/coverage-spinner.js.map +1 -0
  83. package/dist/lib/detector.d.ts +13 -0
  84. package/dist/lib/detector.d.ts.map +1 -0
  85. package/dist/lib/detector.js +106 -0
  86. package/dist/lib/detector.js.map +1 -0
  87. package/dist/lib/extract-error.d.ts +2 -0
  88. package/dist/lib/extract-error.d.ts.map +1 -0
  89. package/dist/lib/extract-error.js +116 -0
  90. package/dist/lib/extract-error.js.map +1 -0
  91. package/dist/lib/providers/anthropic.d.ts +8 -0
  92. package/dist/lib/providers/anthropic.d.ts.map +1 -0
  93. package/dist/lib/providers/anthropic.js +38 -0
  94. package/dist/lib/providers/anthropic.js.map +1 -0
  95. package/dist/lib/providers/index.d.ts +6 -0
  96. package/dist/lib/providers/index.d.ts.map +1 -0
  97. package/dist/lib/providers/index.js +27 -0
  98. package/dist/lib/providers/index.js.map +1 -0
  99. package/dist/lib/providers/openai-compatible.d.ts +11 -0
  100. package/dist/lib/providers/openai-compatible.d.ts.map +1 -0
  101. package/dist/lib/providers/openai-compatible.js +93 -0
  102. package/dist/lib/providers/openai-compatible.js.map +1 -0
  103. package/dist/lib/providers/types.d.ts +17 -0
  104. package/dist/lib/providers/types.d.ts.map +1 -0
  105. package/dist/lib/providers/types.js +97 -0
  106. package/dist/lib/providers/types.js.map +1 -0
  107. package/dist/lib/report-upload.d.ts +3 -0
  108. package/dist/lib/report-upload.d.ts.map +1 -0
  109. package/dist/lib/report-upload.js +15 -0
  110. package/dist/lib/report-upload.js.map +1 -0
  111. package/dist/lib/reporter.d.ts +51 -0
  112. package/dist/lib/reporter.d.ts.map +1 -0
  113. package/dist/lib/reporter.js +172 -0
  114. package/dist/lib/reporter.js.map +1 -0
  115. package/dist/lib/runner.d.ts +9 -0
  116. package/dist/lib/runner.d.ts.map +1 -0
  117. package/dist/lib/runner.js +50 -0
  118. package/dist/lib/runner.js.map +1 -0
  119. package/dist/lib/skeleton.d.ts +8 -0
  120. package/dist/lib/skeleton.d.ts.map +1 -0
  121. package/dist/lib/skeleton.js +122 -0
  122. package/dist/lib/skeleton.js.map +1 -0
  123. package/dist/lib/streaming-viewer.d.ts +14 -0
  124. package/dist/lib/streaming-viewer.d.ts.map +1 -0
  125. package/dist/lib/streaming-viewer.js +80 -0
  126. package/dist/lib/streaming-viewer.js.map +1 -0
  127. package/dist/lib/tips.d.ts +16 -0
  128. package/dist/lib/tips.d.ts.map +1 -0
  129. package/dist/lib/tips.js +76 -0
  130. package/dist/lib/tips.js.map +1 -0
  131. package/dist/lib/typecheck.d.ts +3 -0
  132. package/dist/lib/typecheck.d.ts.map +1 -0
  133. package/dist/lib/typecheck.js +28 -0
  134. package/dist/lib/typecheck.js.map +1 -0
  135. package/dist/lib/validate.d.ts +7 -0
  136. package/dist/lib/validate.d.ts.map +1 -0
  137. package/dist/lib/validate.js +82 -0
  138. package/dist/lib/validate.js.map +1 -0
  139. package/dist/lib/worker-display.d.ts +45 -0
  140. package/dist/lib/worker-display.d.ts.map +1 -0
  141. package/dist/lib/worker-display.js +168 -0
  142. package/dist/lib/worker-display.js.map +1 -0
  143. package/oclif.manifest.json +295 -0
  144. package/package.json +62 -0
@@ -0,0 +1,466 @@
1
+ import { readFile, writeFile, mkdir, unlink } from 'fs/promises';
2
+ import { join, dirname, basename, extname } from 'path';
3
+ import { access, stat } from 'fs/promises';
4
+ import chalk from 'chalk';
5
+ import { fileTestCommand } from '../lib/detector.js';
6
+ import { runCommand } from '../lib/runner.js';
7
+ import { startCoverageSpinner } from '../lib/coverage-spinner.js';
8
+ import { WorkerDisplay } from '../lib/worker-display.js';
9
+ import { buildFixFileContext, computeRelativeImport, collectTypeDefinitions, collectLocalImportPaths, detectReactMajorVersion } from './context.js';
10
+ import { TestGenerator, TruncatedOutputError, OscillationError, TRUNCATION_RETRY_MESSAGE } from './generator.js';
11
+ import { ProjectMemory } from './project-memory.js';
12
+ import { getActiveTips, createTipRotator, formatTip } from '../lib/tips.js';
13
+ import { typeCheckFile } from '../lib/typecheck.js';
14
+ import { hasTestFunctions, enrichNoTestsError, isZeroTestsOutput, parsePassCount, buildStructureBrokenMessage, buildRegressionMessage } from '../lib/validate.js';
15
+ import { extractTestFailure } from '../lib/extract-error.js';
16
+ import { StreamingFileViewer } from '../lib/streaming-viewer.js';
17
+ // ─── Failing-files cache ──────────────────────────────────────────────────────
18
+ const FIX_CACHE_TTL_S = 1800; // 30 minutes
19
+ function fixCachePath(cwd) {
20
+ return join(cwd, '.lacuna-fix-cache.json');
21
+ }
22
+ async function loadFixCache(cwd) {
23
+ try {
24
+ const cachePath = fixCachePath(cwd);
25
+ const [raw, fileStat] = await Promise.all([readFile(cachePath, 'utf-8'), stat(cachePath)]);
26
+ const { files } = JSON.parse(raw);
27
+ const ageSeconds = (Date.now() - fileStat.mtimeMs) / 1000;
28
+ return { files, ageSeconds };
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ async function saveFixCache(cwd, files) {
35
+ try {
36
+ await writeFile(fixCachePath(cwd), JSON.stringify({ files }), 'utf-8');
37
+ }
38
+ catch {
39
+ // non-fatal — cache is best-effort
40
+ }
41
+ }
42
+ async function clearFixCache(cwd) {
43
+ try {
44
+ await unlink(fixCachePath(cwd));
45
+ }
46
+ catch { /* already gone — fine */ }
47
+ }
48
+ // ─── Parse failing test files from runner output ──────────────────────────────
49
+ const TEST_FILE_RE = /[\w./\\@-]+\.(?:test|spec)\.(?:tsx|mts|ts|jsx|js)/;
50
+ function parseFailingTestFiles(output, runner) {
51
+ const files = new Set();
52
+ const lines = output.split('\n');
53
+ for (const line of lines) {
54
+ const clean = line.replace(/\x1B\[[0-9;]*m/g, '').trim();
55
+ // Vitest: cross character followed by file path (covers multiple cross symbols across versions)
56
+ if (runner === 'vitest' || runner === 'unknown') {
57
+ const m = clean.match(new RegExp(`^[×✗✕✖✘❌]\\s+(${TEST_FILE_RE.source})`));
58
+ if (m) {
59
+ files.add(m[1]);
60
+ continue;
61
+ }
62
+ }
63
+ // "FAIL <path>" — used by Jest and some Vitest reporters/configurations
64
+ if (runner === 'jest' || runner === 'vitest' || runner === 'unknown') {
65
+ const m = clean.match(new RegExp(`^FAIL\\s+(${TEST_FILE_RE.source})`));
66
+ if (m) {
67
+ files.add(m[1]);
68
+ continue;
69
+ }
70
+ }
71
+ }
72
+ // Fallback: if no files matched via primary patterns, extract test file paths from
73
+ // stack traces. A path in a stack trace always belongs to a file that ran and failed.
74
+ // Over-inclusive is fine — fixFile re-runs each file first and skips it if already passing.
75
+ if (files.size === 0) {
76
+ for (const line of lines) {
77
+ const clean = line.replace(/\x1B\[[0-9;]*m/g, '').trim();
78
+ // stack trace: at ... (src/foo.test.tsx:42:5) or at src/foo.test.tsx:42
79
+ const m = clean.match(new RegExp(`\\(?(${TEST_FILE_RE.source}):\\d+`));
80
+ if (m)
81
+ files.add(m[1]);
82
+ }
83
+ }
84
+ return [...files];
85
+ }
86
+ // ─── Find the source file that a test file is testing ────────────────────────
87
+ async function findSourceFile(testFilePath, cwd) {
88
+ const ext = extname(testFilePath);
89
+ const base = basename(testFilePath, ext);
90
+ const dir = dirname(testFilePath);
91
+ // strip test suffix: Button.test → Button, Button.spec → Button
92
+ const sourceBase = base.replace(/\.(test|spec)$/, '').replace(/^test_/, '').replace(/_test$/, '');
93
+ // if inside __tests__ dir, source is in parent
94
+ const sourceDir = basename(dir) === '__tests__' ? dirname(dir) : dir;
95
+ const exts = [ext, '.ts', '.tsx', '.js', '.jsx'];
96
+ for (const e of exts) {
97
+ const candidate = join(cwd, sourceDir, `${sourceBase}${e}`);
98
+ try {
99
+ await access(candidate);
100
+ return candidate;
101
+ }
102
+ catch { /* try next */ }
103
+ }
104
+ return null;
105
+ }
106
+ // ─── Fix a single test file ───────────────────────────────────────────────────
107
+ async function fixFile(testFilePath, options, generator, onStatus, projectMemory) {
108
+ const { config, env, cwd, dryRun, verbose, log } = options;
109
+ const shortPath = testFilePath.replace(cwd + '/', '');
110
+ const absTestPath = testFilePath.startsWith('/') ? testFilePath : join(cwd, testFilePath);
111
+ if (!onStatus)
112
+ log(chalk.bold(`\n Fixing: ${chalk.cyan(shortPath)}`));
113
+ onStatus?.({ phase: 'running', file: shortPath });
114
+ // Run just this test file to get focused error output
115
+ const firstRun = await runCommand(fileTestCommand(env, absTestPath), cwd, 60_000);
116
+ if (firstRun.success) {
117
+ if (!onStatus)
118
+ log(chalk.green(' Already passing — skipping.'));
119
+ onStatus?.({ phase: 'passed', file: shortPath });
120
+ return { success: true };
121
+ }
122
+ let errorOutput = extractTestFailure(firstRun.stdout + '\n' + firstRun.stderr);
123
+ const initialErrorOutput = errorOutput;
124
+ const baselinePassCount = parsePassCount(firstRun.stdout + '\n' + firstRun.stderr);
125
+ // Read existing test file
126
+ let testCode;
127
+ try {
128
+ testCode = await readFile(absTestPath, 'utf-8');
129
+ }
130
+ catch {
131
+ const msg = `Could not read test file: ${shortPath}`;
132
+ if (!onStatus)
133
+ log(chalk.red(` ${msg}`));
134
+ onStatus?.({ phase: 'failed', file: shortPath });
135
+ return { success: false, error: msg };
136
+ }
137
+ // Find and read the source file being tested
138
+ const sourceFilePath = await findSourceFile(testFilePath, cwd);
139
+ let sourceCode = null;
140
+ if (sourceFilePath) {
141
+ sourceCode = await readFile(sourceFilePath, 'utf-8').catch(() => null);
142
+ }
143
+ const sourceImportPath = sourceFilePath ? computeRelativeImport(absTestPath, sourceFilePath) : null;
144
+ // Collect type definitions, local import paths, and React version in parallel
145
+ const [typeDefinitions, localImportPaths, reactMajorVersion] = await Promise.all([
146
+ sourceCode && sourceFilePath
147
+ ? collectTypeDefinitions(sourceCode, sourceFilePath, cwd).catch(() => null)
148
+ : Promise.resolve(null),
149
+ sourceCode && sourceFilePath
150
+ ? collectLocalImportPaths(sourceCode, sourceFilePath, absTestPath, cwd).catch(() => null)
151
+ : Promise.resolve(null),
152
+ detectReactMajorVersion(cwd).catch(() => null),
153
+ ]);
154
+ // Build mocks/setup context relative to the actual test file path
155
+ const ctx = await buildFixFileContext(absTestPath, cwd, config).catch(() => null);
156
+ if (!onStatus)
157
+ log(chalk.dim(` Sending to ${config.model} for repair...`));
158
+ onStatus?.({ phase: 'generating', file: shortPath });
159
+ for (let attempt = 1; attempt <= config.maxIterations; attempt++) {
160
+ if (attempt > 1) {
161
+ if (!onStatus)
162
+ log(chalk.yellow(`\n Retry ${attempt}/${config.maxIterations}...`));
163
+ onStatus?.({ phase: 'retrying', file: shortPath, attempt, max: config.maxIterations });
164
+ }
165
+ let viewer;
166
+ if (verbose && !onStatus) {
167
+ viewer = new StreamingFileViewer(shortPath);
168
+ generator.setTokenCallback(t => viewer.append(t));
169
+ viewer.start();
170
+ }
171
+ let fixed;
172
+ try {
173
+ fixed = attempt === 1
174
+ ? await generator.fix({
175
+ testFile: shortPath,
176
+ testCode,
177
+ sourceFile: sourceFilePath?.replace(cwd + '/', '') ?? null,
178
+ sourceCode,
179
+ sourceImportPath,
180
+ errorOutput,
181
+ mocksCode: ctx?.mocksCode ?? null,
182
+ mocksImportPath: ctx?.mocksImportPath ?? null,
183
+ setupFileCode: ctx?.setupFileCode ?? null,
184
+ packageDeps: ctx?.packageDeps ?? null,
185
+ tsconfigPaths: ctx?.tsconfigPaths ?? null,
186
+ typeDefinitions,
187
+ localImportPaths,
188
+ reactMajorVersion,
189
+ projectMemory,
190
+ })
191
+ : await generator.retry(errorOutput);
192
+ }
193
+ catch (err) {
194
+ viewer?.stop();
195
+ generator.setTokenCallback(undefined);
196
+ if (err instanceof TruncatedOutputError) {
197
+ errorOutput = TRUNCATION_RETRY_MESSAGE;
198
+ if (!onStatus)
199
+ log(chalk.yellow(`\n Output truncated — retrying with shorter output request...`));
200
+ onStatus?.({ phase: 'retrying', file: shortPath, attempt, max: config.maxIterations });
201
+ continue;
202
+ }
203
+ if (err instanceof OscillationError) {
204
+ if (!onStatus)
205
+ log(chalk.red(`\n ⚠ Agent loop detected — output identical to a previous attempt. Stopping early.`));
206
+ onStatus?.({ phase: 'failed', file: shortPath });
207
+ await writeFile(absTestPath, testCode, 'utf-8').catch(() => { });
208
+ return { success: false, error: err.message };
209
+ }
210
+ const msg = err instanceof Error ? err.message : String(err);
211
+ if (!onStatus)
212
+ log(chalk.red(`\n API error: ${msg}`));
213
+ onStatus?.({ phase: 'failed', file: shortPath });
214
+ return { success: false, error: msg };
215
+ }
216
+ viewer?.stop();
217
+ generator.setTokenCallback(undefined);
218
+ if (dryRun) {
219
+ if (!onStatus) {
220
+ log(chalk.yellow('\n [dry-run] Would write:'));
221
+ log(chalk.dim(fixed.split('\n').slice(0, 10).map((l) => ` ${l}`).join('\n')));
222
+ }
223
+ onStatus?.({ phase: 'passed', file: shortPath });
224
+ return { success: true };
225
+ }
226
+ // Split out mocks file if AI returned one
227
+ const MOCKS_SEPARATOR = '// ---MOCKS_FILE---';
228
+ let testFileContent = fixed;
229
+ if (fixed.includes(MOCKS_SEPARATOR) && config.mocksFile) {
230
+ const [newTestCode, newMocksCode] = fixed.split(MOCKS_SEPARATOR);
231
+ testFileContent = newTestCode.trim();
232
+ if (newMocksCode?.trim()) {
233
+ const absoluteMocksFile = join(cwd, config.mocksFile);
234
+ await mkdir(dirname(absoluteMocksFile), { recursive: true });
235
+ await writeFile(absoluteMocksFile, newMocksCode.trim(), 'utf-8');
236
+ if (!onStatus)
237
+ log(chalk.dim(` Updated mocks file: ${config.mocksFile}`));
238
+ }
239
+ }
240
+ // Catch empty test files before writing
241
+ if (!hasTestFunctions(testFileContent)) {
242
+ errorOutput =
243
+ 'ERROR: The code you returned contains NO test functions (no it() or test() calls).\n' +
244
+ 'Do not write a file with only imports, types, describe() blocks, or helpers.\n' +
245
+ 'Every test file must contain at least one: it(\'description\', () => { expect(...).toBe(...) })\n' +
246
+ 'Rewrite the file and include real test cases.';
247
+ if (!onStatus)
248
+ log(chalk.yellow(` Generated file has no tests — retrying...`));
249
+ onStatus?.({ phase: 'retrying', file: shortPath, attempt, max: config.maxIterations });
250
+ continue;
251
+ }
252
+ onStatus?.({ phase: 'writing', file: shortPath });
253
+ await writeFile(absTestPath, testFileContent, 'utf-8');
254
+ if (!onStatus)
255
+ log(chalk.dim(' Written. Running tests...'));
256
+ onStatus?.({ phase: 'running', file: shortPath });
257
+ const result = await runCommand(fileTestCommand(env, absTestPath), cwd, 60_000);
258
+ if (result.success) {
259
+ const typeErrors = await typeCheckFile(absTestPath, cwd, env);
260
+ if (typeErrors) {
261
+ errorOutput = `Tests passed but TypeScript type errors were found:\n${typeErrors}\n\nFix ALL type errors. Do not use 'as any' or '@ts-ignore'.`;
262
+ if (!onStatus)
263
+ log(chalk.yellow(' Type errors found — retrying...'));
264
+ onStatus?.({ phase: 'retrying', file: shortPath, attempt, max: config.maxIterations });
265
+ continue;
266
+ }
267
+ if (!onStatus)
268
+ log(chalk.green(' Fixed.'));
269
+ onStatus?.({ phase: 'passed', file: shortPath });
270
+ return { success: true };
271
+ }
272
+ const rawRunOutput = result.stdout + '\n' + result.stderr;
273
+ const extracted = enrichNoTestsError(extractTestFailure(rawRunOutput));
274
+ const structureBroken = isZeroTestsOutput(rawRunOutput);
275
+ const currentPassCount = structureBroken ? 0 : parsePassCount(rawRunOutput);
276
+ if (structureBroken) {
277
+ errorOutput = buildStructureBrokenMessage(initialErrorOutput, extracted);
278
+ if (!onStatus)
279
+ log(chalk.red(` Fix broke file structure — 0 tests collected (attempt ${attempt}/${config.maxIterations})`));
280
+ }
281
+ else if (currentPassCount < baselinePassCount) {
282
+ errorOutput = buildRegressionMessage(initialErrorOutput, extracted, baselinePassCount, currentPassCount);
283
+ if (!onStatus)
284
+ log(chalk.red(` Fix caused regression: ${baselinePassCount} → ${currentPassCount} passing (attempt ${attempt}/${config.maxIterations})`));
285
+ }
286
+ else {
287
+ errorOutput = extracted;
288
+ if (!onStatus)
289
+ log(chalk.red(` Still failing (attempt ${attempt}/${config.maxIterations})`));
290
+ }
291
+ if (!onStatus && verbose)
292
+ log(chalk.dim(errorOutput.split('\n').slice(0, 20).join('\n')));
293
+ }
294
+ // Restore original test file — don't leave broken AI code on disk
295
+ await writeFile(absTestPath, testCode, 'utf-8').catch(() => { });
296
+ onStatus?.({ phase: 'failed', file: shortPath });
297
+ return {
298
+ success: false,
299
+ error: `Still failing after ${config.maxIterations} attempts. Last error:\n${errorOutput.slice(0, 1500)}`,
300
+ };
301
+ }
302
+ // ─── Worker pool ──────────────────────────────────────────────────────────────
303
+ async function runFixWorkers(testFiles, options, workerCount, projectMemory) {
304
+ const queue = [...testFiles];
305
+ let filesProcessed = 0;
306
+ let filesFixed = 0;
307
+ const errors = [];
308
+ const stillFailingFiles = [];
309
+ const tips = getActiveTips({
310
+ workers: workerCount,
311
+ targetFile: options.targetFile,
312
+ verbose: options.verbose,
313
+ dryRun: options.dryRun,
314
+ model: options.config.model,
315
+ threshold: options.config.threshold,
316
+ mocksFile: options.config.mocksFile,
317
+ ignore: options.config.ignore,
318
+ command: 'fix',
319
+ });
320
+ const display = new WorkerDisplay(workerCount, testFiles.length, tips, 'fixed');
321
+ display.start();
322
+ await Promise.all(Array.from({ length: workerCount }, async (_, wi) => {
323
+ const generator = new TestGenerator({ config: options.config, env: options.env });
324
+ while (true) {
325
+ const file = queue.shift();
326
+ if (!file)
327
+ break;
328
+ const onStatus = (state) => display.update(wi, state);
329
+ const result = await fixFile(file, { ...options, log: () => { }, verbose: false }, generator, onStatus, projectMemory);
330
+ filesProcessed++;
331
+ if (result.success)
332
+ filesFixed++;
333
+ else {
334
+ stillFailingFiles.push(file);
335
+ if (result.error)
336
+ errors.push(result.error);
337
+ }
338
+ }
339
+ }));
340
+ display.finish();
341
+ return { filesProcessed, filesFixed, errors, stillFailingFiles };
342
+ }
343
+ // ─── Main entry point ─────────────────────────────────────────────────────────
344
+ export async function runFixLoop(options) {
345
+ const { config, env, cwd, log } = options;
346
+ const workerCount = Math.max(1, Math.min(options.workers ?? 1, 10));
347
+ const parallel = workerCount > 1;
348
+ let failingFiles;
349
+ if (options.targetFile) {
350
+ // Single-file mode: skip the full suite run, go straight to the target file
351
+ const absTarget = options.targetFile.startsWith('/')
352
+ ? options.targetFile
353
+ : join(cwd, options.targetFile);
354
+ const spinner = startCoverageSpinner(chalk.dim(` Checking ${options.targetFile}...`), env.testRunner);
355
+ const fileResult = await runCommand(fileTestCommand(env, absTarget), cwd, 60_000, spinner.onLine);
356
+ spinner.stop();
357
+ if (fileResult.success) {
358
+ log(chalk.green('\n All tests are passing — nothing to fix.'));
359
+ return { filesProcessed: 0, filesFixed: 0, errors: [] };
360
+ }
361
+ failingFiles = [absTarget];
362
+ }
363
+ else {
364
+ // Full-suite mode: check cache before running the suite
365
+ const cache = options.fresh ? null : await loadFixCache(cwd);
366
+ const useCached = cache !== null && cache.ageSeconds < FIX_CACHE_TTL_S;
367
+ if (useCached) {
368
+ log(chalk.dim(` Resuming from last run (${Math.round(cache.ageSeconds)}s ago, ${cache.files.length} file(s) still failing). Pass --fresh to re-scan the full suite.`));
369
+ failingFiles = cache.files;
370
+ }
371
+ else {
372
+ const spinner = startCoverageSpinner(chalk.dim(' Running test suite to find failures...'), env.testRunner);
373
+ const suiteResult = await runCommand(env.testCommand, cwd, config.coverageTimeout * 1000, spinner.onLine);
374
+ spinner.stop();
375
+ if (suiteResult.timedOut) {
376
+ throw new Error(`Test suite timed out after ${config.coverageTimeout}s.\n` +
377
+ `Increase it in .lacuna.json: { "coverageTimeout": ${config.coverageTimeout * 2} }`);
378
+ }
379
+ if (suiteResult.success) {
380
+ log(chalk.green('\n All tests are passing — nothing to fix.'));
381
+ return { filesProcessed: 0, filesFixed: 0, errors: [] };
382
+ }
383
+ failingFiles = parseFailingTestFiles(suiteResult.stdout + suiteResult.stderr, env.testRunner);
384
+ failingFiles = failingFiles.filter((f) => {
385
+ const abs = f.startsWith('/') ? f : join(cwd, f);
386
+ return abs.startsWith(cwd) && !abs.includes('node_modules');
387
+ });
388
+ if (failingFiles.length === 0) {
389
+ log(chalk.yellow('\n Could not identify any failing test files from the output.'));
390
+ log(chalk.dim(` Try running ${env.testCommand} directly to inspect the output.`));
391
+ const lastLines = (suiteResult.stdout + suiteResult.stderr)
392
+ .split('\n')
393
+ .filter((l) => l.trim())
394
+ .slice(-20)
395
+ .join('\n');
396
+ if (lastLines)
397
+ log(chalk.dim('\n Last output lines:\n' + lastLines.split('\n').map((l) => ` ${l}`).join('\n')));
398
+ return { filesProcessed: 0, filesFixed: 0, errors: [] };
399
+ }
400
+ await saveFixCache(cwd, failingFiles);
401
+ }
402
+ }
403
+ log(chalk.bold(`\n Found ${failingFiles.length} failing test file(s).`));
404
+ if (parallel) {
405
+ if (options.verbose)
406
+ log(chalk.dim(` (--verbose is not shown in parallel mode — use --workers 1 to see the live code panel)`));
407
+ log(chalk.dim(`\n Workers: ${workerCount}\n`));
408
+ }
409
+ const memory = new ProjectMemory();
410
+ await memory.initialize(cwd, env, config);
411
+ const memorySnapshot = memory.toPromptSection();
412
+ let filesProcessed;
413
+ let filesFixed;
414
+ let errors;
415
+ let stillFailingFiles;
416
+ if (parallel) {
417
+ ;
418
+ ({ filesProcessed, filesFixed, errors, stillFailingFiles } = await runFixWorkers(failingFiles, options, workerCount, memorySnapshot));
419
+ }
420
+ else {
421
+ filesProcessed = 0;
422
+ filesFixed = 0;
423
+ errors = [];
424
+ stillFailingFiles = [];
425
+ const generator = new TestGenerator({ config, env });
426
+ const tips = getActiveTips({
427
+ workers: 1,
428
+ targetFile: options.targetFile,
429
+ verbose: options.verbose,
430
+ dryRun: options.dryRun,
431
+ model: config.model,
432
+ threshold: config.threshold,
433
+ mocksFile: config.mocksFile,
434
+ ignore: config.ignore,
435
+ command: 'fix',
436
+ });
437
+ const nextTip = createTipRotator(tips);
438
+ for (const file of failingFiles) {
439
+ const tip = nextTip();
440
+ if (tip)
441
+ log(formatTip(tip));
442
+ const absFile = file.startsWith('/') ? file : join(cwd, file);
443
+ const result = await fixFile(absFile, options, generator, undefined, memory.toPromptSection());
444
+ filesProcessed++;
445
+ if (result.success)
446
+ filesFixed++;
447
+ else {
448
+ stillFailingFiles.push(file);
449
+ if (result.error)
450
+ errors.push(result.error);
451
+ }
452
+ }
453
+ }
454
+ // Update cache with only the files that are still failing.
455
+ // This means the next `lacuna fix` run skips the full suite and picks up exactly
456
+ // where we left off. If everything was fixed, delete the cache so the next run
457
+ // does a clean suite scan to confirm.
458
+ if (!options.targetFile) {
459
+ if (stillFailingFiles.length > 0)
460
+ await saveFixCache(cwd, stillFailingFiles);
461
+ else
462
+ await clearFixCache(cwd);
463
+ }
464
+ return { filesProcessed, filesFixed, errors };
465
+ }
466
+ //# sourceMappingURL=fix-loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-loop.js","sourceRoot":"","sources":["../../src/agent/fix-loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { LacunaConfig } from '../lib/config.js';
2
+ import type { DetectedEnvironment } from '../lib/detector.js';
3
+ import { buildFixPrompt } from './prompts.js';
4
+ import type { FileContext } from './context.js';
5
+ import type { CoverageGap } from '../lib/coverage/types.js';
6
+ export declare class TruncatedOutputError extends Error {
7
+ readonly partialCode: string;
8
+ constructor(partialCode: string);
9
+ }
10
+ export declare class OscillationError extends Error {
11
+ constructor();
12
+ }
13
+ export interface GeneratorOptions {
14
+ config: LacunaConfig;
15
+ env: DetectedEnvironment;
16
+ onToken?: (token: string) => void;
17
+ }
18
+ declare const TRUNCATION_RETRY_MESSAGE: string;
19
+ export declare class TestGenerator {
20
+ private provider;
21
+ private env;
22
+ private rawOnToken?;
23
+ private maxTokens;
24
+ private history;
25
+ private lastHypothesis;
26
+ private failedAttempts;
27
+ private previousCodes;
28
+ constructor(options: GeneratorOptions);
29
+ setTokenCallback(cb: ((token: string) => void) | undefined): void;
30
+ generate(context: FileContext, gap: CoverageGap, projectMemory?: string | null): Promise<string>;
31
+ fix(args: Parameters<typeof buildFixPrompt>[0]): Promise<string>;
32
+ retry(failureOutput: string): Promise<string>;
33
+ }
34
+ export { TRUNCATION_RETRY_MESSAGE };
35
+ //# sourceMappingURL=generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generator.d.ts","sourceRoot":"","sources":["../../src/agent/generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAA;AAG7D,OAAO,EAA0C,cAAc,EAAoB,MAAM,cAAc,CAAA;AAEvG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC/C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAI3D,qBAAa,oBAAqB,SAAQ,KAAK;aACjB,WAAW,EAAE,MAAM;gBAAnB,WAAW,EAAE,MAAM;CAIhD;AAED,qBAAa,gBAAiB,SAAQ,KAAK;;CAK1C;AA+BD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,YAAY,CAAA;IACpB,GAAG,EAAE,mBAAmB,CAAA;IACxB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC;AAED,QAAA,MAAM,wBAAwB,QAGS,CAAA;AA8DvC,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,UAAU,CAAC,CAAyB;IAC5C,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,cAAc,CAAa;IACnC,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,aAAa,CAAe;gBAExB,OAAO,EAAE,gBAAgB;IAUrC,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS;IAIpD,QAAQ,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,WAAW,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IA4ChG,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;IAqBhE,KAAK,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA2CpD;AAED,OAAO,EAAE,wBAAwB,EAAE,CAAA"}