sqlew 3.2.5 → 3.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/CHANGELOG.md +815 -13
  2. package/README.md +53 -2
  3. package/assets/schema.sql +6 -1
  4. package/dist/config/loader.d.ts +46 -0
  5. package/dist/config/loader.d.ts.map +1 -0
  6. package/dist/config/loader.js +151 -0
  7. package/dist/config/loader.js.map +1 -0
  8. package/dist/config/types.d.ts +77 -0
  9. package/dist/config/types.d.ts.map +1 -0
  10. package/dist/config/types.js +28 -0
  11. package/dist/config/types.js.map +1 -0
  12. package/dist/constants.d.ts +9 -0
  13. package/dist/constants.d.ts.map +1 -1
  14. package/dist/constants.js +10 -0
  15. package/dist/constants.js.map +1 -1
  16. package/dist/database.d.ts +1 -1
  17. package/dist/database.d.ts.map +1 -1
  18. package/dist/database.js +77 -10
  19. package/dist/database.js.map +1 -1
  20. package/dist/index.js +21 -3
  21. package/dist/index.js.map +1 -1
  22. package/dist/migrations/add-v3.5.0-pruned-files.d.ts +26 -0
  23. package/dist/migrations/add-v3.5.0-pruned-files.d.ts.map +1 -0
  24. package/dist/migrations/add-v3.5.0-pruned-files.js +107 -0
  25. package/dist/migrations/add-v3.5.0-pruned-files.js.map +1 -0
  26. package/dist/migrations/index.d.ts +2 -1
  27. package/dist/migrations/index.d.ts.map +1 -1
  28. package/dist/migrations/index.js +16 -1
  29. package/dist/migrations/index.js.map +1 -1
  30. package/dist/tests/git-aware-completion.test.d.ts +6 -0
  31. package/dist/tests/git-aware-completion.test.d.ts.map +1 -0
  32. package/dist/tests/git-aware-completion.test.js +141 -0
  33. package/dist/tests/git-aware-completion.test.js.map +1 -0
  34. package/dist/tests/tasks.auto-pruning-decision-link.test.d.ts +6 -0
  35. package/dist/tests/tasks.auto-pruning-decision-link.test.d.ts.map +1 -0
  36. package/dist/tests/tasks.auto-pruning-decision-link.test.js +250 -0
  37. package/dist/tests/tasks.auto-pruning-decision-link.test.js.map +1 -0
  38. package/dist/tests/tasks.auto-pruning-partial.test.d.ts +6 -0
  39. package/dist/tests/tasks.auto-pruning-partial.test.d.ts.map +1 -0
  40. package/dist/tests/tasks.auto-pruning-partial.test.js +274 -0
  41. package/dist/tests/tasks.auto-pruning-partial.test.js.map +1 -0
  42. package/dist/tests/tasks.auto-pruning-persistence.test.d.ts +6 -0
  43. package/dist/tests/tasks.auto-pruning-persistence.test.d.ts.map +1 -0
  44. package/dist/tests/tasks.auto-pruning-persistence.test.js +232 -0
  45. package/dist/tests/tasks.auto-pruning-persistence.test.js.map +1 -0
  46. package/dist/tests/tasks.auto-pruning-safety.test.d.ts +12 -0
  47. package/dist/tests/tasks.auto-pruning-safety.test.d.ts.map +1 -0
  48. package/dist/tests/tasks.auto-pruning-safety.test.js +196 -0
  49. package/dist/tests/tasks.auto-pruning-safety.test.js.map +1 -0
  50. package/dist/tests/tasks.link-file-backward-compat.test.d.ts +6 -0
  51. package/dist/tests/tasks.link-file-backward-compat.test.d.ts.map +1 -0
  52. package/dist/tests/tasks.link-file-backward-compat.test.js +235 -0
  53. package/dist/tests/tasks.link-file-backward-compat.test.js.map +1 -0
  54. package/dist/tests/tasks.watch-files-action.test.d.ts +6 -0
  55. package/dist/tests/tasks.watch-files-action.test.d.ts.map +1 -0
  56. package/dist/tests/tasks.watch-files-action.test.js +351 -0
  57. package/dist/tests/tasks.watch-files-action.test.js.map +1 -0
  58. package/dist/tests/tasks.watch-files-parameter.test.d.ts +6 -0
  59. package/dist/tests/tasks.watch-files-parameter.test.d.ts.map +1 -0
  60. package/dist/tests/tasks.watch-files-parameter.test.js +249 -0
  61. package/dist/tests/tasks.watch-files-parameter.test.js.map +1 -0
  62. package/dist/tests/two-step-git-completion.test.d.ts +6 -0
  63. package/dist/tests/two-step-git-completion.test.d.ts.map +1 -0
  64. package/dist/tests/two-step-git-completion.test.js +283 -0
  65. package/dist/tests/two-step-git-completion.test.js.map +1 -0
  66. package/dist/tests/vcs-staging.test.d.ts +6 -0
  67. package/dist/tests/vcs-staging.test.d.ts.map +1 -0
  68. package/dist/tests/vcs-staging.test.js +137 -0
  69. package/dist/tests/vcs-staging.test.js.map +1 -0
  70. package/dist/tools/config.d.ts +4 -2
  71. package/dist/tools/config.d.ts.map +1 -1
  72. package/dist/tools/config.js +13 -11
  73. package/dist/tools/config.js.map +1 -1
  74. package/dist/tools/constraints.d.ts +7 -4
  75. package/dist/tools/constraints.d.ts.map +1 -1
  76. package/dist/tools/constraints.js +19 -16
  77. package/dist/tools/constraints.js.map +1 -1
  78. package/dist/tools/context.d.ts +33 -17
  79. package/dist/tools/context.d.ts.map +1 -1
  80. package/dist/tools/context.js +84 -68
  81. package/dist/tools/context.js.map +1 -1
  82. package/dist/tools/files.d.ts +9 -5
  83. package/dist/tools/files.d.ts.map +1 -1
  84. package/dist/tools/files.js +19 -15
  85. package/dist/tools/files.js.map +1 -1
  86. package/dist/tools/messaging.d.ts +9 -5
  87. package/dist/tools/messaging.d.ts.map +1 -1
  88. package/dist/tools/messaging.js +20 -16
  89. package/dist/tools/messaging.js.map +1 -1
  90. package/dist/tools/tasks.d.ts +40 -12
  91. package/dist/tools/tasks.d.ts.map +1 -1
  92. package/dist/tools/tasks.js +475 -87
  93. package/dist/tools/tasks.js.map +1 -1
  94. package/dist/tools/utils.d.ts +11 -6
  95. package/dist/tools/utils.d.ts.map +1 -1
  96. package/dist/tools/utils.js +56 -44
  97. package/dist/tools/utils.js.map +1 -1
  98. package/dist/types.d.ts +4 -0
  99. package/dist/types.d.ts.map +1 -1
  100. package/dist/utils/file-pruning.d.ts +69 -0
  101. package/dist/utils/file-pruning.d.ts.map +1 -0
  102. package/dist/utils/file-pruning.js +185 -0
  103. package/dist/utils/file-pruning.js.map +1 -0
  104. package/dist/utils/quality-checks.d.ts +60 -0
  105. package/dist/utils/quality-checks.d.ts.map +1 -0
  106. package/dist/utils/quality-checks.js +228 -0
  107. package/dist/utils/quality-checks.js.map +1 -0
  108. package/dist/utils/retention.d.ts +8 -0
  109. package/dist/utils/retention.d.ts.map +1 -1
  110. package/dist/utils/retention.js +12 -0
  111. package/dist/utils/retention.js.map +1 -1
  112. package/dist/utils/task-stale-detection.d.ts +69 -1
  113. package/dist/utils/task-stale-detection.d.ts.map +1 -1
  114. package/dist/utils/task-stale-detection.js +494 -17
  115. package/dist/utils/task-stale-detection.js.map +1 -1
  116. package/dist/utils/vcs-adapter.d.ts +68 -0
  117. package/dist/utils/vcs-adapter.d.ts.map +1 -0
  118. package/dist/utils/vcs-adapter.js +187 -0
  119. package/dist/utils/vcs-adapter.js.map +1 -0
  120. package/dist/watcher/file-watcher.d.ts +54 -4
  121. package/dist/watcher/file-watcher.d.ts.map +1 -1
  122. package/dist/watcher/file-watcher.js +312 -30
  123. package/dist/watcher/file-watcher.js.map +1 -1
  124. package/dist/watcher/gitignore-parser.d.ts +70 -0
  125. package/dist/watcher/gitignore-parser.d.ts.map +1 -0
  126. package/dist/watcher/gitignore-parser.js +191 -0
  127. package/dist/watcher/gitignore-parser.js.map +1 -0
  128. package/dist/watcher/index.d.ts +1 -0
  129. package/dist/watcher/index.d.ts.map +1 -1
  130. package/dist/watcher/index.js +1 -0
  131. package/dist/watcher/index.js.map +1 -1
  132. package/docs/AI_AGENT_GUIDE.md +1 -1
  133. package/docs/ARCHITECTURE.md +12 -0
  134. package/docs/AUTO_FILE_TRACKING.md +486 -82
  135. package/docs/CONFIGURATION.md +908 -0
  136. package/docs/GIT_AWARE_AUTO_COMPLETE.md +645 -0
  137. package/docs/MIGRATION_v3.3.md +602 -0
  138. package/docs/SHARED_CONCEPTS.md +2 -1
  139. package/docs/TASK_ACTIONS.md +12 -0
  140. package/docs/TASK_OVERVIEW.md +124 -23
  141. package/docs/TASK_PRUNING.md +589 -0
  142. package/docs/TASK_SYSTEM.md +83 -13
  143. package/docs/TOOL_REFERENCE.md +94 -6
  144. package/package.json +8 -6
@@ -0,0 +1,69 @@
1
+ /**
2
+ * File pruning utilities for v3.5.0 Auto-Pruning feature
3
+ * Automatically removes non-existent watched files with audit trail
4
+ */
5
+ import { Database } from '../types.js';
6
+ /**
7
+ * Prune non-existent files from a task's watch list
8
+ * Records pruned files to audit table for project archaeology
9
+ *
10
+ * Quality gate enforcement:
11
+ * - If ALL watched files are non-existent → throw error (prevents zero-work completion)
12
+ * - If SOME watched files are non-existent → prune them and continue
13
+ *
14
+ * @param db - Database instance
15
+ * @param taskId - Task ID to prune files for
16
+ * @param projectRoot - Project root directory (default: process.cwd())
17
+ * @returns Object with pruned count and remaining count
18
+ * @throws Error if ALL files are non-existent (safety check)
19
+ */
20
+ export declare function pruneNonExistentFiles(db: Database, taskId: number, projectRoot?: string): {
21
+ prunedCount: number;
22
+ remainingCount: number;
23
+ prunedPaths: string[];
24
+ };
25
+ /**
26
+ * Get pruned files for a task
27
+ *
28
+ * @param db - Database instance
29
+ * @param taskId - Task ID
30
+ * @param limit - Maximum number of records (default: 100)
31
+ * @returns Array of pruned file records
32
+ */
33
+ export declare function getPrunedFiles(db: Database, taskId: number, limit?: number): Array<{
34
+ id: number;
35
+ file_path: string;
36
+ pruned_at: string;
37
+ linked_decision: string | null;
38
+ }>;
39
+ /**
40
+ * Link a pruned file to a decision (for WHY reasoning)
41
+ *
42
+ * @param db - Database instance
43
+ * @param prunedFileId - Pruned file record ID
44
+ * @param decisionKey - Decision key to link
45
+ * @throws Error if pruned file or decision not found
46
+ */
47
+ export declare function linkPrunedFileToDecision(db: Database, prunedFileId: number, decisionKey: string): void;
48
+ /**
49
+ * Get all pruned files across all tasks (for audit purposes)
50
+ *
51
+ * @param db - Database instance
52
+ * @param filters - Optional filters
53
+ * @returns Array of pruned file records with task info
54
+ */
55
+ export declare function getAllPrunedFiles(db: Database, filters?: {
56
+ taskId?: number;
57
+ linkedDecision?: string;
58
+ since?: number;
59
+ limit?: number;
60
+ offset?: number;
61
+ }): Array<{
62
+ id: number;
63
+ task_id: number;
64
+ task_title: string;
65
+ file_path: string;
66
+ pruned_at: string;
67
+ linked_decision: string | null;
68
+ }>;
69
+ //# sourceMappingURL=file-pruning.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-pruning.d.ts","sourceRoot":"","sources":["../../src/utils/file-pruning.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,WAAW,GAAE,MAAsB,GAClC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,EAAE,CAAA;CAAE,CAoExE;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,MAAY,GAClB,KAAK,CAAC;IACP,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC,CAoBD;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,EAAE,EAAE,QAAQ,EACZ,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,MAAM,GAClB,IAAI,CAiCN;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,QAAQ,EACZ,OAAO,CAAC,EAAE;IACR,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,KAAK,CAAC;IACP,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC,CAAC,CAoDD"}
@@ -0,0 +1,185 @@
1
+ /**
2
+ * File pruning utilities for v3.5.0 Auto-Pruning feature
3
+ * Automatically removes non-existent watched files with audit trail
4
+ */
5
+ import { existsSync } from 'fs';
6
+ import { join } from 'path';
7
+ /**
8
+ * Prune non-existent files from a task's watch list
9
+ * Records pruned files to audit table for project archaeology
10
+ *
11
+ * Quality gate enforcement:
12
+ * - If ALL watched files are non-existent → throw error (prevents zero-work completion)
13
+ * - If SOME watched files are non-existent → prune them and continue
14
+ *
15
+ * @param db - Database instance
16
+ * @param taskId - Task ID to prune files for
17
+ * @param projectRoot - Project root directory (default: process.cwd())
18
+ * @returns Object with pruned count and remaining count
19
+ * @throws Error if ALL files are non-existent (safety check)
20
+ */
21
+ export function pruneNonExistentFiles(db, taskId, projectRoot = process.cwd()) {
22
+ // 1. Get all watched files for this task
23
+ const watchedFiles = db.prepare(`
24
+ SELECT f.id as file_id, f.path
25
+ FROM t_task_file_links tfl
26
+ JOIN m_files f ON tfl.file_id = f.id
27
+ WHERE tfl.task_id = ?
28
+ `).all(taskId);
29
+ if (watchedFiles.length === 0) {
30
+ // No watched files - nothing to prune
31
+ return { prunedCount: 0, remainingCount: 0, prunedPaths: [] };
32
+ }
33
+ // 2. Check which files exist on filesystem
34
+ const existingFiles = [];
35
+ const nonExistentFiles = [];
36
+ for (const file of watchedFiles) {
37
+ const fullPath = join(projectRoot, file.path);
38
+ if (existsSync(fullPath)) {
39
+ existingFiles.push(file);
40
+ }
41
+ else {
42
+ nonExistentFiles.push(file);
43
+ }
44
+ }
45
+ // 3. Safety check: If ALL files are non-existent, block the operation
46
+ if (nonExistentFiles.length === watchedFiles.length) {
47
+ throw new Error(`Cannot prune files for task #${taskId}: ALL ${watchedFiles.length} watched files are non-existent. ` +
48
+ `This indicates no work was done. Please verify watched files or mark task as invalid.`);
49
+ }
50
+ // 4. If no files need pruning, return early
51
+ if (nonExistentFiles.length === 0) {
52
+ return {
53
+ prunedCount: 0,
54
+ remainingCount: watchedFiles.length,
55
+ prunedPaths: [],
56
+ };
57
+ }
58
+ // 5. Prune non-existent files in a transaction
59
+ db.transaction(() => {
60
+ const insertPruned = db.prepare(`
61
+ INSERT INTO t_task_pruned_files (task_id, file_path, pruned_ts)
62
+ VALUES (?, ?, unixepoch())
63
+ `);
64
+ const deleteLink = db.prepare(`
65
+ DELETE FROM t_task_file_links
66
+ WHERE task_id = ? AND file_id = ?
67
+ `);
68
+ // Record each pruned file to audit table and remove link
69
+ for (const file of nonExistentFiles) {
70
+ insertPruned.run(taskId, file.path);
71
+ deleteLink.run(taskId, file.file_id);
72
+ }
73
+ })();
74
+ return {
75
+ prunedCount: nonExistentFiles.length,
76
+ remainingCount: existingFiles.length,
77
+ prunedPaths: nonExistentFiles.map(f => f.path),
78
+ };
79
+ }
80
+ /**
81
+ * Get pruned files for a task
82
+ *
83
+ * @param db - Database instance
84
+ * @param taskId - Task ID
85
+ * @param limit - Maximum number of records (default: 100)
86
+ * @returns Array of pruned file records
87
+ */
88
+ export function getPrunedFiles(db, taskId, limit = 100) {
89
+ const rows = db.prepare(`
90
+ SELECT
91
+ tpf.id,
92
+ tpf.file_path,
93
+ datetime(tpf.pruned_ts, 'unixepoch') as pruned_at,
94
+ k.key as linked_decision
95
+ FROM t_task_pruned_files tpf
96
+ LEFT JOIN m_context_keys k ON tpf.linked_decision_key_id = k.id
97
+ WHERE tpf.task_id = ?
98
+ ORDER BY tpf.pruned_ts DESC
99
+ LIMIT ?
100
+ `).all(taskId, limit);
101
+ return rows;
102
+ }
103
+ /**
104
+ * Link a pruned file to a decision (for WHY reasoning)
105
+ *
106
+ * @param db - Database instance
107
+ * @param prunedFileId - Pruned file record ID
108
+ * @param decisionKey - Decision key to link
109
+ * @throws Error if pruned file or decision not found
110
+ */
111
+ export function linkPrunedFileToDecision(db, prunedFileId, decisionKey) {
112
+ // 1. Get decision key_id
113
+ const decision = db.prepare(`
114
+ SELECT k.id as key_id
115
+ FROM m_context_keys k
116
+ WHERE k.key = ? AND EXISTS (
117
+ SELECT 1 FROM t_decisions d WHERE d.key_id = k.id
118
+ )
119
+ `).get(decisionKey);
120
+ if (!decision) {
121
+ throw new Error(`Decision not found: ${decisionKey}`);
122
+ }
123
+ // 2. Check if pruned file exists
124
+ const prunedFile = db.prepare(`
125
+ SELECT id FROM t_task_pruned_files WHERE id = ?
126
+ `).get(prunedFileId);
127
+ if (!prunedFile) {
128
+ throw new Error(`Pruned file record not found: ${prunedFileId}`);
129
+ }
130
+ // 3. Update the link
131
+ const result = db.prepare(`
132
+ UPDATE t_task_pruned_files
133
+ SET linked_decision_key_id = ?
134
+ WHERE id = ?
135
+ `).run(decision.key_id, prunedFileId);
136
+ if (result.changes === 0) {
137
+ throw new Error(`Failed to link pruned file #${prunedFileId} to decision ${decisionKey}`);
138
+ }
139
+ }
140
+ /**
141
+ * Get all pruned files across all tasks (for audit purposes)
142
+ *
143
+ * @param db - Database instance
144
+ * @param filters - Optional filters
145
+ * @returns Array of pruned file records with task info
146
+ */
147
+ export function getAllPrunedFiles(db, filters) {
148
+ let query = `
149
+ SELECT
150
+ tpf.id,
151
+ tpf.task_id,
152
+ t.title as task_title,
153
+ tpf.file_path,
154
+ datetime(tpf.pruned_ts, 'unixepoch') as pruned_at,
155
+ k.key as linked_decision
156
+ FROM t_task_pruned_files tpf
157
+ JOIN t_tasks t ON tpf.task_id = t.id
158
+ LEFT JOIN m_context_keys k ON tpf.linked_decision_key_id = k.id
159
+ WHERE 1=1
160
+ `;
161
+ const params = [];
162
+ if (filters?.taskId !== undefined) {
163
+ query += ' AND tpf.task_id = ?';
164
+ params.push(filters.taskId);
165
+ }
166
+ if (filters?.linkedDecision) {
167
+ query += ' AND k.key = ?';
168
+ params.push(filters.linkedDecision);
169
+ }
170
+ if (filters?.since !== undefined) {
171
+ query += ' AND tpf.pruned_ts >= ?';
172
+ params.push(filters.since);
173
+ }
174
+ query += ' ORDER BY tpf.pruned_ts DESC';
175
+ if (filters?.limit) {
176
+ query += ' LIMIT ?';
177
+ params.push(filters.limit);
178
+ }
179
+ if (filters?.offset) {
180
+ query += ' OFFSET ?';
181
+ params.push(filters.offset);
182
+ }
183
+ return db.prepare(query).all(...params);
184
+ }
185
+ //# sourceMappingURL=file-pruning.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-pruning.js","sourceRoot":"","sources":["../../src/utils/file-pruning.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Quality Checks - Validation functions for smart review detection
3
+ * Determines when tasks are ready for review based on quality gates
4
+ */
5
+ import type { Database } from 'better-sqlite3';
6
+ /**
7
+ * Quality check result
8
+ */
9
+ export interface QualityCheckResult {
10
+ passed: boolean;
11
+ message: string;
12
+ details?: string;
13
+ }
14
+ /**
15
+ * Check if all watched files for a task have been modified at least once
16
+ *
17
+ * @param db - Database connection
18
+ * @param taskId - Task ID to check
19
+ * @param modifiedFiles - Set of files that have been modified
20
+ * @returns True if all watched files have been modified, false otherwise
21
+ */
22
+ export declare function checkAllFilesModified(db: Database, taskId: number, modifiedFiles: Set<string>): QualityCheckResult;
23
+ /**
24
+ * Check if TypeScript files compile without syntax errors
25
+ *
26
+ * @param filePaths - Array of file paths to check
27
+ * @returns Promise resolving to true if TypeScript compiles, false otherwise
28
+ */
29
+ export declare function checkTypeScriptCompiles(filePaths: string[]): Promise<QualityCheckResult>;
30
+ /**
31
+ * Check if tests pass for the task
32
+ *
33
+ * @param db - Database connection
34
+ * @param taskId - Task ID to check
35
+ * @param filePaths - Array of file paths being watched
36
+ * @returns Promise resolving to true if tests pass, false otherwise
37
+ */
38
+ export declare function checkTestsPass(db: Database, taskId: number, filePaths: string[]): Promise<QualityCheckResult>;
39
+ /**
40
+ * Check if task is ready for review based on all quality gates
41
+ *
42
+ * @param db - Database connection
43
+ * @param taskId - Task ID to check
44
+ * @param filePaths - Array of file paths being watched
45
+ * @param modifiedFiles - Set of files that have been modified
46
+ * @param config - Configuration flags for which checks to run
47
+ * @returns Promise resolving to object with overall result and individual check results
48
+ */
49
+ export declare function checkReadyForReview(db: Database, taskId: number, filePaths: string[], modifiedFiles: Set<string>, config: {
50
+ requireAllFilesModified: boolean;
51
+ requireTestsPass: boolean;
52
+ requireCompile: boolean;
53
+ }): Promise<{
54
+ ready: boolean;
55
+ results: Array<{
56
+ check: string;
57
+ result: QualityCheckResult;
58
+ }>;
59
+ }>;
60
+ //# sourceMappingURL=quality-checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality-checks.d.ts","sourceRoot":"","sources":["../../src/utils/quality-checks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI/C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GACzB,kBAAkB,CA8CpB;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA8C9F;AAED;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,kBAAkB,CAAC,CA4F7B;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EAAE,EACnB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,MAAM,EAAE;IACN,uBAAuB,EAAE,OAAO,CAAC;IACjC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,EAAE,OAAO,CAAC;CACzB,GACA,OAAO,CAAC;IACT,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,kBAAkB,CAAA;KAAE,CAAC,CAAC;CAC/D,CAAC,CAuBD"}
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Quality Checks - Validation functions for smart review detection
3
+ * Determines when tasks are ready for review based on quality gates
4
+ */
5
+ import { exec } from 'child_process';
6
+ import { promisify } from 'util';
7
+ const execAsync = promisify(exec);
8
+ /**
9
+ * Check if all watched files for a task have been modified at least once
10
+ *
11
+ * @param db - Database connection
12
+ * @param taskId - Task ID to check
13
+ * @param modifiedFiles - Set of files that have been modified
14
+ * @returns True if all watched files have been modified, false otherwise
15
+ */
16
+ export function checkAllFilesModified(db, taskId, modifiedFiles) {
17
+ try {
18
+ // Get all watched files for this task
19
+ const stmt = db.prepare(`
20
+ SELECT f.path
21
+ FROM t_task_file_links tfl
22
+ JOIN m_files f ON f.id = tfl.file_id
23
+ WHERE tfl.task_id = ?
24
+ `);
25
+ const watchedFiles = stmt.all(taskId);
26
+ if (watchedFiles.length === 0) {
27
+ // No files to watch - consider this check passed
28
+ return {
29
+ passed: true,
30
+ message: 'No files being watched (check skipped)',
31
+ };
32
+ }
33
+ // Check if all watched files have been modified
34
+ const unmodifiedFiles = [];
35
+ for (const { path } of watchedFiles) {
36
+ if (!modifiedFiles.has(path)) {
37
+ unmodifiedFiles.push(path);
38
+ }
39
+ }
40
+ if (unmodifiedFiles.length === 0) {
41
+ return {
42
+ passed: true,
43
+ message: `All ${watchedFiles.length} watched files have been modified`,
44
+ };
45
+ }
46
+ else {
47
+ return {
48
+ passed: false,
49
+ message: `${unmodifiedFiles.length} of ${watchedFiles.length} watched files not yet modified`,
50
+ details: `Unmodified: ${unmodifiedFiles.slice(0, 3).join(', ')}${unmodifiedFiles.length > 3 ? '...' : ''}`,
51
+ };
52
+ }
53
+ }
54
+ catch (error) {
55
+ return {
56
+ passed: false,
57
+ message: `Error checking file modifications: ${error instanceof Error ? error.message : String(error)}`,
58
+ };
59
+ }
60
+ }
61
+ /**
62
+ * Check if TypeScript files compile without syntax errors
63
+ *
64
+ * @param filePaths - Array of file paths to check
65
+ * @returns Promise resolving to true if TypeScript compiles, false otherwise
66
+ */
67
+ export async function checkTypeScriptCompiles(filePaths) {
68
+ try {
69
+ // Filter for TypeScript files
70
+ const tsFiles = filePaths.filter(path => path.endsWith('.ts') || path.endsWith('.tsx'));
71
+ if (tsFiles.length === 0) {
72
+ return {
73
+ passed: true,
74
+ message: 'No TypeScript files to check (check skipped)',
75
+ };
76
+ }
77
+ // Run tsc --noEmit to check for syntax errors
78
+ // This checks the entire project, not just individual files,
79
+ // because TypeScript needs full context for type checking
80
+ try {
81
+ const { stdout, stderr } = await execAsync('npx tsc --noEmit', {
82
+ timeout: 30000, // 30 second timeout
83
+ maxBuffer: 1024 * 1024 * 5, // 5MB buffer
84
+ });
85
+ return {
86
+ passed: true,
87
+ message: `TypeScript compilation successful (${tsFiles.length} .ts/.tsx files)`,
88
+ };
89
+ }
90
+ catch (error) {
91
+ // tsc returns non-zero exit code if there are errors
92
+ const output = (error.stdout || '') + (error.stderr || '');
93
+ const errorLines = output.split('\n').filter((line) => line.includes('error TS')).slice(0, 3); // First 3 errors
94
+ return {
95
+ passed: false,
96
+ message: 'TypeScript compilation failed',
97
+ details: errorLines.join('\n') || output.slice(0, 300),
98
+ };
99
+ }
100
+ }
101
+ catch (error) {
102
+ return {
103
+ passed: false,
104
+ message: `Error running TypeScript check: ${error instanceof Error ? error.message : String(error)}`,
105
+ };
106
+ }
107
+ }
108
+ /**
109
+ * Check if tests pass for the task
110
+ *
111
+ * @param db - Database connection
112
+ * @param taskId - Task ID to check
113
+ * @param filePaths - Array of file paths being watched
114
+ * @returns Promise resolving to true if tests pass, false otherwise
115
+ */
116
+ export async function checkTestsPass(db, taskId, filePaths) {
117
+ try {
118
+ // Check if any files match test patterns
119
+ const testPatterns = [/\.test\.(ts|tsx|js|jsx)$/, /\.spec\.(ts|tsx|js|jsx)$/];
120
+ const testFiles = filePaths.filter(path => testPatterns.some(pattern => pattern.test(path)));
121
+ if (testFiles.length === 0) {
122
+ return {
123
+ passed: true,
124
+ message: 'No test files found (check skipped)',
125
+ };
126
+ }
127
+ // Look for acceptance_criteria with tests_pass type
128
+ const stmt = db.prepare(`
129
+ SELECT acceptance_criteria
130
+ FROM t_task_details
131
+ WHERE task_id = ?
132
+ `);
133
+ const row = stmt.get(taskId);
134
+ if (!row?.acceptance_criteria) {
135
+ // No acceptance criteria - run default test command if package.json has test script
136
+ return {
137
+ passed: true,
138
+ message: 'No test acceptance criteria defined (check skipped)',
139
+ };
140
+ }
141
+ const criteria = JSON.parse(row.acceptance_criteria);
142
+ const testCriteria = criteria.find((c) => c.type === 'tests_pass');
143
+ if (!testCriteria) {
144
+ return {
145
+ passed: true,
146
+ message: 'No test acceptance criteria defined (check skipped)',
147
+ };
148
+ }
149
+ // Execute the test command
150
+ const command = testCriteria.command || 'npm test';
151
+ const timeout = testCriteria.timeout || 60; // Default 60s timeout
152
+ try {
153
+ const { stdout, stderr } = await execAsync(command, {
154
+ timeout: timeout * 1000,
155
+ maxBuffer: 1024 * 1024 * 10, // 10MB buffer
156
+ });
157
+ const output = stdout + stderr;
158
+ // Check for expected pattern if specified
159
+ if (testCriteria.expected_pattern) {
160
+ const regex = new RegExp(testCriteria.expected_pattern);
161
+ if (regex.test(output)) {
162
+ return {
163
+ passed: true,
164
+ message: `Tests passed (${testFiles.length} test files)`,
165
+ details: `Command: ${command}`,
166
+ };
167
+ }
168
+ else {
169
+ return {
170
+ passed: false,
171
+ message: 'Tests ran but output does not match expected pattern',
172
+ details: output.slice(0, 300),
173
+ };
174
+ }
175
+ }
176
+ // No pattern specified - success if exit code is 0
177
+ return {
178
+ passed: true,
179
+ message: `Tests passed (${testFiles.length} test files)`,
180
+ details: `Command: ${command}`,
181
+ };
182
+ }
183
+ catch (error) {
184
+ const output = (error.stdout || '') + (error.stderr || '');
185
+ return {
186
+ passed: false,
187
+ message: error.killed ? 'Tests timed out' : 'Tests failed',
188
+ details: output.slice(0, 300),
189
+ };
190
+ }
191
+ }
192
+ catch (error) {
193
+ return {
194
+ passed: false,
195
+ message: `Error running tests: ${error instanceof Error ? error.message : String(error)}`,
196
+ };
197
+ }
198
+ }
199
+ /**
200
+ * Check if task is ready for review based on all quality gates
201
+ *
202
+ * @param db - Database connection
203
+ * @param taskId - Task ID to check
204
+ * @param filePaths - Array of file paths being watched
205
+ * @param modifiedFiles - Set of files that have been modified
206
+ * @param config - Configuration flags for which checks to run
207
+ * @returns Promise resolving to object with overall result and individual check results
208
+ */
209
+ export async function checkReadyForReview(db, taskId, filePaths, modifiedFiles, config) {
210
+ const results = [];
211
+ // Run all enabled checks
212
+ if (config.requireAllFilesModified) {
213
+ const result = checkAllFilesModified(db, taskId, modifiedFiles);
214
+ results.push({ check: 'all_files_modified', result });
215
+ }
216
+ if (config.requireCompile) {
217
+ const result = await checkTypeScriptCompiles(filePaths);
218
+ results.push({ check: 'typescript_compiles', result });
219
+ }
220
+ if (config.requireTestsPass) {
221
+ const result = await checkTestsPass(db, taskId, filePaths);
222
+ results.push({ check: 'tests_pass', result });
223
+ }
224
+ // All enabled checks must pass
225
+ const ready = results.every(({ result }) => result.passed);
226
+ return { ready, results };
227
+ }
228
+ //# sourceMappingURL=quality-checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"quality-checks.js","sourceRoot":"","sources":["../../src/utils/quality-checks.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,14 @@ export declare function calculateMessageCutoff(db: Database): number;
19
19
  * @returns Unix timestamp (seconds) for cutoff
20
20
  */
21
21
  export declare function calculateFileChangeCutoff(db: Database): number;
22
+ /**
23
+ * Calculate cutoff timestamp for task archive (done → archived)
24
+ * Respects weekend-awareness configuration
25
+ *
26
+ * @param db - Database instance
27
+ * @returns Unix timestamp (seconds) for cutoff
28
+ */
29
+ export declare function calculateTaskArchiveCutoff(db: Database): number;
22
30
  /**
23
31
  * Calculate cutoff timestamp with optional weekend-awareness
24
32
  *
@@ -1 +1 @@
1
- {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/utils/retention.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAK3D;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAK9D;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,OAAO,EACvB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,MAAM,CAYR;AA4CD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,MAAM,CAavE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAe9D"}
1
+ {"version":3,"file":"retention.d.ts","sourceRoot":"","sources":["../../src/utils/retention.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAIvC;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAK3D;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAK9D;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAK/D;AAED;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,OAAO,EACvB,IAAI,EAAE,OAAO,GAAG,MAAM,GACrB,MAAM,CAYR;AA4CD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,MAAM,CAavE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAe9D"}
@@ -28,6 +28,18 @@ export function calculateFileChangeCutoff(db) {
28
28
  const retentionDays = getConfigInt(db, CONFIG_KEYS.AUTODELETE_FILE_HISTORY_DAYS, 7);
29
29
  return calculateCutoffTimestamp(retentionDays, ignoreWeekends, 'days');
30
30
  }
31
+ /**
32
+ * Calculate cutoff timestamp for task archive (done → archived)
33
+ * Respects weekend-awareness configuration
34
+ *
35
+ * @param db - Database instance
36
+ * @returns Unix timestamp (seconds) for cutoff
37
+ */
38
+ export function calculateTaskArchiveCutoff(db) {
39
+ const ignoreWeekends = getConfigBool(db, CONFIG_KEYS.AUTODELETE_IGNORE_WEEKEND, false);
40
+ const retentionDays = getConfigInt(db, CONFIG_KEYS.AUTO_ARCHIVE_DONE_DAYS, 2); // Default: 2 days (48 hours)
41
+ return calculateCutoffTimestamp(retentionDays, ignoreWeekends, 'days');
42
+ }
31
43
  /**
32
44
  * Calculate cutoff timestamp with optional weekend-awareness
33
45
  *
@@ -1 +1 @@
1
- {"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/utils/retention.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"retention.js","sourceRoot":"","sources":["../../src/utils/retention.ts"],"names":[],"mappings":"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"}