tlc-claude-code 2.5.0 → 2.6.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.
Files changed (76) hide show
  1. package/.claude/commands/tlc/autofix.md +34 -1
  2. package/.claude/commands/tlc/build.md +89 -6
  3. package/.claude/commands/tlc/ci.md +178 -414
  4. package/.claude/commands/tlc/coverage.md +34 -0
  5. package/.claude/commands/tlc/deploy.md +19 -6
  6. package/.claude/commands/tlc/discuss.md +34 -0
  7. package/.claude/commands/tlc/docs.md +35 -1
  8. package/.claude/commands/tlc/e2e.md +300 -0
  9. package/.claude/commands/tlc/edge-cases.md +35 -1
  10. package/.claude/commands/tlc/init.md +38 -8
  11. package/.claude/commands/tlc/new-project.md +46 -4
  12. package/.claude/commands/tlc/plan.md +33 -0
  13. package/.claude/commands/tlc/quick.md +33 -0
  14. package/.claude/commands/tlc/release.md +85 -135
  15. package/.claude/commands/tlc/restore.md +14 -0
  16. package/.claude/commands/tlc/review.md +76 -1
  17. package/.claude/commands/tlc/tlc.md +134 -0
  18. package/.claude/commands/tlc/verify.md +64 -65
  19. package/.claude/commands/tlc/watchci.md +10 -0
  20. package/.claude/hooks/tlc-block-tools.sh +13 -0
  21. package/.claude/hooks/tlc-session-init.sh +9 -0
  22. package/CODING-STANDARDS.md +35 -10
  23. package/package.json +1 -1
  24. package/server/lib/block-tools-hook.js +23 -0
  25. package/server/lib/e2e/acceptance-parser.js +132 -0
  26. package/server/lib/e2e/acceptance-parser.test.js +110 -0
  27. package/server/lib/e2e/framework-detector.js +47 -0
  28. package/server/lib/e2e/framework-detector.test.js +94 -0
  29. package/server/lib/e2e/log-assertions.js +107 -0
  30. package/server/lib/e2e/log-assertions.test.js +68 -0
  31. package/server/lib/e2e/test-generator.js +159 -0
  32. package/server/lib/e2e/test-generator.test.js +121 -0
  33. package/server/lib/e2e/verify-runner.js +191 -0
  34. package/server/lib/e2e/verify-runner.test.js +167 -0
  35. package/server/lib/hooks/block-tools-hook.test.js +54 -0
  36. package/server/lib/orchestration/cli-dispatch.js +16 -1
  37. package/server/lib/orchestration/cli-dispatch.test.js +94 -8
  38. package/server/lib/orchestration/completion-checker.js +101 -0
  39. package/server/lib/orchestration/completion-checker.test.js +177 -0
  40. package/server/lib/orchestration/result-verifier.js +143 -0
  41. package/server/lib/orchestration/result-verifier.test.js +291 -0
  42. package/server/lib/orchestration/session-dispatcher.js +99 -0
  43. package/server/lib/orchestration/session-dispatcher.test.js +215 -0
  44. package/server/lib/orchestration/session-status.js +147 -0
  45. package/server/lib/orchestration/session-status.test.js +130 -0
  46. package/server/lib/release/agent-runner-updates.js +24 -0
  47. package/server/lib/release/agent-runner-updates.test.js +22 -0
  48. package/server/lib/release/changelog-generator.js +142 -0
  49. package/server/lib/release/changelog-generator.test.js +113 -0
  50. package/server/lib/release/ci-watcher.js +83 -0
  51. package/server/lib/release/ci-watcher.test.js +81 -0
  52. package/server/lib/release/health-checker.js +111 -0
  53. package/server/lib/release/health-checker.test.js +121 -0
  54. package/server/lib/release/release-pipeline.js +187 -0
  55. package/server/lib/release/release-pipeline.test.js +262 -0
  56. package/server/lib/release/version-bumper.js +183 -0
  57. package/server/lib/release/version-bumper.test.js +142 -0
  58. package/server/lib/routing-preamble.integration.test.js +12 -0
  59. package/server/lib/routing-preamble.js +13 -2
  60. package/server/lib/routing-preamble.test.js +49 -0
  61. package/server/lib/scaffolding/ci-detector.js +139 -0
  62. package/server/lib/scaffolding/ci-detector.test.js +198 -0
  63. package/server/lib/scaffolding/ci-scaffolder.js +347 -0
  64. package/server/lib/scaffolding/ci-scaffolder.test.js +157 -0
  65. package/server/lib/scaffolding/deploy-detector.js +135 -0
  66. package/server/lib/scaffolding/deploy-detector.test.js +106 -0
  67. package/server/lib/scaffolding/health-scaffold.js +374 -0
  68. package/server/lib/scaffolding/health-scaffold.test.js +99 -0
  69. package/server/lib/scaffolding/logger-scaffold.js +196 -0
  70. package/server/lib/scaffolding/logger-scaffold.test.js +146 -0
  71. package/server/lib/scaffolding/migration-detector.js +78 -0
  72. package/server/lib/scaffolding/migration-detector.test.js +127 -0
  73. package/server/lib/scaffolding/snapshot-manager.js +142 -0
  74. package/server/lib/scaffolding/snapshot-manager.test.js +225 -0
  75. package/server/lib/task-router-config.js +50 -20
  76. package/server/lib/task-router-config.test.js +29 -15
@@ -0,0 +1,106 @@
1
+ import { afterEach, describe, expect, it } from 'vitest';
2
+ import fs from 'fs';
3
+ import os from 'os';
4
+ import path from 'path';
5
+
6
+ import { detectDeployTarget } from './deploy-detector.js';
7
+
8
+ function makeTempProject() {
9
+ return fs.mkdtempSync(path.join(os.tmpdir(), 'deploy-detector-test-'));
10
+ }
11
+
12
+ function writeFile(projectDir, relativePath, contents = '') {
13
+ const filePath = path.join(projectDir, relativePath);
14
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
15
+ fs.writeFileSync(filePath, contents);
16
+ }
17
+
18
+ function makeDir(projectDir, relativePath) {
19
+ fs.mkdirSync(path.join(projectDir, relativePath), { recursive: true });
20
+ }
21
+
22
+ const tempDirs = [];
23
+
24
+ function createProject() {
25
+ const projectDir = makeTempProject();
26
+ tempDirs.push(projectDir);
27
+ return projectDir;
28
+ }
29
+
30
+ afterEach(() => {
31
+ while (tempDirs.length > 0) {
32
+ fs.rmSync(tempDirs.pop(), { recursive: true, force: true });
33
+ }
34
+ });
35
+
36
+ describe('detectDeployTarget', () => {
37
+ it('detects docker-compose.yml as docker-compose with high confidence', () => {
38
+ const projectDir = createProject();
39
+ writeFile(projectDir, 'docker-compose.yml', 'services:\n app:\n image: app\n');
40
+
41
+ expect(detectDeployTarget({ projectDir, fs })).toEqual({
42
+ target: 'docker-compose',
43
+ confidence: 'high',
44
+ evidence: ['docker-compose.yml'],
45
+ });
46
+ });
47
+
48
+ it('detects helm directory as k8s with high confidence', () => {
49
+ const projectDir = createProject();
50
+ makeDir(projectDir, 'helm');
51
+
52
+ expect(detectDeployTarget({ projectDir, fs })).toEqual({
53
+ target: 'k8s',
54
+ confidence: 'high',
55
+ evidence: ['helm/'],
56
+ });
57
+ });
58
+
59
+ it('detects Dockerfile alone as vps with medium confidence', () => {
60
+ const projectDir = createProject();
61
+ writeFile(projectDir, 'Dockerfile', 'FROM node:20-alpine\n');
62
+
63
+ expect(detectDeployTarget({ projectDir, fs })).toEqual({
64
+ target: 'vps',
65
+ confidence: 'medium',
66
+ evidence: ['Dockerfile'],
67
+ });
68
+ });
69
+
70
+ it('returns unknown when docker-compose and helm both exist', () => {
71
+ const projectDir = createProject();
72
+ writeFile(projectDir, 'docker-compose.yaml', 'services:\n app:\n image: app\n');
73
+ makeDir(projectDir, 'helm');
74
+
75
+ expect(detectDeployTarget({ projectDir, fs })).toEqual({
76
+ target: 'unknown',
77
+ confidence: 'low',
78
+ evidence: ['docker-compose.yaml', 'helm/', 'multiple deployment targets detected'],
79
+ });
80
+ });
81
+
82
+ it('returns unknown with low confidence for an empty project', () => {
83
+ const projectDir = createProject();
84
+
85
+ expect(detectDeployTarget({ projectDir, fs })).toEqual({
86
+ target: 'unknown',
87
+ confidence: 'low',
88
+ evidence: [],
89
+ });
90
+ });
91
+
92
+ it('includes file evidence for k8s deployment manifests', () => {
93
+ const projectDir = createProject();
94
+ writeFile(
95
+ projectDir,
96
+ 'manifests/api-deployment.yaml',
97
+ 'apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: api\n'
98
+ );
99
+
100
+ expect(detectDeployTarget({ projectDir, fs })).toEqual({
101
+ target: 'k8s',
102
+ confidence: 'high',
103
+ evidence: ['kind: Deployment in manifests/api-deployment.yaml'],
104
+ });
105
+ });
106
+ });
@@ -0,0 +1,374 @@
1
+ const { detectDeployTarget } = require('./deploy-detector.js');
2
+
3
+ function scaffoldHealth({ projectDir, deployTarget, framework, fs }) {
4
+ const resolvedFramework = framework === 'fastify' ? 'fastify' : 'express';
5
+ const resolvedDeployTarget = resolveDeployTarget({ projectDir, deployTarget, fs });
6
+ const files = [
7
+ {
8
+ path: 'src/health.js',
9
+ content: createHealthFileContent({
10
+ deployTarget: resolvedDeployTarget,
11
+ framework: resolvedFramework,
12
+ }),
13
+ },
14
+ ];
15
+
16
+ if (resolvedDeployTarget === 'vps') {
17
+ files.push({
18
+ path: 'ecosystem.config.js',
19
+ content: createPm2Snippet(),
20
+ });
21
+ }
22
+
23
+ return {
24
+ files,
25
+ dependencies: [],
26
+ };
27
+ }
28
+
29
+ function resolveDeployTarget({ projectDir, deployTarget, fs }) {
30
+ if (deployTarget && typeof deployTarget === 'object' && deployTarget.target) {
31
+ return deployTarget.target;
32
+ }
33
+
34
+ if (typeof deployTarget === 'string' && deployTarget.length > 0) {
35
+ return deployTarget;
36
+ }
37
+
38
+ if (projectDir && fs) {
39
+ return detectDeployTarget({ projectDir, fs }).target;
40
+ }
41
+
42
+ return 'unknown';
43
+ }
44
+
45
+ function createHealthFileContent({ deployTarget, framework }) {
46
+ if (framework === 'fastify') {
47
+ return createFastifyContent(deployTarget);
48
+ }
49
+
50
+ return createExpressContent(deployTarget);
51
+ }
52
+
53
+ function createExpressContent(deployTarget) {
54
+ const routeDefinitions = createExpressRouteDefinitions(deployTarget);
55
+
56
+ return `'use strict';
57
+
58
+ function withTimeout(operation, timeoutMs = 2000) {
59
+ return Promise.race([
60
+ Promise.resolve().then(operation),
61
+ new Promise((_, reject) => {
62
+ setTimeout(() => reject(new Error('timeout')), timeoutMs);
63
+ }),
64
+ ]);
65
+ }
66
+
67
+ async function pingDatabase(options = {}) {
68
+ if (!options.db) {
69
+ return { configured: false, ok: true, status: 'not_configured' };
70
+ }
71
+
72
+ try {
73
+ await withTimeout(async () => {
74
+ if (typeof options.db.ping === 'function') {
75
+ await options.db.ping();
76
+ return;
77
+ }
78
+
79
+ if (typeof options.db.query === 'function') {
80
+ await options.db.query('SELECT 1');
81
+ return;
82
+ }
83
+
84
+ throw new Error('no supported database ping method');
85
+ });
86
+
87
+ return { configured: true, ok: true, status: 'up' };
88
+ } catch (error) {
89
+ return { configured: true, ok: false, status: 'down', error: error.message };
90
+ }
91
+ }
92
+
93
+ async function pingRedis(options = {}) {
94
+ if (!options.redis) {
95
+ return { configured: false, ok: true, status: 'not_configured' };
96
+ }
97
+
98
+ try {
99
+ await withTimeout(async () => {
100
+ if (typeof options.redis.ping === 'function') {
101
+ await options.redis.ping();
102
+ return;
103
+ }
104
+
105
+ if (typeof options.redis.sendCommand === 'function') {
106
+ await options.redis.sendCommand(['PING']);
107
+ return;
108
+ }
109
+
110
+ throw new Error('no supported redis ping method');
111
+ });
112
+
113
+ return { configured: true, ok: true, status: 'up' };
114
+ } catch (error) {
115
+ return { configured: true, ok: false, status: 'down', error: error.message };
116
+ }
117
+ }
118
+
119
+ async function getDependencyStatus(options = {}) {
120
+ const [database, redis] = await Promise.all([
121
+ pingDatabase(options),
122
+ pingRedis(options),
123
+ ]);
124
+
125
+ const dependencies = {};
126
+
127
+ if (database.configured) {
128
+ dependencies.db = database;
129
+ }
130
+
131
+ if (redis.configured) {
132
+ dependencies.redis = redis;
133
+ }
134
+
135
+ const status = Object.values(dependencies).every(dependency => dependency.ok !== false)
136
+ ? 'ok'
137
+ : 'degraded';
138
+
139
+ return {
140
+ status,
141
+ dependencies,
142
+ uptime: process.uptime(),
143
+ };
144
+ }
145
+
146
+ function getStartupState(options = {}) {
147
+ if (typeof options.isStartupComplete === 'function') {
148
+ return Boolean(options.isStartupComplete());
149
+ }
150
+
151
+ if (typeof options.startupComplete === 'boolean') {
152
+ return options.startupComplete;
153
+ }
154
+
155
+ return true;
156
+ }
157
+
158
+ function sendJson(res, statusCode, payload) {
159
+ res.status(statusCode).json(payload);
160
+ }
161
+
162
+ function registerHealthRoutes(app, options = {}) {
163
+ ${routeDefinitions}
164
+ }
165
+
166
+ module.exports = {
167
+ registerHealthRoutes,
168
+ };
169
+ `;
170
+ }
171
+
172
+ function createFastifyContent(deployTarget) {
173
+ const routeDefinitions = createFastifyRouteDefinitions(deployTarget);
174
+
175
+ return `'use strict';
176
+
177
+ function withTimeout(operation, timeoutMs = 2000) {
178
+ return Promise.race([
179
+ Promise.resolve().then(operation),
180
+ new Promise((_, reject) => {
181
+ setTimeout(() => reject(new Error('timeout')), timeoutMs);
182
+ }),
183
+ ]);
184
+ }
185
+
186
+ async function pingDatabase(options = {}) {
187
+ if (!options.db) {
188
+ return { configured: false, ok: true, status: 'not_configured' };
189
+ }
190
+
191
+ try {
192
+ await withTimeout(async () => {
193
+ if (typeof options.db.ping === 'function') {
194
+ await options.db.ping();
195
+ return;
196
+ }
197
+
198
+ if (typeof options.db.query === 'function') {
199
+ await options.db.query('SELECT 1');
200
+ return;
201
+ }
202
+
203
+ throw new Error('no supported database ping method');
204
+ });
205
+
206
+ return { configured: true, ok: true, status: 'up' };
207
+ } catch (error) {
208
+ return { configured: true, ok: false, status: 'down', error: error.message };
209
+ }
210
+ }
211
+
212
+ async function pingRedis(options = {}) {
213
+ if (!options.redis) {
214
+ return { configured: false, ok: true, status: 'not_configured' };
215
+ }
216
+
217
+ try {
218
+ await withTimeout(async () => {
219
+ if (typeof options.redis.ping === 'function') {
220
+ await options.redis.ping();
221
+ return;
222
+ }
223
+
224
+ if (typeof options.redis.sendCommand === 'function') {
225
+ await options.redis.sendCommand(['PING']);
226
+ return;
227
+ }
228
+
229
+ throw new Error('no supported redis ping method');
230
+ });
231
+
232
+ return { configured: true, ok: true, status: 'up' };
233
+ } catch (error) {
234
+ return { configured: true, ok: false, status: 'down', error: error.message };
235
+ }
236
+ }
237
+
238
+ async function getDependencyStatus(options = {}) {
239
+ const [database, redis] = await Promise.all([
240
+ pingDatabase(options),
241
+ pingRedis(options),
242
+ ]);
243
+
244
+ const dependencies = {};
245
+
246
+ if (database.configured) {
247
+ dependencies.db = database;
248
+ }
249
+
250
+ if (redis.configured) {
251
+ dependencies.redis = redis;
252
+ }
253
+
254
+ const status = Object.values(dependencies).every(dependency => dependency.ok !== false)
255
+ ? 'ok'
256
+ : 'degraded';
257
+
258
+ return {
259
+ status,
260
+ dependencies,
261
+ uptime: process.uptime(),
262
+ };
263
+ }
264
+
265
+ function getStartupState(options = {}) {
266
+ if (typeof options.isStartupComplete === 'function') {
267
+ return Boolean(options.isStartupComplete());
268
+ }
269
+
270
+ if (typeof options.startupComplete === 'boolean') {
271
+ return options.startupComplete;
272
+ }
273
+
274
+ return true;
275
+ }
276
+
277
+ async function registerHealthRoutes(fastify, options = {}) {
278
+ ${routeDefinitions}
279
+ }
280
+
281
+ module.exports = {
282
+ registerHealthRoutes,
283
+ };
284
+ `;
285
+ }
286
+
287
+ function createExpressRouteDefinitions(deployTarget) {
288
+ if (deployTarget === 'k8s') {
289
+ return ` app.get('/healthz', async (_req, res) => {
290
+ sendJson(res, 200, {
291
+ status: 'ok',
292
+ dependencies: {},
293
+ uptime: process.uptime(),
294
+ });
295
+ });
296
+
297
+ app.get('/ready', async (_req, res) => {
298
+ const { status, dependencies, uptime } = await getDependencyStatus(options);
299
+ const statusCode = status === 'ok' ? 200 : 503;
300
+ sendJson(res, statusCode, { status, dependencies, uptime });
301
+ });
302
+
303
+ app.get('/startup', (_req, res) => {
304
+ const startupComplete = getStartupState(options);
305
+ const status = startupComplete ? 'ok' : 'starting';
306
+ const statusCode = startupComplete ? 200 : 503;
307
+ sendJson(res, statusCode, {
308
+ status,
309
+ dependencies: {},
310
+ uptime: process.uptime(),
311
+ });
312
+ });`;
313
+ }
314
+
315
+ return ` app.get('/health', async (_req, res) => {
316
+ const { status, dependencies, uptime } = await getDependencyStatus(options);
317
+ const statusCode = status === 'ok' ? 200 : 503;
318
+ sendJson(res, statusCode, { status, dependencies, uptime });
319
+ });`;
320
+ }
321
+
322
+ function createFastifyRouteDefinitions(deployTarget) {
323
+ if (deployTarget === 'k8s') {
324
+ return ` fastify.get('/healthz', async () => ({
325
+ status: 'ok',
326
+ dependencies: {},
327
+ uptime: process.uptime(),
328
+ }));
329
+
330
+ fastify.get('/ready', async (_request, reply) => {
331
+ const { status, dependencies, uptime } = await getDependencyStatus(options);
332
+ reply.code(status === 'ok' ? 200 : 503);
333
+ return { status, dependencies, uptime };
334
+ });
335
+
336
+ fastify.get('/startup', async (_request, reply) => {
337
+ const startupComplete = getStartupState(options);
338
+ const status = startupComplete ? 'ok' : 'starting';
339
+ reply.code(startupComplete ? 200 : 503);
340
+ return {
341
+ status,
342
+ dependencies: {},
343
+ uptime: process.uptime(),
344
+ };
345
+ });`;
346
+ }
347
+
348
+ return ` fastify.get('/health', async (_request, reply) => {
349
+ const { status, dependencies, uptime } = await getDependencyStatus(options);
350
+ reply.code(status === 'ok' ? 200 : 503);
351
+ return { status, dependencies, uptime };
352
+ });`;
353
+ }
354
+
355
+ function createPm2Snippet() {
356
+ return `module.exports = {
357
+ apps: [
358
+ {
359
+ name: 'app',
360
+ script: 'src/index.js',
361
+ instances: 1,
362
+ exec_mode: 'fork',
363
+ env: {
364
+ NODE_ENV: 'production',
365
+ },
366
+ },
367
+ ],
368
+ };
369
+ `;
370
+ }
371
+
372
+ module.exports = {
373
+ scaffoldHealth,
374
+ };
@@ -0,0 +1,99 @@
1
+ import { describe, expect, it } from 'vitest';
2
+
3
+ import { scaffoldHealth } from './health-scaffold.js';
4
+
5
+ function createFsMock() {
6
+ return {};
7
+ }
8
+
9
+ describe('scaffoldHealth', () => {
10
+ it('generates a single /health endpoint for docker-compose targets', () => {
11
+ const result = scaffoldHealth({
12
+ projectDir: '/project',
13
+ deployTarget: 'docker-compose',
14
+ framework: 'express',
15
+ fs: createFsMock(),
16
+ });
17
+
18
+ expect(result.dependencies).toEqual([]);
19
+ expect(result.files).toHaveLength(1);
20
+ expect(result.files[0].path).toBe('src/health.js');
21
+ expect(result.files[0].content).toContain("'/health'");
22
+ expect(result.files[0].content).not.toContain('/healthz');
23
+ expect(result.files[0].content).not.toContain('/ready');
24
+ expect(result.files[0].content).not.toContain('/startup');
25
+ });
26
+
27
+ it('generates three probe endpoints for k8s targets', () => {
28
+ const result = scaffoldHealth({
29
+ projectDir: '/project',
30
+ deployTarget: 'k8s',
31
+ framework: 'express',
32
+ fs: createFsMock(),
33
+ });
34
+
35
+ expect(result.files).toHaveLength(1);
36
+ expect(result.files[0].content).toContain("'/healthz'");
37
+ expect(result.files[0].content).toContain("'/ready'");
38
+ expect(result.files[0].content).toContain("'/startup'");
39
+ });
40
+
41
+ it('generates /health and a pm2 ecosystem config snippet for vps targets', () => {
42
+ const result = scaffoldHealth({
43
+ projectDir: '/project',
44
+ deployTarget: 'vps',
45
+ framework: 'express',
46
+ fs: createFsMock(),
47
+ });
48
+
49
+ expect(result.files).toHaveLength(2);
50
+ expect(result.files.map(file => file.path)).toEqual(['src/health.js', 'ecosystem.config.js']);
51
+
52
+ const healthFile = result.files.find(file => file.path === 'src/health.js');
53
+ const pm2File = result.files.find(file => file.path === 'ecosystem.config.js');
54
+
55
+ expect(healthFile.content).toContain("'/health'");
56
+ expect(pm2File.content).toContain('module.exports');
57
+ expect(pm2File.content).toContain('apps:');
58
+ expect(pm2File.content).toContain('env:');
59
+ });
60
+
61
+ it('uses Express route syntax for express projects', () => {
62
+ const result = scaffoldHealth({
63
+ projectDir: '/project',
64
+ deployTarget: 'docker-compose',
65
+ framework: 'express',
66
+ fs: createFsMock(),
67
+ });
68
+
69
+ expect(result.files[0].content).toContain('function registerHealthRoutes(app');
70
+ expect(result.files[0].content).toContain("app.get('/health'");
71
+ });
72
+
73
+ it('uses Fastify route syntax for fastify projects', () => {
74
+ const result = scaffoldHealth({
75
+ projectDir: '/project',
76
+ deployTarget: 'docker-compose',
77
+ framework: 'fastify',
78
+ fs: createFsMock(),
79
+ });
80
+
81
+ expect(result.files[0].content).toContain('async function registerHealthRoutes(fastify');
82
+ expect(result.files[0].content).toContain("fastify.get('/health'");
83
+ });
84
+
85
+ it('includes status, dependencies, and uptime fields in the generated health response', () => {
86
+ const result = scaffoldHealth({
87
+ projectDir: '/project',
88
+ deployTarget: 'docker-compose',
89
+ framework: 'express',
90
+ fs: createFsMock(),
91
+ });
92
+
93
+ expect(result.files[0].content).toContain('status,');
94
+ expect(result.files[0].content).toContain('dependencies,');
95
+ expect(result.files[0].content).toContain('uptime: process.uptime()');
96
+ expect(result.files[0].content).toContain('Promise.race');
97
+ expect(result.files[0].content).toContain('2000');
98
+ });
99
+ });