testchimp-runner-core 0.0.35 → 0.0.37

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 (81) hide show
  1. package/dist/orchestrator/orchestrator-agent.d.ts.map +1 -1
  2. package/dist/orchestrator/orchestrator-agent.js +7 -4
  3. package/dist/orchestrator/orchestrator-agent.js.map +1 -1
  4. package/dist/orchestrator/orchestrator-prompts.d.ts.map +1 -1
  5. package/dist/orchestrator/orchestrator-prompts.js +73 -15
  6. package/dist/orchestrator/orchestrator-prompts.js.map +1 -1
  7. package/dist/orchestrator/page-som-handler.d.ts +1 -2
  8. package/dist/orchestrator/page-som-handler.d.ts.map +1 -1
  9. package/dist/orchestrator/page-som-handler.js +51 -25
  10. package/dist/orchestrator/page-som-handler.js.map +1 -1
  11. package/package.json +6 -1
  12. package/plandocs/BEFORE_AFTER_VERIFICATION.md +0 -148
  13. package/plandocs/COORDINATE_MODE_DIAGNOSIS.md +0 -144
  14. package/plandocs/CREDIT_CALLBACK_ARCHITECTURE.md +0 -253
  15. package/plandocs/HUMAN_LIKE_IMPROVEMENTS.md +0 -642
  16. package/plandocs/IMPLEMENTATION_STATUS.md +0 -108
  17. package/plandocs/INTEGRATION_COMPLETE.md +0 -322
  18. package/plandocs/MULTI_AGENT_ARCHITECTURE_REVIEW.md +0 -844
  19. package/plandocs/ORCHESTRATOR_MVP_SUMMARY.md +0 -539
  20. package/plandocs/PHASE1_ABSTRACTION_COMPLETE.md +0 -241
  21. package/plandocs/PHASE1_FINAL_STATUS.md +0 -210
  22. package/plandocs/PHASE_1_COMPLETE.md +0 -165
  23. package/plandocs/PHASE_1_SUMMARY.md +0 -184
  24. package/plandocs/PLANNING_SESSION_SUMMARY.md +0 -372
  25. package/plandocs/PROMPT_OPTIMIZATION_ANALYSIS.md +0 -120
  26. package/plandocs/PROMPT_SANITY_CHECK.md +0 -120
  27. package/plandocs/SCRIPT_CLEANUP_FEATURE.md +0 -201
  28. package/plandocs/SCRIPT_GENERATION_ARCHITECTURE.md +0 -364
  29. package/plandocs/SELECTOR_IMPROVEMENTS.md +0 -139
  30. package/plandocs/SESSION_SUMMARY_v0.0.33.md +0 -151
  31. package/plandocs/TROUBLESHOOTING_SESSION.md +0 -72
  32. package/plandocs/VISION_DIAGNOSTICS_IMPROVEMENTS.md +0 -336
  33. package/plandocs/VISUAL_AGENT_EVOLUTION_PLAN.md +0 -396
  34. package/plandocs/WHATS_NEW_v0.0.33.md +0 -183
  35. package/plandocs/exploratory-mode-support-v2.plan.md +0 -953
  36. package/plandocs/exploratory-mode-support.plan.md +0 -928
  37. package/plandocs/journey-id-tracking-addendum.md +0 -227
  38. package/releasenotes/RELEASE_0.0.26.md +0 -165
  39. package/releasenotes/RELEASE_0.0.27.md +0 -236
  40. package/releasenotes/RELEASE_0.0.28.md +0 -286
  41. package/src/auth-config.ts +0 -84
  42. package/src/credit-usage-service.ts +0 -188
  43. package/src/env-loader.ts +0 -103
  44. package/src/execution-service.ts +0 -996
  45. package/src/file-handler.ts +0 -104
  46. package/src/index.ts +0 -432
  47. package/src/llm-facade.ts +0 -821
  48. package/src/llm-provider.ts +0 -53
  49. package/src/model-constants.ts +0 -35
  50. package/src/orchestrator/decision-parser.ts +0 -139
  51. package/src/orchestrator/index.ts +0 -58
  52. package/src/orchestrator/orchestrator-agent.ts +0 -1282
  53. package/src/orchestrator/orchestrator-prompts.ts +0 -786
  54. package/src/orchestrator/page-som-handler.ts +0 -1565
  55. package/src/orchestrator/som-types.ts +0 -188
  56. package/src/orchestrator/tool-registry.ts +0 -184
  57. package/src/orchestrator/tools/check-page-ready.ts +0 -75
  58. package/src/orchestrator/tools/extract-data.ts +0 -92
  59. package/src/orchestrator/tools/index.ts +0 -15
  60. package/src/orchestrator/tools/inspect-page.ts +0 -42
  61. package/src/orchestrator/tools/recall-history.ts +0 -72
  62. package/src/orchestrator/tools/refresh-som-markers.ts +0 -69
  63. package/src/orchestrator/tools/take-screenshot.ts +0 -128
  64. package/src/orchestrator/tools/verify-action-result.ts +0 -159
  65. package/src/orchestrator/tools/view-previous-screenshot.ts +0 -103
  66. package/src/orchestrator/types.ts +0 -291
  67. package/src/playwright-mcp-service.ts +0 -224
  68. package/src/progress-reporter.ts +0 -144
  69. package/src/prompts.ts +0 -842
  70. package/src/providers/backend-proxy-llm-provider.ts +0 -91
  71. package/src/providers/local-llm-provider.ts +0 -38
  72. package/src/scenario-service.ts +0 -252
  73. package/src/scenario-worker-class.ts +0 -1110
  74. package/src/script-utils.ts +0 -203
  75. package/src/types.ts +0 -239
  76. package/src/utils/browser-utils.ts +0 -348
  77. package/src/utils/coordinate-converter.ts +0 -162
  78. package/src/utils/page-info-retry.ts +0 -65
  79. package/src/utils/page-info-utils.ts +0 -285
  80. package/testchimp-runner-core-0.0.35.tgz +0 -0
  81. package/tsconfig.json +0 -19
@@ -1,104 +0,0 @@
1
- /**
2
- * File Handler Interface
3
- * Defines how different platforms handle file operations
4
- */
5
-
6
- export interface FileHandler {
7
- /**
8
- * Read test file content
9
- * @param filePath Path to the test file
10
- * @returns File content as string
11
- */
12
- readTestFile(filePath: string): Promise<string>;
13
-
14
- /**
15
- * Resolve a relative path to an absolute path based on the current working directory
16
- * @param relativePath Relative path to resolve
17
- * @returns Absolute path
18
- */
19
- resolvePath(relativePath: string): string;
20
-
21
- /**
22
- * Check if a file exists
23
- * @param filePath Path to check
24
- * @returns True if file exists
25
- */
26
- fileExists(filePath: string): Promise<boolean>;
27
- }
28
-
29
- /**
30
- * Local File Handler - Direct file system operations
31
- * Used by VS Code extension for local development
32
- */
33
- export class LocalFileHandler implements FileHandler {
34
- private fs = require('fs');
35
- private path = require('path');
36
- private basePath: string;
37
-
38
- constructor(basePath?: string) {
39
- this.basePath = basePath || String(process.cwd());
40
- }
41
-
42
- async readTestFile(filePath: string): Promise<string> {
43
- return this.fs.readFileSync(String(filePath), 'utf8');
44
- }
45
-
46
- resolvePath(relativePath: string): string {
47
- return this.path.resolve(String(this.basePath), String(relativePath));
48
- }
49
-
50
- async fileExists(filePath: string): Promise<boolean> {
51
- try {
52
- return this.fs.existsSync(String(filePath));
53
- } catch {
54
- return false;
55
- }
56
- }
57
- }
58
-
59
- /**
60
- * CI/CD File Handler - For CI/CD environments
61
- * Used by GitHub Actions for CI/CD environments
62
- */
63
- export class CIFileHandler implements FileHandler {
64
- private fs = require('fs');
65
- private path = require('path');
66
- private basePath: string;
67
-
68
- constructor(basePath?: string) {
69
- this.basePath = basePath || String(process.cwd());
70
- }
71
-
72
- async readTestFile(filePath: string): Promise<string> {
73
- return this.fs.readFileSync(String(filePath), 'utf8');
74
- }
75
-
76
- resolvePath(relativePath: string): string {
77
- return this.path.resolve(String(this.basePath), String(relativePath));
78
- }
79
-
80
- async fileExists(filePath: string): Promise<boolean> {
81
- try {
82
- return this.fs.existsSync(String(filePath));
83
- } catch {
84
- return false;
85
- }
86
- }
87
- }
88
-
89
- /**
90
- * No-op File Handler - For testing or when file operations are not needed
91
- */
92
- export class NoOpFileHandler implements FileHandler {
93
- async readTestFile(filePath: string): Promise<string> {
94
- return '';
95
- }
96
-
97
- resolvePath(relativePath: string): string {
98
- return relativePath;
99
- }
100
-
101
- async fileExists(filePath: string): Promise<boolean> {
102
- return false;
103
- }
104
- }
package/src/index.ts DELETED
@@ -1,432 +0,0 @@
1
- /**
2
- * TestChimp Runner Core
3
- * Shared functionality for VS Code extension and GitHub Actions
4
- */
5
-
6
- // Core services
7
- import { ExecutionService } from './execution-service';
8
- import { ScenarioService } from './scenario-service';
9
- import { ScenarioWorker } from './scenario-worker-class';
10
- import { PlaywrightMCPService } from './playwright-mcp-service';
11
- import { LLMFacade } from './llm-facade';
12
- import { AuthConfig } from './auth-config';
13
- import { CreditUsageService, CreditUsageCallback, CreditUsage, CreditUsageReason } from './credit-usage-service';
14
-
15
- export { ExecutionService, ScenarioService, ScenarioWorker, PlaywrightMCPService, LLMFacade, CreditUsageService, CreditUsageCallback, CreditUsage, CreditUsageReason };
16
-
17
- // File handlers
18
- import { FileHandler, LocalFileHandler, CIFileHandler, NoOpFileHandler } from './file-handler';
19
- export { FileHandler, LocalFileHandler, CIFileHandler, NoOpFileHandler };
20
-
21
- // LLM Provider interfaces
22
- import { LLMProvider, LLMRequest, LLMResponse } from './llm-provider';
23
- import { ProgressReporter, StepProgress, JobProgress, StepExecutionStatus, StepInfo } from './progress-reporter';
24
- import { BackendProxyLLMProvider } from './providers/backend-proxy-llm-provider';
25
- import { LocalLLMProvider } from './providers/local-llm-provider';
26
-
27
- export { LLMProvider, LLMRequest, LLMResponse };
28
- export { ProgressReporter, StepProgress, JobProgress, StepExecutionStatus, StepInfo };
29
- export { BackendProxyLLMProvider, LocalLLMProvider };
30
-
31
- // Orchestrator (tool-using agent)
32
- import type { AgentConfig } from './orchestrator';
33
- export {
34
- OrchestratorAgent,
35
- ToolRegistry,
36
- Tool,
37
- ToolParameter,
38
- ToolExecutionContext,
39
- AgentConfig,
40
- AgentContext,
41
- AgentDecision,
42
- JourneyMemory,
43
- MemoryStep,
44
- OrchestratorStepResult,
45
- SelfReflection,
46
- ToolCall,
47
- ToolResult,
48
- ExplorationMode,
49
- DEFAULT_AGENT_CONFIG,
50
- // Tools (information-gathering only)
51
- TakeScreenshotTool,
52
- RecallHistoryTool,
53
- InspectPageTool,
54
- CheckPageReadyTool,
55
- ExtractDataTool
56
- } from './orchestrator';
57
-
58
- // Types
59
- export * from './types';
60
- export { PageInfo, InteractiveElement } from './utils/page-info-utils';
61
-
62
- // Model constants
63
- export { DEFAULT_MODEL, DEFAULT_SIMPLER_MODEL, VISION_MODEL } from './model-constants';
64
-
65
- // Authentication
66
- export * from './auth-config';
67
-
68
- // Environment configuration
69
- export { loadEnvConfig } from './env-loader';
70
-
71
- // Script utilities
72
- export * from './script-utils';
73
-
74
- // Main TestChimp service class
75
- export class TestChimpService {
76
- private executionService: ExecutionService;
77
- public scenarioService: ScenarioService; // Make public for event listening
78
- private playwrightService: PlaywrightMCPService;
79
- private llmProvider: LLMProvider;
80
- private progressReporter?: ProgressReporter;
81
- private creditUsageService: CreditUsageService;
82
- private fileHandler: FileHandler;
83
- private authConfig: AuthConfig | null;
84
- private backendUrl: string;
85
- private logger?: (message: string, level?: 'log' | 'error' | 'warn') => void;
86
- private orchestratorOptions?: { useOrchestrator?: boolean; orchestratorConfig?: Partial<AgentConfig>; debugMode?: boolean };
87
- private outputChannel?: any; // Store outputChannel to preserve it across service recreations
88
- private creditUsageCallback?: CreditUsageCallback; // Store credit callback to preserve it across service recreations
89
-
90
- constructor(
91
- fileHandler?: FileHandler,
92
- authConfig?: AuthConfig,
93
- backendUrl?: string,
94
- maxWorkers?: number,
95
- llmProvider?: LLMProvider,
96
- progressReporter?: ProgressReporter,
97
- orchestratorOptions?: { useOrchestrator?: boolean; orchestratorConfig?: Partial<AgentConfig>; debugMode?: boolean },
98
- creditUsageCallback?: CreditUsageCallback
99
- ) {
100
- this.fileHandler = fileHandler || new NoOpFileHandler();
101
- this.authConfig = authConfig || null;
102
- this.backendUrl = backendUrl || 'https://featureservice.testchimp.io'; // Default to production
103
- this.progressReporter = progressReporter;
104
- this.orchestratorOptions = orchestratorOptions;
105
- this.creditUsageCallback = creditUsageCallback;
106
-
107
- // Use provided LLM provider or default to backend proxy (backward compatible)
108
- this.llmProvider = llmProvider || new BackendProxyLLMProvider(authConfig, backendUrl);
109
-
110
- this.playwrightService = new PlaywrightMCPService();
111
- // Pass credit callback to constructor - preserved across recreations via this.creditUsageCallback
112
- this.creditUsageService = new CreditUsageService(this.authConfig || undefined, this.backendUrl, this.creditUsageCallback);
113
-
114
- // Create services with providers
115
- this.executionService = new ExecutionService(
116
- this.authConfig || undefined,
117
- this.backendUrl,
118
- maxWorkers || 10,
119
- this.llmProvider, // Pass the LLM provider
120
- this.progressReporter // Pass the progress reporter
121
- );
122
-
123
- this.scenarioService = new ScenarioService(
124
- maxWorkers || 2,
125
- this.fileHandler,
126
- this.llmProvider,
127
- this.progressReporter,
128
- this.authConfig || undefined,
129
- this.backendUrl,
130
- this.orchestratorOptions // Pass orchestrator options
131
- );
132
- }
133
-
134
- /**
135
- * Set authentication configuration for the service
136
- * Recreates LLM provider and services with new auth config
137
- */
138
- async setAuthConfig(authConfig: AuthConfig): Promise<void> {
139
- this.authConfig = authConfig;
140
- this.creditUsageService.setAuthConfig(authConfig);
141
-
142
- // Recreate LLM provider with new auth config
143
- this.llmProvider = new BackendProxyLLMProvider(authConfig, this.backendUrl);
144
-
145
- // Set logger on new provider if we have one
146
- if (this.logger) {
147
- this.llmProvider.setLogger?.(this.logger);
148
- }
149
-
150
- // Recreate services with new provider AND pass llmProvider and progressReporter
151
- this.executionService = new ExecutionService(
152
- this.authConfig,
153
- this.backendUrl,
154
- 10,
155
- this.llmProvider, // Pass the LLM provider
156
- this.progressReporter // Pass the progress reporter
157
- );
158
-
159
- this.scenarioService = new ScenarioService(
160
- 2,
161
- this.fileHandler,
162
- this.llmProvider,
163
- this.progressReporter,
164
- this.authConfig,
165
- this.backendUrl,
166
- this.orchestratorOptions // Pass orchestrator options
167
- );
168
-
169
- // Set logger on recreated services if we have one
170
- if (this.logger) {
171
- this.executionService.setLogger(this.logger);
172
- this.scenarioService.setLogger(this.logger);
173
- }
174
-
175
- // Reapply outputChannel if we have one (critical for orchestrator logs)
176
- if (this.outputChannel) {
177
- this.scenarioService.setOutputChannel(this.outputChannel);
178
- }
179
-
180
- // Reinitialize the services
181
- await this.executionService.initialize();
182
- await this.scenarioService.initialize();
183
- }
184
-
185
- /**
186
- * Set backend URL for the service
187
- * Recreates LLM provider and services with new backend URL
188
- */
189
- setBackendUrl(backendUrl: string): void {
190
- this.backendUrl = backendUrl;
191
-
192
- // Recreate LLM provider with new backend URL
193
- this.llmProvider = new BackendProxyLLMProvider(this.authConfig || undefined, backendUrl);
194
-
195
- // Set logger on new provider if we have one
196
- if (this.logger) {
197
- this.llmProvider.setLogger?.(this.logger);
198
- }
199
-
200
- // Recreate services with new provider (preserve credit callback)
201
- this.creditUsageService = new CreditUsageService(this.authConfig || undefined, this.backendUrl, this.creditUsageCallback);
202
- this.executionService = new ExecutionService(
203
- this.authConfig || undefined,
204
- this.backendUrl,
205
- 10,
206
- this.llmProvider, // Pass the LLM provider
207
- this.progressReporter // Pass the progress reporter
208
- );
209
-
210
- this.scenarioService = new ScenarioService(
211
- 2,
212
- this.fileHandler,
213
- this.llmProvider,
214
- this.progressReporter,
215
- this.authConfig || undefined,
216
- this.backendUrl,
217
- this.orchestratorOptions // Pass orchestrator options
218
- );
219
-
220
- // Set logger on recreated services if we have one
221
- if (this.logger) {
222
- this.executionService.setLogger(this.logger);
223
- this.scenarioService.setLogger(this.logger);
224
- }
225
-
226
- // Reapply outputChannel if we have one (critical for orchestrator logs)
227
- if (this.outputChannel) {
228
- this.scenarioService.setOutputChannel(this.outputChannel);
229
- }
230
- }
231
-
232
- /**
233
- * Set logger callback for capturing execution logs
234
- */
235
- setLogger(logger: (message: string, level?: 'log' | 'error' | 'warn') => void): void {
236
- this.logger = logger;
237
- this.executionService.setLogger(logger);
238
- this.scenarioService.setLogger(logger);
239
- this.llmProvider.setLogger?.(logger);
240
- this.creditUsageService.setLogger(logger);
241
- }
242
-
243
- /**
244
- * Set output channel for worker logs (VS Code OutputChannel)
245
- * This enables orchestrator thinking logs to appear in output console
246
- */
247
- setOutputChannel(outputChannel: any): void {
248
- this.outputChannel = outputChannel; // Store for future service recreations
249
- if (typeof this.scenarioService?.setOutputChannel === 'function') {
250
- this.scenarioService.setOutputChannel(outputChannel);
251
- }
252
- }
253
-
254
- /**
255
- * Set credit usage callback
256
- * Server-side: Use callback to update DB directly (no axios calls)
257
- * Client-side: Don't set callback, uses auth for axios calls to backend
258
- */
259
- setCreditUsageCallback(callback: CreditUsageCallback): void {
260
- this.creditUsageCallback = callback; // Store for future service recreations
261
- this.creditUsageService.setCreditUsageCallback(callback);
262
- }
263
-
264
- /**
265
- * Log a message using the configured logger
266
- */
267
- private log(message: string, level: 'log' | 'error' | 'warn' = 'log'): void {
268
- if (this.logger) {
269
- this.logger(message, level);
270
- }
271
- // No console fallback - logs are routed to consumer
272
- }
273
-
274
- /**
275
- * Get current authentication configuration
276
- */
277
- getAuthConfig(): AuthConfig | null {
278
- return this.authConfig;
279
- }
280
-
281
- async initialize(): Promise<void> {
282
- await this.playwrightService.initialize();
283
- await this.executionService.initialize();
284
- await this.scenarioService.initialize();
285
- }
286
-
287
- async shutdown(): Promise<void> {
288
- // Cleanup resources
289
- }
290
-
291
- // Scenario generation
292
- async generateScript(
293
- scenario: string,
294
- testName?: string,
295
- config?: string,
296
- model?: string,
297
- scenarioFileName?: string,
298
- existingBrowser?: any,
299
- existingContext?: any,
300
- existingPage?: any
301
- ): Promise<string> {
302
- return this.scenarioService.processScenario(
303
- scenario,
304
- testName,
305
- config,
306
- model,
307
- scenarioFileName,
308
- existingBrowser,
309
- existingContext,
310
- existingPage
311
- );
312
- }
313
-
314
- // Test execution
315
- async executeScript(request: any): Promise<any> {
316
- // Read script content if not provided but scriptFilePath is
317
- if (!request.script && request.scriptFilePath) {
318
- try {
319
- const resolvedPath = this.fileHandler.resolvePath(request.scriptFilePath);
320
- request.script = await this.fileHandler.readTestFile(resolvedPath);
321
- this.log(`Read script content from file: ${resolvedPath}`);
322
- } catch (error) {
323
- throw new Error(`Failed to read script file: ${error}`);
324
- }
325
- }
326
-
327
- // Read Playwright config content if not provided but playwrightConfigFilePath is
328
- if (!request.playwrightConfig && request.playwrightConfigFilePath) {
329
- try {
330
- const resolvedPath = this.fileHandler.resolvePath(request.playwrightConfigFilePath);
331
- request.playwrightConfig = await this.fileHandler.readTestFile(resolvedPath);
332
- this.log(`Read Playwright config content from file: ${resolvedPath}`);
333
- } catch (error) {
334
- this.log(`Failed to read Playwright config file: ${error}. Using default configuration.`, 'warn');
335
- // Don't throw error, just use default config
336
- }
337
- }
338
-
339
- // Log content status
340
- if (request.script) {
341
- this.log(`Using provided script content (${request.script.length} characters)`);
342
- } else if (request.steps && request.steps.length > 0) {
343
- this.log(`Using ${request.steps.length} pre-parsed steps (script will be generated if needed)`);
344
- } else {
345
- throw new Error('Script content is required. Provide either script or scriptFilePath.');
346
- }
347
-
348
- if (request.playwrightConfig) {
349
- this.log(`Using provided Playwright config (${request.playwrightConfig.length} characters)`);
350
- } else {
351
- this.log(`Using default Playwright configuration`);
352
- }
353
-
354
- const result = await this.executionService.executeScript(request);
355
-
356
- // Return result - consumer decides what to do with updated_script
357
- return result;
358
- }
359
-
360
- // Test execution with AI repair
361
- async executeScriptWithAIRepair(request: any): Promise<any> {
362
- const repairRequest = { ...request, mode: 'RUN_WITH_AI_REPAIR' };
363
- return this.executeScript(repairRequest);
364
- }
365
-
366
- // Exploration mode execution
367
- async executeExploration(page: any, explorationConfig: any, jobId: string): Promise<any> {
368
- // Delegate to scenario service's orchestrator
369
- return this.scenarioService.executeExploration(page, explorationConfig, jobId);
370
- }
371
-
372
- // Credit usage reporting methods
373
- async reportScriptGenerationCredit(jobId?: string): Promise<void> {
374
- return this.creditUsageService.reportScriptGenerationCredit(jobId);
375
- }
376
-
377
- async reportAIRepairCredit(jobId?: string): Promise<void> {
378
- return this.creditUsageService.reportAIRepairCredit(jobId);
379
- }
380
-
381
- // Find TestChimp smart/managed tests (prioritizes Smart Test detection)
382
- findTestChimpTests(directory: string, recursive: boolean = true): string[] {
383
- const fs = require('fs');
384
- const path = require('path');
385
-
386
- const testFiles: string[] = [];
387
-
388
- function scanDir(dir: string) {
389
- try {
390
- const items = fs.readdirSync(String(dir));
391
-
392
- for (const item of items) {
393
- const fullPath = path.join(String(dir), String(item));
394
- const stat = fs.statSync(String(fullPath));
395
-
396
- if (stat.isDirectory() && recursive) {
397
- scanDir(fullPath);
398
- } else if (stat.isFile() && isTestChimpTest(fullPath)) {
399
- testFiles.push(fullPath);
400
- }
401
- }
402
- } catch (error) {
403
- // Skip directories that can't be read
404
- }
405
- }
406
-
407
- function isTestChimpTest(filePath: string): boolean {
408
- // Check if file is a test file (including smart test files)
409
- if (!filePath.match(/\.(smart\.spec|spec|test)\.(js|ts)$/)) {
410
- return false;
411
- }
412
-
413
- try {
414
- // Read file content
415
- const content = fs.readFileSync(filePath, 'utf8');
416
-
417
- // Check for TestChimp markers - only exact comment phrases
418
- const testChimpMarkers = [
419
- /This is a TestChimp Smart Test/i,
420
- /This is a TestChimp Managed Test/i
421
- ];
422
-
423
- return testChimpMarkers.some(marker => marker.test(content));
424
- } catch (error) {
425
- return false;
426
- }
427
- }
428
-
429
- scanDir(directory);
430
- return testFiles;
431
- }
432
- }