sqlew 2.1.4 → 3.1.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 (97) hide show
  1. package/CHANGELOG.md +891 -605
  2. package/LICENSE +49 -18
  3. package/README.md +337 -690
  4. package/assets/kanban-style.png +0 -0
  5. package/assets/schema.sql +532 -402
  6. package/dist/database.d.ts +9 -0
  7. package/dist/database.d.ts.map +1 -1
  8. package/dist/database.js +33 -34
  9. package/dist/database.js.map +1 -1
  10. package/dist/index.js +1050 -215
  11. package/dist/index.js.map +1 -1
  12. package/dist/migrations/add-task-tables.d.ts +47 -0
  13. package/dist/migrations/add-task-tables.d.ts.map +1 -0
  14. package/dist/migrations/add-task-tables.js +285 -0
  15. package/dist/migrations/add-task-tables.js.map +1 -0
  16. package/dist/migrations/index.d.ts +96 -0
  17. package/dist/migrations/index.d.ts.map +1 -0
  18. package/dist/migrations/index.js +239 -0
  19. package/dist/migrations/index.js.map +1 -0
  20. package/dist/migrations/migrate-decisions-to-tasks.d.ts +61 -0
  21. package/dist/migrations/migrate-decisions-to-tasks.d.ts.map +1 -0
  22. package/dist/migrations/migrate-decisions-to-tasks.js +442 -0
  23. package/dist/migrations/migrate-decisions-to-tasks.js.map +1 -0
  24. package/dist/schema.d.ts.map +1 -1
  25. package/dist/schema.js +14 -3
  26. package/dist/schema.js.map +1 -1
  27. package/dist/tools/constraints.d.ts +4 -0
  28. package/dist/tools/constraints.d.ts.map +1 -1
  29. package/dist/tools/constraints.js +6 -27
  30. package/dist/tools/constraints.js.map +1 -1
  31. package/dist/tools/context.d.ts +17 -1
  32. package/dist/tools/context.d.ts.map +1 -1
  33. package/dist/tools/context.js +195 -190
  34. package/dist/tools/context.js.map +1 -1
  35. package/dist/tools/files.d.ts.map +1 -1
  36. package/dist/tools/files.js +113 -166
  37. package/dist/tools/files.js.map +1 -1
  38. package/dist/tools/messaging.d.ts +2 -9
  39. package/dist/tools/messaging.d.ts.map +1 -1
  40. package/dist/tools/messaging.js +67 -126
  41. package/dist/tools/messaging.js.map +1 -1
  42. package/dist/tools/tasks.d.ts +90 -0
  43. package/dist/tools/tasks.d.ts.map +1 -0
  44. package/dist/tools/tasks.js +844 -0
  45. package/dist/tools/tasks.js.map +1 -0
  46. package/dist/tools/utils.d.ts +8 -1
  47. package/dist/tools/utils.d.ts.map +1 -1
  48. package/dist/tools/utils.js +50 -21
  49. package/dist/tools/utils.js.map +1 -1
  50. package/dist/types.d.ts +29 -0
  51. package/dist/types.d.ts.map +1 -1
  52. package/dist/utils/batch.d.ts +69 -0
  53. package/dist/utils/batch.d.ts.map +1 -0
  54. package/dist/utils/batch.js +148 -0
  55. package/dist/utils/batch.js.map +1 -0
  56. package/dist/utils/query-builder.d.ts +68 -0
  57. package/dist/utils/query-builder.d.ts.map +1 -0
  58. package/dist/utils/query-builder.js +116 -0
  59. package/dist/utils/query-builder.js.map +1 -0
  60. package/dist/utils/task-stale-detection.d.ts +28 -0
  61. package/dist/utils/task-stale-detection.d.ts.map +1 -0
  62. package/dist/utils/task-stale-detection.js +92 -0
  63. package/dist/utils/task-stale-detection.js.map +1 -0
  64. package/dist/utils/validators.d.ts +57 -0
  65. package/dist/utils/validators.d.ts.map +1 -0
  66. package/dist/utils/validators.js +117 -0
  67. package/dist/utils/validators.js.map +1 -0
  68. package/dist/watcher/file-watcher.d.ts +75 -0
  69. package/dist/watcher/file-watcher.d.ts.map +1 -0
  70. package/dist/watcher/file-watcher.js +374 -0
  71. package/dist/watcher/file-watcher.js.map +1 -0
  72. package/dist/watcher/index.d.ts +8 -0
  73. package/dist/watcher/index.d.ts.map +1 -0
  74. package/dist/watcher/index.js +7 -0
  75. package/dist/watcher/index.js.map +1 -0
  76. package/dist/watcher/test-executor.d.ts +23 -0
  77. package/dist/watcher/test-executor.d.ts.map +1 -0
  78. package/dist/watcher/test-executor.js +226 -0
  79. package/dist/watcher/test-executor.js.map +1 -0
  80. package/docs/ACCEPTANCE_CRITERIA.md +625 -0
  81. package/docs/AI_AGENT_GUIDE.md +1471 -648
  82. package/{ARCHITECTURE.md → docs/ARCHITECTURE.md} +636 -636
  83. package/docs/AUTO_FILE_TRACKING.md +436 -0
  84. package/docs/BEST_PRACTICES.md +481 -0
  85. package/docs/DECISION_TO_TASK_MIGRATION_GUIDE.md +457 -0
  86. package/docs/MIGRATION_CHAIN.md +280 -0
  87. package/{MIGRATION_v2.md → docs/MIGRATION_v2.md} +538 -538
  88. package/docs/SHARED_CONCEPTS.md +339 -0
  89. package/docs/TASK_ACTIONS.md +854 -0
  90. package/docs/TASK_LINKING.md +729 -0
  91. package/docs/TASK_MIGRATION.md +701 -0
  92. package/docs/TASK_OVERVIEW.md +363 -0
  93. package/docs/TASK_SYSTEM.md +1244 -0
  94. package/docs/TOOL_REFERENCE.md +471 -0
  95. package/docs/TOOL_SELECTION.md +279 -0
  96. package/docs/WORKFLOWS.md +602 -0
  97. package/package.json +65 -64
@@ -0,0 +1,374 @@
1
+ /**
2
+ * File Watcher - Auto-tracking file changes linked to tasks
3
+ * Monitors files and auto-transitions task status on file modification
4
+ *
5
+ * Features:
6
+ * - chokidar-based file watching with debouncing
7
+ * - Dynamic file registration (add/remove files at runtime)
8
+ * - Auto-transition: todo → in_progress on file change
9
+ * - Maps file paths → task IDs for efficient lookup
10
+ */
11
+ import chokidar from 'chokidar';
12
+ import { getDatabase } from '../database.js';
13
+ import { basename, dirname } from 'path';
14
+ import { existsSync } from 'fs';
15
+ import { executeAcceptanceCriteria } from './test-executor.js';
16
+ /**
17
+ * FileWatcher class - Singleton pattern
18
+ */
19
+ export class FileWatcher {
20
+ static instance = null;
21
+ watcher = null;
22
+ watchedFiles = new Map();
23
+ isRunning = false;
24
+ debounceTimers = new Map();
25
+ DEBOUNCE_MS = 2000; // Wait 2s after last write
26
+ constructor() {
27
+ // Private constructor for singleton
28
+ }
29
+ /**
30
+ * Get singleton instance
31
+ */
32
+ static getInstance() {
33
+ if (!FileWatcher.instance) {
34
+ FileWatcher.instance = new FileWatcher();
35
+ }
36
+ return FileWatcher.instance;
37
+ }
38
+ /**
39
+ * Initialize and start the file watcher
40
+ */
41
+ async start() {
42
+ if (this.isRunning) {
43
+ console.error('⚠ File watcher already running');
44
+ return;
45
+ }
46
+ try {
47
+ // Initialize chokidar with debouncing
48
+ this.watcher = chokidar.watch([], {
49
+ persistent: true,
50
+ ignoreInitial: true, // Don't trigger on startup
51
+ awaitWriteFinish: {
52
+ stabilityThreshold: this.DEBOUNCE_MS,
53
+ pollInterval: 100
54
+ },
55
+ ignored: /(^|[\/\\])\../, // Ignore dotfiles
56
+ });
57
+ // Set up event handlers
58
+ this.watcher.on('change', (path) => {
59
+ this.handleFileChange(path);
60
+ });
61
+ this.watcher.on('add', (path) => {
62
+ this.handleFileChange(path);
63
+ });
64
+ this.watcher.on('error', (error) => {
65
+ console.error('File watcher error:', error);
66
+ });
67
+ // Load existing task-file links from database
68
+ await this.loadTaskFileLinks();
69
+ this.isRunning = true;
70
+ console.error('✓ File watcher started successfully');
71
+ console.error(` Watching ${this.watchedFiles.size} files for ${this.getTotalTaskCount()} tasks`);
72
+ }
73
+ catch (error) {
74
+ console.error('Failed to start file watcher:', error);
75
+ throw error;
76
+ }
77
+ }
78
+ /**
79
+ * Stop the file watcher
80
+ */
81
+ async stop() {
82
+ if (!this.isRunning) {
83
+ return;
84
+ }
85
+ try {
86
+ // Clear all debounce timers
87
+ this.debounceTimers.forEach(timer => clearTimeout(timer));
88
+ this.debounceTimers.clear();
89
+ // Close watcher
90
+ if (this.watcher) {
91
+ await this.watcher.close();
92
+ this.watcher = null;
93
+ }
94
+ this.isRunning = false;
95
+ console.error('✓ File watcher stopped');
96
+ }
97
+ catch (error) {
98
+ console.error('Error stopping file watcher:', error);
99
+ throw error;
100
+ }
101
+ }
102
+ /**
103
+ * Register a file to watch for a specific task
104
+ */
105
+ registerFile(filePath, taskId, taskTitle, currentStatus) {
106
+ if (!this.watcher) {
107
+ console.error('Cannot register file: watcher not initialized');
108
+ return;
109
+ }
110
+ // Normalize path
111
+ const normalizedPath = this.normalizePath(filePath);
112
+ // Add to watched files map
113
+ if (!this.watchedFiles.has(normalizedPath)) {
114
+ this.watchedFiles.set(normalizedPath, []);
115
+ // Check if file exists
116
+ if (existsSync(normalizedPath)) {
117
+ // File exists - watch it directly
118
+ this.watcher.add(normalizedPath);
119
+ console.error(` Watching file: ${basename(normalizedPath)} for task #${taskId}`);
120
+ }
121
+ else {
122
+ // File doesn't exist - watch parent directory
123
+ const parentDir = dirname(normalizedPath);
124
+ this.watcher.add(parentDir);
125
+ console.error(` Watching directory: ${parentDir} for task #${taskId} (file doesn't exist yet)`);
126
+ }
127
+ }
128
+ const mappings = this.watchedFiles.get(normalizedPath);
129
+ // Check if task already registered for this file
130
+ const existing = mappings.find(m => m.taskId === taskId);
131
+ if (existing) {
132
+ // Update status
133
+ existing.currentStatus = currentStatus;
134
+ existing.taskTitle = taskTitle;
135
+ }
136
+ else {
137
+ // Add new mapping
138
+ mappings.push({ taskId, taskTitle, currentStatus });
139
+ }
140
+ }
141
+ /**
142
+ * Unregister a file from watching (when task completes or is archived)
143
+ */
144
+ unregisterFile(filePath, taskId) {
145
+ const normalizedPath = this.normalizePath(filePath);
146
+ const mappings = this.watchedFiles.get(normalizedPath);
147
+ if (!mappings) {
148
+ return;
149
+ }
150
+ // Remove this task from the file's mappings
151
+ const filtered = mappings.filter(m => m.taskId !== taskId);
152
+ if (filtered.length === 0) {
153
+ // No more tasks watching this file
154
+ this.watchedFiles.delete(normalizedPath);
155
+ if (this.watcher) {
156
+ this.watcher.unwatch(normalizedPath);
157
+ }
158
+ console.error(` Stopped watching: ${basename(normalizedPath)}`);
159
+ }
160
+ else {
161
+ this.watchedFiles.set(normalizedPath, filtered);
162
+ }
163
+ }
164
+ /**
165
+ * Unregister all files for a specific task
166
+ */
167
+ unregisterTask(taskId) {
168
+ const filesToUnregister = [];
169
+ // Find all files linked to this task
170
+ this.watchedFiles.forEach((mappings, filePath) => {
171
+ if (mappings.some(m => m.taskId === taskId)) {
172
+ filesToUnregister.push(filePath);
173
+ }
174
+ });
175
+ // Unregister each file
176
+ filesToUnregister.forEach(filePath => {
177
+ this.unregisterFile(filePath, taskId);
178
+ });
179
+ }
180
+ /**
181
+ * Handle file change event
182
+ */
183
+ async handleFileChange(filePath) {
184
+ const normalizedPath = this.normalizePath(filePath);
185
+ const mappings = this.watchedFiles.get(normalizedPath);
186
+ if (!mappings || mappings.length === 0) {
187
+ return;
188
+ }
189
+ console.error(`\n📝 File changed: ${basename(normalizedPath)}`);
190
+ const db = getDatabase();
191
+ // Process each task linked to this file
192
+ for (const mapping of mappings) {
193
+ const { taskId, taskTitle, currentStatus } = mapping;
194
+ // Auto-transition: todo → in_progress
195
+ if (currentStatus === 'todo') {
196
+ try {
197
+ // Get status IDs
198
+ const todoStatusId = db.prepare('SELECT id FROM m_task_statuses WHERE name = ?').get('todo');
199
+ const inProgressStatusId = db.prepare('SELECT id FROM m_task_statuses WHERE name = ?').get('in_progress');
200
+ if (!todoStatusId || !inProgressStatusId) {
201
+ console.error('Cannot find task status IDs');
202
+ return;
203
+ }
204
+ // Update task status: todo → in_progress
205
+ db.prepare(`
206
+ UPDATE t_tasks
207
+ SET status_id = ?, updated_ts = unixepoch()
208
+ WHERE id = ? AND status_id = ?
209
+ `).run(inProgressStatusId.id, taskId, todoStatusId.id);
210
+ // Update in-memory status
211
+ mapping.currentStatus = 'in_progress';
212
+ console.error(` ✓ Task #${taskId} "${taskTitle}": todo → in_progress`);
213
+ // Log to activity log
214
+ const agentId = db.prepare('SELECT assigned_agent_id FROM t_tasks WHERE id = ?').get(taskId);
215
+ if (agentId?.assigned_agent_id) {
216
+ db.prepare(`
217
+ INSERT INTO t_activity_log (agent_id, action_type, target, details)
218
+ VALUES (?, ?, ?, ?)
219
+ `).run(agentId.assigned_agent_id, 'task_auto_transition', `task_id:${taskId}`, JSON.stringify({
220
+ from_status: 'todo',
221
+ to_status: 'in_progress',
222
+ trigger: 'file_change',
223
+ file_path: normalizedPath
224
+ }));
225
+ }
226
+ }
227
+ catch (error) {
228
+ console.error(`Error auto-transitioning task #${taskId}:`, error);
229
+ }
230
+ }
231
+ // Check acceptance criteria for in_progress tasks
232
+ if (currentStatus === 'in_progress' || mapping.currentStatus === 'in_progress') {
233
+ await this.checkAcceptanceCriteria(taskId, taskTitle, mapping);
234
+ }
235
+ else {
236
+ console.error(` • Task #${taskId} "${taskTitle}": status ${currentStatus}`);
237
+ }
238
+ }
239
+ }
240
+ /**
241
+ * Check acceptance criteria and auto-complete task if all pass
242
+ */
243
+ async checkAcceptanceCriteria(taskId, taskTitle, mapping) {
244
+ const db = getDatabase();
245
+ try {
246
+ // Get acceptance criteria JSON
247
+ const taskDetails = db.prepare(`
248
+ SELECT acceptance_criteria_json
249
+ FROM t_task_details
250
+ WHERE task_id = ?
251
+ `).get(taskId);
252
+ if (!taskDetails || !taskDetails.acceptance_criteria_json) {
253
+ // No acceptance criteria defined, skip auto-completion
254
+ return;
255
+ }
256
+ const checks = JSON.parse(taskDetails.acceptance_criteria_json);
257
+ if (!Array.isArray(checks) || checks.length === 0) {
258
+ return;
259
+ }
260
+ console.error(` 🔍 Checking acceptance criteria for task #${taskId}...`);
261
+ // Execute all checks
262
+ const { allPassed, results } = await executeAcceptanceCriteria(checks);
263
+ // Log individual check results
264
+ results.forEach((result, index) => {
265
+ const icon = result.success ? '✓' : '✗';
266
+ console.error(` ${icon} Check ${index + 1}: ${result.message}`);
267
+ if (result.details) {
268
+ console.error(` Details: ${result.details}`);
269
+ }
270
+ });
271
+ if (allPassed) {
272
+ // All checks passed - auto-complete task: in_progress → done
273
+ const inProgressStatusId = db.prepare('SELECT id FROM m_task_statuses WHERE name = ?').get('in_progress');
274
+ const doneStatusId = db.prepare('SELECT id FROM m_task_statuses WHERE name = ?').get('done');
275
+ if (!inProgressStatusId || !doneStatusId) {
276
+ console.error('Cannot find task status IDs');
277
+ return;
278
+ }
279
+ db.prepare(`
280
+ UPDATE t_tasks
281
+ SET status_id = ?, completed_ts = unixepoch(), updated_ts = unixepoch()
282
+ WHERE id = ? AND status_id = ?
283
+ `).run(doneStatusId.id, taskId, inProgressStatusId.id);
284
+ // Update in-memory status
285
+ mapping.currentStatus = 'done';
286
+ console.error(` 🎉 Task #${taskId} "${taskTitle}": in_progress → done (all checks passed!)`);
287
+ // Unregister from watcher (done tasks don't need watching)
288
+ this.unregisterTask(taskId);
289
+ // Log to activity log
290
+ const agentId = db.prepare('SELECT assigned_agent_id FROM t_tasks WHERE id = ?').get(taskId);
291
+ if (agentId?.assigned_agent_id) {
292
+ db.prepare(`
293
+ INSERT INTO t_activity_log (agent_id, action_type, target, details)
294
+ VALUES (?, ?, ?, ?)
295
+ `).run(agentId.assigned_agent_id, 'task_auto_complete', `task_id:${taskId}`, JSON.stringify({
296
+ from_status: 'in_progress',
297
+ to_status: 'done',
298
+ trigger: 'acceptance_criteria_passed',
299
+ checks_passed: results.length
300
+ }));
301
+ }
302
+ }
303
+ else {
304
+ const failedCount = results.filter(r => !r.success).length;
305
+ console.error(` ⏳ Task #${taskId}: ${failedCount}/${results.length} checks failed, staying in_progress`);
306
+ }
307
+ }
308
+ catch (error) {
309
+ console.error(`Error checking acceptance criteria for task #${taskId}:`, error);
310
+ }
311
+ }
312
+ /**
313
+ * Load existing task-file links from database
314
+ */
315
+ async loadTaskFileLinks() {
316
+ const db = getDatabase();
317
+ try {
318
+ // Query all active tasks with file links
319
+ const query = `
320
+ SELECT
321
+ t.id as task_id,
322
+ t.title as task_title,
323
+ s.name as status,
324
+ f.path as file_path
325
+ FROM t_tasks t
326
+ JOIN m_task_statuses s ON t.status_id = s.id
327
+ JOIN t_task_file_links tfl ON t.id = tfl.task_id
328
+ JOIN m_files f ON tfl.file_id = f.id
329
+ WHERE s.name IN ('todo', 'in_progress', 'waiting_review', 'blocked')
330
+ `;
331
+ const links = db.prepare(query).all();
332
+ // Register each file
333
+ links.forEach(link => {
334
+ this.registerFile(link.file_path, link.task_id, link.task_title, link.status);
335
+ });
336
+ console.error(` Loaded ${links.length} task-file links from database`);
337
+ }
338
+ catch (error) {
339
+ console.error('Error loading task-file links:', error);
340
+ throw error;
341
+ }
342
+ }
343
+ /**
344
+ * Normalize file path (resolve relative paths, remove trailing slashes)
345
+ */
346
+ normalizePath(filePath) {
347
+ // Remove trailing slashes
348
+ let normalized = filePath.replace(/[\/\\]+$/, '');
349
+ // Convert backslashes to forward slashes (Windows compatibility)
350
+ normalized = normalized.replace(/\\/g, '/');
351
+ return normalized;
352
+ }
353
+ /**
354
+ * Get total count of tasks being watched
355
+ */
356
+ getTotalTaskCount() {
357
+ const taskIds = new Set();
358
+ this.watchedFiles.forEach(mappings => {
359
+ mappings.forEach(m => taskIds.add(m.taskId));
360
+ });
361
+ return taskIds.size;
362
+ }
363
+ /**
364
+ * Get current watcher status
365
+ */
366
+ getStatus() {
367
+ return {
368
+ running: this.isRunning,
369
+ filesWatched: this.watchedFiles.size,
370
+ tasksWatched: this.getTotalTaskCount()
371
+ };
372
+ }
373
+ }
374
+ //# sourceMappingURL=file-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-watcher.js","sourceRoot":"","sources":["../../src/watcher/file-watcher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Watcher module exports
3
+ * Provides file watching and test execution functionality
4
+ */
5
+ export { FileWatcher } from './file-watcher.js';
6
+ export { executeAcceptanceCriteria } from './test-executor.js';
7
+ export type { CheckResult } from './test-executor.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/watcher/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Watcher module exports
3
+ * Provides file watching and test execution functionality
4
+ */
5
+ export { FileWatcher } from './file-watcher.js';
6
+ export { executeAcceptanceCriteria } from './test-executor.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/watcher/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Test Executor - Runs acceptance criteria checks for tasks
3
+ * Supports multiple check types: tests_pass, code_removed, code_contains, file_exists
4
+ */
5
+ import { AcceptanceCheck } from '../types.js';
6
+ /**
7
+ * Result of executing an acceptance check
8
+ */
9
+ export interface CheckResult {
10
+ success: boolean;
11
+ message: string;
12
+ details?: string;
13
+ }
14
+ /**
15
+ * Execute all acceptance checks for a task
16
+ * @param checks - Array of acceptance check definitions
17
+ * @returns Object with overall success status and individual results
18
+ */
19
+ export declare function executeAcceptanceCriteria(checks: AcceptanceCheck[]): Promise<{
20
+ allPassed: boolean;
21
+ results: CheckResult[];
22
+ }>;
23
+ //# sourceMappingURL=test-executor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-executor.d.ts","sourceRoot":"","sources":["../../src/watcher/test-executor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAI9C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,eAAe,EAAE,GACxB,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,WAAW,EAAE,CAAA;CAAE,CAAC,CAuCzD"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Test Executor - Runs acceptance criteria checks for tasks
3
+ * Supports multiple check types: tests_pass, code_removed, code_contains, file_exists
4
+ */
5
+ import { exec } from 'child_process';
6
+ import { promisify } from 'util';
7
+ import { readFileSync, existsSync } from 'fs';
8
+ const execAsync = promisify(exec);
9
+ /**
10
+ * Execute all acceptance checks for a task
11
+ * @param checks - Array of acceptance check definitions
12
+ * @returns Object with overall success status and individual results
13
+ */
14
+ export async function executeAcceptanceCriteria(checks) {
15
+ const results = [];
16
+ for (const check of checks) {
17
+ let result;
18
+ try {
19
+ switch (check.type) {
20
+ case 'tests_pass':
21
+ result = await executeTestsPass(check);
22
+ break;
23
+ case 'code_removed':
24
+ result = executeCodeRemoved(check);
25
+ break;
26
+ case 'code_contains':
27
+ result = executeCodeContains(check);
28
+ break;
29
+ case 'file_exists':
30
+ result = executeFileExists(check);
31
+ break;
32
+ default:
33
+ result = {
34
+ success: false,
35
+ message: `Unknown check type: ${check.type}`
36
+ };
37
+ }
38
+ }
39
+ catch (error) {
40
+ result = {
41
+ success: false,
42
+ message: `Error executing check: ${error instanceof Error ? error.message : String(error)}`
43
+ };
44
+ }
45
+ results.push(result);
46
+ }
47
+ const allPassed = results.every(r => r.success);
48
+ return { allPassed, results };
49
+ }
50
+ /**
51
+ * Execute a shell command and check if it passes
52
+ * Check type: tests_pass
53
+ */
54
+ async function executeTestsPass(check) {
55
+ if (!check.command) {
56
+ return {
57
+ success: false,
58
+ message: 'tests_pass check requires "command" parameter'
59
+ };
60
+ }
61
+ const timeout = check.timeout || 60; // Default 60s timeout
62
+ try {
63
+ const { stdout, stderr } = await execAsync(check.command, {
64
+ timeout: timeout * 1000,
65
+ maxBuffer: 1024 * 1024 * 10 // 10MB buffer
66
+ });
67
+ const output = stdout + stderr;
68
+ // If expected_pattern specified, check for it in output
69
+ if (check.expected_pattern) {
70
+ const regex = new RegExp(check.expected_pattern);
71
+ if (regex.test(output)) {
72
+ return {
73
+ success: true,
74
+ message: `Command succeeded and output matches pattern "${check.expected_pattern}"`,
75
+ details: output.slice(0, 500) // First 500 chars
76
+ };
77
+ }
78
+ else {
79
+ return {
80
+ success: false,
81
+ message: `Command succeeded but output does not match pattern "${check.expected_pattern}"`,
82
+ details: output.slice(0, 500)
83
+ };
84
+ }
85
+ }
86
+ // No pattern specified, success if command exits with code 0
87
+ return {
88
+ success: true,
89
+ message: `Command "${check.command}" executed successfully`,
90
+ details: output.slice(0, 500)
91
+ };
92
+ }
93
+ catch (error) {
94
+ // Command failed or timed out
95
+ const output = (error.stdout || '') + (error.stderr || '');
96
+ return {
97
+ success: false,
98
+ message: error.killed
99
+ ? `Command "${check.command}" timed out after ${timeout}s`
100
+ : `Command "${check.command}" failed with exit code ${error.code || 'unknown'}`,
101
+ details: output.slice(0, 500)
102
+ };
103
+ }
104
+ }
105
+ /**
106
+ * Check if code pattern has been removed from file
107
+ * Check type: code_removed
108
+ */
109
+ function executeCodeRemoved(check) {
110
+ if (!check.file) {
111
+ return {
112
+ success: false,
113
+ message: 'code_removed check requires "file" parameter'
114
+ };
115
+ }
116
+ if (!check.pattern) {
117
+ return {
118
+ success: false,
119
+ message: 'code_removed check requires "pattern" parameter'
120
+ };
121
+ }
122
+ if (!existsSync(check.file)) {
123
+ // File doesn't exist - pattern is definitely removed!
124
+ return {
125
+ success: true,
126
+ message: `File "${check.file}" does not exist (pattern removed)`
127
+ };
128
+ }
129
+ try {
130
+ const content = readFileSync(check.file, 'utf-8');
131
+ const regex = new RegExp(check.pattern);
132
+ if (!regex.test(content)) {
133
+ return {
134
+ success: true,
135
+ message: `Pattern "${check.pattern}" not found in "${check.file}" (removed)`
136
+ };
137
+ }
138
+ else {
139
+ const match = content.match(regex);
140
+ return {
141
+ success: false,
142
+ message: `Pattern "${check.pattern}" still exists in "${check.file}"`,
143
+ details: match ? `Found: ${match[0].slice(0, 100)}` : undefined
144
+ };
145
+ }
146
+ }
147
+ catch (error) {
148
+ return {
149
+ success: false,
150
+ message: `Error reading file "${check.file}": ${error instanceof Error ? error.message : String(error)}`
151
+ };
152
+ }
153
+ }
154
+ /**
155
+ * Check if code pattern exists in file
156
+ * Check type: code_contains
157
+ */
158
+ function executeCodeContains(check) {
159
+ if (!check.file) {
160
+ return {
161
+ success: false,
162
+ message: 'code_contains check requires "file" parameter'
163
+ };
164
+ }
165
+ if (!check.pattern) {
166
+ return {
167
+ success: false,
168
+ message: 'code_contains check requires "pattern" parameter'
169
+ };
170
+ }
171
+ if (!existsSync(check.file)) {
172
+ return {
173
+ success: false,
174
+ message: `File "${check.file}" does not exist`
175
+ };
176
+ }
177
+ try {
178
+ const content = readFileSync(check.file, 'utf-8');
179
+ const regex = new RegExp(check.pattern);
180
+ if (regex.test(content)) {
181
+ const match = content.match(regex);
182
+ return {
183
+ success: true,
184
+ message: `Pattern "${check.pattern}" found in "${check.file}"`,
185
+ details: match ? `Match: ${match[0].slice(0, 100)}` : undefined
186
+ };
187
+ }
188
+ else {
189
+ return {
190
+ success: false,
191
+ message: `Pattern "${check.pattern}" not found in "${check.file}"`
192
+ };
193
+ }
194
+ }
195
+ catch (error) {
196
+ return {
197
+ success: false,
198
+ message: `Error reading file "${check.file}": ${error instanceof Error ? error.message : String(error)}`
199
+ };
200
+ }
201
+ }
202
+ /**
203
+ * Check if file exists
204
+ * Check type: file_exists
205
+ */
206
+ function executeFileExists(check) {
207
+ if (!check.file) {
208
+ return {
209
+ success: false,
210
+ message: 'file_exists check requires "file" parameter'
211
+ };
212
+ }
213
+ if (existsSync(check.file)) {
214
+ return {
215
+ success: true,
216
+ message: `File "${check.file}" exists`
217
+ };
218
+ }
219
+ else {
220
+ return {
221
+ success: false,
222
+ message: `File "${check.file}" does not exist`
223
+ };
224
+ }
225
+ }
226
+ //# sourceMappingURL=test-executor.js.map