@paths.design/caws-cli 4.0.0 → 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/dist/commands/archive.d.ts +50 -0
- package/dist/commands/archive.d.ts.map +1 -0
- package/dist/commands/archive.js +353 -0
- package/dist/commands/iterate.d.ts.map +1 -1
- package/dist/commands/iterate.js +12 -13
- package/dist/commands/mode.d.ts +24 -0
- package/dist/commands/mode.d.ts.map +1 -0
- package/dist/commands/mode.js +259 -0
- package/dist/commands/plan.d.ts +49 -0
- package/dist/commands/plan.d.ts.map +1 -0
- package/dist/commands/plan.js +448 -0
- package/dist/commands/quality-gates.d.ts +52 -0
- package/dist/commands/quality-gates.d.ts.map +1 -0
- package/dist/commands/quality-gates.js +490 -0
- package/dist/commands/specs.d.ts +71 -0
- package/dist/commands/specs.d.ts.map +1 -0
- package/dist/commands/specs.js +735 -0
- package/dist/commands/status.d.ts +4 -3
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +552 -22
- package/dist/commands/tutorial.d.ts +55 -0
- package/dist/commands/tutorial.d.ts.map +1 -0
- package/dist/commands/tutorial.js +481 -0
- package/dist/commands/validate.d.ts +10 -3
- package/dist/commands/validate.d.ts.map +1 -1
- package/dist/commands/validate.js +137 -54
- package/dist/config/modes.d.ts +225 -0
- package/dist/config/modes.d.ts.map +1 -0
- package/dist/config/modes.js +321 -0
- package/dist/constants/spec-types.d.ts +41 -0
- package/dist/constants/spec-types.d.ts.map +1 -0
- package/dist/constants/spec-types.js +42 -0
- package/dist/index-new.d.ts +5 -0
- package/dist/index-new.d.ts.map +1 -0
- package/dist/index-new.js +317 -0
- package/dist/index.js +225 -10
- package/dist/index.js.backup +4711 -0
- package/dist/scaffold/git-hooks.d.ts.map +1 -1
- package/dist/scaffold/git-hooks.js +32 -44
- package/dist/scaffold/index.d.ts.map +1 -1
- package/dist/scaffold/index.js +19 -0
- package/dist/utils/quality-gates-errors.js +520 -0
- package/dist/utils/quality-gates.d.ts +49 -0
- package/dist/utils/quality-gates.d.ts.map +1 -0
- package/dist/utils/quality-gates.js +361 -0
- package/dist/utils/spec-resolver.d.ts +88 -0
- package/dist/utils/spec-resolver.d.ts.map +1 -0
- package/dist/utils/spec-resolver.js +602 -0
- package/package.json +6 -5
- package/templates/.cursor/hooks/caws-scope-guard.sh +64 -8
- package/templates/.cursor/hooks/validate-spec.sh +22 -12
- package/templates/.cursor/rules/{01-claims-verification.mdc → 00-claims-verification.mdc} +1 -1
- package/templates/.cursor/rules/01-working-style.mdc +50 -0
- package/templates/.cursor/rules/{02-testing-standards.mdc → 02-quality-gates.mdc} +84 -29
- package/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
- package/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
- package/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
- package/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
- package/templates/.cursor/rules/07-process-ops.mdc +20 -0
- package/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
- package/templates/.cursor/rules/09-docstrings.mdc +89 -0
- package/templates/.cursor/rules/10-authorship-and-attribution.mdc +15 -0
- package/templates/.cursor/rules/11-documentation-quality-standards.mdc +390 -0
- package/templates/.cursor/rules/12-scope-management-waivers.mdc +385 -0
- package/templates/.cursor/rules/13-implementation-completeness.mdc +516 -0
- package/templates/.cursor/rules/14-language-agnostic-standards.mdc +588 -0
- package/templates/.cursor/rules/15-sophisticated-todo-detection.mdc +425 -0
- package/templates/.cursor/rules/README.md +93 -7
- package/templates/apps/tools/caws/prompt-lint.js.backup +274 -0
- package/templates/apps/tools/caws/provenance.js.backup +73 -0
- package/templates/scripts/quality-gates/check-god-objects.js +146 -0
- package/templates/scripts/quality-gates/run-quality-gates.js +50 -0
- package/templates/scripts/v3/analysis/todo_analyzer.py +1950 -0
- package/templates/.cursor/rules/03-infrastructure-standards.mdc +0 -251
- package/templates/.cursor/rules/04-documentation-integrity.mdc +0 -291
- package/templates/.cursor/rules/05-production-readiness-checklist.mdc +0 -214
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-hooks.d.ts","sourceRoot":"","sources":["../../src/scaffold/git-hooks.js"],"names":[],"mappings":"AASA;;;;GAIG;AACH,6CAHW,MAAM;;;GAwGhB;
|
|
1
|
+
{"version":3,"file":"git-hooks.d.ts","sourceRoot":"","sources":["../../src/scaffold/git-hooks.js"],"names":[],"mappings":"AASA;;;;GAIG;AACH,6CAHW,MAAM;;;GAwGhB;AAwND;;;GAGG;AACH,2CAFW,MAAM,iBAkChB;AAED;;;GAGG;AACH,gDAFW,MAAM,iBAgDhB"}
|
|
@@ -116,10 +116,10 @@ async function scaffoldGitHooks(projectDir, options = {}) {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
* Generate pre-commit hook content
|
|
119
|
+
* Generate pre-commit hook content with staged file quality gates
|
|
120
120
|
*/
|
|
121
121
|
function generatePreCommitHook(options) {
|
|
122
|
-
const { qualityGates = true } = options;
|
|
122
|
+
const { qualityGates = true, stagedOnly = true } = options;
|
|
123
123
|
|
|
124
124
|
return `#!/bin/bash
|
|
125
125
|
# CAWS Pre-commit Hook
|
|
@@ -127,8 +127,8 @@ function generatePreCommitHook(options) {
|
|
|
127
127
|
|
|
128
128
|
set -e
|
|
129
129
|
|
|
130
|
-
echo "
|
|
131
|
-
echo "
|
|
130
|
+
echo "🚦 Running CAWS Quality Gates${qualityGates ? ' (Crisis Response Mode)' : ''}..."
|
|
131
|
+
echo "📁 Analyzing ${stagedOnly ? 'staged files only' : 'all files'}..."
|
|
132
132
|
|
|
133
133
|
# Check if CAWS is initialized
|
|
134
134
|
if [ ! -d ".caws" ]; then
|
|
@@ -136,55 +136,43 @@ if [ ! -d ".caws" ]; then
|
|
|
136
136
|
exit 0
|
|
137
137
|
fi
|
|
138
138
|
|
|
139
|
-
# Run
|
|
140
|
-
if command -v
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
echo "✅ CAWS validation passed"
|
|
139
|
+
# Run quality gates
|
|
140
|
+
if command -v node >/dev/null 2>&1; then
|
|
141
|
+
if node scripts/quality-gates/run-quality-gates.js; then
|
|
142
|
+
echo "✅ Quality gates passed"
|
|
144
143
|
else
|
|
145
|
-
echo "❌
|
|
146
|
-
echo "💡 Fix
|
|
144
|
+
echo "❌ Quality gates failed - commit blocked"
|
|
145
|
+
echo "💡 Fix the violations above before committing"
|
|
146
|
+
echo "📖 See docs/refactoring.md for crisis response plan"
|
|
147
147
|
exit 1
|
|
148
148
|
fi
|
|
149
149
|
else
|
|
150
|
-
echo "⚠️
|
|
150
|
+
echo "⚠️ Node.js not found - skipping quality gates"
|
|
151
|
+
echo "💡 Install Node.js to enable automatic quality checking"
|
|
152
|
+
exit 0
|
|
151
153
|
fi
|
|
152
154
|
|
|
153
|
-
# Run
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
echo "
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
echo "
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
echo "💡 Fix issues or skip with: git commit --no-verify (allowed)"
|
|
167
|
-
exit 1
|
|
168
|
-
fi
|
|
169
|
-
fi
|
|
170
|
-
|
|
171
|
-
# Run tests if available
|
|
172
|
-
if [ -f "package.json" ] && grep -q '"test"' package.json; then
|
|
173
|
-
echo "🧪 Running tests..."
|
|
174
|
-
if npm test; then
|
|
175
|
-
echo "✅ Tests passed"
|
|
176
|
-
else
|
|
177
|
-
echo "❌ Tests failed"
|
|
178
|
-
echo "💡 Fix issues or skip with: git commit --no-verify (allowed)"
|
|
179
|
-
exit 1
|
|
180
|
-
fi
|
|
155
|
+
# Run hidden TODO analysis on staged files only
|
|
156
|
+
echo "🔍 Checking for hidden TODOs in staged files..."
|
|
157
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
158
|
+
if python3 scripts/v3/analysis/todo_analyzer.py --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
|
|
159
|
+
echo "✅ No critical hidden TODOs found in staged files"
|
|
160
|
+
else
|
|
161
|
+
echo "❌ Critical hidden TODOs detected in staged files - commit blocked"
|
|
162
|
+
echo "💡 Fix stub implementations and placeholder code before committing"
|
|
163
|
+
echo "📖 See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
|
|
164
|
+
echo ""
|
|
165
|
+
echo "🔍 Running detailed analysis on staged files..."
|
|
166
|
+
python3 scripts/v3/analysis/todo_analyzer.py --staged-only --min-confidence 0.8
|
|
167
|
+
exit 1
|
|
181
168
|
fi
|
|
169
|
+
else
|
|
170
|
+
echo "⚠️ Python3 not found - skipping hidden TODO analysis"
|
|
171
|
+
echo "💡 Install Python3 to enable automatic TODO checking"
|
|
182
172
|
fi
|
|
183
|
-
`
|
|
184
|
-
: ''
|
|
185
|
-
}
|
|
186
173
|
|
|
187
|
-
echo "
|
|
174
|
+
echo "✅ All quality checks passed - proceeding with commit"
|
|
175
|
+
exit 0
|
|
188
176
|
`;
|
|
189
177
|
}
|
|
190
178
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scaffold/index.js"],"names":[],"mappings":"AAkKA;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scaffold/index.js"],"names":[],"mappings":"AAkKA;;;GAGG;AACH,6DA6VC;AAhfD;;;;GAIG;AACH,mDAHW,MAAM;;;GA8HhB;AAMD;;;GAGG;AACH,yDAGC"}
|
package/dist/scaffold/index.js
CHANGED
|
@@ -311,6 +311,25 @@ async function scaffoldProject(options) {
|
|
|
311
311
|
},
|
|
312
312
|
});
|
|
313
313
|
|
|
314
|
+
// Add quality gates scripts for staged file analysis
|
|
315
|
+
enhancements.push({
|
|
316
|
+
name: 'scripts/quality-gates/run-quality-gates.js',
|
|
317
|
+
description: 'Quality gates runner for staged files',
|
|
318
|
+
required: false,
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
enhancements.push({
|
|
322
|
+
name: 'scripts/quality-gates/check-god-objects.js',
|
|
323
|
+
description: 'God object detector for staged files',
|
|
324
|
+
required: false,
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
enhancements.push({
|
|
328
|
+
name: 'scripts/v3/analysis/todo_analyzer.py',
|
|
329
|
+
description: 'Advanced hidden TODO analyzer with dependency resolution',
|
|
330
|
+
required: false,
|
|
331
|
+
});
|
|
332
|
+
|
|
314
333
|
// Add commit conventions for setups that don't have them
|
|
315
334
|
if (!setup.hasTemplates || !fs.existsSync(path.join(currentDir, 'COMMIT_CONVENTIONS.md'))) {
|
|
316
335
|
enhancements.push({
|
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Quality Gates Error Taxonomy
|
|
3
|
+
* Comprehensive error handling for CAWS quality gates with structured error types,
|
|
4
|
+
* recovery strategies, and audit trails.
|
|
5
|
+
*
|
|
6
|
+
* @author @darianrosebrook
|
|
7
|
+
* @ts-nocheck
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const crypto = require('crypto');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Quality Gates Error Categories
|
|
14
|
+
*/
|
|
15
|
+
const ERROR_CATEGORIES = {
|
|
16
|
+
VALIDATION: 'validation',
|
|
17
|
+
CONFIGURATION: 'configuration',
|
|
18
|
+
EXECUTION: 'execution',
|
|
19
|
+
NETWORK: 'network',
|
|
20
|
+
SECURITY: 'security',
|
|
21
|
+
PERFORMANCE: 'performance',
|
|
22
|
+
BUSINESS_LOGIC: 'business_logic',
|
|
23
|
+
INFRASTRUCTURE: 'infrastructure',
|
|
24
|
+
DATA: 'data',
|
|
25
|
+
TIMEOUT: 'timeout',
|
|
26
|
+
INTERNAL: 'internal',
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Error Severity Levels
|
|
31
|
+
*/
|
|
32
|
+
const ERROR_SEVERITY = {
|
|
33
|
+
DEBUG: 'debug',
|
|
34
|
+
INFO: 'info',
|
|
35
|
+
WARNING: 'warning',
|
|
36
|
+
ERROR: 'error',
|
|
37
|
+
CRITICAL: 'critical',
|
|
38
|
+
FATAL: 'fatal',
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Recovery Strategies
|
|
43
|
+
*/
|
|
44
|
+
const RECOVERY_STRATEGIES = {
|
|
45
|
+
RETRY: 'retry',
|
|
46
|
+
FALLBACK: 'fallback',
|
|
47
|
+
SKIP: 'skip',
|
|
48
|
+
ESCALATE: 'escalate',
|
|
49
|
+
MANUAL_INTERVENTION: 'manual_intervention',
|
|
50
|
+
AUTO_FIX: 'auto_fix',
|
|
51
|
+
WAIVER: 'waiver',
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Quality Gates Error Class
|
|
56
|
+
* @typedef {Object} QualityGatesErrorOptions
|
|
57
|
+
* @property {string} category
|
|
58
|
+
* @property {string} code
|
|
59
|
+
* @property {string} message
|
|
60
|
+
* @property {string} [severity]
|
|
61
|
+
* @property {string} [component]
|
|
62
|
+
* @property {string} [operation]
|
|
63
|
+
* @property {Object} [context]
|
|
64
|
+
* @property {string[]} [recoveryStrategies]
|
|
65
|
+
* @property {boolean} [retryable]
|
|
66
|
+
* @property {string|null} [correlationId]
|
|
67
|
+
* @property {string[]} [errorChain]
|
|
68
|
+
*/
|
|
69
|
+
class QualityGatesError extends Error {
|
|
70
|
+
/**
|
|
71
|
+
* @param {QualityGatesErrorOptions} options
|
|
72
|
+
*/
|
|
73
|
+
constructor(options) {
|
|
74
|
+
const {
|
|
75
|
+
category,
|
|
76
|
+
code,
|
|
77
|
+
message,
|
|
78
|
+
severity = ERROR_SEVERITY.ERROR,
|
|
79
|
+
component = 'quality-gates',
|
|
80
|
+
operation = 'unknown',
|
|
81
|
+
context = {},
|
|
82
|
+
recoveryStrategies = [],
|
|
83
|
+
retryable = false,
|
|
84
|
+
correlationId = null,
|
|
85
|
+
errorChain = [],
|
|
86
|
+
} = options;
|
|
87
|
+
|
|
88
|
+
super(message);
|
|
89
|
+
|
|
90
|
+
this.name = 'QualityGatesError';
|
|
91
|
+
this.errorId = `qg-err-${Date.now()}-${crypto.randomBytes(4).toString('hex')}`;
|
|
92
|
+
this.category = category;
|
|
93
|
+
this.code = code;
|
|
94
|
+
this.severity = severity;
|
|
95
|
+
this.component = component;
|
|
96
|
+
this.operation = operation;
|
|
97
|
+
this.context = context;
|
|
98
|
+
this.recoveryStrategies = recoveryStrategies;
|
|
99
|
+
this.retryable = retryable;
|
|
100
|
+
this.correlationId = correlationId;
|
|
101
|
+
this.errorChain = errorChain;
|
|
102
|
+
this.timestamp = new Date().toISOString();
|
|
103
|
+
this.stack = this.stack || new Error().stack;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Add context to the error
|
|
108
|
+
*/
|
|
109
|
+
withContext(key, value) {
|
|
110
|
+
this.context[key] = value;
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Add a recovery strategy
|
|
116
|
+
*/
|
|
117
|
+
withRecoveryStrategy(strategy) {
|
|
118
|
+
this.recoveryStrategies.push(strategy);
|
|
119
|
+
return this;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Mark as retryable
|
|
124
|
+
*/
|
|
125
|
+
retryable(retryable) {
|
|
126
|
+
this.retryable = retryable;
|
|
127
|
+
return this;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Set correlation ID for tracing
|
|
132
|
+
*/
|
|
133
|
+
withCorrelationId(correlationId) {
|
|
134
|
+
this.correlationId = correlationId;
|
|
135
|
+
return this;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Add to error chain
|
|
140
|
+
*/
|
|
141
|
+
withErrorChain(previousError) {
|
|
142
|
+
this.errorChain.push(previousError);
|
|
143
|
+
return this;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Convert to JSON for logging
|
|
148
|
+
*/
|
|
149
|
+
toJSON() {
|
|
150
|
+
return {
|
|
151
|
+
errorId: this.errorId,
|
|
152
|
+
name: this.name,
|
|
153
|
+
category: this.category,
|
|
154
|
+
code: this.code,
|
|
155
|
+
message: this.message,
|
|
156
|
+
severity: this.severity,
|
|
157
|
+
component: this.component,
|
|
158
|
+
operation: this.operation,
|
|
159
|
+
context: this.context,
|
|
160
|
+
recoveryStrategies: this.recoveryStrategies,
|
|
161
|
+
retryable: this.retryable,
|
|
162
|
+
correlationId: this.correlationId,
|
|
163
|
+
errorChain: this.errorChain,
|
|
164
|
+
timestamp: this.timestamp,
|
|
165
|
+
stack: this.stack,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Get human-readable error summary
|
|
171
|
+
*/
|
|
172
|
+
getSummary() {
|
|
173
|
+
return `[${this.category.toUpperCase()}] ${this.code}: ${this.message}`;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Check if error requires human intervention
|
|
178
|
+
*/
|
|
179
|
+
requiresHumanIntervention() {
|
|
180
|
+
return (
|
|
181
|
+
this.recoveryStrategies.includes(RECOVERY_STRATEGIES.MANUAL_INTERVENTION) ||
|
|
182
|
+
this.recoveryStrategies.includes(RECOVERY_STRATEGIES.ESCALATE) ||
|
|
183
|
+
this.severity === ERROR_SEVERITY.FATAL
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Check if error can be auto-recovered
|
|
189
|
+
*/
|
|
190
|
+
canAutoRecover() {
|
|
191
|
+
return (
|
|
192
|
+
this.recoveryStrategies.includes(RECOVERY_STRATEGIES.AUTO_FIX) ||
|
|
193
|
+
this.recoveryStrategies.includes(RECOVERY_STRATEGIES.RETRY) ||
|
|
194
|
+
this.recoveryStrategies.includes(RECOVERY_STRATEGIES.FALLBACK)
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Specific Error Types for Quality Gates
|
|
201
|
+
*/
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* God Object Detection Errors
|
|
205
|
+
*/
|
|
206
|
+
class GodObjectError extends QualityGatesError {
|
|
207
|
+
constructor(file, lineCount, threshold, options = {}) {
|
|
208
|
+
super({
|
|
209
|
+
category: ERROR_CATEGORIES.BUSINESS_LOGIC,
|
|
210
|
+
code: 'GOD_OBJECT_DETECTED',
|
|
211
|
+
message: `God object detected: ${file} has ${lineCount} lines (threshold: ${threshold})`,
|
|
212
|
+
severity: lineCount > threshold * 1.5 ? ERROR_SEVERITY.CRITICAL : ERROR_SEVERITY.ERROR,
|
|
213
|
+
component: 'god-object-detector',
|
|
214
|
+
operation: 'analyze_file_size',
|
|
215
|
+
context: {
|
|
216
|
+
file,
|
|
217
|
+
lineCount,
|
|
218
|
+
threshold,
|
|
219
|
+
fileSizeKB: options.fileSizeKB,
|
|
220
|
+
relativePath: options.relativePath,
|
|
221
|
+
},
|
|
222
|
+
recoveryStrategies: [RECOVERY_STRATEGIES.MANUAL_INTERVENTION, RECOVERY_STRATEGIES.WAIVER],
|
|
223
|
+
retryable: false,
|
|
224
|
+
...options,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Hidden TODO Detection Errors
|
|
231
|
+
*/
|
|
232
|
+
class HiddenTodoError extends QualityGatesError {
|
|
233
|
+
constructor(file, todoCount, confidence, options = {}) {
|
|
234
|
+
super({
|
|
235
|
+
category: ERROR_CATEGORIES.BUSINESS_LOGIC,
|
|
236
|
+
code: 'HIDDEN_TODOS_DETECTED',
|
|
237
|
+
message: `Hidden TODOs detected: ${file} has ${todoCount} TODOs (confidence: ${confidence})`,
|
|
238
|
+
severity: confidence > 0.9 ? ERROR_SEVERITY.CRITICAL : ERROR_SEVERITY.ERROR,
|
|
239
|
+
component: 'todo-analyzer',
|
|
240
|
+
operation: 'analyze_hidden_todos',
|
|
241
|
+
context: {
|
|
242
|
+
file,
|
|
243
|
+
todoCount,
|
|
244
|
+
confidence,
|
|
245
|
+
blockingTodos: options.blockingTodos || 0,
|
|
246
|
+
nonBlockingTodos: options.nonBlockingTodos || 0,
|
|
247
|
+
},
|
|
248
|
+
recoveryStrategies: [
|
|
249
|
+
RECOVERY_STRATEGIES.MANUAL_INTERVENTION,
|
|
250
|
+
RECOVERY_STRATEGIES.WAIVER,
|
|
251
|
+
RECOVERY_STRATEGIES.AUTO_FIX,
|
|
252
|
+
],
|
|
253
|
+
retryable: false,
|
|
254
|
+
...options,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Configuration Errors
|
|
261
|
+
*/
|
|
262
|
+
class ConfigurationError extends QualityGatesError {
|
|
263
|
+
constructor(configKey, expectedType, actualValue, options = {}) {
|
|
264
|
+
super({
|
|
265
|
+
category: ERROR_CATEGORIES.CONFIGURATION,
|
|
266
|
+
code: 'INVALID_CONFIGURATION',
|
|
267
|
+
message: `Invalid configuration: ${configKey} expected ${expectedType}, got ${typeof actualValue}`,
|
|
268
|
+
severity: ERROR_SEVERITY.ERROR,
|
|
269
|
+
component: 'config-manager',
|
|
270
|
+
operation: 'validate_config',
|
|
271
|
+
context: {
|
|
272
|
+
configKey,
|
|
273
|
+
expectedType,
|
|
274
|
+
actualValue,
|
|
275
|
+
configFile: options.configFile,
|
|
276
|
+
},
|
|
277
|
+
recoveryStrategies: [RECOVERY_STRATEGIES.MANUAL_INTERVENTION, RECOVERY_STRATEGIES.FALLBACK],
|
|
278
|
+
retryable: false,
|
|
279
|
+
...options,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Waiver Validation Errors
|
|
286
|
+
*/
|
|
287
|
+
class WaiverError extends QualityGatesError {
|
|
288
|
+
constructor(waiverId, reason, options = {}) {
|
|
289
|
+
super({
|
|
290
|
+
category: ERROR_CATEGORIES.VALIDATION,
|
|
291
|
+
code: 'INVALID_WAIVER',
|
|
292
|
+
message: `Invalid waiver: ${waiverId} - ${reason}`,
|
|
293
|
+
severity: ERROR_SEVERITY.WARNING,
|
|
294
|
+
component: 'waiver-manager',
|
|
295
|
+
operation: 'validate_waiver',
|
|
296
|
+
context: {
|
|
297
|
+
waiverId,
|
|
298
|
+
reason,
|
|
299
|
+
expiresAt: options.expiresAt,
|
|
300
|
+
gates: options.gates,
|
|
301
|
+
},
|
|
302
|
+
recoveryStrategies: [RECOVERY_STRATEGIES.MANUAL_INTERVENTION, RECOVERY_STRATEGIES.SKIP],
|
|
303
|
+
retryable: false,
|
|
304
|
+
...options,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Execution Errors
|
|
311
|
+
*/
|
|
312
|
+
class ExecutionError extends QualityGatesError {
|
|
313
|
+
constructor(command, exitCode, stderr, options = {}) {
|
|
314
|
+
super({
|
|
315
|
+
category: ERROR_CATEGORIES.EXECUTION,
|
|
316
|
+
code: 'COMMAND_FAILED',
|
|
317
|
+
message: `Command failed: ${command} (exit code: ${exitCode})`,
|
|
318
|
+
severity: ERROR_SEVERITY.ERROR,
|
|
319
|
+
component: 'command-executor',
|
|
320
|
+
operation: 'execute_command',
|
|
321
|
+
context: {
|
|
322
|
+
command,
|
|
323
|
+
exitCode,
|
|
324
|
+
stderr,
|
|
325
|
+
stdout: options.stdout,
|
|
326
|
+
workingDirectory: options.workingDirectory,
|
|
327
|
+
},
|
|
328
|
+
recoveryStrategies: [RECOVERY_STRATEGIES.RETRY, RECOVERY_STRATEGIES.MANUAL_INTERVENTION],
|
|
329
|
+
retryable: true,
|
|
330
|
+
...options,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Network/External Service Errors
|
|
337
|
+
*/
|
|
338
|
+
class NetworkError extends QualityGatesError {
|
|
339
|
+
constructor(url, statusCode, response, options = {}) {
|
|
340
|
+
super({
|
|
341
|
+
category: ERROR_CATEGORIES.NETWORK,
|
|
342
|
+
code: 'NETWORK_REQUEST_FAILED',
|
|
343
|
+
message: `Network request failed: ${url} (status: ${statusCode})`,
|
|
344
|
+
severity: statusCode >= 500 ? ERROR_SEVERITY.ERROR : ERROR_SEVERITY.WARNING,
|
|
345
|
+
component: 'network-client',
|
|
346
|
+
operation: 'make_request',
|
|
347
|
+
context: {
|
|
348
|
+
url,
|
|
349
|
+
statusCode,
|
|
350
|
+
response,
|
|
351
|
+
method: options.method,
|
|
352
|
+
headers: options.headers,
|
|
353
|
+
},
|
|
354
|
+
recoveryStrategies: [RECOVERY_STRATEGIES.RETRY, RECOVERY_STRATEGIES.FALLBACK],
|
|
355
|
+
retryable: true,
|
|
356
|
+
...options,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* File System Errors
|
|
363
|
+
*/
|
|
364
|
+
class FileSystemError extends QualityGatesError {
|
|
365
|
+
constructor(operation, filePath, originalError, options = {}) {
|
|
366
|
+
super({
|
|
367
|
+
category: ERROR_CATEGORIES.INFRASTRUCTURE,
|
|
368
|
+
code: 'FILE_SYSTEM_ERROR',
|
|
369
|
+
message: `File system error: ${operation} failed for ${filePath}`,
|
|
370
|
+
severity: ERROR_SEVERITY.ERROR,
|
|
371
|
+
component: 'file-system',
|
|
372
|
+
operation,
|
|
373
|
+
context: {
|
|
374
|
+
filePath,
|
|
375
|
+
originalError: originalError.message,
|
|
376
|
+
errorCode: originalError.code,
|
|
377
|
+
permissions: options.permissions,
|
|
378
|
+
},
|
|
379
|
+
recoveryStrategies: [RECOVERY_STRATEGIES.RETRY, RECOVERY_STRATEGIES.MANUAL_INTERVENTION],
|
|
380
|
+
retryable: true,
|
|
381
|
+
...options,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Error Factory Functions
|
|
388
|
+
*/
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Create a god object error
|
|
392
|
+
*/
|
|
393
|
+
function createGodObjectError(file, lineCount, threshold, options = {}) {
|
|
394
|
+
return new GodObjectError(file, lineCount, threshold, options);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Create a hidden TODO error
|
|
399
|
+
*/
|
|
400
|
+
function createHiddenTodoError(file, todoCount, confidence, options = {}) {
|
|
401
|
+
return new HiddenTodoError(file, todoCount, confidence, options);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Create a configuration error
|
|
406
|
+
*/
|
|
407
|
+
function createConfigurationError(configKey, expectedType, actualValue, options = {}) {
|
|
408
|
+
return new ConfigurationError(configKey, expectedType, actualValue, options);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Create a waiver error
|
|
413
|
+
*/
|
|
414
|
+
function createWaiverError(waiverId, reason, options = {}) {
|
|
415
|
+
return new WaiverError(waiverId, reason, options);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Create an execution error
|
|
420
|
+
*/
|
|
421
|
+
function createExecutionError(command, exitCode, stderr, options = {}) {
|
|
422
|
+
return new ExecutionError(command, exitCode, stderr, options);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Create a network error
|
|
427
|
+
*/
|
|
428
|
+
function createNetworkError(url, statusCode, response, options = {}) {
|
|
429
|
+
return new NetworkError(url, statusCode, response, options);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Create a file system error
|
|
434
|
+
*/
|
|
435
|
+
function createFileSystemError(operation, filePath, originalError, options = {}) {
|
|
436
|
+
return new FileSystemError(operation, filePath, originalError, options);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Error Classification Utilities
|
|
441
|
+
*/
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Classify an error by its properties
|
|
445
|
+
*/
|
|
446
|
+
function classifyError(error) {
|
|
447
|
+
const classification = {
|
|
448
|
+
category: ERROR_CATEGORIES.INTERNAL,
|
|
449
|
+
severity: ERROR_SEVERITY.ERROR,
|
|
450
|
+
retryable: false,
|
|
451
|
+
requiresHumanIntervention: false,
|
|
452
|
+
canAutoRecover: false,
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
if (error instanceof QualityGatesError) {
|
|
456
|
+
classification.category = error.category;
|
|
457
|
+
classification.severity = error.severity;
|
|
458
|
+
classification.retryable = error.retryable;
|
|
459
|
+
classification.requiresHumanIntervention = error.requiresHumanIntervention();
|
|
460
|
+
classification.canAutoRecover = error.canAutoRecover();
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
return classification;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Get error statistics from a collection of errors
|
|
468
|
+
*/
|
|
469
|
+
function getErrorStatistics(errors) {
|
|
470
|
+
const stats = {
|
|
471
|
+
total: errors.length,
|
|
472
|
+
byCategory: {},
|
|
473
|
+
bySeverity: {},
|
|
474
|
+
retryable: 0,
|
|
475
|
+
requiresHumanIntervention: 0,
|
|
476
|
+
canAutoRecover: 0,
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
errors.forEach((error) => {
|
|
480
|
+
const classification = classifyError(error);
|
|
481
|
+
|
|
482
|
+
// Count by category
|
|
483
|
+
stats.byCategory[classification.category] =
|
|
484
|
+
(stats.byCategory[classification.category] || 0) + 1;
|
|
485
|
+
|
|
486
|
+
// Count by severity
|
|
487
|
+
stats.bySeverity[classification.severity] =
|
|
488
|
+
(stats.bySeverity[classification.severity] || 0) + 1;
|
|
489
|
+
|
|
490
|
+
// Count flags
|
|
491
|
+
if (classification.retryable) stats.retryable++;
|
|
492
|
+
if (classification.requiresHumanIntervention) stats.requiresHumanIntervention++;
|
|
493
|
+
if (classification.canAutoRecover) stats.canAutoRecover++;
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
return stats;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
module.exports = {
|
|
500
|
+
QualityGatesError,
|
|
501
|
+
GodObjectError,
|
|
502
|
+
HiddenTodoError,
|
|
503
|
+
ConfigurationError,
|
|
504
|
+
WaiverError,
|
|
505
|
+
ExecutionError,
|
|
506
|
+
NetworkError,
|
|
507
|
+
FileSystemError,
|
|
508
|
+
ERROR_CATEGORIES,
|
|
509
|
+
ERROR_SEVERITY,
|
|
510
|
+
RECOVERY_STRATEGIES,
|
|
511
|
+
createGodObjectError,
|
|
512
|
+
createHiddenTodoError,
|
|
513
|
+
createConfigurationError,
|
|
514
|
+
createWaiverError,
|
|
515
|
+
createExecutionError,
|
|
516
|
+
createNetworkError,
|
|
517
|
+
createFileSystemError,
|
|
518
|
+
classifyError,
|
|
519
|
+
getErrorStatistics,
|
|
520
|
+
};
|