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.
- package/CHANGELOG.md +1805 -1762
- package/LICENSE +177 -39
- package/NOTICE +24 -0
- package/README.md +409 -390
- package/assets/claude-md-snippets/plan-mode-integration.md +17 -6
- package/assets/config.example.toml +282 -284
- package/assets/sample-agents/README.md +36 -40
- package/assets/sample-agents/sqlew-architect.md +321 -322
- package/assets/sample-agents/sqlew-researcher.md +292 -293
- package/assets/sample-agents/sqlew-scrum-master.md +286 -287
- package/assets/sample-commands/README.md +56 -57
- package/assets/sample-skills/sqlew-plan-guidance/SKILL.md +33 -26
- package/dist/cli/hooks/check-completion.d.ts +19 -0
- package/dist/cli/hooks/check-completion.d.ts.map +1 -0
- package/dist/cli/hooks/check-completion.js +104 -0
- package/dist/cli/hooks/check-completion.js.map +1 -0
- package/dist/cli/hooks/init-hooks.d.ts +35 -0
- package/dist/cli/hooks/init-hooks.d.ts.map +1 -0
- package/dist/cli/hooks/init-hooks.js +425 -0
- package/dist/cli/hooks/init-hooks.js.map +1 -0
- package/dist/cli/hooks/mark-done.d.ts +25 -0
- package/dist/cli/hooks/mark-done.d.ts.map +1 -0
- package/dist/cli/hooks/mark-done.js +128 -0
- package/dist/cli/hooks/mark-done.js.map +1 -0
- package/dist/cli/hooks/plan-id-utils.d.ts +83 -0
- package/dist/cli/hooks/plan-id-utils.d.ts.map +1 -0
- package/dist/cli/hooks/plan-id-utils.js +183 -0
- package/dist/cli/hooks/plan-id-utils.js.map +1 -0
- package/dist/cli/hooks/save.d.ts +23 -0
- package/dist/cli/hooks/save.d.ts.map +1 -0
- package/dist/cli/hooks/save.js +90 -0
- package/dist/cli/hooks/save.js.map +1 -0
- package/dist/cli/hooks/stdin-parser.d.ts +139 -0
- package/dist/cli/hooks/stdin-parser.d.ts.map +1 -0
- package/dist/cli/hooks/stdin-parser.js +127 -0
- package/dist/cli/hooks/stdin-parser.js.map +1 -0
- package/dist/cli/hooks/suggest.d.ts +19 -0
- package/dist/cli/hooks/suggest.d.ts.map +1 -0
- package/dist/cli/hooks/suggest.js +157 -0
- package/dist/cli/hooks/suggest.js.map +1 -0
- package/dist/cli/hooks/track-plan.d.ts +36 -0
- package/dist/cli/hooks/track-plan.d.ts.map +1 -0
- package/dist/cli/hooks/track-plan.js +152 -0
- package/dist/cli/hooks/track-plan.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +56 -16
- package/dist/cli.js.map +1 -1
- package/dist/config/global-config.d.ts +187 -0
- package/dist/config/global-config.d.ts.map +1 -0
- package/dist/config/global-config.js +206 -0
- package/dist/config/global-config.js.map +1 -0
- package/dist/config/loader.d.ts +42 -0
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +96 -0
- package/dist/config/loader.js.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -0
- package/dist/constants.js.map +1 -1
- package/dist/database/operations/queries.d.ts.map +1 -1
- package/dist/database/operations/queries.js +11 -2
- package/dist/database/operations/queries.js.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/init-agents.js +0 -1
- package/dist/init-agents.js.map +1 -1
- package/dist/init-skills.d.ts +4 -3
- package/dist/init-skills.d.ts.map +1 -1
- package/dist/init-skills.js +10 -3
- package/dist/init-skills.js.map +1 -1
- package/dist/server/setup.d.ts +8 -0
- package/dist/server/setup.d.ts.map +1 -1
- package/dist/server/setup.js +141 -21
- package/dist/server/setup.js.map +1 -1
- package/dist/sync-agents.d.ts.map +1 -1
- package/dist/sync-agents.js +48 -3
- package/dist/sync-agents.js.map +1 -1
- package/dist/sync-commands.d.ts.map +1 -1
- package/dist/sync-commands.js +43 -3
- package/dist/sync-commands.js.map +1 -1
- package/dist/tools/constraints/actions/get.d.ts.map +1 -1
- package/dist/tools/constraints/actions/get.js +5 -8
- package/dist/tools/constraints/actions/get.js.map +1 -1
- package/dist/tools/constraints/help/help.d.ts.map +1 -1
- package/dist/tools/constraints/help/help.js +1 -6
- package/dist/tools/constraints/help/help.js.map +1 -1
- package/dist/tools/context/actions/get.d.ts.map +1 -1
- package/dist/tools/context/actions/get.js.map +1 -1
- package/dist/tools/context/actions/search-layer.d.ts.map +1 -1
- package/dist/tools/context/actions/search-layer.js +5 -3
- package/dist/tools/context/actions/search-layer.js.map +1 -1
- package/dist/tools/context/actions/set-from-policy.d.ts +2 -1
- package/dist/tools/context/actions/set-from-policy.d.ts.map +1 -1
- package/dist/tools/context/actions/set-from-policy.js.map +1 -1
- package/dist/tools/context/help/help.d.ts.map +1 -1
- package/dist/tools/context/help/help.js +1 -7
- package/dist/tools/context/help/help.js.map +1 -1
- package/dist/tools/context/internal/queries.d.ts.map +1 -1
- package/dist/tools/context/internal/queries.js +5 -2
- package/dist/tools/context/internal/queries.js.map +1 -1
- package/dist/tools/context/types.d.ts +1 -1
- package/dist/tools/context/types.d.ts.map +1 -1
- package/dist/tools/files/actions/get.d.ts.map +1 -1
- package/dist/tools/files/actions/get.js +4 -6
- package/dist/tools/files/actions/get.js.map +1 -1
- package/dist/tools/files/help/help.d.ts.map +1 -1
- package/dist/tools/files/help/help.js +1 -6
- package/dist/tools/files/help/help.js.map +1 -1
- package/dist/tools/suggest/help/constraint-help.d.ts.map +1 -1
- package/dist/tools/suggest/help/constraint-help.js +0 -2
- package/dist/tools/suggest/help/constraint-help.js.map +1 -1
- package/dist/tools/suggest/internal/constraint-queries.d.ts.map +1 -1
- package/dist/tools/suggest/internal/constraint-queries.js +12 -5
- package/dist/tools/suggest/internal/constraint-queries.js.map +1 -1
- package/dist/tools/suggest/internal/queries.js +2 -2
- package/dist/tools/suggest/internal/queries.js.map +1 -1
- package/dist/tools/tasks/help/help.d.ts.map +1 -1
- package/dist/tools/tasks/help/help.js +0 -6
- package/dist/tools/tasks/help/help.js.map +1 -1
- package/dist/tools/tasks/help/use-case.d.ts.map +1 -1
- package/dist/tools/tasks/help/use-case.js +0 -1
- package/dist/tools/tasks/help/use-case.js.map +1 -1
- package/dist/tools/tasks/watcher/status.d.ts.map +1 -1
- package/dist/tools/tasks/watcher/status.js +5 -1
- package/dist/tools/tasks/watcher/status.js.map +1 -1
- package/dist/types/decision/params.d.ts +7 -6
- package/dist/types/decision/params.d.ts.map +1 -1
- package/dist/types/decision/templates.d.ts +3 -2
- package/dist/types/decision/templates.d.ts.map +1 -1
- package/dist/types/view-entities.d.ts +2 -1
- package/dist/types/view-entities.d.ts.map +1 -1
- package/dist/types.d.ts +19 -11
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/enum-converter.d.ts +72 -0
- package/dist/utils/enum-converter.d.ts.map +1 -0
- package/dist/utils/enum-converter.js +76 -0
- package/dist/utils/enum-converter.js.map +1 -0
- package/dist/utils/hook-queue.d.ts +81 -0
- package/dist/utils/hook-queue.d.ts.map +1 -0
- package/dist/utils/hook-queue.js +156 -0
- package/dist/utils/hook-queue.js.map +1 -0
- package/dist/utils/project-root.d.ts +9 -2
- package/dist/utils/project-root.d.ts.map +1 -1
- package/dist/utils/project-root.js +16 -2
- package/dist/utils/project-root.js.map +1 -1
- package/dist/utils/tag-parser.d.ts.map +1 -1
- package/dist/utils/tag-parser.js +6 -0
- package/dist/utils/tag-parser.js.map +1 -1
- package/dist/utils/validators.d.ts +1 -1
- package/dist/utils/validators.d.ts.map +1 -1
- package/dist/utils/validators.js +1 -1
- package/dist/utils/validators.js.map +1 -1
- package/dist/utils/vcs-adapter.d.ts +44 -0
- package/dist/utils/vcs-adapter.d.ts.map +1 -1
- package/dist/utils/vcs-adapter.js +88 -0
- package/dist/utils/vcs-adapter.js.map +1 -1
- package/dist/utils/view-queries.d.ts.map +1 -1
- package/dist/utils/view-queries.js +9 -19
- package/dist/utils/view-queries.js.map +1 -1
- package/dist/watcher/base-watcher.d.ts +69 -0
- package/dist/watcher/base-watcher.d.ts.map +1 -0
- package/dist/watcher/base-watcher.js +130 -0
- package/dist/watcher/base-watcher.js.map +1 -0
- package/dist/watcher/index.d.ts +3 -0
- package/dist/watcher/index.d.ts.map +1 -1
- package/dist/watcher/index.js +2 -0
- package/dist/watcher/index.js.map +1 -1
- package/dist/watcher/queue-watcher.d.ts +64 -0
- package/dist/watcher/queue-watcher.d.ts.map +1 -0
- package/dist/watcher/queue-watcher.js +187 -0
- package/dist/watcher/queue-watcher.js.map +1 -0
- package/docs/ADR_CONCEPTS.md +140 -0
- package/docs/CONFIGURATION.md +922 -925
- package/docs/CROSS_DATABASE.md +153 -0
- package/docs/DATABASE_AUTH.md +70 -356
- package/docs/HOOKS_GUIDE.md +159 -0
- package/docs/SLASH_COMMANDS.md +329 -337
- package/docs/TASK_SYSTEM_DEPRECATED.md +88 -0
- package/docs/changelogs/CHANGELOG_ARCHIVE_v3.4_and_older.md +293 -296
- package/docs/cli/DATA_EXPORT_IMPORT.md +699 -700
- package/docs/cli/README.md +276 -277
- package/package.json +123 -119
- package/docs/ACCEPTANCE_CRITERIA.md +0 -625
- package/docs/AI_AGENT_GUIDE.md +0 -198
- package/docs/ARCHITECTURE.md +0 -167
- package/docs/AUTO_FILE_TRACKING.md +0 -841
- package/docs/BATCH_VALIDATION.md +0 -617
- package/docs/BEST_PRACTICES.md +0 -168
- package/docs/CONSTRAINT_INTELLIGENCE.md +0 -339
- package/docs/DECISION_CONTEXT.md +0 -675
- package/docs/DECISION_INTELLIGENCE.md +0 -605
- package/docs/GIT_AWARE_AUTO_COMPLETE.md +0 -646
- package/docs/MIGRATION_GUIDE_V3.9.0.md +0 -371
- package/docs/SHARED_CONCEPTS.md +0 -225
- package/docs/SPECIALIZED_AGENTS.md +0 -126
- package/docs/TASK_ACTIONS.md +0 -1177
- package/docs/TASK_OVERVIEW.md +0 -452
- package/docs/TASK_PRUNING.md +0 -594
- package/docs/TOOL_REFERENCE.md +0 -1077
- package/docs/TOOL_SELECTION.md +0 -83
- package/docs/WORKFLOWS.md +0 -941
package/docs/BATCH_VALIDATION.md
DELETED
|
@@ -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)
|