sofia-cli 0.1.1 → 0.1.4
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 +42 -20
- package/dist/infra/deploy.sh +193 -0
- package/dist/infra/gather-env.sh +211 -0
- package/dist/infra/infra/deploy.sh +193 -0
- package/dist/infra/infra/gather-env.sh +211 -0
- package/dist/infra/infra/main.bicep +90 -0
- package/dist/infra/infra/main.bicepparam +18 -0
- package/dist/infra/infra/resources.bicep +134 -0
- package/dist/infra/infra/teardown.sh +114 -0
- package/dist/infra/main.bicep +90 -0
- package/dist/infra/main.bicepparam +18 -0
- package/dist/infra/resources.bicep +134 -0
- package/dist/infra/teardown.sh +114 -0
- package/dist/src/cli/developCommand.js +0 -2
- package/dist/src/cli/index.js +8 -1
- package/dist/src/cli/workshopCommand.js +1 -1
- package/dist/src/develop/index.js +1 -1
- package/dist/src/develop/pocUtils.js +228 -0
- package/dist/src/develop/ralphLoop.js +3 -3
- package/dist/src/shared/data/cards.json +655 -670
- package/docs/architecture.md +2 -1
- package/package.json +5 -3
- package/src/cli/developCommand.ts +1 -3
- package/src/cli/index.ts +11 -1
- package/src/cli/workshopCommand.ts +21 -17
- package/src/develop/dynamicScaffolder.ts +36 -30
- package/src/develop/index.ts +13 -2
- package/src/develop/pocUtils.ts +296 -0
- package/src/develop/ralphLoop.ts +8 -28
- package/src/develop/templateRegistry.ts +19 -18
- package/src/shared/data/cards.json +655 -670
- package/tests/e2e/developE2e.spec.ts +3 -61
- package/tests/e2e/developFailureE2e.spec.ts +34 -38
- package/tests/integration/pocGithubMcp.spec.ts +29 -39
- package/tests/integration/pocLocalFallback.spec.ts +29 -39
- package/tests/integration/ralphLoopFlow.spec.ts +46 -66
- package/tests/integration/ralphLoopPartial.spec.ts +30 -37
- package/tests/unit/develop/githubMcpAdapter.spec.ts +0 -134
- package/tests/unit/develop/outputValidator.spec.ts +45 -21
- package/tests/unit/develop/ralphLoop.spec.ts +58 -94
- package/tsconfig.json +2 -1
- package/vitest.workspace.ts +5 -0
- package/dist/src/develop/pocScaffolder.js +0 -542
- package/dist/tests/e2e/developE2e.spec.js +0 -126
- package/dist/tests/e2e/developFailureE2e.spec.js +0 -247
- package/dist/tests/e2e/developPty.spec.js +0 -75
- package/dist/tests/e2e/discoveryWebSearchRelevance.spec.js +0 -84
- package/dist/tests/e2e/harness.spec.js +0 -83
- package/dist/tests/e2e/mcpLive.spec.js +0 -120
- package/dist/tests/e2e/newSession.e2e.spec.js +0 -177
- package/dist/tests/e2e/ralphLoopEnrichmentComparison.spec.js +0 -62
- package/dist/tests/e2e/workiqEnrichment.spec.js +0 -56
- package/dist/tests/e2e/zavaSimulation.spec.js +0 -452
- package/dist/tests/fixtures/test-fixture-project/src/add.js +0 -3
- package/dist/tests/fixtures/test-fixture-project/tests/failing.test.js +0 -6
- package/dist/tests/fixtures/test-fixture-project/tests/hanging.test.js +0 -8
- package/dist/tests/fixtures/test-fixture-project/tests/passing.test.js +0 -10
- package/dist/tests/fixtures/test-fixture-project/vitest.config.js +0 -6
- package/dist/tests/integration/autoStartConversation.spec.js +0 -138
- package/dist/tests/integration/defaultCommand.spec.js +0 -147
- package/dist/tests/integration/directCommandNonTty.spec.js +0 -224
- package/dist/tests/integration/directCommandTty.spec.js +0 -151
- package/dist/tests/integration/discoveryEnrichmentFlow.spec.js +0 -175
- package/dist/tests/integration/exportArtifacts.spec.js +0 -202
- package/dist/tests/integration/exportFallbackFlow.spec.js +0 -99
- package/dist/tests/integration/mcpDegradationFlow.spec.js +0 -190
- package/dist/tests/integration/mcpTransportFlow.spec.js +0 -139
- package/dist/tests/integration/newSessionFlow.spec.js +0 -343
- package/dist/tests/integration/pocGithubMcp.spec.js +0 -186
- package/dist/tests/integration/pocLocalFallback.spec.js +0 -171
- package/dist/tests/integration/pocScaffold.spec.js +0 -163
- package/dist/tests/integration/ralphLoopFlow.spec.js +0 -359
- package/dist/tests/integration/ralphLoopPartial.spec.js +0 -368
- package/dist/tests/integration/resumeAndBacktrack.spec.js +0 -247
- package/dist/tests/integration/spinnerLifecycle.spec.js +0 -220
- package/dist/tests/integration/summarizationFlow.spec.js +0 -115
- package/dist/tests/integration/testRunnerReal.spec.js +0 -52
- package/dist/tests/integration/webSearchAgent.spec.js +0 -128
- package/dist/tests/live/copilotSdkLive.spec.js +0 -107
- package/dist/tests/live/zavaFullWorkshop.spec.js +0 -392
- package/dist/tests/setup/loadEnv.js +0 -3
- package/dist/tests/unit/cli/developCommand.spec.js +0 -567
- package/dist/tests/unit/cli/directCommands.spec.js +0 -279
- package/dist/tests/unit/cli/envLoader.spec.js +0 -58
- package/dist/tests/unit/cli/ioContext.spec.js +0 -119
- package/dist/tests/unit/cli/preflight.spec.js +0 -108
- package/dist/tests/unit/cli/statusCommand.spec.js +0 -111
- package/dist/tests/unit/cli/workshopClientFallback.spec.js +0 -80
- package/dist/tests/unit/cli/workshopCommand.spec.js +0 -329
- package/dist/tests/unit/config/vitestEnvSetup.spec.js +0 -13
- package/dist/tests/unit/develop/checkpointState.spec.js +0 -315
- package/dist/tests/unit/develop/codeGenerator.spec.js +0 -355
- package/dist/tests/unit/develop/githubMcpAdapter.spec.js +0 -231
- package/dist/tests/unit/develop/mcpContextEnricher.spec.js +0 -433
- package/dist/tests/unit/develop/outputValidator.spec.js +0 -119
- package/dist/tests/unit/develop/pocScaffolder.spec.js +0 -353
- package/dist/tests/unit/develop/ralphLoop.spec.js +0 -1248
- package/dist/tests/unit/develop/templateRegistry.spec.js +0 -85
- package/dist/tests/unit/develop/testRunner.spec.js +0 -249
- package/dist/tests/unit/infraBicep.spec.js +0 -92
- package/dist/tests/unit/infraDeploy.spec.js +0 -82
- package/dist/tests/unit/infraTeardown.spec.js +0 -63
- package/dist/tests/unit/logging/logger.spec.js +0 -43
- package/dist/tests/unit/loop/conversationLoop.spec.js +0 -592
- package/dist/tests/unit/loop/phaseSummarizer.spec.js +0 -141
- package/dist/tests/unit/loop/streamingMarkdown.spec.js +0 -147
- package/dist/tests/unit/mcp/mcpManager.spec.js +0 -279
- package/dist/tests/unit/mcp/mcpTransport.spec.js +0 -529
- package/dist/tests/unit/mcp/retryPolicy.spec.js +0 -218
- package/dist/tests/unit/mcp/timeoutValidation.spec.js +0 -46
- package/dist/tests/unit/mcp/webSearch.spec.js +0 -567
- package/dist/tests/unit/phases/contextSummarizer.spec.js +0 -140
- package/dist/tests/unit/phases/discoveryEnricher.repeatCalls.spec.js +0 -93
- package/dist/tests/unit/phases/discoveryEnricher.spec.js +0 -411
- package/dist/tests/unit/phases/phaseExtractors.spec.js +0 -352
- package/dist/tests/unit/phases/phaseHandlers.spec.js +0 -425
- package/dist/tests/unit/prompts/promptLoader.spec.js +0 -118
- package/dist/tests/unit/schemas/pocSchemas.spec.js +0 -412
- package/dist/tests/unit/schemas/session.spec.js +0 -257
- package/dist/tests/unit/sessions/exportPaths.spec.js +0 -31
- package/dist/tests/unit/sessions/exportWriter.spec.js +0 -655
- package/dist/tests/unit/sessions/sessionManager.spec.js +0 -151
- package/dist/tests/unit/sessions/sessionStore.spec.js +0 -116
- package/dist/tests/unit/shared/activitySpinner.spec.js +0 -175
- package/dist/tests/unit/shared/cardsLoader.spec.js +0 -76
- package/dist/tests/unit/shared/copilotClient.spec.js +0 -155
- package/dist/tests/unit/shared/errorClassifier.spec.js +0 -131
- package/dist/tests/unit/shared/events.spec.js +0 -55
- package/dist/tests/unit/shared/markdownRenderer.spec.js +0 -35
- package/dist/tests/unit/shared/markdownRendererChunks.spec.js +0 -70
- package/dist/tests/unit/shared/tableRenderer.spec.js +0 -34
- package/dist/vitest.config.js +0 -14
- package/dist/vitest.live.config.js +0 -18
- package/src/develop/pocScaffolder.ts +0 -646
- package/tests/integration/pocScaffold.spec.ts +0 -220
- package/tests/unit/develop/pocScaffolder.spec.ts +0 -451
|
@@ -15,7 +15,9 @@ import { join } from 'node:path';
|
|
|
15
15
|
import { tmpdir } from 'node:os';
|
|
16
16
|
|
|
17
17
|
import { RalphLoop } from '../../../src/develop/ralphLoop.js';
|
|
18
|
-
import {
|
|
18
|
+
import { validatePocOutput } from '../../../src/develop/pocUtils.js';
|
|
19
|
+
import * as pocUtils from '../../../src/develop/pocUtils.js';
|
|
20
|
+
import { generateDynamicScaffold } from '../../../src/develop/dynamicScaffolder.js';
|
|
19
21
|
import { TestRunner } from '../../../src/develop/testRunner.js';
|
|
20
22
|
import { GitHubMcpAdapter } from '../../../src/develop/githubMcpAdapter.js';
|
|
21
23
|
import type { WorkshopSession } from '../../../src/shared/schemas/session.js';
|
|
@@ -50,14 +52,19 @@ vi.mock('node:child_process', async (importOriginal) => {
|
|
|
50
52
|
});
|
|
51
53
|
|
|
52
54
|
// Mock validatePocOutput — default: valid
|
|
53
|
-
vi.mock('../../../src/develop/
|
|
54
|
-
const actual = await importOriginal<typeof import('../../../src/develop/
|
|
55
|
+
vi.mock('../../../src/develop/pocUtils.js', async (importOriginal) => {
|
|
56
|
+
const actual = await importOriginal<typeof import('../../../src/develop/pocUtils.js')>();
|
|
55
57
|
return {
|
|
56
58
|
...actual,
|
|
57
59
|
validatePocOutput: vi.fn().mockResolvedValue({ valid: true, missingFiles: [], errors: [] }),
|
|
58
60
|
};
|
|
59
61
|
});
|
|
60
62
|
|
|
63
|
+
// Mock generateDynamicScaffold to create minimal files for tests
|
|
64
|
+
vi.mock('../../../src/develop/dynamicScaffolder.js', () => ({
|
|
65
|
+
generateDynamicScaffold: vi.fn(),
|
|
66
|
+
}));
|
|
67
|
+
|
|
61
68
|
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
62
69
|
|
|
63
70
|
function makeSession(overrides?: Partial<WorkshopSession>): WorkshopSession {
|
|
@@ -178,40 +185,27 @@ function makeAlwaysFailingTestRunner(): TestRunner {
|
|
|
178
185
|
} as unknown as TestRunner;
|
|
179
186
|
}
|
|
180
187
|
|
|
181
|
-
function
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
context: {
|
|
203
|
-
projectName: 'test-poc',
|
|
204
|
-
ideaTitle: 'Test',
|
|
205
|
-
ideaDescription: 'Test',
|
|
206
|
-
techStack: { language: 'TypeScript', runtime: 'Node.js 20', testRunner: 'npm test' },
|
|
207
|
-
planSummary: 'Test',
|
|
208
|
-
sessionId: 'ralph-test-session',
|
|
209
|
-
outputDir,
|
|
210
|
-
},
|
|
211
|
-
};
|
|
212
|
-
}),
|
|
213
|
-
getTemplateFiles: () => ['package.json', 'src/index.ts'],
|
|
214
|
-
} as unknown as PocScaffolder;
|
|
188
|
+
function setupDynamicScaffoldMock(outputDir: string): void {
|
|
189
|
+
vi.mocked(generateDynamicScaffold).mockImplementation(async () => {
|
|
190
|
+
const { writeFile, mkdir } = await import('node:fs/promises');
|
|
191
|
+
await mkdir(join(outputDir, 'src'), { recursive: true });
|
|
192
|
+
await mkdir(join(outputDir, 'tests'), { recursive: true });
|
|
193
|
+
await writeFile(
|
|
194
|
+
join(outputDir, 'package.json'),
|
|
195
|
+
JSON.stringify({
|
|
196
|
+
name: 'test-poc',
|
|
197
|
+
scripts: { test: 'vitest run' },
|
|
198
|
+
dependencies: {},
|
|
199
|
+
devDependencies: {},
|
|
200
|
+
}),
|
|
201
|
+
'utf-8',
|
|
202
|
+
);
|
|
203
|
+
await writeFile(join(outputDir, 'src', 'index.ts'), 'export function main() {}', 'utf-8');
|
|
204
|
+
return {
|
|
205
|
+
createdFiles: ['package.json', 'src/index.ts'],
|
|
206
|
+
techStack: { language: 'TypeScript', runtime: 'Node.js 20', testRunner: 'npm test' },
|
|
207
|
+
};
|
|
208
|
+
});
|
|
215
209
|
}
|
|
216
210
|
|
|
217
211
|
// ── Tests ─────────────────────────────────────────────────────────────────────
|
|
@@ -268,7 +262,7 @@ describe('RalphLoop', () => {
|
|
|
268
262
|
const io = makeIo();
|
|
269
263
|
const client = makePassingClient();
|
|
270
264
|
const testRunner = makePassingTestRunner();
|
|
271
|
-
|
|
265
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
272
266
|
|
|
273
267
|
const ralph = new RalphLoop({
|
|
274
268
|
client,
|
|
@@ -277,7 +271,6 @@ describe('RalphLoop', () => {
|
|
|
277
271
|
outputDir: tmpDir,
|
|
278
272
|
maxIterations: 5,
|
|
279
273
|
testRunner,
|
|
280
|
-
scaffolder,
|
|
281
274
|
});
|
|
282
275
|
|
|
283
276
|
const result = await ralph.run();
|
|
@@ -291,7 +284,7 @@ describe('RalphLoop', () => {
|
|
|
291
284
|
const io = makeIo();
|
|
292
285
|
const client = makePassingClient();
|
|
293
286
|
const testRunner = makePassingTestRunner();
|
|
294
|
-
|
|
287
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
295
288
|
|
|
296
289
|
const ralph = new RalphLoop({
|
|
297
290
|
client,
|
|
@@ -300,7 +293,6 @@ describe('RalphLoop', () => {
|
|
|
300
293
|
outputDir: tmpDir,
|
|
301
294
|
maxIterations: 5,
|
|
302
295
|
testRunner,
|
|
303
|
-
scaffolder,
|
|
304
296
|
});
|
|
305
297
|
|
|
306
298
|
const result = await ralph.run();
|
|
@@ -314,7 +306,7 @@ describe('RalphLoop', () => {
|
|
|
314
306
|
const io = makeIo();
|
|
315
307
|
const client = makePassingClient();
|
|
316
308
|
const testRunner = makePassingTestRunner();
|
|
317
|
-
|
|
309
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
318
310
|
const onSessionUpdate = vi.fn().mockResolvedValue(undefined);
|
|
319
311
|
|
|
320
312
|
const ralph = new RalphLoop({
|
|
@@ -324,7 +316,6 @@ describe('RalphLoop', () => {
|
|
|
324
316
|
outputDir: tmpDir,
|
|
325
317
|
maxIterations: 3,
|
|
326
318
|
testRunner,
|
|
327
|
-
scaffolder,
|
|
328
319
|
onSessionUpdate,
|
|
329
320
|
});
|
|
330
321
|
|
|
@@ -339,7 +330,7 @@ describe('RalphLoop', () => {
|
|
|
339
330
|
const io = makeIo();
|
|
340
331
|
const client = makePassingClient();
|
|
341
332
|
const testRunner = makePassingTestRunner();
|
|
342
|
-
|
|
333
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
343
334
|
|
|
344
335
|
const ralph = new RalphLoop({
|
|
345
336
|
client,
|
|
@@ -348,7 +339,6 @@ describe('RalphLoop', () => {
|
|
|
348
339
|
outputDir: tmpDir,
|
|
349
340
|
maxIterations: 5,
|
|
350
341
|
testRunner,
|
|
351
|
-
scaffolder,
|
|
352
342
|
});
|
|
353
343
|
|
|
354
344
|
const result = await ralph.run();
|
|
@@ -366,7 +356,7 @@ describe('RalphLoop', () => {
|
|
|
366
356
|
const io = makeIo();
|
|
367
357
|
const client = makePassingClient();
|
|
368
358
|
const testRunner = makeAlwaysFailingTestRunner();
|
|
369
|
-
|
|
359
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
370
360
|
|
|
371
361
|
const ralph = new RalphLoop({
|
|
372
362
|
client,
|
|
@@ -375,7 +365,6 @@ describe('RalphLoop', () => {
|
|
|
375
365
|
outputDir: tmpDir,
|
|
376
366
|
maxIterations: 3,
|
|
377
367
|
testRunner,
|
|
378
|
-
scaffolder,
|
|
379
368
|
});
|
|
380
369
|
|
|
381
370
|
const result = await ralph.run();
|
|
@@ -402,7 +391,7 @@ describe('RalphLoop', () => {
|
|
|
402
391
|
} satisfies TestResults),
|
|
403
392
|
} as unknown as TestRunner;
|
|
404
393
|
|
|
405
|
-
|
|
394
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
406
395
|
|
|
407
396
|
const ralph = new RalphLoop({
|
|
408
397
|
client,
|
|
@@ -411,7 +400,6 @@ describe('RalphLoop', () => {
|
|
|
411
400
|
outputDir: tmpDir,
|
|
412
401
|
maxIterations: 2,
|
|
413
402
|
testRunner,
|
|
414
|
-
scaffolder,
|
|
415
403
|
});
|
|
416
404
|
|
|
417
405
|
const result = await ralph.run();
|
|
@@ -425,7 +413,7 @@ describe('RalphLoop', () => {
|
|
|
425
413
|
const io = makeIo();
|
|
426
414
|
const client = makePassingClient();
|
|
427
415
|
const testRunner = makeAlwaysFailingTestRunner();
|
|
428
|
-
|
|
416
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
429
417
|
|
|
430
418
|
const ralph = new RalphLoop({
|
|
431
419
|
client,
|
|
@@ -434,7 +422,6 @@ describe('RalphLoop', () => {
|
|
|
434
422
|
outputDir: tmpDir,
|
|
435
423
|
maxIterations: 2,
|
|
436
424
|
testRunner,
|
|
437
|
-
scaffolder,
|
|
438
425
|
});
|
|
439
426
|
|
|
440
427
|
const result = await ralph.run();
|
|
@@ -447,7 +434,7 @@ describe('RalphLoop', () => {
|
|
|
447
434
|
const session = makeSession();
|
|
448
435
|
const io = makeIo();
|
|
449
436
|
const testRunner = makeAlwaysFailingTestRunner();
|
|
450
|
-
|
|
437
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
451
438
|
|
|
452
439
|
// Client that emits SIGINT mid-generation to simulate Ctrl+C
|
|
453
440
|
const client: CopilotClient = {
|
|
@@ -474,7 +461,6 @@ describe('RalphLoop', () => {
|
|
|
474
461
|
outputDir: tmpDir,
|
|
475
462
|
maxIterations: 5,
|
|
476
463
|
testRunner,
|
|
477
|
-
scaffolder,
|
|
478
464
|
onSessionUpdate: async (s) => {
|
|
479
465
|
sessionUpdates.push(s);
|
|
480
466
|
},
|
|
@@ -497,7 +483,7 @@ describe('RalphLoop', () => {
|
|
|
497
483
|
const io = makeIo();
|
|
498
484
|
const client = makePassingClient();
|
|
499
485
|
const testRunner = makePassingTestRunner();
|
|
500
|
-
|
|
486
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
501
487
|
const events: string[] = [];
|
|
502
488
|
|
|
503
489
|
const ralph = new RalphLoop({
|
|
@@ -507,7 +493,6 @@ describe('RalphLoop', () => {
|
|
|
507
493
|
outputDir: tmpDir,
|
|
508
494
|
maxIterations: 3,
|
|
509
495
|
testRunner,
|
|
510
|
-
scaffolder,
|
|
511
496
|
onEvent: (e) => events.push(e.type),
|
|
512
497
|
});
|
|
513
498
|
|
|
@@ -523,7 +508,7 @@ describe('RalphLoop', () => {
|
|
|
523
508
|
const io = makeIo();
|
|
524
509
|
const client = makePassingClient();
|
|
525
510
|
const testRunner = makePassingTestRunner();
|
|
526
|
-
|
|
511
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
527
512
|
|
|
528
513
|
const ralph = new RalphLoop({
|
|
529
514
|
client,
|
|
@@ -532,7 +517,6 @@ describe('RalphLoop', () => {
|
|
|
532
517
|
outputDir: tmpDir,
|
|
533
518
|
maxIterations: 3,
|
|
534
519
|
testRunner,
|
|
535
|
-
scaffolder,
|
|
536
520
|
});
|
|
537
521
|
|
|
538
522
|
const result = await ralph.run();
|
|
@@ -545,7 +529,7 @@ describe('RalphLoop', () => {
|
|
|
545
529
|
const session = makeSession();
|
|
546
530
|
const io = makeIo();
|
|
547
531
|
const client = makePassingClient();
|
|
548
|
-
|
|
532
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
549
533
|
|
|
550
534
|
// First test run fails, second (final run after loop) passes
|
|
551
535
|
let runCount = 0;
|
|
@@ -582,7 +566,6 @@ describe('RalphLoop', () => {
|
|
|
582
566
|
outputDir: tmpDir,
|
|
583
567
|
maxIterations: 2, // scaffold + 1 iterate = 2 iterations, then final test
|
|
584
568
|
testRunner,
|
|
585
|
-
scaffolder,
|
|
586
569
|
});
|
|
587
570
|
|
|
588
571
|
const result = await ralph.run();
|
|
@@ -598,7 +581,7 @@ describe('RalphLoop', () => {
|
|
|
598
581
|
const session = makeSession();
|
|
599
582
|
const io = makeIo();
|
|
600
583
|
const client = makePassingClient();
|
|
601
|
-
|
|
584
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
602
585
|
let persistedSession: WorkshopSession | null = null;
|
|
603
586
|
|
|
604
587
|
// Slow test runner: yields after first call so SIGINT can fire
|
|
@@ -633,7 +616,6 @@ describe('RalphLoop', () => {
|
|
|
633
616
|
outputDir: tmpDir,
|
|
634
617
|
maxIterations: 10,
|
|
635
618
|
testRunner,
|
|
636
|
-
scaffolder,
|
|
637
619
|
onSessionUpdate,
|
|
638
620
|
});
|
|
639
621
|
|
|
@@ -659,7 +641,7 @@ describe('RalphLoop', () => {
|
|
|
659
641
|
const session = makeSession();
|
|
660
642
|
const io = makeIo();
|
|
661
643
|
const client = makePassingClient();
|
|
662
|
-
|
|
644
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
663
645
|
|
|
664
646
|
// Partially passing test runner that delays so SIGINT can fire
|
|
665
647
|
let runCount = 0;
|
|
@@ -688,7 +670,6 @@ describe('RalphLoop', () => {
|
|
|
688
670
|
outputDir: tmpDir,
|
|
689
671
|
maxIterations: 10,
|
|
690
672
|
testRunner,
|
|
691
|
-
scaffolder,
|
|
692
673
|
});
|
|
693
674
|
|
|
694
675
|
const runPromise = ralph.run();
|
|
@@ -755,7 +736,7 @@ describe('RalphLoop', () => {
|
|
|
755
736
|
}),
|
|
756
737
|
} as unknown as TestRunner;
|
|
757
738
|
|
|
758
|
-
|
|
739
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
759
740
|
|
|
760
741
|
// Create a mock GitHub adapter that captures pushFiles calls
|
|
761
742
|
const pushFilesMock = vi.fn().mockResolvedValue({ available: true, commitSha: 'abc123' });
|
|
@@ -777,7 +758,6 @@ describe('RalphLoop', () => {
|
|
|
777
758
|
outputDir: tmpDir,
|
|
778
759
|
maxIterations: 5,
|
|
779
760
|
testRunner,
|
|
780
|
-
scaffolder,
|
|
781
761
|
});
|
|
782
762
|
|
|
783
763
|
await ralph.run();
|
|
@@ -826,7 +806,6 @@ describe('RalphLoop', () => {
|
|
|
826
806
|
outputDir: tmpDir,
|
|
827
807
|
maxIterations: 5,
|
|
828
808
|
testRunner,
|
|
829
|
-
scaffolder: makeFakeScaffolder(tmpDir),
|
|
830
809
|
});
|
|
831
810
|
|
|
832
811
|
const result = await ralph.run();
|
|
@@ -865,7 +844,6 @@ describe('RalphLoop', () => {
|
|
|
865
844
|
outputDir: tmpDir,
|
|
866
845
|
maxIterations: 5,
|
|
867
846
|
testRunner,
|
|
868
|
-
scaffolder: makeFakeScaffolder(tmpDir),
|
|
869
847
|
});
|
|
870
848
|
|
|
871
849
|
const result = await ralph.run();
|
|
@@ -918,7 +896,6 @@ describe('RalphLoop', () => {
|
|
|
918
896
|
outputDir: tmpDir,
|
|
919
897
|
maxIterations: 10,
|
|
920
898
|
testRunner,
|
|
921
|
-
scaffolder: makeFakeScaffolder(tmpDir),
|
|
922
899
|
checkpoint: {
|
|
923
900
|
hasPriorRun: true,
|
|
924
901
|
completedIterations: 2,
|
|
@@ -940,7 +917,7 @@ describe('RalphLoop', () => {
|
|
|
940
917
|
it('skips scaffold when checkpoint says canSkipScaffold=true (T014)', async () => {
|
|
941
918
|
const io = makeIo();
|
|
942
919
|
const testRunner = makePassingTestRunner();
|
|
943
|
-
|
|
920
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
944
921
|
|
|
945
922
|
const session = makeSession({
|
|
946
923
|
poc: {
|
|
@@ -964,7 +941,6 @@ describe('RalphLoop', () => {
|
|
|
964
941
|
outputDir: tmpDir,
|
|
965
942
|
maxIterations: 10,
|
|
966
943
|
testRunner,
|
|
967
|
-
scaffolder,
|
|
968
944
|
checkpoint: {
|
|
969
945
|
hasPriorRun: true,
|
|
970
946
|
completedIterations: 1,
|
|
@@ -979,11 +955,9 @@ describe('RalphLoop', () => {
|
|
|
979
955
|
await ralph.run();
|
|
980
956
|
|
|
981
957
|
// Scaffold should NOT have been called — it was skipped
|
|
982
|
-
expect(
|
|
958
|
+
expect(generateDynamicScaffold).not.toHaveBeenCalled();
|
|
983
959
|
// Should log that scaffold was skipped
|
|
984
|
-
expect(io.writeActivity).toHaveBeenCalledWith(
|
|
985
|
-
expect.stringContaining('Skipping scaffold'),
|
|
986
|
-
);
|
|
960
|
+
expect(io.writeActivity).toHaveBeenCalledWith(expect.stringContaining('Skipping scaffold'));
|
|
987
961
|
});
|
|
988
962
|
|
|
989
963
|
it('pops incomplete last iteration and re-runs it (T015, FR-001a)', async () => {
|
|
@@ -1021,7 +995,6 @@ describe('RalphLoop', () => {
|
|
|
1021
995
|
outputDir: tmpDir,
|
|
1022
996
|
maxIterations: 10,
|
|
1023
997
|
testRunner,
|
|
1024
|
-
scaffolder: makeFakeScaffolder(tmpDir),
|
|
1025
998
|
checkpoint: {
|
|
1026
999
|
hasPriorRun: true,
|
|
1027
1000
|
completedIterations: 1,
|
|
@@ -1045,7 +1018,7 @@ describe('RalphLoop', () => {
|
|
|
1045
1018
|
it('re-scaffolds when output directory is missing but iterations exist (T018, FR-007)', async () => {
|
|
1046
1019
|
const io = makeIo();
|
|
1047
1020
|
const testRunner = makePassingTestRunner();
|
|
1048
|
-
|
|
1021
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
1049
1022
|
|
|
1050
1023
|
const session = makeSession({
|
|
1051
1024
|
poc: {
|
|
@@ -1069,7 +1042,6 @@ describe('RalphLoop', () => {
|
|
|
1069
1042
|
outputDir: tmpDir,
|
|
1070
1043
|
maxIterations: 10,
|
|
1071
1044
|
testRunner,
|
|
1072
|
-
scaffolder,
|
|
1073
1045
|
checkpoint: {
|
|
1074
1046
|
hasPriorRun: true,
|
|
1075
1047
|
completedIterations: 1,
|
|
@@ -1084,10 +1056,8 @@ describe('RalphLoop', () => {
|
|
|
1084
1056
|
await ralph.run();
|
|
1085
1057
|
|
|
1086
1058
|
// Scaffold SHOULD have been called since canSkipScaffold is false
|
|
1087
|
-
expect(
|
|
1088
|
-
expect(io.writeActivity).toHaveBeenCalledWith(
|
|
1089
|
-
expect.stringContaining('re-scaffolding'),
|
|
1090
|
-
);
|
|
1059
|
+
expect(generateDynamicScaffold).toHaveBeenCalled();
|
|
1060
|
+
expect(io.writeActivity).toHaveBeenCalledWith(expect.stringContaining('re-scaffolding'));
|
|
1091
1061
|
});
|
|
1092
1062
|
});
|
|
1093
1063
|
|
|
@@ -1099,7 +1069,7 @@ describe('RalphLoop', () => {
|
|
|
1099
1069
|
const io = makeIo();
|
|
1100
1070
|
const client = makePassingClient();
|
|
1101
1071
|
const testRunner = makePassingTestRunner();
|
|
1102
|
-
|
|
1072
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
1103
1073
|
|
|
1104
1074
|
const pushOrder: string[] = [];
|
|
1105
1075
|
const pushFilesMock = vi.fn().mockImplementation(async () => {
|
|
@@ -1133,7 +1103,6 @@ describe('RalphLoop', () => {
|
|
|
1133
1103
|
outputDir: tmpDir,
|
|
1134
1104
|
maxIterations: 3,
|
|
1135
1105
|
testRunner,
|
|
1136
|
-
scaffolder,
|
|
1137
1106
|
});
|
|
1138
1107
|
|
|
1139
1108
|
await ralph.run();
|
|
@@ -1168,7 +1137,7 @@ describe('RalphLoop', () => {
|
|
|
1168
1137
|
it('always re-runs dependency install even when scaffolding is skipped (T065, FR-003)', async () => {
|
|
1169
1138
|
const io = makeIo();
|
|
1170
1139
|
const testRunner = makePassingTestRunner();
|
|
1171
|
-
|
|
1140
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
1172
1141
|
|
|
1173
1142
|
const session = makeSession({
|
|
1174
1143
|
poc: {
|
|
@@ -1192,7 +1161,6 @@ describe('RalphLoop', () => {
|
|
|
1192
1161
|
outputDir: tmpDir,
|
|
1193
1162
|
maxIterations: 10,
|
|
1194
1163
|
testRunner,
|
|
1195
|
-
scaffolder,
|
|
1196
1164
|
checkpoint: {
|
|
1197
1165
|
hasPriorRun: true,
|
|
1198
1166
|
completedIterations: 1,
|
|
@@ -1207,7 +1175,7 @@ describe('RalphLoop', () => {
|
|
|
1207
1175
|
await ralph.run();
|
|
1208
1176
|
|
|
1209
1177
|
// Scaffold should be skipped
|
|
1210
|
-
expect(
|
|
1178
|
+
expect(generateDynamicScaffold).not.toHaveBeenCalled();
|
|
1211
1179
|
// But install should still run
|
|
1212
1180
|
expect(io.writeActivity).toHaveBeenCalledWith(
|
|
1213
1181
|
expect.stringContaining('Re-running dependency installation'),
|
|
@@ -1277,7 +1245,6 @@ describe('RalphLoop', () => {
|
|
|
1277
1245
|
outputDir: tmpDir,
|
|
1278
1246
|
maxIterations: 4,
|
|
1279
1247
|
testRunner,
|
|
1280
|
-
scaffolder: makeFakeScaffolder(tmpDir),
|
|
1281
1248
|
checkpoint: {
|
|
1282
1249
|
hasPriorRun: true,
|
|
1283
1250
|
completedIterations: 2,
|
|
@@ -1303,7 +1270,7 @@ describe('RalphLoop', () => {
|
|
|
1303
1270
|
it('resume decision logging emits info-level messages (T067, FR-007a)', async () => {
|
|
1304
1271
|
const io = makeIo();
|
|
1305
1272
|
const testRunner = makePassingTestRunner();
|
|
1306
|
-
|
|
1273
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
1307
1274
|
|
|
1308
1275
|
const session = makeSession({
|
|
1309
1276
|
poc: {
|
|
@@ -1327,7 +1294,6 @@ describe('RalphLoop', () => {
|
|
|
1327
1294
|
outputDir: tmpDir,
|
|
1328
1295
|
maxIterations: 10,
|
|
1329
1296
|
testRunner,
|
|
1330
|
-
scaffolder,
|
|
1331
1297
|
checkpoint: {
|
|
1332
1298
|
hasPriorRun: true,
|
|
1333
1299
|
completedIterations: 1,
|
|
@@ -1355,7 +1321,7 @@ describe('RalphLoop', () => {
|
|
|
1355
1321
|
describe('TODO marker rescan after iteration (T073)', () => {
|
|
1356
1322
|
it('calls scanAndRecordTodos after each failing iteration', async () => {
|
|
1357
1323
|
const scanSpy = vi
|
|
1358
|
-
.spyOn(
|
|
1324
|
+
.spyOn(pocUtils, 'scanAndRecordTodos')
|
|
1359
1325
|
.mockResolvedValue({ totalInitial: 3, remaining: 2, markers: [] });
|
|
1360
1326
|
|
|
1361
1327
|
const session = makeSession();
|
|
@@ -1370,7 +1336,7 @@ describe('RalphLoop', () => {
|
|
|
1370
1336
|
};
|
|
1371
1337
|
const testRunner = makeAlwaysFailingTestRunner();
|
|
1372
1338
|
const client = makePassingClient();
|
|
1373
|
-
|
|
1339
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
1374
1340
|
|
|
1375
1341
|
const ralph = new RalphLoop({
|
|
1376
1342
|
client,
|
|
@@ -1379,7 +1345,6 @@ describe('RalphLoop', () => {
|
|
|
1379
1345
|
outputDir: tmpDir,
|
|
1380
1346
|
maxIterations: 2,
|
|
1381
1347
|
testRunner,
|
|
1382
|
-
scaffolder,
|
|
1383
1348
|
});
|
|
1384
1349
|
|
|
1385
1350
|
await ralph.run();
|
|
@@ -1412,7 +1377,7 @@ describe('RalphLoop', () => {
|
|
|
1412
1377
|
const io = makeIo();
|
|
1413
1378
|
const session = makeSession();
|
|
1414
1379
|
const testRunner = makeAlwaysFailingTestRunner();
|
|
1415
|
-
|
|
1380
|
+
setupDynamicScaffoldMock(tmpDir);
|
|
1416
1381
|
|
|
1417
1382
|
const ralph = new RalphLoop({
|
|
1418
1383
|
client,
|
|
@@ -1421,7 +1386,6 @@ describe('RalphLoop', () => {
|
|
|
1421
1386
|
outputDir: tmpDir,
|
|
1422
1387
|
maxIterations: 2,
|
|
1423
1388
|
testRunner,
|
|
1424
|
-
scaffolder,
|
|
1425
1389
|
});
|
|
1426
1390
|
|
|
1427
1391
|
await ralph.run();
|
package/tsconfig.json
CHANGED