@itz4blitz/agentful 1.2.0 → 1.3.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 (59) hide show
  1. package/README.md +28 -1
  2. package/bin/cli.js +11 -1055
  3. package/bin/hooks/block-file-creation.js +271 -0
  4. package/bin/hooks/product-spec-watcher.js +151 -0
  5. package/lib/index.js +0 -11
  6. package/lib/init.js +2 -21
  7. package/lib/parallel-execution.js +235 -0
  8. package/lib/presets.js +26 -4
  9. package/package.json +4 -7
  10. package/template/.claude/agents/architect.md +2 -2
  11. package/template/.claude/agents/backend.md +17 -30
  12. package/template/.claude/agents/frontend.md +17 -39
  13. package/template/.claude/agents/orchestrator.md +63 -4
  14. package/template/.claude/agents/product-analyzer.md +1 -1
  15. package/template/.claude/agents/tester.md +16 -29
  16. package/template/.claude/commands/agentful-generate.md +221 -14
  17. package/template/.claude/commands/agentful-init.md +621 -0
  18. package/template/.claude/commands/agentful-product.md +1 -1
  19. package/template/.claude/commands/agentful-start.md +99 -1
  20. package/template/.claude/product/EXAMPLES.md +2 -2
  21. package/template/.claude/product/index.md +1 -1
  22. package/template/.claude/settings.json +22 -0
  23. package/template/.claude/skills/research/SKILL.md +432 -0
  24. package/template/CLAUDE.md +5 -6
  25. package/template/bin/hooks/architect-drift-detector.js +242 -0
  26. package/template/bin/hooks/product-spec-watcher.js +151 -0
  27. package/version.json +1 -1
  28. package/bin/hooks/post-agent.js +0 -101
  29. package/bin/hooks/post-feature.js +0 -227
  30. package/bin/hooks/pre-agent.js +0 -118
  31. package/bin/hooks/pre-feature.js +0 -138
  32. package/lib/VALIDATION_README.md +0 -455
  33. package/lib/ci/claude-action-integration.js +0 -641
  34. package/lib/ci/index.js +0 -10
  35. package/lib/core/analyzer.js +0 -497
  36. package/lib/core/cli.js +0 -141
  37. package/lib/core/detectors/conventions.js +0 -342
  38. package/lib/core/detectors/framework.js +0 -276
  39. package/lib/core/detectors/index.js +0 -15
  40. package/lib/core/detectors/language.js +0 -199
  41. package/lib/core/detectors/patterns.js +0 -356
  42. package/lib/core/generator.js +0 -626
  43. package/lib/core/index.js +0 -9
  44. package/lib/core/output-parser.js +0 -458
  45. package/lib/core/storage.js +0 -515
  46. package/lib/core/templates.js +0 -556
  47. package/lib/pipeline/cli.js +0 -423
  48. package/lib/pipeline/engine.js +0 -928
  49. package/lib/pipeline/executor.js +0 -440
  50. package/lib/pipeline/index.js +0 -33
  51. package/lib/pipeline/integrations.js +0 -559
  52. package/lib/pipeline/schemas.js +0 -288
  53. package/lib/remote/client.js +0 -361
  54. package/lib/server/auth.js +0 -270
  55. package/lib/server/client-example.js +0 -190
  56. package/lib/server/executor.js +0 -477
  57. package/lib/server/index.js +0 -494
  58. package/lib/update-helpers.js +0 -505
  59. package/lib/validation.js +0 -460
package/lib/validation.js DELETED
@@ -1,460 +0,0 @@
1
- import fs from 'fs';
2
- import Ajv from 'ajv';
3
- import addFormats from 'ajv-formats';
4
-
5
- /**
6
- * Centralized Validation Library
7
- *
8
- * Provides unified validation functions for state files with:
9
- * - File existence checks
10
- * - JSON parsing validation
11
- * - Schema validation using AJV
12
- * - Required field validation
13
- *
14
- * Standardized action codes:
15
- * - "missing": File does not exist
16
- * - "corrupted": File exists but is not valid JSON
17
- * - "invalid": JSON is valid but doesn't match schema
18
- * - "incomplete": Schema is valid but required fields are missing
19
- */
20
-
21
- // Initialize AJV with formats support
22
- const ajv = new Ajv({ allErrors: true });
23
- addFormats(ajv);
24
-
25
- /**
26
- * JSON Schemas for state files
27
- */
28
- export const schemas = {
29
- state: {
30
- type: 'object',
31
- required: ['initialized', 'version', 'agents', 'skills'],
32
- properties: {
33
- initialized: {
34
- type: 'string',
35
- format: 'date-time'
36
- },
37
- version: {
38
- type: 'string',
39
- pattern: '^\\d+\\.\\d+\\.\\d+$'
40
- },
41
- agents: {
42
- type: 'array',
43
- items: {
44
- type: 'string'
45
- }
46
- },
47
- skills: {
48
- type: 'array',
49
- items: {
50
- type: 'string'
51
- }
52
- }
53
- },
54
- additionalProperties: true
55
- },
56
-
57
- completion: {
58
- type: 'object',
59
- required: ['agents', 'skills', 'lastUpdated'],
60
- properties: {
61
- agents: {
62
- type: 'object',
63
- additionalProperties: {
64
- type: 'object',
65
- properties: {
66
- completed: { type: 'boolean' },
67
- progress: { type: 'number', minimum: 0, maximum: 100 }
68
- }
69
- }
70
- },
71
- skills: {
72
- type: 'object',
73
- additionalProperties: {
74
- type: 'object',
75
- properties: {
76
- completed: { type: 'boolean' },
77
- progress: { type: 'number', minimum: 0, maximum: 100 }
78
- }
79
- }
80
- },
81
- lastUpdated: {
82
- type: 'string',
83
- format: 'date-time'
84
- }
85
- },
86
- additionalProperties: true
87
- },
88
-
89
- decisions: {
90
- type: 'object',
91
- required: ['decisions', 'lastUpdated'],
92
- properties: {
93
- decisions: {
94
- type: 'array',
95
- items: {
96
- type: 'object',
97
- required: ['id', 'question', 'status'],
98
- properties: {
99
- id: { type: 'string' },
100
- question: { type: 'string' },
101
- status: {
102
- type: 'string',
103
- enum: ['pending', 'answered', 'cancelled']
104
- },
105
- answer: { type: 'string' },
106
- context: { type: 'string' },
107
- created: { type: 'string', format: 'date-time' },
108
- updated: { type: 'string', format: 'date-time' }
109
- }
110
- }
111
- },
112
- lastUpdated: {
113
- type: 'string',
114
- format: 'date-time'
115
- }
116
- },
117
- additionalProperties: false
118
- },
119
-
120
- architecture: {
121
- type: 'object',
122
- required: ['version', 'analyzedAt', 'projectRoot', 'fileCount', 'confidence', 'languages', 'frameworks', 'patterns', 'conventions', 'recommendations'],
123
- properties: {
124
- version: { type: 'string' },
125
- analyzedAt: {
126
- type: 'string',
127
- format: 'date-time'
128
- },
129
- duration: { type: 'number' },
130
- projectRoot: { type: 'string' },
131
- fileCount: { type: 'number', minimum: 0 },
132
- isNewProject: { type: 'boolean' },
133
- confidence: { type: 'number', minimum: 0, maximum: 100 },
134
- languages: {
135
- type: 'array',
136
- items: {
137
- type: 'object',
138
- required: ['name', 'confidence', 'files'],
139
- properties: {
140
- name: { type: 'string' },
141
- confidence: { type: 'number' },
142
- files: { type: 'number' },
143
- percentage: { type: 'number' },
144
- extensions: { type: 'array', items: { type: 'string' } }
145
- }
146
- }
147
- },
148
- primaryLanguage: { type: ['string', 'null'] },
149
- frameworks: {
150
- type: 'array',
151
- items: {
152
- type: 'object',
153
- required: ['name', 'confidence'],
154
- properties: {
155
- name: { type: 'string' },
156
- version: { type: 'string' },
157
- type: { type: 'string' },
158
- category: { type: 'string' },
159
- confidence: { type: 'number' },
160
- source: { type: 'string' }
161
- }
162
- }
163
- },
164
- patterns: {
165
- type: 'object',
166
- properties: {
167
- components: { type: 'object' },
168
- api: { type: 'object' },
169
- database: { type: 'object' },
170
- tests: { type: 'object' },
171
- auth: { type: 'object' }
172
- }
173
- },
174
- conventions: {
175
- type: 'object'
176
- },
177
- recommendations: {
178
- type: 'array',
179
- items: {
180
- type: 'object',
181
- required: ['type', 'priority', 'message', 'action'],
182
- properties: {
183
- type: { type: 'string' },
184
- priority: { type: 'string' },
185
- message: { type: 'string' },
186
- action: { type: 'string' }
187
- }
188
- }
189
- }
190
- },
191
- additionalProperties: true
192
- },
193
-
194
- product: {
195
- type: 'object',
196
- required: ['name', 'description', 'features', 'lastUpdated'],
197
- properties: {
198
- name: { type: 'string' },
199
- description: { type: 'string' },
200
- features: {
201
- type: 'array',
202
- items: {
203
- type: 'object',
204
- required: ['id', 'name'],
205
- properties: {
206
- id: { type: 'string' },
207
- name: { type: 'string' },
208
- description: { type: 'string' },
209
- priority: {
210
- type: 'string',
211
- enum: ['high', 'medium', 'low']
212
- }
213
- }
214
- }
215
- },
216
- lastUpdated: {
217
- type: 'string',
218
- format: 'date-time'
219
- }
220
- },
221
- additionalProperties: true
222
- }
223
- };
224
-
225
- // Compile all schemas
226
- const compiledSchemas = {
227
- state: ajv.compile(schemas.state),
228
- completion: ajv.compile(schemas.completion),
229
- decisions: ajv.compile(schemas.decisions),
230
- architecture: ajv.compile(schemas.architecture),
231
- product: ajv.compile(schemas.product)
232
- };
233
-
234
- /**
235
- * Unified validation function for state files
236
- *
237
- * @param {string} filePath - Absolute path to the file to validate
238
- * @param {string} schemaName - Name of schema to use ('state', 'completion', 'decisions', 'architecture', 'product')
239
- * @param {string[]} requiredFields - Additional required fields to check beyond schema
240
- * @returns {Object} Validation result with standardized structure
241
- *
242
- * Return format for invalid:
243
- * { valid: false, action: "missing" | "corrupted" | "invalid" | "incomplete", errors?: array, missing_field?: string }
244
- *
245
- * Return format for valid:
246
- * { valid: true, content: object }
247
- */
248
- export function validateStateFile(filePath, schemaName, requiredFields = []) {
249
- // 1. Check file exists
250
- if (!fs.existsSync(filePath)) {
251
- return {
252
- valid: false,
253
- action: 'missing',
254
- error: `File not found: ${filePath}`
255
- };
256
- }
257
-
258
- // 2. Parse JSON
259
- let content;
260
- try {
261
- const fileContent = fs.readFileSync(filePath, 'utf-8');
262
- content = JSON.parse(fileContent);
263
- } catch (error) {
264
- return {
265
- valid: false,
266
- action: 'corrupted',
267
- error: `Invalid JSON in ${filePath}: ${error.message}`
268
- };
269
- }
270
-
271
- // 3. Validate against schema using AJV
272
- const validator = compiledSchemas[schemaName];
273
- if (!validator) {
274
- throw new Error(`Unknown schema name: ${schemaName}. Valid schemas: ${Object.keys(compiledSchemas).join(', ')}`);
275
- }
276
-
277
- const schemaValid = validator(content);
278
- if (!schemaValid) {
279
- return {
280
- valid: false,
281
- action: 'invalid',
282
- errors: validator.errors,
283
- error: `Schema validation failed for ${filePath}`
284
- };
285
- }
286
-
287
- // 4. Check additional required fields
288
- for (const field of requiredFields) {
289
- if (!(field in content)) {
290
- return {
291
- valid: false,
292
- action: 'incomplete',
293
- missing_field: field,
294
- error: `Missing required field '${field}' in ${filePath}`
295
- };
296
- }
297
- }
298
-
299
- // 5. Success
300
- return {
301
- valid: true,
302
- content
303
- };
304
- }
305
-
306
- /**
307
- * Validate state.json file
308
- *
309
- * @param {string} filePath - Path to state.json (defaults to .agentful/state.json)
310
- * @param {string[]} additionalFields - Additional required fields beyond schema
311
- * @returns {Object} Validation result
312
- */
313
- export function validateState(filePath = '.agentful/state.json', additionalFields = []) {
314
- return validateStateFile(filePath, 'state', additionalFields);
315
- }
316
-
317
- /**
318
- * Validate completion.json file
319
- *
320
- * @param {string} filePath - Path to completion.json (defaults to .agentful/completion.json)
321
- * @param {string[]} additionalFields - Additional required fields beyond schema
322
- * @returns {Object} Validation result
323
- */
324
- export function validateCompletion(filePath = '.agentful/completion.json', additionalFields = []) {
325
- return validateStateFile(filePath, 'completion', additionalFields);
326
- }
327
-
328
- /**
329
- * Validate decisions.json file
330
- *
331
- * @param {string} filePath - Path to decisions.json (defaults to .agentful/decisions.json)
332
- * @param {string[]} additionalFields - Additional required fields beyond schema
333
- * @returns {Object} Validation result
334
- */
335
- export function validateDecisions(filePath = '.agentful/decisions.json', additionalFields = []) {
336
- return validateStateFile(filePath, 'decisions', additionalFields);
337
- }
338
-
339
- /**
340
- * Validate architecture.json file
341
- *
342
- * @param {string} filePath - Path to architecture.json (defaults to .agentful/architecture.json)
343
- * @param {string[]} additionalFields - Additional required fields beyond schema
344
- * @returns {Object} Validation result
345
- */
346
- export function validateArchitecture(filePath = '.agentful/architecture.json', additionalFields = []) {
347
- return validateStateFile(filePath, 'architecture', additionalFields);
348
- }
349
-
350
- /**
351
- * Validate product.json file
352
- *
353
- * @param {string} filePath - Path to product.json (defaults to .agentful/product.json)
354
- * @param {string[]} additionalFields - Additional required fields beyond schema
355
- * @returns {Object} Validation result
356
- */
357
- export function validateProduct(filePath = '.agentful/product.json', additionalFields = []) {
358
- return validateStateFile(filePath, 'product', additionalFields);
359
- }
360
-
361
- /**
362
- * Batch validate multiple state files
363
- *
364
- * @param {Object[]} files - Array of {filePath, schemaName, requiredFields?}
365
- * @returns {Object} Map of filePath to validation result
366
- *
367
- * Example:
368
- * const results = validateBatch([
369
- * { filePath: '.agentful/state.json', schemaName: 'state' },
370
- * { filePath: '.agentful/completion.json', schemaName: 'completion', requiredFields: ['gates'] }
371
- * ]);
372
- */
373
- export function validateBatch(files) {
374
- const results = {};
375
-
376
- for (const { filePath, schemaName, requiredFields = [] } of files) {
377
- results[filePath] = validateStateFile(filePath, schemaName, requiredFields);
378
- }
379
-
380
- return results;
381
- }
382
-
383
- /**
384
- * Get human-readable error message for validation result
385
- *
386
- * @param {Object} validationResult - Result from validateStateFile
387
- * @returns {string} Human-readable error message
388
- */
389
- export function getErrorMessage(validationResult) {
390
- if (validationResult.valid) {
391
- return 'Validation passed';
392
- }
393
-
394
- switch (validationResult.action) {
395
- case 'missing':
396
- return `File not found. Initialize it first.`;
397
-
398
- case 'corrupted':
399
- return `File is corrupted (invalid JSON). Backup and reset recommended.`;
400
-
401
- case 'invalid':
402
- if (validationResult.errors && validationResult.errors.length > 0) {
403
- const errorDetails = validationResult.errors
404
- .map(err => ` - ${err.instancePath || 'root'}: ${err.message}`)
405
- .join('\n');
406
- return `Schema validation failed:\n${errorDetails}`;
407
- }
408
- return `Schema validation failed.`;
409
-
410
- case 'incomplete':
411
- return `Missing required field: '${validationResult.missing_field}'`;
412
-
413
- default:
414
- return validationResult.error || 'Unknown validation error';
415
- }
416
- }
417
-
418
- /**
419
- * Suggested action for validation result
420
- *
421
- * @param {Object} validationResult - Result from validateStateFile
422
- * @returns {string} Suggested action to fix the issue
423
- */
424
- export function getSuggestedAction(validationResult) {
425
- if (validationResult.valid) {
426
- return 'No action needed';
427
- }
428
-
429
- switch (validationResult.action) {
430
- case 'missing':
431
- return 'Run initialization command to create the file';
432
-
433
- case 'corrupted':
434
- return 'Backup the file and create a new one with valid JSON';
435
-
436
- case 'invalid':
437
- return 'Fix schema validation errors in the file';
438
-
439
- case 'incomplete':
440
- return `Add the missing field: '${validationResult.missing_field}'`;
441
-
442
- default:
443
- return 'Check the file and fix any issues';
444
- }
445
- }
446
-
447
- /**
448
- * Export AJV instance for custom schemas
449
- */
450
- export { ajv };
451
-
452
- /**
453
- * Export action constants for easy reference
454
- */
455
- export const ValidationActions = {
456
- MISSING: 'missing',
457
- CORRUPTED: 'corrupted',
458
- INVALID: 'invalid',
459
- INCOMPLETE: 'incomplete'
460
- };