@paths.design/caws-cli 3.4.0 → 4.0.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.
@@ -1 +1 @@
1
- {"version":3,"file":"spec-validation.d.ts","sourceRoot":"","sources":["../../src/validation/spec-validation.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,mEA8HC;AAED;;;;;GAKG;AACH,kFAyLC;AAED;;;;;GAKG;AACH,0CAJW,MAAM,eAEJ,MAAM,CAkBlB;AAED;;;;;GAKG;AACH,uCAJW,MAAM,eAEJ,OAAO,CAKnB"}
1
+ {"version":3,"file":"spec-validation.d.ts","sourceRoot":"","sources":["../../src/validation/spec-validation.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,mEA8HC;AAED;;;;;GAKG;AACH,kFAyWC;AAoCD;;;;;GAKG;AACH,0CAJW,MAAM,eAEJ,MAAM,CAkBlB;AAED;;;;;GAKG;AACH,uCAJW,MAAM,eAEJ,OAAO,CAKnB;AAnED;;;;;;GAMG;AACH,0EAFa,MAAM,CAclB;AAED;;;;GAIG;AACH,0CAHW,MAAM,GACJ,MAAM,CAQlB"}
@@ -190,8 +190,9 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
190
190
  });
191
191
  }
192
192
 
193
- // Validate risk tier
193
+ // Validate risk tier with enhanced auto-fix
194
194
  if (spec.risk_tier !== undefined && (spec.risk_tier < 1 || spec.risk_tier > 3)) {
195
+ const fixedValue = Math.max(1, Math.min(3, spec.risk_tier || 2));
195
196
  errors.push({
196
197
  instancePath: '/risk_tier',
197
198
  message: 'Risk tier must be 1, 2, or 3',
@@ -199,7 +200,99 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
199
200
  'Tier 1: Critical (auth, billing), Tier 2: Standard (features), Tier 3: Low risk (UI)',
200
201
  canAutoFix: true,
201
202
  });
202
- fixes.push({ field: 'risk_tier', value: Math.max(1, Math.min(3, spec.risk_tier || 2)) });
203
+ fixes.push({
204
+ field: 'risk_tier',
205
+ value: fixedValue,
206
+ description: `Clamping risk_tier from ${spec.risk_tier} to valid range [1-3]: ${fixedValue}`,
207
+ reason: 'Risk tier out of bounds',
208
+ });
209
+ }
210
+
211
+ // Auto-fix empty arrays with sensible defaults
212
+ if (!spec.invariants || spec.invariants.length === 0) {
213
+ if (autoFix) {
214
+ fixes.push({
215
+ field: 'invariants',
216
+ value: ['System must remain operational during changes'],
217
+ description: 'Adding default invariant for empty invariants array',
218
+ reason: 'Invariants array was empty',
219
+ });
220
+ }
221
+ }
222
+
223
+ if (!spec.acceptance || spec.acceptance.length === 0) {
224
+ if (autoFix) {
225
+ fixes.push({
226
+ field: 'acceptance',
227
+ value: [
228
+ {
229
+ id: 'A1',
230
+ given: 'the system is in a valid state',
231
+ when: 'the change is applied',
232
+ then: 'the system remains functional',
233
+ },
234
+ ],
235
+ description: 'Adding placeholder acceptance criteria',
236
+ reason: 'Acceptance criteria array was empty',
237
+ });
238
+ }
239
+ }
240
+
241
+ // Auto-fix missing scope.out
242
+ if (spec.scope && !spec.scope.out) {
243
+ fixes.push({
244
+ field: 'scope.out',
245
+ value: ['node_modules/', 'dist/', '.git/'],
246
+ description: 'Adding default exclusions to scope.out',
247
+ reason: 'scope.out was missing',
248
+ });
249
+ }
250
+
251
+ // Auto-fix missing mode
252
+ if (!spec.mode) {
253
+ fixes.push({
254
+ field: 'mode',
255
+ value: 'feature',
256
+ description: 'Setting default mode to "feature"',
257
+ reason: 'mode field was missing',
258
+ });
259
+ }
260
+
261
+ // Auto-fix missing blast_radius
262
+ if (!spec.blast_radius) {
263
+ fixes.push({
264
+ field: 'blast_radius',
265
+ value: {
266
+ modules: [],
267
+ data_migration: false,
268
+ },
269
+ description: 'Adding empty blast_radius structure',
270
+ reason: 'blast_radius was missing',
271
+ });
272
+ }
273
+
274
+ // Auto-fix missing non_functional
275
+ if (!spec.non_functional) {
276
+ fixes.push({
277
+ field: 'non_functional',
278
+ value: {
279
+ a11y: [],
280
+ perf: {},
281
+ security: [],
282
+ },
283
+ description: 'Adding empty non_functional requirements structure',
284
+ reason: 'non_functional was missing',
285
+ });
286
+ }
287
+
288
+ // Auto-fix missing contracts
289
+ if (!spec.contracts) {
290
+ fixes.push({
291
+ field: 'contracts',
292
+ value: [],
293
+ description: 'Adding empty contracts array',
294
+ reason: 'contracts field was missing',
295
+ });
203
296
  }
204
297
 
205
298
  // Validate scope.in is not empty
@@ -241,6 +334,40 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
241
334
  }
242
335
  }
243
336
 
337
+ // Tier 1 specific requirements (critical changes)
338
+ if (spec.risk_tier === 1) {
339
+ if (!spec.observability) {
340
+ errors.push({
341
+ instancePath: '/observability',
342
+ message: 'Observability required for Tier 1 changes',
343
+ suggestion: 'Define logging, metrics, and tracing strategy',
344
+ canAutoFix: false,
345
+ });
346
+ }
347
+
348
+ if (!spec.rollback || spec.rollback.length === 0) {
349
+ errors.push({
350
+ instancePath: '/rollback',
351
+ message: 'Rollback procedures required for Tier 1 changes',
352
+ suggestion: 'Document rollback steps and data migration reversal',
353
+ canAutoFix: false,
354
+ });
355
+ }
356
+
357
+ if (
358
+ !spec.non_functional ||
359
+ !spec.non_functional.security ||
360
+ spec.non_functional.security.length === 0
361
+ ) {
362
+ errors.push({
363
+ instancePath: '/non_functional/security',
364
+ message: 'Security requirements required for Tier 1 changes',
365
+ suggestion: 'Define authentication, authorization, and data protection requirements',
366
+ canAutoFix: false,
367
+ });
368
+ }
369
+ }
370
+
244
371
  // Validate waiver_ids format if present
245
372
  if (spec.waiver_ids) {
246
373
  if (!Array.isArray(spec.waiver_ids)) {
@@ -256,7 +383,7 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
256
383
  errors.push({
257
384
  instancePath: '/waiver_ids',
258
385
  message: `Invalid waiver ID format: ${waiverId}`,
259
- suggestion: 'Use format: WV-XXXX (e.g., WV-0001)',
386
+ suggestion: 'Use format: WV-XXXX where XXXX is exactly 4 digits (e.g., WV-0001)',
260
387
  canAutoFix: false,
261
388
  });
262
389
  }
@@ -264,6 +391,17 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
264
391
  }
265
392
  }
266
393
 
394
+ // Warn if change_budget is present (deprecated/informational only)
395
+ if (spec.change_budget) {
396
+ warnings.push({
397
+ instancePath: '/change_budget',
398
+ message:
399
+ 'change_budget field in working spec is informational only and not used for validation',
400
+ suggestion:
401
+ 'Budget is derived from policy.yaml risk_tier + waivers. This field is auto-calculated.',
402
+ });
403
+ }
404
+
267
405
  // Derive and check budget if requested
268
406
  let budgetCheck = null;
269
407
  if (checkBudget && projectRoot) {
@@ -288,6 +426,16 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
288
426
  canAutoFix: false,
289
427
  });
290
428
  }
429
+
430
+ // Suggest adding waiver_ids if budget exceeded and none referenced
431
+ if (!spec.waiver_ids || spec.waiver_ids.length === 0) {
432
+ warnings.push({
433
+ instancePath: '/waiver_ids',
434
+ message: 'Budget exceeded but no waivers referenced',
435
+ suggestion:
436
+ 'Add waiver_ids: ["WV-0001"] to working spec, then create waiver file with: caws waiver create',
437
+ });
438
+ }
291
439
  }
292
440
  } catch (error) {
293
441
  warnings.push({
@@ -298,27 +446,55 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
298
446
  }
299
447
  }
300
448
 
301
- // Apply auto-fixes if requested
449
+ // Apply auto-fixes if requested and not in dry-run mode
450
+ const { dryRun = false } = options;
451
+ let appliedFixes = [];
452
+
302
453
  if (autoFix && fixes.length > 0) {
303
- console.log('🔧 Applying auto-fixes...');
304
- for (const fix of fixes) {
305
- const pathParts = fix.field.split('.');
306
- let current = spec;
307
- for (let i = 0; i < pathParts.length - 1; i++) {
308
- if (!current[pathParts[i]]) current[pathParts[i]] = {};
309
- current = current[pathParts[i]];
454
+ if (dryRun) {
455
+ console.log('🔍 Auto-fix preview (dry-run mode):');
456
+ for (const fix of fixes) {
457
+ console.log(` [WOULD FIX] ${fix.field}`);
458
+ console.log(` Description: ${fix.description}`);
459
+ console.log(` Reason: ${fix.reason}`);
460
+ console.log(
461
+ ` Value: ${typeof fix.value === 'object' ? JSON.stringify(fix.value) : fix.value}`
462
+ );
463
+ console.log('');
464
+ }
465
+ } else {
466
+ console.log('🔧 Applying auto-fixes...');
467
+ for (const fix of fixes) {
468
+ try {
469
+ const pathParts = fix.field.split('.');
470
+ let current = spec;
471
+ for (let i = 0; i < pathParts.length - 1; i++) {
472
+ if (!current[pathParts[i]]) current[pathParts[i]] = {};
473
+ current = current[pathParts[i]];
474
+ }
475
+ current[pathParts[pathParts.length - 1]] = fix.value;
476
+ appliedFixes.push(fix);
477
+ console.log(` ✅ Fixed ${fix.field}`);
478
+ console.log(` ${fix.description}`);
479
+ } catch (error) {
480
+ console.warn(` ⚠️ Failed to apply fix for ${fix.field}: ${error.message}`);
481
+ }
310
482
  }
311
- current[pathParts[pathParts.length - 1]] = fix.value;
312
- console.log(` Fixed ${fix.field}: ${fix.value}`);
313
483
  }
314
484
  }
315
485
 
486
+ // Calculate compliance score (0-1 scale)
487
+ const complianceScore = calculateComplianceScore(errors, warnings);
488
+
316
489
  return {
317
490
  valid: errors.length === 0,
318
491
  errors,
319
492
  warnings,
320
493
  fixes: fixes.length > 0 ? fixes : undefined,
494
+ appliedFixes: appliedFixes.length > 0 ? appliedFixes : undefined,
495
+ dryRun,
321
496
  budget_check: budgetCheck,
497
+ complianceScore,
322
498
  };
323
499
  } catch (error) {
324
500
  return {
@@ -333,6 +509,40 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
333
509
  }
334
510
  }
335
511
 
512
+ /**
513
+ * Calculate compliance score based on errors and warnings
514
+ * Score ranges from 0 (many issues) to 1 (perfect)
515
+ * @param {Array} errors - Validation errors
516
+ * @param {Array} warnings - Validation warnings
517
+ * @returns {number} Compliance score (0-1)
518
+ */
519
+ function calculateComplianceScore(errors, warnings) {
520
+ // Start at perfect score
521
+ let score = 1.0;
522
+
523
+ // Each error reduces score by 0.2
524
+ score -= errors.length * 0.2;
525
+
526
+ // Each warning reduces score by 0.1
527
+ score -= warnings.length * 0.1;
528
+
529
+ // Floor at 0
530
+ return Math.max(0, score);
531
+ }
532
+
533
+ /**
534
+ * Get compliance grade from score
535
+ * @param {number} score - Compliance score (0-1)
536
+ * @returns {string} Grade (A, B, C, D, F)
537
+ */
538
+ function getComplianceGrade(score) {
539
+ if (score >= 0.9) return 'A';
540
+ if (score >= 0.8) return 'B';
541
+ if (score >= 0.7) return 'C';
542
+ if (score >= 0.6) return 'D';
543
+ return 'F';
544
+ }
545
+
336
546
  /**
337
547
  * Get suggestion for a missing field
338
548
  * @param {string} field - Field name
@@ -373,4 +583,6 @@ module.exports = {
373
583
  validateWorkingSpecWithSuggestions,
374
584
  getFieldSuggestion,
375
585
  canAutoFixField,
586
+ calculateComplianceScore,
587
+ getComplianceGrade,
376
588
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paths.design/caws-cli",
3
- "version": "3.4.0",
3
+ "version": "4.0.0",
4
4
  "description": "CAWS CLI - Coding Agent Workflow System command line tools",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -0,0 +1,144 @@
1
+ ---
2
+ description: Production readiness claims require rigorous verification - agents must prove, not assert
3
+ globs:
4
+ alwaysApply: true
5
+ ---
6
+
7
+ # Production Readiness Verification & Accountability
8
+
9
+ ## Core Principle
10
+
11
+ **Never claim "production-ready", "production-grade", or similar unless ALL criteria below are met.** If any criterion is not satisfied, use these statuses instead:
12
+
13
+ - ❌ **"In development"** - Active development with known issues
14
+ - ❌ **"Partially implemented"** - Some features working, major gaps remain
15
+ - ❌ **"Proof of concept"** - Core concept demonstrated, not production-viable
16
+
17
+ ## Mandatory Production Readiness Criteria
18
+
19
+ Before claiming production readiness, **agents must verify ALL of these**:
20
+
21
+ ### ✅ Code Quality Gates
22
+
23
+ - **Zero linting errors or warnings** (ESLint, TypeScript, etc.)
24
+ - **Zero TypeScript compilation errors**
25
+ - **All TODOs, PLACEHOLDERs, and MOCK DATA cleared from production code**
26
+ - **No dead code or unused imports**
27
+ - **Consistent code formatting** (Prettier/ESLint rules)
28
+
29
+ ### ✅ Testing & Quality Assurance
30
+
31
+ - **Complete unit test coverage** (80%+ line coverage, 90%+ branch coverage)
32
+ - **All unit tests passing** (no skipped tests in production code)
33
+ - **Integration tests passing** (database, external APIs, end-to-end flows)
34
+ - **Mutation testing** (70%+ score for critical components)
35
+ - **Performance tests** meeting documented SLAs
36
+
37
+ ### ✅ Infrastructure & Persistence
38
+
39
+ - **Actual database persistence implemented** (not just in-memory mocks)
40
+ - **Database integration tests passing** with real database
41
+ - **Migration scripts tested and working**
42
+ - **Data consistency and rollback capabilities**
43
+ - **Connection pooling and error handling**
44
+
45
+ ### ✅ Security & Reliability
46
+
47
+ - **Security controls tested and validated** (authentication, authorization, input validation)
48
+ - **No security scan violations** (SAST, dependency scanning)
49
+ - **Circuit breakers and retry logic** for external dependencies
50
+ - **Graceful degradation** under failure conditions
51
+ - **Logging and monitoring** implemented
52
+
53
+ ### ✅ Documentation & Reality Alignment
54
+
55
+ - **Documentation matches implementation reality** (no claims of features that don't exist)
56
+ - **API documentation** current and accurate
57
+ - **Deployment and operational docs** exist
58
+ - **Architecture diagrams** reflect actual implementation
59
+ - **README and changelogs** accurate
60
+
61
+ ## Accountability Measures for Coding Agents
62
+
63
+ ### Pre-Claim Verification Process
64
+
65
+ 1. **Run full test suite** - All tests pass locally
66
+ 2. **Run linters** - Zero errors/warnings
67
+ 3. **Run security scans** - No vulnerabilities
68
+ 4. **Check coverage reports** - Meet or exceed thresholds
69
+ 5. **Verify database operations** - Real persistence working
70
+ 6. **Test deployment pipeline** - CI/CD passes
71
+ 7. **Document verification evidence** - Include in PR/commit
72
+
73
+ ### Prohibited Claims
74
+
75
+ **NEVER claim these without verification:**
76
+
77
+ - "Production-ready" without all criteria met
78
+ - "Enterprise-grade" without enterprise testing
79
+ - "Battle-tested" without comprehensive testing
80
+ - "Stable" with failing tests or linting errors
81
+ - "Complete" with TODOs, placeholders, or mock data
82
+ - "Secure" without security testing and scans
83
+
84
+ ### Evidence Requirements
85
+
86
+ For any production readiness claim, provide:
87
+
88
+ - Test execution results (screenshots/logs)
89
+ - Coverage reports
90
+ - Lint results
91
+ - Security scan reports
92
+ - Performance benchmarks
93
+ - Database connectivity proofs
94
+ - Deployment verification
95
+
96
+ ## Common Failure Patterns to Avoid
97
+
98
+ ### Implementation Gaps
99
+
100
+ - Empty directories claiming "full implementation"
101
+ - Mock functions in production code
102
+ - TODO comments in core business logic
103
+ - Placeholder implementations
104
+ - Missing error handling
105
+
106
+ ### Testing Shortcuts
107
+
108
+ - Skipping integration tests
109
+ - Mocking database operations
110
+ - Ignoring linting errors
111
+ - Not testing error conditions
112
+ - Fake test data instead of real fixtures
113
+
114
+ ### Documentation Lies
115
+
116
+ - Claiming 100% coverage with 75% actual
117
+ - Features documented but not implemented
118
+ - APIs documented with wrong signatures
119
+ - Missing breaking changes in changelogs
120
+
121
+ ### Infrastructure Pretending
122
+
123
+ - In-memory storage claiming "persistence"
124
+ - No-op security claiming "secure"
125
+ - Console.log claiming "monitoring"
126
+ - No circuit breakers claiming "resilient"
127
+
128
+ ## Verification Checklist
129
+
130
+ Use this before any production claim:
131
+
132
+ - [ ] `npm test` passes all tests
133
+ - [ ] `npm run lint` shows zero errors
134
+ - [ ] `npm run typecheck` passes
135
+ - [ ] Database tests use real PostgreSQL/MySQL/etc.
136
+ - [ ] Security tests validate actual controls
137
+ - [ ] Performance tests meet SLAs
138
+ - [ ] No TODO/PLACEHOLDER/MOCK_DATA in src/
139
+ - [ ] Coverage reports show adequate thresholds
140
+ - [ ] CI/CD pipeline passes
141
+ - [ ] Deployment docs exist and are tested
142
+ - [ ] Documentation matches code reality
143
+
144
+ **If ANY box is unchecked, do not claim production readiness.**