sqlew 4.0.4 → 4.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 (203) hide show
  1. package/CHANGELOG.md +1805 -1762
  2. package/LICENSE +177 -39
  3. package/NOTICE +24 -0
  4. package/README.md +409 -390
  5. package/assets/claude-md-snippets/plan-mode-integration.md +17 -6
  6. package/assets/config.example.toml +282 -284
  7. package/assets/sample-agents/README.md +36 -40
  8. package/assets/sample-agents/sqlew-architect.md +321 -322
  9. package/assets/sample-agents/sqlew-researcher.md +292 -293
  10. package/assets/sample-agents/sqlew-scrum-master.md +286 -287
  11. package/assets/sample-commands/README.md +56 -57
  12. package/assets/sample-skills/sqlew-plan-guidance/SKILL.md +33 -26
  13. package/dist/cli/hooks/check-completion.d.ts +19 -0
  14. package/dist/cli/hooks/check-completion.d.ts.map +1 -0
  15. package/dist/cli/hooks/check-completion.js +104 -0
  16. package/dist/cli/hooks/check-completion.js.map +1 -0
  17. package/dist/cli/hooks/init-hooks.d.ts +35 -0
  18. package/dist/cli/hooks/init-hooks.d.ts.map +1 -0
  19. package/dist/cli/hooks/init-hooks.js +425 -0
  20. package/dist/cli/hooks/init-hooks.js.map +1 -0
  21. package/dist/cli/hooks/mark-done.d.ts +25 -0
  22. package/dist/cli/hooks/mark-done.d.ts.map +1 -0
  23. package/dist/cli/hooks/mark-done.js +128 -0
  24. package/dist/cli/hooks/mark-done.js.map +1 -0
  25. package/dist/cli/hooks/plan-id-utils.d.ts +83 -0
  26. package/dist/cli/hooks/plan-id-utils.d.ts.map +1 -0
  27. package/dist/cli/hooks/plan-id-utils.js +183 -0
  28. package/dist/cli/hooks/plan-id-utils.js.map +1 -0
  29. package/dist/cli/hooks/save.d.ts +23 -0
  30. package/dist/cli/hooks/save.d.ts.map +1 -0
  31. package/dist/cli/hooks/save.js +90 -0
  32. package/dist/cli/hooks/save.js.map +1 -0
  33. package/dist/cli/hooks/stdin-parser.d.ts +139 -0
  34. package/dist/cli/hooks/stdin-parser.d.ts.map +1 -0
  35. package/dist/cli/hooks/stdin-parser.js +127 -0
  36. package/dist/cli/hooks/stdin-parser.js.map +1 -0
  37. package/dist/cli/hooks/suggest.d.ts +19 -0
  38. package/dist/cli/hooks/suggest.d.ts.map +1 -0
  39. package/dist/cli/hooks/suggest.js +157 -0
  40. package/dist/cli/hooks/suggest.js.map +1 -0
  41. package/dist/cli/hooks/track-plan.d.ts +36 -0
  42. package/dist/cli/hooks/track-plan.d.ts.map +1 -0
  43. package/dist/cli/hooks/track-plan.js +152 -0
  44. package/dist/cli/hooks/track-plan.js.map +1 -0
  45. package/dist/cli.d.ts.map +1 -1
  46. package/dist/cli.js +56 -16
  47. package/dist/cli.js.map +1 -1
  48. package/dist/config/global-config.d.ts +187 -0
  49. package/dist/config/global-config.d.ts.map +1 -0
  50. package/dist/config/global-config.js +206 -0
  51. package/dist/config/global-config.js.map +1 -0
  52. package/dist/config/loader.d.ts +42 -0
  53. package/dist/config/loader.d.ts.map +1 -1
  54. package/dist/config/loader.js +96 -0
  55. package/dist/config/loader.js.map +1 -1
  56. package/dist/constants.d.ts +4 -0
  57. package/dist/constants.d.ts.map +1 -1
  58. package/dist/constants.js +10 -0
  59. package/dist/constants.js.map +1 -1
  60. package/dist/database/operations/queries.d.ts.map +1 -1
  61. package/dist/database/operations/queries.js +11 -2
  62. package/dist/database/operations/queries.js.map +1 -1
  63. package/dist/index.js +5 -2
  64. package/dist/index.js.map +1 -1
  65. package/dist/init-agents.js +0 -1
  66. package/dist/init-agents.js.map +1 -1
  67. package/dist/init-skills.d.ts +4 -3
  68. package/dist/init-skills.d.ts.map +1 -1
  69. package/dist/init-skills.js +10 -3
  70. package/dist/init-skills.js.map +1 -1
  71. package/dist/server/setup.d.ts +8 -0
  72. package/dist/server/setup.d.ts.map +1 -1
  73. package/dist/server/setup.js +141 -21
  74. package/dist/server/setup.js.map +1 -1
  75. package/dist/sync-agents.d.ts.map +1 -1
  76. package/dist/sync-agents.js +48 -3
  77. package/dist/sync-agents.js.map +1 -1
  78. package/dist/sync-commands.d.ts.map +1 -1
  79. package/dist/sync-commands.js +43 -3
  80. package/dist/sync-commands.js.map +1 -1
  81. package/dist/tools/constraints/actions/get.d.ts.map +1 -1
  82. package/dist/tools/constraints/actions/get.js +5 -8
  83. package/dist/tools/constraints/actions/get.js.map +1 -1
  84. package/dist/tools/constraints/help/help.d.ts.map +1 -1
  85. package/dist/tools/constraints/help/help.js +1 -6
  86. package/dist/tools/constraints/help/help.js.map +1 -1
  87. package/dist/tools/context/actions/get.d.ts.map +1 -1
  88. package/dist/tools/context/actions/get.js.map +1 -1
  89. package/dist/tools/context/actions/search-layer.d.ts.map +1 -1
  90. package/dist/tools/context/actions/search-layer.js +5 -3
  91. package/dist/tools/context/actions/search-layer.js.map +1 -1
  92. package/dist/tools/context/actions/set-from-policy.d.ts +2 -1
  93. package/dist/tools/context/actions/set-from-policy.d.ts.map +1 -1
  94. package/dist/tools/context/actions/set-from-policy.js.map +1 -1
  95. package/dist/tools/context/help/help.d.ts.map +1 -1
  96. package/dist/tools/context/help/help.js +1 -7
  97. package/dist/tools/context/help/help.js.map +1 -1
  98. package/dist/tools/context/internal/queries.d.ts.map +1 -1
  99. package/dist/tools/context/internal/queries.js +5 -2
  100. package/dist/tools/context/internal/queries.js.map +1 -1
  101. package/dist/tools/context/types.d.ts +1 -1
  102. package/dist/tools/context/types.d.ts.map +1 -1
  103. package/dist/tools/files/actions/get.d.ts.map +1 -1
  104. package/dist/tools/files/actions/get.js +4 -6
  105. package/dist/tools/files/actions/get.js.map +1 -1
  106. package/dist/tools/files/help/help.d.ts.map +1 -1
  107. package/dist/tools/files/help/help.js +1 -6
  108. package/dist/tools/files/help/help.js.map +1 -1
  109. package/dist/tools/suggest/help/constraint-help.d.ts.map +1 -1
  110. package/dist/tools/suggest/help/constraint-help.js +0 -2
  111. package/dist/tools/suggest/help/constraint-help.js.map +1 -1
  112. package/dist/tools/suggest/internal/constraint-queries.d.ts.map +1 -1
  113. package/dist/tools/suggest/internal/constraint-queries.js +12 -5
  114. package/dist/tools/suggest/internal/constraint-queries.js.map +1 -1
  115. package/dist/tools/suggest/internal/queries.js +2 -2
  116. package/dist/tools/suggest/internal/queries.js.map +1 -1
  117. package/dist/tools/tasks/help/help.d.ts.map +1 -1
  118. package/dist/tools/tasks/help/help.js +0 -6
  119. package/dist/tools/tasks/help/help.js.map +1 -1
  120. package/dist/tools/tasks/help/use-case.d.ts.map +1 -1
  121. package/dist/tools/tasks/help/use-case.js +0 -1
  122. package/dist/tools/tasks/help/use-case.js.map +1 -1
  123. package/dist/tools/tasks/watcher/status.d.ts.map +1 -1
  124. package/dist/tools/tasks/watcher/status.js +5 -1
  125. package/dist/tools/tasks/watcher/status.js.map +1 -1
  126. package/dist/types/decision/params.d.ts +7 -6
  127. package/dist/types/decision/params.d.ts.map +1 -1
  128. package/dist/types/decision/templates.d.ts +3 -2
  129. package/dist/types/decision/templates.d.ts.map +1 -1
  130. package/dist/types/view-entities.d.ts +2 -1
  131. package/dist/types/view-entities.d.ts.map +1 -1
  132. package/dist/types.d.ts +19 -11
  133. package/dist/types.d.ts.map +1 -1
  134. package/dist/types.js +4 -1
  135. package/dist/types.js.map +1 -1
  136. package/dist/utils/enum-converter.d.ts +72 -0
  137. package/dist/utils/enum-converter.d.ts.map +1 -0
  138. package/dist/utils/enum-converter.js +76 -0
  139. package/dist/utils/enum-converter.js.map +1 -0
  140. package/dist/utils/hook-queue.d.ts +81 -0
  141. package/dist/utils/hook-queue.d.ts.map +1 -0
  142. package/dist/utils/hook-queue.js +156 -0
  143. package/dist/utils/hook-queue.js.map +1 -0
  144. package/dist/utils/project-root.d.ts +9 -2
  145. package/dist/utils/project-root.d.ts.map +1 -1
  146. package/dist/utils/project-root.js +16 -2
  147. package/dist/utils/project-root.js.map +1 -1
  148. package/dist/utils/tag-parser.d.ts.map +1 -1
  149. package/dist/utils/tag-parser.js +6 -0
  150. package/dist/utils/tag-parser.js.map +1 -1
  151. package/dist/utils/validators.d.ts +1 -1
  152. package/dist/utils/validators.d.ts.map +1 -1
  153. package/dist/utils/validators.js +1 -1
  154. package/dist/utils/validators.js.map +1 -1
  155. package/dist/utils/vcs-adapter.d.ts +44 -0
  156. package/dist/utils/vcs-adapter.d.ts.map +1 -1
  157. package/dist/utils/vcs-adapter.js +88 -0
  158. package/dist/utils/vcs-adapter.js.map +1 -1
  159. package/dist/utils/view-queries.d.ts.map +1 -1
  160. package/dist/utils/view-queries.js +9 -19
  161. package/dist/utils/view-queries.js.map +1 -1
  162. package/dist/watcher/base-watcher.d.ts +69 -0
  163. package/dist/watcher/base-watcher.d.ts.map +1 -0
  164. package/dist/watcher/base-watcher.js +130 -0
  165. package/dist/watcher/base-watcher.js.map +1 -0
  166. package/dist/watcher/index.d.ts +3 -0
  167. package/dist/watcher/index.d.ts.map +1 -1
  168. package/dist/watcher/index.js +2 -0
  169. package/dist/watcher/index.js.map +1 -1
  170. package/dist/watcher/queue-watcher.d.ts +64 -0
  171. package/dist/watcher/queue-watcher.d.ts.map +1 -0
  172. package/dist/watcher/queue-watcher.js +187 -0
  173. package/dist/watcher/queue-watcher.js.map +1 -0
  174. package/docs/ADR_CONCEPTS.md +140 -0
  175. package/docs/CONFIGURATION.md +922 -925
  176. package/docs/CROSS_DATABASE.md +153 -0
  177. package/docs/DATABASE_AUTH.md +70 -356
  178. package/docs/HOOKS_GUIDE.md +159 -0
  179. package/docs/SLASH_COMMANDS.md +329 -337
  180. package/docs/TASK_SYSTEM_DEPRECATED.md +88 -0
  181. package/docs/changelogs/CHANGELOG_ARCHIVE_v3.4_and_older.md +293 -296
  182. package/docs/cli/DATA_EXPORT_IMPORT.md +699 -700
  183. package/docs/cli/README.md +276 -277
  184. package/package.json +123 -119
  185. package/docs/ACCEPTANCE_CRITERIA.md +0 -625
  186. package/docs/AI_AGENT_GUIDE.md +0 -198
  187. package/docs/ARCHITECTURE.md +0 -167
  188. package/docs/AUTO_FILE_TRACKING.md +0 -841
  189. package/docs/BATCH_VALIDATION.md +0 -617
  190. package/docs/BEST_PRACTICES.md +0 -168
  191. package/docs/CONSTRAINT_INTELLIGENCE.md +0 -339
  192. package/docs/DECISION_CONTEXT.md +0 -675
  193. package/docs/DECISION_INTELLIGENCE.md +0 -605
  194. package/docs/GIT_AWARE_AUTO_COMPLETE.md +0 -646
  195. package/docs/MIGRATION_GUIDE_V3.9.0.md +0 -371
  196. package/docs/SHARED_CONCEPTS.md +0 -225
  197. package/docs/SPECIALIZED_AGENTS.md +0 -126
  198. package/docs/TASK_ACTIONS.md +0 -1177
  199. package/docs/TASK_OVERVIEW.md +0 -452
  200. package/docs/TASK_PRUNING.md +0 -594
  201. package/docs/TOOL_REFERENCE.md +0 -1077
  202. package/docs/TOOL_SELECTION.md +0 -83
  203. package/docs/WORKFLOWS.md +0 -941
@@ -1,617 +0,0 @@
1
- # Batch Validation Utilities
2
-
3
- **Version**: 4.0.0
4
- **Status**: ✅ Implemented and Tested
5
- **Impact**: 70-85% reduction in batch validation failures
6
-
7
- ## Overview
8
-
9
- Shared batch validation utilities that provide comprehensive pre-transaction validation for all batch operations (tasks, decisions, file changes, constraints). Validates ALL items at once and reports ALL errors with AI-friendly, actionable fix instructions.
10
-
11
- ## Key Benefits
12
-
13
- 1. **Pre-Transaction Validation**: Validate ALL items BEFORE starting database transaction
14
- 2. **Comprehensive Error Reporting**: Report ALL errors at once (not just first error)
15
- 3. **AI-Friendly Messages**: Structured errors with actionable fix instructions, typo suggestions, and valid options
16
- 4. **Reusable Validators**: Shared validation building blocks for all batch operations
17
- 5. **70-85% Failure Reduction**: Expected reduction in batch validation failures based on design analysis
18
-
19
- ## Architecture
20
-
21
- ### Core Components
22
-
23
- ```
24
- src/utils/
25
- ├── batch-validation.ts # Main validation utilities (530 lines)
26
- │ ├── Core Validators # validateRequiredField, validateEnum, validateType, etc.
27
- │ ├── Batch Orchestrator # validateBatch (runs all validators)
28
- │ └── Error Formatter # formatBatchValidationError (AI-readable output)
29
-
30
- ├── levenshtein.ts # Shared Levenshtein distance (45 lines)
31
- │ └── Used by parameter-validator.ts and batch-validation.ts
32
-
33
- └── batch-validation.example.ts # Usage examples and documentation
34
- ```
35
-
36
- ### Test Coverage
37
-
38
- ```
39
- src/tests/batch-validation.test.ts
40
- ├── 7 test suites
41
- ├── 33 test cases
42
- └── ✅ 100% pass rate
43
- ```
44
-
45
- ## API Reference
46
-
47
- ### Type Definitions
48
-
49
- ```typescript
50
- /**
51
- * Structured validation error for single field in single batch item
52
- */
53
- interface BatchValidationError {
54
- itemIndex: number; // 0-based index in batch array
55
- itemIdentifier: string; // Item identifier (e.g., task.title, decision.key)
56
- field: string; // Field name that failed
57
- issue: string; // Human-readable issue description
58
- fix: string; // Actionable fix instruction
59
- current?: any; // Current invalid value
60
- validOptions?: string[]; // Valid enum values (if applicable)
61
- }
62
-
63
- /**
64
- * Aggregate validation result for entire batch
65
- */
66
- interface BatchValidationResult {
67
- valid: boolean; // Overall validation status
68
- errors: BatchValidationError[];
69
- validCount: number; // Count of valid items
70
- invalidCount: number; // Count of invalid items
71
- summary: string; // Summary message for AI
72
- }
73
-
74
- /**
75
- * Batch item validator function signature
76
- */
77
- type BatchItemValidator<T> = (
78
- item: T,
79
- index: number,
80
- adapter: DatabaseAdapter,
81
- errors: BatchValidationError[]
82
- ) => Promise<void>;
83
- ```
84
-
85
- ### Core Validators
86
-
87
- #### validateRequiredField
88
- ```typescript
89
- function validateRequiredField(
90
- value: any,
91
- fieldName: string,
92
- itemIndex: number,
93
- itemIdentifier: string,
94
- errors: BatchValidationError[]
95
- ): void
96
- ```
97
- Validates field exists and is non-empty (undefined, null, or empty string).
98
-
99
- **Example**:
100
- ```typescript
101
- validateRequiredField(task.title, 'title', 0, 'Task 1', errors);
102
- // If missing: adds error with fix "Provide a non-empty value for 'title'"
103
- ```
104
-
105
- #### validateEnum
106
- ```typescript
107
- function validateEnum(
108
- value: any,
109
- fieldName: string,
110
- validOptions: readonly string[],
111
- itemIndex: number,
112
- itemIdentifier: string,
113
- errors: BatchValidationError[]
114
- ): void
115
- ```
116
- Validates enum value with typo suggestions using Levenshtein distance ≤ 2.
117
-
118
- **Example**:
119
- ```typescript
120
- validateEnum(task.layer, 'layer', STANDARD_LAYERS, 0, 'Task 1', errors);
121
- // If typo "busines": suggests "business (closest match)"
122
- ```
123
-
124
- #### validateType
125
- ```typescript
126
- function validateType(
127
- value: any,
128
- fieldName: string,
129
- expectedType: 'array' | 'string' | 'number' | 'object',
130
- itemIndex: number,
131
- itemIdentifier: string,
132
- errors: BatchValidationError[]
133
- ): void
134
- ```
135
- Validates type (array, string, number, object).
136
-
137
- **Example**:
138
- ```typescript
139
- validateType(task.tags, 'tags', 'array', 0, 'Task 1', errors);
140
- // If string "api,security": fix "Change to array format: [\"item1\", \"item2\"]"
141
- ```
142
-
143
- #### validateRange
144
- ```typescript
145
- function validateRange(
146
- value: any,
147
- fieldName: string,
148
- min: number,
149
- max: number,
150
- itemIndex: number,
151
- itemIdentifier: string,
152
- errors: BatchValidationError[]
153
- ): void
154
- ```
155
- Validates numeric range (inclusive).
156
-
157
- **Example**:
158
- ```typescript
159
- validateRange(task.priority, 'priority', 1, 4, 0, 'Task 1', errors);
160
- // If 5: fix "Provide a number between 1 and 4"
161
- ```
162
-
163
- #### validateLength
164
- ```typescript
165
- function validateLength(
166
- value: any,
167
- fieldName: string,
168
- maxLength: number,
169
- itemIndex: number,
170
- itemIdentifier: string,
171
- errors: BatchValidationError[]
172
- ): void
173
- ```
174
- Validates string length.
175
-
176
- **Example**:
177
- ```typescript
178
- validateLength(task.title, 'title', 200, 0, 'Task 1', errors);
179
- // If 201 chars: fix "Shorten to 200 characters or less (currently 201 chars)"
180
- ```
181
-
182
- #### validateForeignKey
183
- ```typescript
184
- async function validateForeignKey(
185
- value: any,
186
- fieldName: string,
187
- tableName: string,
188
- columnName: string,
189
- adapter: DatabaseAdapter,
190
- itemIndex: number,
191
- itemIdentifier: string,
192
- errors: BatchValidationError[]
193
- ): Promise<void>
194
- ```
195
- Validates foreign key reference exists in database.
196
-
197
- **Example**:
198
- ```typescript
199
- await validateForeignKey(
200
- task.layer, 'layer', 'v4_layers', 'name',
201
- adapter, 0, 'Task 1', errors
202
- );
203
- // If invalid: provides list of valid layers from database
204
- ```
205
-
206
- #### validateLayerFileRequirement
207
- ```typescript
208
- function validateLayerFileRequirement(
209
- layer: string | undefined,
210
- fileActions: any,
211
- itemIndex: number,
212
- itemIdentifier: string,
213
- errors: BatchValidationError[]
214
- ): void
215
- ```
216
- Validates FILE_REQUIRED layers have file_actions parameter (v3.8.0).
217
-
218
- **Example**:
219
- ```typescript
220
- validateLayerFileRequirement('business', undefined, 0, 'Task 1', errors);
221
- // Error: "Layer 'business' requires file_actions parameter"
222
- // Fix: "Add file_actions: [{ action: 'edit', path: 'src/...' }] or use [] for planning tasks"
223
- ```
224
-
225
- ### Batch Orchestrator
226
-
227
- #### validateBatch
228
- ```typescript
229
- async function validateBatch<T>(
230
- items: T[],
231
- itemValidator: BatchItemValidator<T>,
232
- adapter: DatabaseAdapter
233
- ): Promise<BatchValidationResult>
234
- ```
235
- Validates entire batch before transaction. Returns structured result with ALL validation errors.
236
-
237
- **Example**:
238
- ```typescript
239
- const result = await validateBatch(
240
- params.tasks,
241
- validateTaskItem, // Your item validator function
242
- adapter
243
- );
244
-
245
- if (!result.valid) {
246
- throw new Error(formatBatchValidationError(result));
247
- }
248
- ```
249
-
250
- ### Error Formatter
251
-
252
- #### formatBatchValidationError
253
- ```typescript
254
- function formatBatchValidationError(
255
- result: BatchValidationResult
256
- ): string
257
- ```
258
- Formats batch validation errors for AI comprehension with actionable fix instructions.
259
-
260
- **Example Output**:
261
- ```
262
- Batch validation failed. Found 4 validation error(s) in 2 item(s). 1 items are valid.
263
-
264
- Item 0 (Task 1):
265
- ❌ layer: Invalid layer: "busines"
266
- 💡 Fix: Change to "business" (closest match)
267
- Current: "busines"
268
- Valid: presentation, business, data, infrastructure, cross-cutting, documentation, planning, coordination, review
269
-
270
- ❌ priority: Field "priority" must be between 1 and 4
271
- 💡 Fix: Provide a number between 1 and 4
272
- Current: 5
273
-
274
- Item 1 (Task 2):
275
- ❌ title: Field "title" is required but missing or empty
276
- 💡 Fix: Provide a non-empty value for "title"
277
- Current: undefined
278
-
279
- ❌ file_actions: Layer "presentation" requires file_actions parameter
280
- 💡 Fix: Add file_actions: [{ action: "edit", path: "src/..." }] or use [] for planning tasks
281
- Current: undefined
282
- Valid: Add file_actions array, Change to FILE_OPTIONAL layer (planning/coordination/review)
283
-
284
- 💡 Result: 1 valid, 2 invalid
285
- 💡 Action: Fix the 2 invalid item(s) and retry batch operation
286
- ```
287
-
288
- ## Integration Pattern
289
-
290
- ### Before (Without Batch Validation)
291
-
292
- ```typescript
293
- // ❌ PROBLEMATIC - Validation happens INSIDE transaction
294
- export async function batchCreateTasks(params: { tasks: any[] }) {
295
- if (!params.tasks || !Array.isArray(params.tasks)) {
296
- throw new Error('Parameter "tasks" is required and must be an array');
297
- }
298
-
299
- // Start transaction immediately
300
- return await adapter.transaction(async (trx) => {
301
- for (const task of params.tasks) {
302
- // Validation happens INSIDE transaction
303
- // Fails on FIRST error, wastes resources on partial processing
304
- const result = await createTaskInternal(task, adapter, trx);
305
- // ...
306
- }
307
- });
308
- }
309
- ```
310
-
311
- **Problems**:
312
- - Validates inside transaction (wasted resources on partial processing)
313
- - Fails on first error (AI must fix one error at a time, retry, discover next error)
314
- - Generic error messages (no context, no guidance)
315
-
316
- ### After (With Batch Validation)
317
-
318
- ```typescript
319
- // ✅ IMPROVED - Pre-validation BEFORE transaction
320
- export async function batchCreateTasks(params: { tasks: any[] }, adapter?: DatabaseAdapter) {
321
- const actualAdapter = adapter ?? getAdapter();
322
-
323
- // Basic validation
324
- if (!params.tasks || !Array.isArray(params.tasks)) {
325
- throw new Error('Parameter "tasks" is required and must be an array');
326
- }
327
-
328
- if (params.tasks.length > 50) {
329
- throw new Error('Parameter "tasks" must contain at most 50 items');
330
- }
331
-
332
- // ✅ PRE-VALIDATION: Check ALL items BEFORE transaction
333
- const validationResult = await validateBatch(
334
- params.tasks,
335
- validateTaskItem,
336
- actualAdapter
337
- );
338
-
339
- // ✅ FAIL FAST: If validation fails, throw formatted error with ALL issues
340
- if (!validationResult.valid) {
341
- const errorMessage = formatBatchValidationError(validationResult);
342
- throw new Error(errorMessage);
343
- }
344
-
345
- // Validation passed - proceed with transaction
346
- const atomic = params.atomic !== undefined ? params.atomic : true;
347
-
348
- if (atomic) {
349
- // All items are valid - safe to process in single transaction
350
- return await actualAdapter.transaction(async (trx) => {
351
- const results = [];
352
- for (const task of params.tasks) {
353
- // No validation needed here - already validated
354
- const result = await createTaskInternal(task, actualAdapter, trx);
355
- results.push({
356
- title: task.title,
357
- task_id: result.task_id,
358
- success: true
359
- });
360
- }
361
- return { success: true, created: results.length, failed: 0, results };
362
- });
363
- } else {
364
- // Non-atomic mode: still validate upfront, but process independently
365
- // ... existing non-atomic logic
366
- }
367
- }
368
- ```
369
-
370
- **Benefits**:
371
- - Validates ALL items BEFORE transaction (no wasted resources)
372
- - Reports ALL errors at once (AI fixes all issues in one retry)
373
- - AI-friendly error messages (actionable fixes, typo suggestions, valid options)
374
-
375
- ## Usage Examples
376
-
377
- ### Example 1: Task Batch Validator
378
-
379
- ```typescript
380
- import {
381
- validateRequiredField,
382
- validateEnum,
383
- validateType,
384
- validateRange,
385
- validateLength,
386
- validateLayerFileRequirement,
387
- type BatchValidationError
388
- } from '../utils/batch-validation.js';
389
-
390
- async function validateTaskItem(
391
- task: any,
392
- index: number,
393
- adapter: DatabaseAdapter,
394
- errors: BatchValidationError[]
395
- ): Promise<void> {
396
- const identifier = task.title || `Item ${index}`;
397
-
398
- // Required fields
399
- validateRequiredField(task.title, 'title', index, identifier, errors);
400
-
401
- // String length
402
- if (task.title) {
403
- validateLength(task.title, 'title', 200, index, identifier, errors);
404
- }
405
-
406
- // Enums
407
- if (task.status) {
408
- validateEnum(
409
- task.status,
410
- 'status',
411
- ['todo', 'in_progress', 'waiting_review', 'blocked', 'done', 'archived', 'rejected'],
412
- index,
413
- identifier,
414
- errors
415
- );
416
- }
417
-
418
- if (task.layer) {
419
- validateEnum(
420
- task.layer,
421
- 'layer',
422
- ['presentation', 'business', 'data', 'infrastructure', 'cross-cutting',
423
- 'documentation', 'planning', 'coordination', 'review'],
424
- index,
425
- identifier,
426
- errors
427
- );
428
- }
429
-
430
- // Range validation
431
- if (task.priority !== undefined) {
432
- validateRange(task.priority, 'priority', 1, 4, index, identifier, errors);
433
- }
434
-
435
- // Type validation
436
- if (task.tags !== undefined) {
437
- validateType(task.tags, 'tags', 'array', index, identifier, errors);
438
- }
439
-
440
- // Complex field validation: file_actions
441
- if (task.file_actions !== undefined) {
442
- validateType(task.file_actions, 'file_actions', 'array', index, identifier, errors);
443
-
444
- if (Array.isArray(task.file_actions)) {
445
- task.file_actions.forEach((fa: any, faIndex: number) => {
446
- if (!fa.action) {
447
- errors.push({
448
- itemIndex: index,
449
- itemIdentifier: identifier,
450
- field: `file_actions[${faIndex}].action`,
451
- issue: 'Missing action field in file_actions',
452
- fix: 'Add action field: { action: "create"|"edit"|"delete", path: "..." }',
453
- current: fa
454
- });
455
- } else {
456
- validateEnum(
457
- fa.action,
458
- `file_actions[${faIndex}].action`,
459
- ['create', 'edit', 'delete'],
460
- index,
461
- identifier,
462
- errors
463
- );
464
- }
465
-
466
- if (!fa.path || typeof fa.path !== 'string') {
467
- errors.push({
468
- itemIndex: index,
469
- itemIdentifier: identifier,
470
- field: `file_actions[${faIndex}].path`,
471
- issue: 'Missing or invalid path field in file_actions',
472
- fix: 'Add path field as string: { action: "...", path: "src/file.ts" }',
473
- current: fa
474
- });
475
- }
476
- });
477
- }
478
- }
479
-
480
- // Layer-specific validation (FILE_REQUIRED vs FILE_OPTIONAL)
481
- validateLayerFileRequirement(task.layer, task.file_actions, index, identifier, errors);
482
- }
483
- ```
484
-
485
- ### Example 2: Decision Batch Validator
486
-
487
- ```typescript
488
- async function validateDecisionItem(
489
- decision: any,
490
- index: number,
491
- adapter: DatabaseAdapter,
492
- errors: BatchValidationError[]
493
- ): Promise<void> {
494
- const identifier = decision.key || `Item ${index}`;
495
-
496
- // Required fields
497
- validateRequiredField(decision.key, 'key', index, identifier, errors);
498
- validateRequiredField(decision.value, 'value', index, identifier, errors);
499
-
500
- // Enums
501
- if (decision.status) {
502
- validateEnum(
503
- decision.status,
504
- 'status',
505
- ['active', 'deprecated', 'draft'],
506
- index,
507
- identifier,
508
- errors
509
- );
510
- }
511
-
512
- if (decision.layer) {
513
- validateEnum(
514
- decision.layer,
515
- 'layer',
516
- STANDARD_LAYERS,
517
- index,
518
- identifier,
519
- errors
520
- );
521
- }
522
-
523
- // Type validation
524
- if (decision.tags !== undefined) {
525
- validateType(decision.tags, 'tags', 'array', index, identifier, errors);
526
- }
527
- }
528
- ```
529
-
530
- ## Success Metrics
531
-
532
- ### Before (Current State)
533
- - **AI retry rate**: 5-10 retries per batch with multiple issues
534
- - **Error comprehension**: Low (generic messages, single error at a time)
535
- - **Fix accuracy**: 60-70% (AI guesses at fixes due to incomplete error info)
536
-
537
- ### After (With Batch Validation)
538
- - **AI retry rate**: 1-2 retries per batch (all errors reported at once)
539
- - **Error comprehension**: High (structured errors with fix instructions)
540
- - **Fix accuracy**: 90-95% (AI has complete error context and actionable fixes)
541
- - **Reduction in batch failures**: 70-85% (pre-validation catches issues before transaction)
542
-
543
- ## AI Interaction Flow Comparison
544
-
545
- ### Before (Iterative Debugging Loop - 4 attempts)
546
- 1. AI submits batch with 3 invalid items
547
- 2. System processes item 0, item 1, fails at item 2 with "Invalid layer: busines"
548
- 3. AI fixes item 2 layer typo, retries
549
- 4. System processes item 0, fails with "Priority must be between 1 and 4"
550
- 5. AI fixes item 0 priority, retries
551
- 6. System processes item 0, item 1, fails with "Missing required field: title"
552
- 7. AI fixes item 1 title, retries
553
- 8. Success
554
-
555
- **Total iterations**: 4
556
- **Time wasted**: 3 failed transactions
557
- **AI frustration**: High (whack-a-mole debugging)
558
-
559
- ### After (Single Fix Cycle - 2 attempts)
560
- 1. AI submits batch with 3 invalid items
561
- 2. System validates all items BEFORE transaction
562
- 3. System returns formatted error with ALL 5 validation issues across 3 items
563
- 4. AI reads error, sees all issues at once:
564
- - Item 0: layer typo "busines" → "business"
565
- - Item 0: priority 5 → must be 1-4
566
- - Item 1: missing title
567
- - Item 2: file_actions wrong type (string → array)
568
- - Item 2: layer requires file_actions
569
- 5. AI fixes all 5 issues, retries
570
- 6. Success
571
-
572
- **Total iterations**: 2 (1 failure + 1 success)
573
- **Time wasted**: 0 transactions (validation before transaction)
574
- **AI frustration**: Low (clear fix instructions)
575
-
576
- ## Files
577
-
578
- ```
579
- src/utils/
580
- ├── batch-validation.ts # Main implementation (530 lines)
581
- ├── levenshtein.ts # Shared Levenshtein distance (45 lines)
582
- └── batch-validation.example.ts # Usage examples (230 lines)
583
-
584
- src/tests/
585
- └── batch-validation.test.ts # Unit tests (33 tests, 7 suites)
586
-
587
- docs/
588
- └── BATCH_VALIDATION.md # This file
589
- ```
590
-
591
- ## Related Documentation
592
-
593
- - **Design Document**: `batch-validation-architecture-design` (Serena memory)
594
- - **Parameter Validation**: `src/utils/parameter-validator.ts` (uses shared Levenshtein)
595
- - **Constants**: `src/constants.ts` (STANDARD_LAYERS, FILE_REQUIRED_LAYERS, etc.)
596
- - **Types**: `src/adapters/types.ts` (DatabaseAdapter interface)
597
-
598
- ## Version History
599
-
600
- - **v3.8.0**: Initial implementation (2025-11-09)
601
- - Core validators: validateRequiredField, validateEnum, validateType, validateRange, validateLength, validateForeignKey, validateLayerFileRequirement
602
- - Batch orchestrator: validateBatch
603
- - Error formatter: formatBatchValidationError
604
- - Shared Levenshtein distance extraction
605
- - 33 unit tests (100% pass rate)
606
- - Integration examples and documentation
607
-
608
- ## Future Enhancements
609
-
610
- 1. **Phase 2**: Tool-specific validators (validateTaskItem, validateDecisionItem, validateFileChangeItem)
611
- 2. **Phase 3**: Integration into batch actions (batch-create.ts, batch-set.ts, record-batch.ts)
612
- 3. **Phase 4**: Integration tests with real batch operations
613
- 4. **Metrics**: Track actual AI retry rate reduction and fix accuracy
614
-
615
- ## License
616
-
617
- MIT License - Part of MCP Shared Context Server (mcp-sqlew)