@paths.design/caws-cli 8.2.1 โ 8.2.3
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.js +10 -10
- package/dist/commands/archive.js +22 -22
- package/dist/commands/burnup.js +7 -7
- package/dist/commands/diagnose.js +25 -25
- package/dist/commands/evaluate.js +20 -20
- package/dist/commands/init.js +71 -72
- package/dist/commands/iterate.js +21 -21
- package/dist/commands/mode.js +11 -11
- package/dist/commands/plan.js +5 -5
- package/dist/commands/provenance.js +86 -86
- package/dist/commands/quality-gates.js +3 -3
- package/dist/commands/quality-monitor.js +17 -17
- package/dist/commands/session.js +312 -0
- package/dist/commands/specs.js +44 -44
- package/dist/commands/status.js +43 -43
- package/dist/commands/templates.js +14 -14
- package/dist/commands/tool.js +1 -1
- package/dist/commands/troubleshoot.js +11 -11
- package/dist/commands/tutorial.js +119 -119
- package/dist/commands/validate.js +6 -6
- package/dist/commands/waivers.js +93 -60
- package/dist/commands/workflow.js +17 -17
- package/dist/commands/worktree.js +13 -13
- package/dist/config/index.js +5 -5
- package/dist/config/modes.js +7 -7
- package/dist/constants/spec-types.js +5 -5
- package/dist/error-handler.js +4 -4
- package/dist/generators/jest-config-generator.js +3 -3
- package/dist/generators/working-spec.js +4 -4
- package/dist/index.js +79 -27
- package/dist/minimal-cli.js +9 -9
- package/dist/policy/PolicyManager.js +1 -1
- package/dist/scaffold/claude-hooks.js +7 -7
- package/dist/scaffold/cursor-hooks.js +8 -8
- package/dist/scaffold/git-hooks.js +152 -152
- package/dist/scaffold/index.js +48 -48
- package/dist/session/session-manager.js +548 -0
- package/dist/test-analysis.js +20 -20
- package/dist/utils/command-wrapper.js +8 -8
- package/dist/utils/detection.js +7 -7
- package/dist/utils/finalization.js +21 -21
- package/dist/utils/git-lock.js +3 -3
- package/dist/utils/gitignore-updater.js +1 -1
- package/dist/utils/project-analysis.js +7 -7
- package/dist/utils/quality-gates-utils.js +35 -35
- package/dist/utils/spec-resolver.js +8 -8
- package/dist/utils/typescript-detector.js +5 -5
- package/dist/utils/yaml-validation.js +1 -1
- package/dist/validation/spec-validation.js +4 -4
- package/dist/worktree/worktree-manager.js +11 -5
- package/package.json +1 -1
|
@@ -16,15 +16,15 @@ const { getTodoAnalyzerSuggestion } = require('../utils/project-analysis');
|
|
|
16
16
|
async function scaffoldGitHooks(projectDir, options = {}) {
|
|
17
17
|
const { provenance = true, validation = true, qualityGates = true, force = false } = options;
|
|
18
18
|
|
|
19
|
-
console.log('
|
|
19
|
+
console.log('Setting up Git hooks for CAWS provenance...');
|
|
20
20
|
|
|
21
21
|
const gitDir = path.join(projectDir, '.git');
|
|
22
22
|
const hooksDir = path.join(gitDir, 'hooks');
|
|
23
23
|
|
|
24
24
|
// Check if this is a git repository
|
|
25
25
|
if (!(await fs.pathExists(gitDir))) {
|
|
26
|
-
console.log('
|
|
27
|
-
console.log('
|
|
26
|
+
console.log('Not a git repository - skipping git hooks setup');
|
|
27
|
+
console.log('Initialize git first: git init');
|
|
28
28
|
return { added: 0, skipped: 0 };
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -75,13 +75,13 @@ async function scaffoldGitHooks(projectDir, options = {}) {
|
|
|
75
75
|
// Check if it's already a CAWS hook
|
|
76
76
|
const content = await fs.readFile(hookPath, 'utf8');
|
|
77
77
|
if (content.includes('# CAWS Hook')) {
|
|
78
|
-
console.log(
|
|
78
|
+
console.log(`Skipped ${hook.description} (already configured)`);
|
|
79
79
|
skippedCount++;
|
|
80
80
|
continue;
|
|
81
81
|
} else {
|
|
82
|
-
console.log(
|
|
82
|
+
console.log(`${hook.description} exists but not CAWS-managed`);
|
|
83
83
|
if (!options.backup) {
|
|
84
|
-
console.log(
|
|
84
|
+
console.log(`Use --force to replace, or --backup to preserve original`);
|
|
85
85
|
skippedCount++;
|
|
86
86
|
continue;
|
|
87
87
|
}
|
|
@@ -92,25 +92,25 @@ async function scaffoldGitHooks(projectDir, options = {}) {
|
|
|
92
92
|
if (exists && options.backup) {
|
|
93
93
|
const backupPath = `${hookPath}.backup.${Date.now()}`;
|
|
94
94
|
await fs.copy(hookPath, backupPath);
|
|
95
|
-
console.log(
|
|
95
|
+
console.log(`Backed up existing ${hook.name} to ${path.basename(backupPath)}`);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
// Write the hook
|
|
99
99
|
await fs.writeFile(hookPath, hook.content);
|
|
100
100
|
await fs.chmod(hookPath, 0o755);
|
|
101
101
|
|
|
102
|
-
console.log(
|
|
102
|
+
console.log(`Configured ${hook.description}`);
|
|
103
103
|
addedCount++;
|
|
104
104
|
} catch (error) {
|
|
105
|
-
console.log(
|
|
105
|
+
console.log(`Failed to configure ${hook.description}: ${error.message}`);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
if (addedCount > 0) {
|
|
110
|
-
console.log(`\
|
|
111
|
-
console.log('
|
|
112
|
-
console.log('
|
|
113
|
-
console.log('
|
|
110
|
+
console.log(`\nGit hooks configured: ${addedCount} hooks active`);
|
|
111
|
+
console.log('Hooks will run automatically on git operations');
|
|
112
|
+
console.log('Use --no-verify to skip commit hooks: git commit --no-verify');
|
|
113
|
+
console.log('Note: --no-verify is BLOCKED on git push for safety');
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
return { added: addedCount, skipped: skippedCount };
|
|
@@ -133,12 +133,12 @@ function generatePreCommitHook(options) {
|
|
|
133
133
|
|
|
134
134
|
set -e
|
|
135
135
|
|
|
136
|
-
echo "
|
|
137
|
-
echo "
|
|
136
|
+
echo "Running CAWS Quality Gates${qualityGates ? ' (Crisis Response Mode)' : ''}..."
|
|
137
|
+
echo "Analyzing ${stagedOnly ? 'staged files only' : 'all files'}..."
|
|
138
138
|
|
|
139
139
|
# Check if CAWS is initialized
|
|
140
140
|
if [ ! -d ".caws" ]; then
|
|
141
|
-
echo "
|
|
141
|
+
echo "CAWS not initialized - skipping validation"
|
|
142
142
|
exit 0
|
|
143
143
|
fi
|
|
144
144
|
|
|
@@ -148,21 +148,21 @@ if [ -f ".git/index.lock" ]; then
|
|
|
148
148
|
LOCK_AGE_MINUTES=$((LOCK_AGE / 60))
|
|
149
149
|
|
|
150
150
|
if [ $LOCK_AGE_MINUTES -gt 5 ]; then
|
|
151
|
-
echo "
|
|
152
|
-
echo "
|
|
153
|
-
echo "
|
|
154
|
-
echo "
|
|
151
|
+
echo "Stale git lock detected (\${LOCK_AGE_MINUTES} minutes old)"
|
|
152
|
+
echo "This may indicate a crashed git process"
|
|
153
|
+
echo "Remove stale lock: rm .git/index.lock"
|
|
154
|
+
echo "Warning: Check for running git/editor processes before removing"
|
|
155
155
|
exit 1
|
|
156
156
|
else
|
|
157
|
-
echo "
|
|
158
|
-
echo "
|
|
159
|
-
echo "
|
|
157
|
+
echo "Git lock detected (\${LOCK_AGE_MINUTES} minutes old)"
|
|
158
|
+
echo "Another git process may be running"
|
|
159
|
+
echo "Wait for the other process to complete, or check for running processes"
|
|
160
160
|
exit 1
|
|
161
161
|
fi
|
|
162
162
|
fi
|
|
163
163
|
|
|
164
164
|
# Validate YAML syntax for all CAWS spec files
|
|
165
|
-
echo "
|
|
165
|
+
echo "Validating YAML syntax for CAWS spec files..."
|
|
166
166
|
YAML_VALIDATION_FAILED=false
|
|
167
167
|
|
|
168
168
|
# Find all staged .yaml/.yml files in .caws directory
|
|
@@ -184,7 +184,7 @@ if [ -n "$STAGED_YAML_FILES" ]; then
|
|
|
184
184
|
yaml.load(content);
|
|
185
185
|
process.exit(0);
|
|
186
186
|
} catch (error) {
|
|
187
|
-
console.error('
|
|
187
|
+
console.error('Invalid YAML in $file');
|
|
188
188
|
console.error(' Error:', error.message);
|
|
189
189
|
if (error.mark) {
|
|
190
190
|
console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
|
|
@@ -209,7 +209,7 @@ if [ -n "$STAGED_YAML_FILES" ]; then
|
|
|
209
209
|
yaml.load(content);
|
|
210
210
|
process.exit(0);
|
|
211
211
|
} catch (error) {
|
|
212
|
-
console.error('
|
|
212
|
+
console.error('Invalid YAML in $file');
|
|
213
213
|
console.error(' Error:', error.message);
|
|
214
214
|
if (error.mark) {
|
|
215
215
|
console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
|
|
@@ -224,15 +224,15 @@ if [ -n "$STAGED_YAML_FILES" ]; then
|
|
|
224
224
|
done
|
|
225
225
|
fi
|
|
226
226
|
else
|
|
227
|
-
echo "
|
|
228
|
-
echo "
|
|
227
|
+
echo "Node.js not available - skipping YAML validation"
|
|
228
|
+
echo "Install Node.js to enable YAML syntax validation"
|
|
229
229
|
fi
|
|
230
230
|
fi
|
|
231
231
|
|
|
232
232
|
if [ "$YAML_VALIDATION_FAILED" = true ]; then
|
|
233
|
-
echo "
|
|
234
|
-
echo "
|
|
235
|
-
echo "
|
|
233
|
+
echo "YAML syntax validation failed - commit blocked"
|
|
234
|
+
echo "Fix YAML syntax errors above before committing"
|
|
235
|
+
echo "Consider using 'caws specs create <id>' instead of manual creation"
|
|
236
236
|
exit 1
|
|
237
237
|
fi
|
|
238
238
|
|
|
@@ -248,87 +248,87 @@ QUALITY_GATES_RAN=false
|
|
|
248
248
|
# Option 1: Quality gates package (installed via npm)
|
|
249
249
|
if [ -f "node_modules/@paths.design/quality-gates/run-quality-gates.mjs" ]; then
|
|
250
250
|
if command -v node >/dev/null 2>&1; then
|
|
251
|
-
echo "
|
|
252
|
-
if node node_modules/@paths.design/quality-gates/run-quality-gates.mjs --
|
|
253
|
-
echo "
|
|
251
|
+
echo "Running quality gates package..."
|
|
252
|
+
if CI= node node_modules/@paths.design/quality-gates/run-quality-gates.mjs --context=commit; then
|
|
253
|
+
echo "Quality gates passed"
|
|
254
254
|
QUALITY_GATES_RAN=true
|
|
255
255
|
else
|
|
256
|
-
echo "
|
|
257
|
-
echo "
|
|
256
|
+
echo "Quality gates failed - commit blocked"
|
|
257
|
+
echo "Fix the violations above before committing"
|
|
258
258
|
exit 1
|
|
259
259
|
fi
|
|
260
260
|
fi
|
|
261
261
|
# Option 1b: Quality gates package (monorepo/local copy)
|
|
262
262
|
elif [ -f "node_modules/@caws/quality-gates/run-quality-gates.mjs" ]; then
|
|
263
263
|
if command -v node >/dev/null 2>&1; then
|
|
264
|
-
echo "
|
|
265
|
-
if node node_modules/@caws/quality-gates/run-quality-gates.mjs --
|
|
266
|
-
echo "
|
|
264
|
+
echo "Running quality gates package (local)..."
|
|
265
|
+
if CI= node node_modules/@caws/quality-gates/run-quality-gates.mjs --context=commit; then
|
|
266
|
+
echo "Quality gates passed"
|
|
267
267
|
QUALITY_GATES_RAN=true
|
|
268
268
|
else
|
|
269
|
-
echo "
|
|
270
|
-
echo "
|
|
269
|
+
echo "Quality gates failed - commit blocked"
|
|
270
|
+
echo "Fix the violations above before committing"
|
|
271
271
|
exit 1
|
|
272
272
|
fi
|
|
273
273
|
fi
|
|
274
274
|
# Option 2: Legacy Node.js quality gates script (deprecated)
|
|
275
275
|
elif [ -f "scripts/quality-gates/run-quality-gates.js" ]; then
|
|
276
276
|
if command -v node >/dev/null 2>&1; then
|
|
277
|
-
echo "
|
|
277
|
+
echo "Running legacy Node.js quality gates script..."
|
|
278
278
|
if node scripts/quality-gates/run-quality-gates.js; then
|
|
279
|
-
echo "
|
|
279
|
+
echo "Quality gates passed"
|
|
280
280
|
QUALITY_GATES_RAN=true
|
|
281
281
|
else
|
|
282
|
-
echo "
|
|
283
|
-
echo "
|
|
282
|
+
echo "Quality gates failed - commit blocked"
|
|
283
|
+
echo "Fix the violations above before committing"
|
|
284
284
|
exit 1
|
|
285
285
|
fi
|
|
286
286
|
fi
|
|
287
287
|
# Option 3: CAWS CLI validation
|
|
288
288
|
elif command -v caws >/dev/null 2>&1; then
|
|
289
|
-
echo "
|
|
289
|
+
echo "Running CAWS CLI validation..."
|
|
290
290
|
if caws validate --quiet 2>/dev/null; then
|
|
291
|
-
echo "
|
|
291
|
+
echo "CAWS validation passed"
|
|
292
292
|
QUALITY_GATES_RAN=true
|
|
293
293
|
else
|
|
294
|
-
echo "
|
|
295
|
-
echo "
|
|
294
|
+
echo "CAWS validation failed, but allowing commit (non-blocking)"
|
|
295
|
+
echo "Run 'caws validate' for details"
|
|
296
296
|
QUALITY_GATES_RAN=true
|
|
297
297
|
fi
|
|
298
298
|
# Option 3: Makefile target
|
|
299
299
|
elif [ -f "Makefile" ] && grep -q "caws-validate\\|caws-gates" Makefile; then
|
|
300
|
-
echo "
|
|
300
|
+
echo "Running Makefile quality gates..."
|
|
301
301
|
if make caws-validate >/dev/null 2>&1 || make caws-gates >/dev/null 2>&1; then
|
|
302
|
-
echo "
|
|
302
|
+
echo "Makefile quality gates passed"
|
|
303
303
|
QUALITY_GATES_RAN=true
|
|
304
304
|
else
|
|
305
|
-
echo "
|
|
305
|
+
echo "Makefile quality gates failed, but allowing commit (non-blocking)"
|
|
306
306
|
QUALITY_GATES_RAN=true
|
|
307
307
|
fi
|
|
308
308
|
# Option 4: Python scripts
|
|
309
309
|
elif [ -f "scripts/simple_gates.py" ] && command -v python3 >/dev/null 2>&1; then
|
|
310
|
-
echo "
|
|
310
|
+
echo "Running Python quality gates script..."
|
|
311
311
|
if python3 scripts/simple_gates.py all --tier 2 --profile backend-api >/dev/null 2>&1; then
|
|
312
|
-
echo "
|
|
312
|
+
echo "Python quality gates passed"
|
|
313
313
|
QUALITY_GATES_RAN=true
|
|
314
314
|
else
|
|
315
|
-
echo "
|
|
315
|
+
echo "Python quality gates failed, but allowing commit (non-blocking)"
|
|
316
316
|
QUALITY_GATES_RAN=true
|
|
317
317
|
fi
|
|
318
318
|
# Option 5: Skip gracefully
|
|
319
319
|
else
|
|
320
|
-
echo "
|
|
321
|
-
echo "
|
|
322
|
-
echo "
|
|
323
|
-
echo "
|
|
324
|
-
echo "
|
|
325
|
-
echo "
|
|
320
|
+
echo "Quality gates not available - skipping"
|
|
321
|
+
echo "Available options:"
|
|
322
|
+
echo " - Install quality gates: npm install --save-dev @paths.design/quality-gates"
|
|
323
|
+
echo " - Install CAWS CLI: npm install -g @paths.design/caws-cli"
|
|
324
|
+
echo " - Use Python: python3 scripts/simple_gates.py"
|
|
325
|
+
echo " - Use Makefile: make caws-gates"
|
|
326
326
|
QUALITY_GATES_RAN=true
|
|
327
327
|
fi
|
|
328
328
|
|
|
329
329
|
# Run hidden TODO analysis on staged files only (if available)
|
|
330
330
|
if [ "$QUALITY_GATES_RAN" = true ]; then
|
|
331
|
-
echo "
|
|
331
|
+
echo "Checking for hidden TODOs in staged files..."
|
|
332
332
|
|
|
333
333
|
TODO_CHECK_RAN=false
|
|
334
334
|
|
|
@@ -353,14 +353,14 @@ if [ "$QUALITY_GATES_RAN" = true ]; then
|
|
|
353
353
|
# Run TODO analyzer if found
|
|
354
354
|
if [ -n "$TODO_ANALYZER" ] && command -v node >/dev/null 2>&1; then
|
|
355
355
|
if node "$TODO_ANALYZER" --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
|
|
356
|
-
echo "
|
|
356
|
+
echo "No critical hidden TODOs found in staged files"
|
|
357
357
|
TODO_CHECK_RAN=true
|
|
358
358
|
else
|
|
359
|
-
echo "
|
|
360
|
-
echo "
|
|
361
|
-
echo "
|
|
359
|
+
echo "Critical hidden TODOs detected in staged files - commit blocked"
|
|
360
|
+
echo "Fix stub implementations and placeholder code before committing"
|
|
361
|
+
echo "See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
|
|
362
362
|
echo ""
|
|
363
|
-
echo "
|
|
363
|
+
echo "Running detailed analysis on staged files..."
|
|
364
364
|
node "$TODO_ANALYZER" --staged-only --min-confidence 0.8
|
|
365
365
|
exit 1
|
|
366
366
|
fi
|
|
@@ -369,16 +369,16 @@ if [ "$QUALITY_GATES_RAN" = true ]; then
|
|
|
369
369
|
|
|
370
370
|
# Option 2: Fallback to legacy Python analyzer (deprecated - will be removed)
|
|
371
371
|
if [ "$TODO_CHECK_RAN" = false ] && command -v python3 >/dev/null 2>&1 && [ -f "scripts/v3/analysis/todo_analyzer.py" ]; then
|
|
372
|
-
echo "
|
|
372
|
+
echo "Using legacy Python TODO analyzer (deprecated)"
|
|
373
373
|
if python3 scripts/v3/analysis/todo_analyzer.py --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
|
|
374
|
-
echo "
|
|
374
|
+
echo "No critical hidden TODOs found in staged files"
|
|
375
375
|
TODO_CHECK_RAN=true
|
|
376
376
|
else
|
|
377
|
-
echo "
|
|
378
|
-
echo "
|
|
379
|
-
echo "
|
|
377
|
+
echo "Critical hidden TODOs detected in staged files - commit blocked"
|
|
378
|
+
echo "Fix stub implementations and placeholder code before committing"
|
|
379
|
+
echo "See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
|
|
380
380
|
echo ""
|
|
381
|
-
echo "
|
|
381
|
+
echo "Running detailed analysis on staged files..."
|
|
382
382
|
python3 scripts/v3/analysis/todo_analyzer.py --staged-only --min-confidence 0.8
|
|
383
383
|
exit 1
|
|
384
384
|
fi
|
|
@@ -386,8 +386,8 @@ if [ "$QUALITY_GATES_RAN" = true ]; then
|
|
|
386
386
|
|
|
387
387
|
# Option 3: No analyzer available - show language-aware suggestions
|
|
388
388
|
if [ "$TODO_CHECK_RAN" = false ]; then
|
|
389
|
-
echo "
|
|
390
|
-
echo "
|
|
389
|
+
echo "TODO analyzer not available - skipping hidden TODO check"
|
|
390
|
+
echo "Available options for TODO analysis:"
|
|
391
391
|
${todoSuggestion
|
|
392
392
|
.split('\n')
|
|
393
393
|
.map((line) => ` echo "${line.replace(/"/g, '\\"')}"`)
|
|
@@ -395,7 +395,7 @@ ${todoSuggestion
|
|
|
395
395
|
fi
|
|
396
396
|
fi
|
|
397
397
|
|
|
398
|
-
echo "
|
|
398
|
+
echo "All quality checks passed - proceeding with commit"
|
|
399
399
|
exit 0
|
|
400
400
|
`;
|
|
401
401
|
}
|
|
@@ -425,7 +425,7 @@ function generatePostCommitHook() {
|
|
|
425
425
|
|
|
426
426
|
# Update provenance if CAWS CLI is available
|
|
427
427
|
if command -v caws >/dev/null 2>&1; then
|
|
428
|
-
echo "
|
|
428
|
+
echo "Updating CAWS provenance for commit \${COMMIT_HASH:0:8}..."
|
|
429
429
|
|
|
430
430
|
# Run provenance update in background
|
|
431
431
|
(
|
|
@@ -455,11 +455,11 @@ set -e
|
|
|
455
455
|
# Block --no-verify on push operations
|
|
456
456
|
for arg in "$@"; do
|
|
457
457
|
if [[ "$arg" == "--no-verify" ]] || [[ "$arg" == "-n" ]]; then
|
|
458
|
-
echo "
|
|
459
|
-
echo "
|
|
458
|
+
echo "Error: --no-verify is BLOCKED on git push"
|
|
459
|
+
echo "==================================================="
|
|
460
460
|
echo "Push operations must pass all quality gates."
|
|
461
461
|
echo ""
|
|
462
|
-
echo "
|
|
462
|
+
echo "To fix issues locally:"
|
|
463
463
|
echo " 1. Run: caws validate"
|
|
464
464
|
echo " 2. Fix reported issues"
|
|
465
465
|
echo " 3. Commit fixes: git commit --no-verify \\(allowed\\)"
|
|
@@ -468,39 +468,39 @@ for arg in "$@"; do
|
|
|
468
468
|
fi
|
|
469
469
|
done
|
|
470
470
|
|
|
471
|
-
echo "
|
|
472
|
-
echo "
|
|
471
|
+
echo "CAWS Pre-push Validation"
|
|
472
|
+
echo "==================================================="
|
|
473
473
|
|
|
474
474
|
# Check if CAWS is initialized
|
|
475
475
|
if [ ! -d ".caws" ]; then
|
|
476
|
-
echo "
|
|
476
|
+
echo "CAWS not initialized - skipping validation"
|
|
477
477
|
exit 0
|
|
478
478
|
fi
|
|
479
479
|
|
|
480
480
|
# Run full validation suite
|
|
481
481
|
if command -v caws >/dev/null 2>&1; then
|
|
482
|
-
echo "
|
|
482
|
+
echo "Running comprehensive CAWS validation..."
|
|
483
483
|
|
|
484
484
|
# Run validation and capture output
|
|
485
485
|
VALIDATION_OUTPUT=$(caws validate 2>&1)
|
|
486
486
|
VALIDATION_EXIT=$?
|
|
487
487
|
|
|
488
488
|
if [ $VALIDATION_EXIT -eq 0 ]; then
|
|
489
|
-
echo "
|
|
489
|
+
echo "CAWS validation passed"
|
|
490
490
|
else
|
|
491
|
-
echo "
|
|
491
|
+
echo "CAWS validation failed"
|
|
492
492
|
echo ""
|
|
493
|
-
echo "
|
|
493
|
+
echo "==================================================="
|
|
494
494
|
echo "Validation Errors:"
|
|
495
|
-
echo "
|
|
496
|
-
echo "$VALIDATION_OUTPUT" | grep -E "(
|
|
495
|
+
echo "==================================================="
|
|
496
|
+
echo "$VALIDATION_OUTPUT" | grep -E "(|error|Error|Missing|required)" || echo "$VALIDATION_OUTPUT"
|
|
497
497
|
echo ""
|
|
498
498
|
|
|
499
499
|
# Check for contract-related errors
|
|
500
500
|
if echo "$VALIDATION_OUTPUT" | grep -qi "contract"; then
|
|
501
|
-
echo "
|
|
502
|
-
echo "
|
|
503
|
-
echo "
|
|
501
|
+
echo "Contract Requirements:"
|
|
502
|
+
echo " - Tier 1 & 2 changes require at least one contract"
|
|
503
|
+
echo " - For infrastructure/setup work, use 'chore' mode or add a minimal contract:"
|
|
504
504
|
echo ""
|
|
505
505
|
echo " Example minimal contract (.caws/working-spec.yaml):"
|
|
506
506
|
echo " contracts:"
|
|
@@ -514,18 +514,18 @@ if command -v caws >/dev/null 2>&1; then
|
|
|
514
514
|
fi
|
|
515
515
|
|
|
516
516
|
# Check for active waivers
|
|
517
|
-
echo "
|
|
517
|
+
echo "Checking for active waivers..."
|
|
518
518
|
if command -v caws >/dev/null 2>&1 && caws waivers list --status=active --format=count 2>/dev/null | grep -q "[1-9]"; then
|
|
519
519
|
ACTIVE_WAIVERS=$(caws waivers list --status=active 2>/dev/null)
|
|
520
|
-
echo "
|
|
520
|
+
echo "Active waivers found:"
|
|
521
521
|
echo "$ACTIVE_WAIVERS" | head -5
|
|
522
522
|
echo ""
|
|
523
|
-
echo "
|
|
523
|
+
echo "Note: Waivers may not cover all validation failures"
|
|
524
524
|
echo " Review waiver coverage: caws waivers list --status=active"
|
|
525
525
|
else
|
|
526
526
|
echo " No active waivers found"
|
|
527
527
|
echo ""
|
|
528
|
-
echo "
|
|
528
|
+
echo "If this is infrastructure/setup work, you can create a waiver:"
|
|
529
529
|
echo " caws waivers create \\\\"
|
|
530
530
|
echo " --title='Initial CAWS setup' \\\\"
|
|
531
531
|
echo " --reason=infrastructure_limitation \\\\"
|
|
@@ -537,14 +537,14 @@ if command -v caws >/dev/null 2>&1; then
|
|
|
537
537
|
fi
|
|
538
538
|
|
|
539
539
|
echo ""
|
|
540
|
-
echo "
|
|
540
|
+
echo "==================================================="
|
|
541
541
|
echo "Next Steps:"
|
|
542
542
|
echo " 1. Review errors above"
|
|
543
543
|
echo " 2. Fix issues in .caws/working-spec.yaml"
|
|
544
544
|
echo " 3. Run: caws validate \\(to verify fixes\\)"
|
|
545
545
|
echo " 4. Commit fixes: git commit --no-verify \\(allowed\\)"
|
|
546
546
|
echo " 5. Push again: git push"
|
|
547
|
-
echo "
|
|
547
|
+
echo "==================================================="
|
|
548
548
|
exit 1
|
|
549
549
|
fi
|
|
550
550
|
fi
|
|
@@ -552,8 +552,8 @@ fi
|
|
|
552
552
|
# Run full pre-push checks (full test suite required before push)
|
|
553
553
|
# Note: Pre-commit uses filtered tests for speed, but push requires full suite
|
|
554
554
|
echo ""
|
|
555
|
-
echo "
|
|
556
|
-
echo "
|
|
555
|
+
echo "Running full pre-push checks (full test suite required)..."
|
|
556
|
+
echo "==================================================="
|
|
557
557
|
|
|
558
558
|
QUICK_CHECKS_FAILED=false
|
|
559
559
|
|
|
@@ -561,12 +561,12 @@ QUICK_CHECKS_FAILED=false
|
|
|
561
561
|
if [ -f "package.json" ]; then
|
|
562
562
|
if command -v npm >/dev/null 2>&1; then
|
|
563
563
|
if grep -q '"lint"' package.json; then
|
|
564
|
-
echo "
|
|
564
|
+
echo "Running linting..."
|
|
565
565
|
if npm run lint >/dev/null 2>&1; then
|
|
566
|
-
echo "
|
|
566
|
+
echo "Linting passed"
|
|
567
567
|
else
|
|
568
|
-
echo "
|
|
569
|
-
echo "
|
|
568
|
+
echo "Linting failed"
|
|
569
|
+
echo "Fix lint errors: npm run lint"
|
|
570
570
|
QUICK_CHECKS_FAILED=true
|
|
571
571
|
fi
|
|
572
572
|
fi
|
|
@@ -577,12 +577,12 @@ fi
|
|
|
577
577
|
if [ -f "package.json" ]; then
|
|
578
578
|
if command -v npm >/dev/null 2>&1; then
|
|
579
579
|
if grep -q '"typecheck"' package.json; then
|
|
580
|
-
echo "
|
|
580
|
+
echo "Running type checking..."
|
|
581
581
|
if npm run typecheck >/dev/null 2>&1; then
|
|
582
|
-
echo "
|
|
582
|
+
echo "Type checking passed"
|
|
583
583
|
else
|
|
584
|
-
echo "
|
|
585
|
-
echo "
|
|
584
|
+
echo "Type checking failed"
|
|
585
|
+
echo "Fix type errors: npm run typecheck"
|
|
586
586
|
QUICK_CHECKS_FAILED=true
|
|
587
587
|
fi
|
|
588
588
|
fi
|
|
@@ -593,19 +593,19 @@ fi
|
|
|
593
593
|
# Pre-commit uses filtered tests for speed, but push requires full suite
|
|
594
594
|
if [ -f "package.json" ]; then
|
|
595
595
|
if command -v npm >/dev/null 2>&1 && grep -q '"test"' package.json; then
|
|
596
|
-
echo "
|
|
597
|
-
echo "
|
|
596
|
+
echo "Running FULL test suite (required for push)..."
|
|
597
|
+
echo "==================================================="
|
|
598
598
|
if npm test 2>&1 | tee /tmp/pre-push-test-full.log; then
|
|
599
|
-
echo "
|
|
599
|
+
echo "Full test suite passed"
|
|
600
600
|
rm -f /tmp/pre-push-test-full.log
|
|
601
601
|
else
|
|
602
602
|
FULL_TEST_EXIT_CODE=\${PIPESTATUS[0]}
|
|
603
|
-
echo "
|
|
604
|
-
echo "
|
|
603
|
+
echo "Full test suite failed (exit code: \${FULL_TEST_EXIT_CODE})"
|
|
604
|
+
echo "==================================================="
|
|
605
605
|
echo "Test output (last 100 lines):"
|
|
606
606
|
tail -100 /tmp/pre-push-test-full.log 2>/dev/null || echo "No test output captured"
|
|
607
|
-
echo "
|
|
608
|
-
echo "
|
|
607
|
+
echo "==================================================="
|
|
608
|
+
echo "Fix test failures before pushing: npm test"
|
|
609
609
|
rm -f /tmp/pre-push-test-full.log
|
|
610
610
|
QUICK_CHECKS_FAILED=true
|
|
611
611
|
fi
|
|
@@ -614,48 +614,48 @@ fi
|
|
|
614
614
|
|
|
615
615
|
# 4. Security checks (non-blocking warnings)
|
|
616
616
|
echo ""
|
|
617
|
-
echo "
|
|
617
|
+
echo "Running security checks..."
|
|
618
618
|
if [ -f "package.json" ]; then
|
|
619
619
|
if command -v npm >/dev/null 2>&1; then
|
|
620
|
-
echo "
|
|
620
|
+
echo "Checking for vulnerabilities..."
|
|
621
621
|
if npm audit --audit-level moderate >/dev/null 2>&1; then
|
|
622
|
-
echo "
|
|
622
|
+
echo "Security audit passed"
|
|
623
623
|
else
|
|
624
|
-
echo "
|
|
625
|
-
echo "
|
|
624
|
+
echo "Security vulnerabilities found (non-blocking)"
|
|
625
|
+
echo "Review with: npm audit"
|
|
626
626
|
fi
|
|
627
627
|
fi
|
|
628
628
|
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
629
629
|
if command -v pip-audit >/dev/null 2>&1; then
|
|
630
|
-
echo "
|
|
631
|
-
pip-audit --desc 2>/dev/null || echo "
|
|
630
|
+
echo "Checking Python vulnerabilities..."
|
|
631
|
+
pip-audit --desc 2>/dev/null || echo "Install pip-audit: pip install pip-audit"
|
|
632
632
|
fi
|
|
633
633
|
elif [ -f "Cargo.toml" ]; then
|
|
634
634
|
if command -v cargo-audit >/dev/null 2>&1; then
|
|
635
|
-
echo "
|
|
636
|
-
cargo audit 2>/dev/null || echo "
|
|
635
|
+
echo "Checking Rust vulnerabilities..."
|
|
636
|
+
cargo audit 2>/dev/null || echo "Install cargo-audit: cargo install cargo-audit"
|
|
637
637
|
fi
|
|
638
638
|
fi
|
|
639
639
|
|
|
640
640
|
# Fail if any checks failed
|
|
641
641
|
if [ "$QUICK_CHECKS_FAILED" = true ]; then
|
|
642
642
|
echo ""
|
|
643
|
-
echo "
|
|
644
|
-
echo "
|
|
645
|
-
echo "
|
|
643
|
+
echo "==================================================="
|
|
644
|
+
echo "Pre-push checks failed"
|
|
645
|
+
echo "==================================================="
|
|
646
646
|
echo "All checks (linting/type checking/full test suite) must pass before push."
|
|
647
647
|
echo ""
|
|
648
|
-
echo "
|
|
648
|
+
echo "Fix failures before pushing:"
|
|
649
649
|
echo " - Linting: npm run lint"
|
|
650
650
|
echo " - Type checking: npm run typecheck"
|
|
651
651
|
echo " - Tests: npm test"
|
|
652
|
-
echo "
|
|
652
|
+
echo "==================================================="
|
|
653
653
|
exit 1
|
|
654
654
|
fi
|
|
655
655
|
|
|
656
656
|
echo ""
|
|
657
|
-
echo "
|
|
658
|
-
echo "
|
|
657
|
+
echo "Pre-push checks completed!"
|
|
658
|
+
echo "All quality gates passed - ready to push"
|
|
659
659
|
`;
|
|
660
660
|
}
|
|
661
661
|
|
|
@@ -679,16 +679,16 @@ fi
|
|
|
679
679
|
|
|
680
680
|
# Basic commit message validation
|
|
681
681
|
if [ \${#COMMIT_MSG} -lt 10 ]; then
|
|
682
|
-
echo "
|
|
683
|
-
echo "
|
|
682
|
+
echo "Commit message too short \\(minimum 10 characters\\)"
|
|
683
|
+
echo "Write descriptive commit messages"
|
|
684
684
|
exit 1
|
|
685
685
|
fi
|
|
686
686
|
|
|
687
687
|
# Check for conventional commit format (optional but encouraged)
|
|
688
688
|
if [[ $COMMIT_MSG =~ ^(feat|fix|docs|style|refactor|test|chore)(.+)? ]]; then
|
|
689
|
-
echo "
|
|
689
|
+
echo "Conventional commit format detected"
|
|
690
690
|
else
|
|
691
|
-
echo "
|
|
691
|
+
echo "Consider using conventional commit format:"
|
|
692
692
|
echo " feat: add new feature"
|
|
693
693
|
echo " fix: bug fix"
|
|
694
694
|
echo " docs: documentation"
|
|
@@ -698,7 +698,7 @@ else
|
|
|
698
698
|
echo " chore: maintenance"
|
|
699
699
|
fi
|
|
700
700
|
|
|
701
|
-
echo "
|
|
701
|
+
echo "Commit message validation passed"
|
|
702
702
|
`;
|
|
703
703
|
}
|
|
704
704
|
|
|
@@ -707,7 +707,7 @@ echo "โ
Commit message validation passed"
|
|
|
707
707
|
* @param {string} projectDir - Project directory path
|
|
708
708
|
*/
|
|
709
709
|
async function removeGitHooks(projectDir) {
|
|
710
|
-
console.log('
|
|
710
|
+
console.log('Removing CAWS Git hooks...');
|
|
711
711
|
|
|
712
712
|
const hooksDir = path.join(projectDir, '.git', 'hooks');
|
|
713
713
|
const cawsHooks = ['pre-commit', 'post-commit', 'pre-push', 'commit-msg'];
|
|
@@ -722,21 +722,21 @@ async function removeGitHooks(projectDir) {
|
|
|
722
722
|
const content = await fs.readFile(hookPath, 'utf8');
|
|
723
723
|
if (content.includes('# CAWS Hook') || content.includes('# CAWS Pre-commit Hook')) {
|
|
724
724
|
await fs.remove(hookPath);
|
|
725
|
-
console.log(
|
|
725
|
+
console.log(`Removed ${hookName} hook`);
|
|
726
726
|
removedCount++;
|
|
727
727
|
} else {
|
|
728
|
-
console.log(
|
|
728
|
+
console.log(`Skipped ${hookName} (not CAWS-managed)`);
|
|
729
729
|
}
|
|
730
730
|
}
|
|
731
731
|
} catch (error) {
|
|
732
|
-
console.log(
|
|
732
|
+
console.log(`Failed to remove ${hookName}: ${error.message}`);
|
|
733
733
|
}
|
|
734
734
|
}
|
|
735
735
|
|
|
736
736
|
if (removedCount > 0) {
|
|
737
|
-
console.log(
|
|
737
|
+
console.log(`Removed ${removedCount} CAWS git hooks`);
|
|
738
738
|
} else {
|
|
739
|
-
console.log('
|
|
739
|
+
console.log('No CAWS git hooks found');
|
|
740
740
|
}
|
|
741
741
|
}
|
|
742
742
|
|
|
@@ -748,8 +748,8 @@ async function checkGitHooksStatus(projectDir) {
|
|
|
748
748
|
const hooksDir = path.join(projectDir, '.git', 'hooks');
|
|
749
749
|
const cawsHooks = ['pre-commit', 'post-commit', 'pre-push', 'commit-msg'];
|
|
750
750
|
|
|
751
|
-
console.log('
|
|
752
|
-
console.log('
|
|
751
|
+
console.log('Git Hooks Status:');
|
|
752
|
+
console.log('===================================================');
|
|
753
753
|
|
|
754
754
|
let activeCount = 0;
|
|
755
755
|
let totalCount = 0;
|
|
@@ -764,30 +764,30 @@ async function checkGitHooksStatus(projectDir) {
|
|
|
764
764
|
const isExecutable = (await fs.stat(hookPath)).mode & 0o111;
|
|
765
765
|
|
|
766
766
|
if (content.includes('# CAWS') && isExecutable) {
|
|
767
|
-
console.log(
|
|
767
|
+
console.log(`${hookName}: Active`);
|
|
768
768
|
activeCount++;
|
|
769
769
|
} else if (content.includes('# CAWS')) {
|
|
770
|
-
console.log(
|
|
770
|
+
console.log(`${hookName}: Configured but not executable`);
|
|
771
771
|
} else {
|
|
772
|
-
console.log(
|
|
772
|
+
console.log(`${hookName}: Not CAWS-managed`);
|
|
773
773
|
}
|
|
774
774
|
} else {
|
|
775
|
-
console.log(
|
|
775
|
+
console.log(`${hookName}: Not installed`);
|
|
776
776
|
}
|
|
777
777
|
} catch (error) {
|
|
778
|
-
console.log(
|
|
778
|
+
console.log(`${hookName}: Error checking status`);
|
|
779
779
|
}
|
|
780
780
|
}
|
|
781
781
|
|
|
782
782
|
console.log('');
|
|
783
|
-
console.log(
|
|
783
|
+
console.log(`Status: ${activeCount}/${totalCount} CAWS hooks active`);
|
|
784
784
|
|
|
785
785
|
if (activeCount < totalCount) {
|
|
786
786
|
console.log('');
|
|
787
|
-
console.log('
|
|
787
|
+
console.log('To install missing hooks:');
|
|
788
788
|
console.log(' caws scaffold');
|
|
789
789
|
console.log('');
|
|
790
|
-
console.log('
|
|
790
|
+
console.log('To check detailed status:');
|
|
791
791
|
console.log(' ls -la .git/hooks/');
|
|
792
792
|
}
|
|
793
793
|
}
|