@itz4blitz/agentful 0.3.0 → 0.5.1

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 (94) hide show
  1. package/README.md +139 -10
  2. package/bin/cli.js +1032 -48
  3. package/bin/hooks/README.md +338 -82
  4. package/bin/hooks/analyze-trigger.js +69 -0
  5. package/bin/hooks/block-random-docs.js +77 -0
  6. package/bin/hooks/health-check.js +153 -0
  7. package/bin/hooks/post-agent.js +101 -0
  8. package/bin/hooks/post-feature.js +227 -0
  9. package/bin/hooks/pre-agent.js +118 -0
  10. package/bin/hooks/pre-feature.js +138 -0
  11. package/lib/VALIDATION_README.md +455 -0
  12. package/lib/atomic.js +350 -0
  13. package/lib/ci/claude-action-integration.js +641 -0
  14. package/lib/ci/index.js +10 -0
  15. package/lib/core/CLAUDE_EXECUTOR.md +371 -0
  16. package/lib/core/README.md +321 -0
  17. package/lib/core/analyzer.js +497 -0
  18. package/lib/core/claude-executor.example.js +210 -0
  19. package/lib/core/claude-executor.js +1046 -0
  20. package/lib/core/cli.js +141 -0
  21. package/lib/core/detectors/conventions.js +342 -0
  22. package/lib/core/detectors/framework.js +276 -0
  23. package/lib/core/detectors/index.js +15 -0
  24. package/lib/core/detectors/language.js +199 -0
  25. package/lib/core/detectors/patterns.js +356 -0
  26. package/lib/core/generator.js +626 -0
  27. package/lib/core/index.js +9 -0
  28. package/lib/core/output-parser.example.js +250 -0
  29. package/lib/core/output-parser.js +458 -0
  30. package/lib/core/storage.js +515 -0
  31. package/lib/core/templates.js +556 -0
  32. package/lib/index.js +32 -0
  33. package/lib/init.js +497 -25
  34. package/lib/pipeline/cli.js +423 -0
  35. package/lib/pipeline/engine.js +928 -0
  36. package/lib/pipeline/executor.js +440 -0
  37. package/lib/pipeline/index.js +33 -0
  38. package/lib/pipeline/integrations.js +559 -0
  39. package/lib/pipeline/schemas.js +288 -0
  40. package/lib/presets.js +207 -0
  41. package/lib/remote/client.js +361 -0
  42. package/lib/server/auth.js +286 -0
  43. package/lib/server/client-example.js +190 -0
  44. package/lib/server/executor.js +426 -0
  45. package/lib/server/index.js +469 -0
  46. package/lib/update-helpers.js +505 -0
  47. package/lib/validation.js +460 -0
  48. package/package.json +19 -2
  49. package/template/.claude/agents/architect.md +260 -0
  50. package/template/.claude/agents/backend.md +203 -0
  51. package/template/.claude/agents/fixer.md +244 -0
  52. package/template/.claude/agents/frontend.md +232 -0
  53. package/template/.claude/agents/orchestrator.md +528 -0
  54. package/template/.claude/agents/product-analyzer.md +1130 -0
  55. package/template/.claude/agents/reviewer.md +229 -0
  56. package/template/.claude/agents/tester.md +242 -0
  57. package/{.claude → template/.claude}/commands/agentful-analyze.md +151 -43
  58. package/template/.claude/commands/agentful-decide.md +470 -0
  59. package/{.claude → template/.claude}/commands/agentful-product.md +92 -8
  60. package/template/.claude/commands/agentful-start.md +432 -0
  61. package/{.claude → template/.claude}/commands/agentful-status.md +88 -3
  62. package/template/.claude/commands/agentful-update.md +402 -0
  63. package/template/.claude/commands/agentful-validate.md +369 -0
  64. package/{.claude → template/.claude}/commands/agentful.md +111 -195
  65. package/template/.claude/product/EXAMPLES.md +167 -0
  66. package/{.claude → template/.claude}/settings.json +9 -13
  67. package/{.claude → template/.claude}/skills/conversation/SKILL.md +13 -7
  68. package/template/.claude/skills/deployment/SKILL.md +116 -0
  69. package/template/.claude/skills/product-planning/SKILL.md +463 -0
  70. package/{.claude → template/.claude}/skills/product-tracking/SKILL.md +10 -21
  71. package/template/.claude/skills/testing/SKILL.md +228 -0
  72. package/template/.claude/skills/validation/SKILL.md +650 -0
  73. package/template/CLAUDE.md +84 -16
  74. package/template/bin/hooks/block-random-docs.js +121 -0
  75. package/version.json +1 -1
  76. package/.claude/agents/architect.md +0 -524
  77. package/.claude/agents/backend.md +0 -315
  78. package/.claude/agents/fixer.md +0 -263
  79. package/.claude/agents/frontend.md +0 -274
  80. package/.claude/agents/orchestrator.md +0 -283
  81. package/.claude/agents/product-analyzer.md +0 -799
  82. package/.claude/agents/reviewer.md +0 -332
  83. package/.claude/agents/tester.md +0 -410
  84. package/.claude/commands/agentful-decide.md +0 -214
  85. package/.claude/commands/agentful-start.md +0 -182
  86. package/.claude/commands/agentful-validate.md +0 -127
  87. package/.claude/product/EXAMPLES.md +0 -610
  88. package/.claude/product/README.md +0 -344
  89. package/.claude/skills/validation/SKILL.md +0 -271
  90. package/bin/hooks/analyze-trigger.sh +0 -57
  91. package/bin/hooks/health-check.sh +0 -36
  92. package/template/PRODUCT.md +0 -584
  93. /package/{.claude → template/.claude}/commands/agentful-generate.md +0 -0
  94. /package/{.claude → template/.claude}/product/index.md +0 -0
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env node
2
+ // pre-feature.js
3
+ // Validates feature readiness before implementation
4
+
5
+ import fs from 'fs';
6
+
7
+ /**
8
+ * Validate feature readiness before implementation
9
+ * @param {string} feature - Feature name
10
+ * @param {string} domain - Domain name (optional)
11
+ * @returns {object} - { errors, warnings, exitCode }
12
+ */
13
+ export function validateFeatureReadiness(feature, domain = '') {
14
+ // Exit successfully if no feature specified
15
+ if (!feature) {
16
+ return { errors: 0, warnings: 0, exitCode: 0 };
17
+ }
18
+
19
+ let errors = 0;
20
+ let warnings = 0;
21
+
22
+ // Check 1: Feature file exists
23
+ let featureFile = '';
24
+ if (domain) {
25
+ // Hierarchical structure
26
+ featureFile = `.claude/product/domains/${domain}/features/${feature}.md`;
27
+ } else {
28
+ // Flat structure
29
+ featureFile = `.claude/product/features/${feature}.md`;
30
+ }
31
+
32
+ if (!fs.existsSync(featureFile)) {
33
+ console.error(`ERROR: Feature file not found: ${featureFile}`);
34
+ errors++;
35
+ }
36
+
37
+ // Check 2: Verify completion.json exists
38
+ const completionJsonPath = '.agentful/completion.json';
39
+ if (!fs.existsSync(completionJsonPath)) {
40
+ console.error('ERROR: .agentful/completion.json not found');
41
+ errors++;
42
+ }
43
+
44
+ // Check 3: Check feature dependencies
45
+ if (fs.existsSync(completionJsonPath)) {
46
+ try {
47
+ const completionContent = fs.readFileSync(completionJsonPath, 'utf8');
48
+ const completion = JSON.parse(completionContent);
49
+
50
+ // Check if feature has dependencies that are incomplete
51
+ if (domain) {
52
+ // Hierarchical: check domain-level dependencies
53
+ const domainStatus = completion.domains?.[domain]?.status || 'unknown';
54
+ if (domainStatus === 'blocked') {
55
+ console.error(`ERROR: Domain '${domain}' is blocked`);
56
+ errors++;
57
+ }
58
+ }
59
+
60
+ // Check for blocking decisions
61
+ const decisionsJsonPath = '.agentful/decisions.json';
62
+ if (fs.existsSync(decisionsJsonPath)) {
63
+ try {
64
+ const decisionsContent = fs.readFileSync(decisionsJsonPath, 'utf8');
65
+ const decisions = JSON.parse(decisionsContent);
66
+
67
+ const featurePath = domain ? `${domain}/${feature}` : feature;
68
+ const blockingDecisions = (decisions.pending || [])
69
+ .filter(d => (d.blocking || []).some(b => b.includes(featurePath)))
70
+ .map(d => d.id);
71
+
72
+ if (blockingDecisions.length > 0) {
73
+ console.error(`ERROR: Feature '${feature}' is blocked by decisions: ${blockingDecisions.join(', ')}`);
74
+ console.error('Run /agentful-decide to resolve blocking decisions');
75
+ errors++;
76
+ }
77
+ } catch (err) {
78
+ // Ignore JSON parse errors for decisions.json
79
+ }
80
+ }
81
+ } catch (err) {
82
+ // Ignore JSON parse errors for completion.json
83
+ }
84
+ }
85
+
86
+ // Check 4: Tech stack compatibility (if architecture.json exists)
87
+ const architectureJsonPath = '.agentful/architecture.json';
88
+ if (fs.existsSync(architectureJsonPath)) {
89
+ try {
90
+ const archContent = fs.readFileSync(architectureJsonPath, 'utf8');
91
+ const arch = JSON.parse(archContent);
92
+ const techStack = arch.techStack;
93
+
94
+ if (!techStack || techStack === null) {
95
+ console.log('WARNING: Tech stack not analyzed. Run /agentful-generate');
96
+ warnings++;
97
+ }
98
+ } catch (err) {
99
+ // Ignore JSON parse errors
100
+ }
101
+ }
102
+
103
+ // Check 5: Verify required agents exist
104
+ const requiredAgents = ['backend', 'frontend', 'tester', 'reviewer'];
105
+ for (const agent of requiredAgents) {
106
+ const agentPath = `.claude/agents/${agent}.md`;
107
+ if (!fs.existsSync(agentPath)) {
108
+ console.log(`WARNING: Core agent missing: ${agentPath}`);
109
+ warnings++;
110
+ }
111
+ }
112
+
113
+ // Exit with error if critical checks failed
114
+ if (errors > 0) {
115
+ console.log('');
116
+ console.log(`Pre-feature validation failed with ${errors} error(s)`);
117
+ console.log(`Feature: ${feature}`);
118
+ if (domain) console.log(`Domain: ${domain}`);
119
+ return { errors, warnings, exitCode: 1 };
120
+ }
121
+
122
+ if (warnings > 0) {
123
+ console.log('');
124
+ console.log(`Pre-feature validation passed with ${warnings} warning(s)`);
125
+ }
126
+
127
+ // All checks passed
128
+ return { errors: 0, warnings, exitCode: 0 };
129
+ }
130
+
131
+ // CLI entrypoint
132
+ if (import.meta.url === `file://${process.argv[1]}`) {
133
+ const FEATURE = process.env.AGENTFUL_FEATURE || '';
134
+ const DOMAIN = process.env.AGENTFUL_DOMAIN || '';
135
+
136
+ const result = validateFeatureReadiness(FEATURE, DOMAIN);
137
+ process.exit(result.exitCode);
138
+ }
@@ -0,0 +1,455 @@
1
+ # Validation Library
2
+
3
+ Centralized validation library for agentful state files. This library consolidates duplicated validation logic from 8+ command files into a single, well-tested module.
4
+
5
+ ## Features
6
+
7
+ - File existence checks
8
+ - JSON parsing validation
9
+ - Schema validation using AJV
10
+ - Required field validation
11
+ - Standardized error codes and messages
12
+ - Helper functions for common state files
13
+ - Batch validation support
14
+
15
+ ## Installation
16
+
17
+ The validation library is already included in the agentful package. Import it from `lib/validation.js`:
18
+
19
+ ```javascript
20
+ import {
21
+ validateStateFile,
22
+ validateState,
23
+ validateCompletion,
24
+ validateDecisions,
25
+ validateArchitecture,
26
+ validateProduct,
27
+ ValidationActions
28
+ } from './lib/validation.js';
29
+ ```
30
+
31
+ ## Standardized Action Codes
32
+
33
+ All validation functions return a standardized `action` field indicating what went wrong:
34
+
35
+ - **`missing`**: File does not exist
36
+ - **`corrupted`**: File exists but is not valid JSON
37
+ - **`invalid`**: JSON is valid but doesn't match the schema
38
+ - **`incomplete`**: Schema is valid but required fields are missing
39
+
40
+ ## Basic Usage
41
+
42
+ ### Validate any state file
43
+
44
+ ```javascript
45
+ import { validateStateFile } from './lib/validation.js';
46
+
47
+ const result = validateStateFile(
48
+ '.agentful/state.json',
49
+ 'state',
50
+ ['custom_field'] // optional additional required fields
51
+ );
52
+
53
+ if (!result.valid) {
54
+ console.error(`Validation failed: ${result.action}`);
55
+ console.error(`Error: ${result.error}`);
56
+
57
+ // Handle different error types
58
+ switch (result.action) {
59
+ case 'missing':
60
+ // Create the file
61
+ break;
62
+ case 'corrupted':
63
+ // Backup and reset
64
+ break;
65
+ case 'invalid':
66
+ // Show schema errors
67
+ console.error(result.errors);
68
+ break;
69
+ case 'incomplete':
70
+ // Add missing field
71
+ console.error(`Missing field: ${result.missing_field}`);
72
+ break;
73
+ }
74
+ } else {
75
+ // Use the validated content
76
+ const data = result.content;
77
+ console.log('Valid state:', data);
78
+ }
79
+ ```
80
+
81
+ ### Helper Functions
82
+
83
+ Use dedicated helper functions for common state files:
84
+
85
+ ```javascript
86
+ import {
87
+ validateState,
88
+ validateCompletion,
89
+ validateDecisions
90
+ } from './lib/validation.js';
91
+
92
+ // Validate state.json (default path: .agentful/state.json)
93
+ const stateResult = validateState();
94
+
95
+ // Validate completion.json with custom path
96
+ const completionResult = validateCompletion('.agentful/completion.json');
97
+
98
+ // Validate decisions.json with additional required fields
99
+ const decisionsResult = validateDecisions(
100
+ '.agentful/decisions.json',
101
+ ['custom_metadata']
102
+ );
103
+ ```
104
+
105
+ ### Batch Validation
106
+
107
+ Validate multiple files at once:
108
+
109
+ ```javascript
110
+ import { validateBatch } from './lib/validation.js';
111
+
112
+ const results = validateBatch([
113
+ { filePath: '.agentful/state.json', schemaName: 'state' },
114
+ { filePath: '.agentful/completion.json', schemaName: 'completion' },
115
+ { filePath: '.agentful/decisions.json', schemaName: 'decisions', requiredFields: ['pending'] }
116
+ ]);
117
+
118
+ // Check all results
119
+ for (const [filePath, result] of Object.entries(results)) {
120
+ if (!result.valid) {
121
+ console.error(`${filePath}: ${result.action}`);
122
+ }
123
+ }
124
+ ```
125
+
126
+ ### Error Messages
127
+
128
+ Get human-readable error messages:
129
+
130
+ ```javascript
131
+ import { getErrorMessage, getSuggestedAction } from './lib/validation.js';
132
+
133
+ const result = validateState();
134
+
135
+ if (!result.valid) {
136
+ console.error(getErrorMessage(result));
137
+ console.log('Suggested action:', getSuggestedAction(result));
138
+ }
139
+ ```
140
+
141
+ ## Available Schemas
142
+
143
+ The library includes schemas for the following state files:
144
+
145
+ ### 1. `state` - state.json
146
+
147
+ Tracks initialization and available agents/skills.
148
+
149
+ **Required fields:**
150
+ - `initialized` (string, ISO 8601 date-time)
151
+ - `version` (string, semantic version)
152
+ - `agents` (array of strings)
153
+ - `skills` (array of strings)
154
+
155
+ **Example:**
156
+ ```json
157
+ {
158
+ "initialized": "2026-01-21T10:00:00.000Z",
159
+ "version": "1.0.0",
160
+ "agents": ["frontend", "backend"],
161
+ "skills": ["react", "nodejs"]
162
+ }
163
+ ```
164
+
165
+ ### 2. `completion` - completion.json
166
+
167
+ Tracks completion progress for agents and skills.
168
+
169
+ **Required fields:**
170
+ - `agents` (object with completion data)
171
+ - `skills` (object with completion data)
172
+ - `lastUpdated` (string, ISO 8601 date-time)
173
+
174
+ **Example:**
175
+ ```json
176
+ {
177
+ "agents": {
178
+ "frontend": { "completed": true, "progress": 100 }
179
+ },
180
+ "skills": {
181
+ "react": { "completed": false, "progress": 75 }
182
+ },
183
+ "lastUpdated": "2026-01-21T10:00:00.000Z"
184
+ }
185
+ ```
186
+
187
+ ### 3. `decisions` - decisions.json
188
+
189
+ Tracks pending decisions and their resolutions.
190
+
191
+ **Required fields:**
192
+ - `decisions` (array of decision objects)
193
+ - `lastUpdated` (string, ISO 8601 date-time)
194
+
195
+ **Decision object required fields:**
196
+ - `id` (string)
197
+ - `question` (string)
198
+ - `status` (enum: "pending", "answered", "cancelled")
199
+
200
+ **Example:**
201
+ ```json
202
+ {
203
+ "decisions": [
204
+ {
205
+ "id": "decision-1",
206
+ "question": "Which database should we use?",
207
+ "status": "pending",
208
+ "created": "2026-01-21T10:00:00.000Z"
209
+ }
210
+ ],
211
+ "lastUpdated": "2026-01-21T10:00:00.000Z"
212
+ }
213
+ ```
214
+
215
+ ### 4. `architecture` - architecture.json
216
+
217
+ Tracks project architecture decisions.
218
+
219
+ **Required fields:**
220
+ - `project_type` (string)
221
+ - `technologies` (object)
222
+ - `patterns` (array of strings)
223
+ - `lastUpdated` (string, ISO 8601 date-time)
224
+
225
+ **Example:**
226
+ ```json
227
+ {
228
+ "project_type": "web-app",
229
+ "technologies": {
230
+ "frontend": "React",
231
+ "backend": "Node.js"
232
+ },
233
+ "patterns": ["MVC", "REST"],
234
+ "lastUpdated": "2026-01-21T10:00:00.000Z"
235
+ }
236
+ ```
237
+
238
+ ### 5. `product` - product.json
239
+
240
+ Tracks product specification and features.
241
+
242
+ **Required fields:**
243
+ - `name` (string)
244
+ - `description` (string)
245
+ - `features` (array of feature objects)
246
+ - `lastUpdated` (string, ISO 8601 date-time)
247
+
248
+ **Feature object required fields:**
249
+ - `id` (string)
250
+ - `name` (string)
251
+
252
+ **Example:**
253
+ ```json
254
+ {
255
+ "name": "Task Manager",
256
+ "description": "A simple task management app",
257
+ "features": [
258
+ {
259
+ "id": "feature-1",
260
+ "name": "User Authentication",
261
+ "priority": "high"
262
+ }
263
+ ],
264
+ "lastUpdated": "2026-01-21T10:00:00.000Z"
265
+ }
266
+ ```
267
+
268
+ ## Replacing Duplicated Code
269
+
270
+ The validation library replaces this duplicated pattern found in 8+ command files:
271
+
272
+ ```javascript
273
+ // OLD - Duplicated in every command
274
+ function validate_state_file(file_path, required_fields) {
275
+ if (!exists(file_path)) {
276
+ return { valid: false, error: `File not found: ${file_path}`, action: "initialize" };
277
+ }
278
+
279
+ let content;
280
+ try {
281
+ content = JSON.parse(Read(file_path));
282
+ } catch (e) {
283
+ return { valid: false, error: `Invalid JSON in ${file_path}`, action: "backup_and_reset" };
284
+ }
285
+
286
+ for (const field of required_fields) {
287
+ if (!(field in content)) {
288
+ return { valid: false, error: `Missing field '${field}'`, action: "add_field", missing_field: field };
289
+ }
290
+ }
291
+
292
+ return { valid: true, content };
293
+ }
294
+
295
+ // NEW - Single centralized function
296
+ import { validateStateFile } from './lib/validation.js';
297
+
298
+ const result = validateStateFile(filePath, schemaName, requiredFields);
299
+ ```
300
+
301
+ ## Benefits
302
+
303
+ 1. **Consistency**: All commands use the same validation logic
304
+ 2. **Maintainability**: Update validation logic in one place
305
+ 3. **Testability**: Comprehensive test coverage (35+ tests)
306
+ 4. **Type Safety**: AJV schema validation catches type errors
307
+ 5. **Standardization**: Consistent error codes and messages
308
+ 6. **Documentation**: Clear API with JSDoc comments
309
+
310
+ ## Testing
311
+
312
+ Run the validation library tests:
313
+
314
+ ```bash
315
+ npm test -- test/unit/validation.test.js
316
+ ```
317
+
318
+ The test suite includes:
319
+ - Missing file validation
320
+ - Corrupted JSON handling
321
+ - Schema validation
322
+ - Required field checks
323
+ - Batch validation
324
+ - Error message generation
325
+ - Edge cases
326
+
327
+ ## Advanced Usage
328
+
329
+ ### Custom Schemas
330
+
331
+ You can access the raw AJV instance and schemas:
332
+
333
+ ```javascript
334
+ import { ajv, schemas } from './lib/validation.js';
335
+
336
+ // Compile a custom schema
337
+ const customSchema = ajv.compile({
338
+ type: 'object',
339
+ required: ['custom_field'],
340
+ properties: {
341
+ custom_field: { type: 'string' }
342
+ }
343
+ });
344
+
345
+ // Use it
346
+ const valid = customSchema(data);
347
+ if (!valid) {
348
+ console.error(customSchema.errors);
349
+ }
350
+ ```
351
+
352
+ ### ValidationActions Constants
353
+
354
+ Use constants instead of strings for action codes:
355
+
356
+ ```javascript
357
+ import { ValidationActions } from './lib/validation.js';
358
+
359
+ if (result.action === ValidationActions.MISSING) {
360
+ // Handle missing file
361
+ } else if (result.action === ValidationActions.CORRUPTED) {
362
+ // Handle corrupted file
363
+ }
364
+ ```
365
+
366
+ ## Migration Guide
367
+
368
+ To migrate existing command validation code to use this library:
369
+
370
+ 1. **Import the validation library**:
371
+ ```javascript
372
+ import { validateStateFile } from './lib/validation.js';
373
+ ```
374
+
375
+ 2. **Replace inline validation with library call**:
376
+ ```javascript
377
+ // Before
378
+ const validation = validate_state_file(".agentful/state.json", ["current_task"]);
379
+
380
+ // After
381
+ const validation = validateStateFile(".agentful/state.json", "state", ["current_task"]);
382
+ ```
383
+
384
+ 3. **Update action names**:
385
+ - `"not_found"` → `"missing"`
386
+ - `"initialize"` → `"missing"`
387
+ - `"backup_and_reset"` → `"corrupted"`
388
+ - `"add_field"` → `"incomplete"`
389
+ - Schema errors → `"invalid"`
390
+
391
+ 4. **Use helper functions for common files**:
392
+ ```javascript
393
+ // Before
394
+ const validation = validate_state_file(".agentful/state.json", []);
395
+
396
+ // After
397
+ const validation = validateState();
398
+ ```
399
+
400
+ ## API Reference
401
+
402
+ ### `validateStateFile(filePath, schemaName, requiredFields)`
403
+
404
+ Universal validation function for any state file.
405
+
406
+ **Parameters:**
407
+ - `filePath` (string): Absolute path to the file
408
+ - `schemaName` (string): Schema to use ('state', 'completion', 'decisions', 'architecture', 'product')
409
+ - `requiredFields` (string[], optional): Additional required fields beyond schema
410
+
411
+ **Returns:**
412
+ - `{ valid: true, content: object }` on success
413
+ - `{ valid: false, action: string, error: string, ... }` on failure
414
+
415
+ ### `validateState(filePath?, additionalFields?)`
416
+
417
+ Validate state.json file. Default path: `.agentful/state.json`
418
+
419
+ ### `validateCompletion(filePath?, additionalFields?)`
420
+
421
+ Validate completion.json file. Default path: `.agentful/completion.json`
422
+
423
+ ### `validateDecisions(filePath?, additionalFields?)`
424
+
425
+ Validate decisions.json file. Default path: `.agentful/decisions.json`
426
+
427
+ ### `validateArchitecture(filePath?, additionalFields?)`
428
+
429
+ Validate architecture.json file. Default path: `.agentful/architecture.json`
430
+
431
+ ### `validateProduct(filePath?, additionalFields?)`
432
+
433
+ Validate product.json file. Default path: `.agentful/product.json`
434
+
435
+ ### `validateBatch(files)`
436
+
437
+ Validate multiple files at once.
438
+
439
+ **Parameters:**
440
+ - `files` (array): Array of `{ filePath, schemaName, requiredFields? }`
441
+
442
+ **Returns:**
443
+ - Object mapping filePath to validation result
444
+
445
+ ### `getErrorMessage(validationResult)`
446
+
447
+ Get human-readable error message for a validation result.
448
+
449
+ ### `getSuggestedAction(validationResult)`
450
+
451
+ Get suggested action to fix a validation error.
452
+
453
+ ## License
454
+
455
+ MIT