@paths.design/caws-cli 3.5.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.
- package/dist/budget-derivation.d.ts +41 -2
- package/dist/budget-derivation.d.ts.map +1 -1
- package/dist/budget-derivation.js +417 -30
- package/dist/commands/validate.d.ts +1 -0
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +105 -28
- package/dist/index.js +2 -0
- package/dist/policy/PolicyManager.d.ts +104 -0
- package/dist/policy/PolicyManager.d.ts.map +1 -0
- package/dist/policy/PolicyManager.js +399 -0
- package/dist/scaffold/cursor-hooks.d.ts.map +1 -1
- package/dist/scaffold/cursor-hooks.js +15 -0
- package/dist/spec/SpecFileManager.d.ts +146 -0
- package/dist/spec/SpecFileManager.d.ts.map +1 -0
- package/dist/spec/SpecFileManager.js +419 -0
- package/dist/validation/spec-validation.d.ts +14 -0
- package/dist/validation/spec-validation.d.ts.map +1 -1
- package/dist/validation/spec-validation.js +225 -13
- package/package.json +1 -1
- package/templates/.cursor/rules/01-claims-verification.mdc +144 -0
- package/templates/.cursor/rules/02-testing-standards.mdc +315 -0
- package/templates/.cursor/rules/03-infrastructure-standards.mdc +251 -0
- package/templates/.cursor/rules/04-documentation-integrity.mdc +291 -0
- package/templates/.cursor/rules/05-production-readiness-checklist.mdc +214 -0
- package/templates/.cursor/rules/README.md +64 -0
|
@@ -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({
|
|
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
|
-
|
|
304
|
-
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
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
|
@@ -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.**
|