@paths.design/caws-cli 8.2.0 → 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 +4 -4
- 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
|
@@ -181,7 +181,7 @@ async function deriveBudget(spec, projectRoot = process.cwd(), options = {}) {
|
|
|
181
181
|
|
|
182
182
|
if (policyExists) {
|
|
183
183
|
console.error(
|
|
184
|
-
'
|
|
184
|
+
'Policy file exists but not loaded: ' +
|
|
185
185
|
expectedPath +
|
|
186
186
|
'\n' +
|
|
187
187
|
' Current working directory: ' +
|
|
@@ -230,7 +230,7 @@ async function deriveBudget(spec, projectRoot = process.cwd(), options = {}) {
|
|
|
230
230
|
// Validate waiver covers budget_limit gate
|
|
231
231
|
if (!waiver.gates || !waiver.gates.includes('budget_limit')) {
|
|
232
232
|
console.warn(
|
|
233
|
-
`\
|
|
233
|
+
`\nWaiver ${waiverId} does not cover 'budget_limit' gate\n` +
|
|
234
234
|
` Current gates: [${waiver.gates ? waiver.gates.join(', ') : 'none'}]\n` +
|
|
235
235
|
` Add 'budget_limit' to gates array to apply to budget violations\n`
|
|
236
236
|
);
|
|
@@ -363,7 +363,7 @@ function loadWaiver(waiverId, projectRoot) {
|
|
|
363
363
|
// Validate ID format before attempting to load
|
|
364
364
|
if (!/^WV-\d{4}$/.test(waiverId)) {
|
|
365
365
|
console.error(
|
|
366
|
-
`\
|
|
366
|
+
`\nInvalid waiver ID format: ${waiverId}\n` +
|
|
367
367
|
` Waiver IDs must be exactly 4 digits: WV-0001 through WV-9999\n` +
|
|
368
368
|
` Fix waiver_ids in .caws/working-spec.yaml\n`
|
|
369
369
|
);
|
|
@@ -373,7 +373,7 @@ function loadWaiver(waiverId, projectRoot) {
|
|
|
373
373
|
const waiverPath = path.join(projectRoot, '.caws', 'waivers', `${waiverId}.yaml`);
|
|
374
374
|
if (!fs.existsSync(waiverPath)) {
|
|
375
375
|
console.error(
|
|
376
|
-
`\
|
|
376
|
+
`\nWaiver file not found: ${waiverId}\n` +
|
|
377
377
|
` Expected location: ${waiverPath}\n` +
|
|
378
378
|
` Create waiver with: caws waiver create\n`
|
|
379
379
|
);
|
|
@@ -386,13 +386,13 @@ function loadWaiver(waiverId, projectRoot) {
|
|
|
386
386
|
try {
|
|
387
387
|
validateWaiverStructure(waiver);
|
|
388
388
|
} catch (error) {
|
|
389
|
-
console.error(`\
|
|
389
|
+
console.error(`\nInvalid waiver ${waiverId}: ${error.message}\n`);
|
|
390
390
|
return null;
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
return waiver;
|
|
394
394
|
} catch (error) {
|
|
395
|
-
console.error(`\
|
|
395
|
+
console.error(`\nFailed to load waiver ${waiverId}: ${error.message}\n`);
|
|
396
396
|
return null;
|
|
397
397
|
}
|
|
398
398
|
}
|
|
@@ -534,7 +534,7 @@ function isApproachingBudgetLimit(budgetCompliance, threshold = 80) {
|
|
|
534
534
|
*/
|
|
535
535
|
function generateBurnupReport(derivedBudget, currentStats) {
|
|
536
536
|
const report = [
|
|
537
|
-
'
|
|
537
|
+
'CAWS Budget Burn-up Report',
|
|
538
538
|
'===============================',
|
|
539
539
|
'',
|
|
540
540
|
`Risk Tier: ${currentStats.risk_tier}`,
|
|
@@ -568,11 +568,11 @@ function generateBurnupReport(derivedBudget, currentStats) {
|
|
|
568
568
|
// Add warnings at different thresholds
|
|
569
569
|
const overall = Math.max(filePercent, locPercent);
|
|
570
570
|
if (overall >= 95) {
|
|
571
|
-
report.push('', '
|
|
571
|
+
report.push('', 'CRITICAL: Budget nearly exhausted!');
|
|
572
572
|
} else if (overall >= 90) {
|
|
573
|
-
report.push('', '
|
|
573
|
+
report.push('', 'WARNING: Approaching budget limits');
|
|
574
574
|
} else if (overall >= 80) {
|
|
575
|
-
report.push('', '
|
|
575
|
+
report.push('', 'Notice: 80% of budget used');
|
|
576
576
|
}
|
|
577
577
|
|
|
578
578
|
return report.join('\n');
|
package/dist/commands/archive.js
CHANGED
|
@@ -133,7 +133,7 @@ async function validateQualityGates(_changeId) {
|
|
|
133
133
|
}
|
|
134
134
|
} catch {
|
|
135
135
|
// JSON parsing failed, check for error indicators in output
|
|
136
|
-
if (result.includes('
|
|
136
|
+
if (result.includes('') || result.includes('FAIL')) {
|
|
137
137
|
violations.push({ message: 'Quality gates reported failures', output: result });
|
|
138
138
|
}
|
|
139
139
|
}
|
|
@@ -141,7 +141,7 @@ async function validateQualityGates(_changeId) {
|
|
|
141
141
|
// Command failed - check exit code and output
|
|
142
142
|
if (execError.status !== 0) {
|
|
143
143
|
const output = execError.stdout || execError.message;
|
|
144
|
-
if (output.includes('violations') || output.includes('
|
|
144
|
+
if (output.includes('violations') || output.includes('')) {
|
|
145
145
|
violations.push({ message: 'Quality gates failed', output: output.substring(0, 500) });
|
|
146
146
|
}
|
|
147
147
|
}
|
|
@@ -259,7 +259,7 @@ async function archiveChange(change) {
|
|
|
259
259
|
// Move change folder to archive
|
|
260
260
|
await fs.move(change.path, archivePath);
|
|
261
261
|
|
|
262
|
-
console.log(chalk.green(`
|
|
262
|
+
console.log(chalk.green(` Moved to: ${archivePath}`));
|
|
263
263
|
}
|
|
264
264
|
|
|
265
265
|
/**
|
|
@@ -297,9 +297,9 @@ async function updateProvenance(change) {
|
|
|
297
297
|
await fs.ensureDir(provenanceDir);
|
|
298
298
|
await fs.writeFile(chainPath, JSON.stringify(chain, null, 2));
|
|
299
299
|
|
|
300
|
-
console.log(chalk.green(`
|
|
300
|
+
console.log(chalk.green(` Provenance updated: ${chain.length} total entries`));
|
|
301
301
|
} catch (error) {
|
|
302
|
-
console.log(chalk.yellow(`
|
|
302
|
+
console.log(chalk.yellow(` Could not update provenance: ${error.message}`));
|
|
303
303
|
}
|
|
304
304
|
}
|
|
305
305
|
|
|
@@ -310,15 +310,15 @@ async function updateProvenance(change) {
|
|
|
310
310
|
* @param {Object} qualityGates - Quality gates result
|
|
311
311
|
*/
|
|
312
312
|
function displayArchiveResults(change, validation, qualityGates) {
|
|
313
|
-
console.log(chalk.bold.cyan(`\
|
|
314
|
-
console.log(chalk.cyan('
|
|
313
|
+
console.log(chalk.bold.cyan(`\nArchiving Change: ${change.id}`));
|
|
314
|
+
console.log(chalk.cyan('==============================================\n'));
|
|
315
315
|
|
|
316
316
|
// Validation status
|
|
317
317
|
if (validation.valid) {
|
|
318
|
-
console.log(chalk.green('
|
|
318
|
+
console.log(chalk.green('Acceptance Criteria'));
|
|
319
319
|
console.log(chalk.gray(` ${validation.message}`));
|
|
320
320
|
} else {
|
|
321
|
-
console.log(chalk.red('
|
|
321
|
+
console.log(chalk.red('Acceptance Criteria'));
|
|
322
322
|
console.log(chalk.gray(` ${validation.message}`));
|
|
323
323
|
}
|
|
324
324
|
|
|
@@ -326,20 +326,20 @@ function displayArchiveResults(change, validation, qualityGates) {
|
|
|
326
326
|
|
|
327
327
|
// Quality gates status
|
|
328
328
|
if (qualityGates.valid) {
|
|
329
|
-
console.log(chalk.green('
|
|
329
|
+
console.log(chalk.green('Quality Gates'));
|
|
330
330
|
console.log(chalk.gray(` ${qualityGates.message}`));
|
|
331
331
|
} else {
|
|
332
|
-
console.log(chalk.red('
|
|
332
|
+
console.log(chalk.red('Quality Gates'));
|
|
333
333
|
console.log(chalk.gray(` ${qualityGates.message}`));
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
console.log('');
|
|
337
337
|
|
|
338
338
|
// Archive action
|
|
339
|
-
console.log(chalk.blue('
|
|
340
|
-
console.log(chalk.gray('
|
|
341
|
-
console.log(chalk.gray('
|
|
342
|
-
console.log(chalk.gray('
|
|
339
|
+
console.log(chalk.blue('Archive Actions:'));
|
|
340
|
+
console.log(chalk.gray(' - Moving change folder to archive'));
|
|
341
|
+
console.log(chalk.gray(' - Updating provenance chain'));
|
|
342
|
+
console.log(chalk.gray(' - Generating change summary'));
|
|
343
343
|
|
|
344
344
|
console.log('');
|
|
345
345
|
}
|
|
@@ -374,7 +374,7 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
374
374
|
workingSpec = resolved.spec;
|
|
375
375
|
} catch (error) {
|
|
376
376
|
console.log(
|
|
377
|
-
chalk.yellow(
|
|
377
|
+
chalk.yellow(`Could not load spec '${options.specId}': ${error.message}`)
|
|
378
378
|
);
|
|
379
379
|
}
|
|
380
380
|
}
|
|
@@ -390,9 +390,9 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
390
390
|
|
|
391
391
|
// Check if we should proceed with archival
|
|
392
392
|
if (!validation.valid) {
|
|
393
|
-
console.log(chalk.yellow('
|
|
393
|
+
console.log(chalk.yellow('Cannot archive: Incomplete acceptance criteria'));
|
|
394
394
|
if (!options.force) {
|
|
395
|
-
console.log(chalk.yellow('
|
|
395
|
+
console.log(chalk.yellow('Use --force to archive anyway'));
|
|
396
396
|
return outputResult({
|
|
397
397
|
command: 'archive',
|
|
398
398
|
change: changeId,
|
|
@@ -403,9 +403,9 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
if (!qualityGates.valid) {
|
|
406
|
-
console.log(chalk.yellow('
|
|
406
|
+
console.log(chalk.yellow('Cannot archive: Quality gates not met'));
|
|
407
407
|
if (!options.force) {
|
|
408
|
-
console.log(chalk.yellow('
|
|
408
|
+
console.log(chalk.yellow('Use --force to archive anyway'));
|
|
409
409
|
return outputResult({
|
|
410
410
|
command: 'archive',
|
|
411
411
|
change: changeId,
|
|
@@ -416,7 +416,7 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
416
416
|
}
|
|
417
417
|
|
|
418
418
|
// Perform archival
|
|
419
|
-
console.log(chalk.blue('
|
|
419
|
+
console.log(chalk.blue('Performing archival...'));
|
|
420
420
|
|
|
421
421
|
// Update metadata with completion timestamp
|
|
422
422
|
change.metadata.completed_at = new Date().toISOString();
|
|
@@ -433,7 +433,7 @@ async function archiveCommand(changeId, options = {}) {
|
|
|
433
433
|
// Update provenance
|
|
434
434
|
await updateProvenance(change);
|
|
435
435
|
|
|
436
|
-
console.log(chalk.green(`\
|
|
436
|
+
console.log(chalk.green(`\nSuccessfully archived change: ${changeId}`));
|
|
437
437
|
|
|
438
438
|
return outputResult({
|
|
439
439
|
command: 'archive',
|
package/dist/commands/burnup.js
CHANGED
|
@@ -93,14 +93,14 @@ async function burnupCommand(specFile) {
|
|
|
93
93
|
let specPath = specFile || path.join('.caws', 'working-spec.yaml');
|
|
94
94
|
|
|
95
95
|
if (!fs.existsSync(specPath)) {
|
|
96
|
-
console.error(chalk.red(
|
|
96
|
+
console.error(chalk.red(`Spec file not found: ${specPath}`));
|
|
97
97
|
process.exit(1);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
const specContent = fs.readFileSync(specPath, 'utf8');
|
|
101
101
|
const spec = yaml.load(specContent);
|
|
102
102
|
|
|
103
|
-
console.log(chalk.cyan('
|
|
103
|
+
console.log(chalk.cyan('Generating CAWS budget burn-up report...'));
|
|
104
104
|
|
|
105
105
|
// Derive budget
|
|
106
106
|
const derivedBudget = deriveBudget(spec, path.dirname(specPath));
|
|
@@ -121,7 +121,7 @@ async function burnupCommand(specFile) {
|
|
|
121
121
|
console.log(chalk.gray(` Analyzing changes since: ${gitStats.base_ref}`));
|
|
122
122
|
} else {
|
|
123
123
|
// Fallback if git analysis fails (not in a repo or no commits)
|
|
124
|
-
console.log(chalk.yellow('
|
|
124
|
+
console.log(chalk.yellow(' Could not analyze git history, using zero values'));
|
|
125
125
|
currentStats = {
|
|
126
126
|
files_changed: 0,
|
|
127
127
|
lines_changed: 0,
|
|
@@ -137,7 +137,7 @@ async function burnupCommand(specFile) {
|
|
|
137
137
|
console.log(report);
|
|
138
138
|
|
|
139
139
|
// Show detailed breakdown
|
|
140
|
-
console.log(chalk.gray('\
|
|
140
|
+
console.log(chalk.gray('\nDetailed Budget Analysis:'));
|
|
141
141
|
console.log(
|
|
142
142
|
chalk.gray(
|
|
143
143
|
` Baseline (Tier ${spec.risk_tier}): ${derivedBudget.baseline.max_files} files, ${derivedBudget.baseline.max_loc} LOC`
|
|
@@ -174,12 +174,12 @@ async function burnupCommand(specFile) {
|
|
|
174
174
|
);
|
|
175
175
|
|
|
176
176
|
if (filePercent > 90 || locPercent > 90) {
|
|
177
|
-
console.log(chalk.yellow('\
|
|
177
|
+
console.log(chalk.yellow('\nWARNING: Approaching budget limits'));
|
|
178
178
|
} else {
|
|
179
|
-
console.log(chalk.green('\
|
|
179
|
+
console.log(chalk.green('\nWithin budget limits'));
|
|
180
180
|
}
|
|
181
181
|
} catch (error) {
|
|
182
|
-
console.error(chalk.red('
|
|
182
|
+
console.error(chalk.red('Error generating burn-up report:'), error.message);
|
|
183
183
|
process.exit(1);
|
|
184
184
|
}
|
|
185
185
|
}
|
|
@@ -295,7 +295,7 @@ async function runDiagnosis() {
|
|
|
295
295
|
{ name: 'CAWS tools', fn: checkCAWSTools },
|
|
296
296
|
];
|
|
297
297
|
|
|
298
|
-
console.log(chalk.cyan('\
|
|
298
|
+
console.log(chalk.cyan('\nDiagnosing CAWS Project...\n'));
|
|
299
299
|
console.log(chalk.gray('Running checks:'));
|
|
300
300
|
|
|
301
301
|
const results = [];
|
|
@@ -309,9 +309,9 @@ async function runDiagnosis() {
|
|
|
309
309
|
if (result.skipped) {
|
|
310
310
|
console.log(chalk.gray('skipped'));
|
|
311
311
|
} else if (result.passed) {
|
|
312
|
-
console.log(chalk.green('
|
|
312
|
+
console.log(chalk.green(''));
|
|
313
313
|
} else {
|
|
314
|
-
const icon = result.severity === 'high' ? chalk.red('
|
|
314
|
+
const icon = result.severity === 'high' ? chalk.red('') : chalk.yellow('');
|
|
315
315
|
console.log(icon);
|
|
316
316
|
}
|
|
317
317
|
|
|
@@ -320,7 +320,7 @@ async function runDiagnosis() {
|
|
|
320
320
|
...result,
|
|
321
321
|
});
|
|
322
322
|
} catch (error) {
|
|
323
|
-
console.log(chalk.red('
|
|
323
|
+
console.log(chalk.red(''));
|
|
324
324
|
results.push({
|
|
325
325
|
name: check.name,
|
|
326
326
|
passed: false,
|
|
@@ -343,16 +343,16 @@ function displayResults(results) {
|
|
|
343
343
|
const issues = results.filter((r) => !r.passed && !r.skipped);
|
|
344
344
|
|
|
345
345
|
if (issues.length === 0) {
|
|
346
|
-
console.log(chalk.green('\
|
|
346
|
+
console.log(chalk.green('\nNo issues found! Your CAWS project is healthy.\n'));
|
|
347
347
|
return;
|
|
348
348
|
}
|
|
349
349
|
|
|
350
350
|
console.log(
|
|
351
|
-
chalk.bold.yellow(`\
|
|
351
|
+
chalk.bold.yellow(`\nFound ${issues.length} issue${issues.length > 1 ? 's' : ''}:\n`)
|
|
352
352
|
);
|
|
353
353
|
|
|
354
354
|
issues.forEach((issue, index) => {
|
|
355
|
-
const icon = issue.severity === 'high' ? chalk.red('
|
|
355
|
+
const icon = issue.severity === 'high' ? chalk.red('') : chalk.yellow('');
|
|
356
356
|
const severity = chalk.gray(`[${issue.severity.toUpperCase()}]`);
|
|
357
357
|
|
|
358
358
|
console.log(`${index + 1}. ${icon} ${issue.name} ${severity}`);
|
|
@@ -360,7 +360,7 @@ function displayResults(results) {
|
|
|
360
360
|
console.log(chalk.cyan(` Fix: ${issue.fix}`));
|
|
361
361
|
|
|
362
362
|
if (issue.autoFixable) {
|
|
363
|
-
console.log(chalk.green('
|
|
363
|
+
console.log(chalk.green(' Auto-fix available'));
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
// Show additional details if available
|
|
@@ -392,7 +392,7 @@ async function applyAutoFixes(results) {
|
|
|
392
392
|
const fixableIssues = results.filter((r) => !r.passed && r.autoFixable && r.autoFix);
|
|
393
393
|
|
|
394
394
|
if (fixableIssues.length === 0) {
|
|
395
|
-
console.log(chalk.yellow('\
|
|
395
|
+
console.log(chalk.yellow('\nNo auto-fixable issues found\n'));
|
|
396
396
|
return {
|
|
397
397
|
applied: 0,
|
|
398
398
|
skipped: 0,
|
|
@@ -400,7 +400,7 @@ async function applyAutoFixes(results) {
|
|
|
400
400
|
};
|
|
401
401
|
}
|
|
402
402
|
|
|
403
|
-
console.log(chalk.cyan(`\
|
|
403
|
+
console.log(chalk.cyan(`\nApplying ${fixableIssues.length} automatic fixes...\n`));
|
|
404
404
|
|
|
405
405
|
let applied = 0;
|
|
406
406
|
let failed = 0;
|
|
@@ -412,7 +412,7 @@ async function applyAutoFixes(results) {
|
|
|
412
412
|
const result = await issue.autoFix();
|
|
413
413
|
|
|
414
414
|
if (result.success) {
|
|
415
|
-
console.log(chalk.green('
|
|
415
|
+
console.log(chalk.green(''));
|
|
416
416
|
applied++;
|
|
417
417
|
|
|
418
418
|
if (result.nextSteps && result.nextSteps.length > 0) {
|
|
@@ -422,16 +422,16 @@ async function applyAutoFixes(results) {
|
|
|
422
422
|
});
|
|
423
423
|
}
|
|
424
424
|
} else {
|
|
425
|
-
console.log(chalk.red('
|
|
425
|
+
console.log(chalk.red(''));
|
|
426
426
|
failed++;
|
|
427
427
|
}
|
|
428
428
|
} catch (error) {
|
|
429
|
-
console.log(chalk.red(
|
|
429
|
+
console.log(chalk.red(`${error.message}`));
|
|
430
430
|
failed++;
|
|
431
431
|
}
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
-
console.log(chalk.bold.green(`\
|
|
434
|
+
console.log(chalk.bold.green(`\nResults: ${applied} fixed, ${failed} failed\n`));
|
|
435
435
|
|
|
436
436
|
return {
|
|
437
437
|
applied,
|
|
@@ -458,7 +458,7 @@ async function diagnoseCommand(options = {}) {
|
|
|
458
458
|
if (fixableCount > 0 && !options.fix) {
|
|
459
459
|
console.log(
|
|
460
460
|
chalk.yellow(
|
|
461
|
-
|
|
461
|
+
`${fixableCount} issue${fixableCount > 1 ? 's' : ''} can be fixed automatically`
|
|
462
462
|
)
|
|
463
463
|
);
|
|
464
464
|
console.log(chalk.yellow(' Run: caws diagnose --fix to apply fixes\n'));
|
|
@@ -466,14 +466,14 @@ async function diagnoseCommand(options = {}) {
|
|
|
466
466
|
const fixResults = await applyAutoFixes(results);
|
|
467
467
|
|
|
468
468
|
if (fixResults.applied > 0) {
|
|
469
|
-
console.log(chalk.green('
|
|
470
|
-
console.log(chalk.blue('
|
|
469
|
+
console.log(chalk.green('Auto-fixes applied successfully'));
|
|
470
|
+
console.log(chalk.blue('Run: caws validate to verify fixes\n'));
|
|
471
471
|
}
|
|
472
472
|
|
|
473
473
|
if (fixResults.skipped > 0) {
|
|
474
474
|
console.log(
|
|
475
475
|
chalk.yellow(
|
|
476
|
-
|
|
476
|
+
`${fixResults.skipped} issue${fixResults.skipped > 1 ? 's' : ''} require manual intervention\n`
|
|
477
477
|
)
|
|
478
478
|
);
|
|
479
479
|
}
|
|
@@ -483,17 +483,17 @@ async function diagnoseCommand(options = {}) {
|
|
|
483
483
|
const issueCount = results.filter((r) => !r.passed && !r.skipped).length;
|
|
484
484
|
|
|
485
485
|
if (issueCount === 0) {
|
|
486
|
-
console.log(chalk.blue('
|
|
487
|
-
console.log(chalk.blue('
|
|
488
|
-
console.log(chalk.blue('
|
|
489
|
-
console.log(chalk.blue('
|
|
486
|
+
console.log(chalk.blue('Next steps:'));
|
|
487
|
+
console.log(chalk.blue(' - Run: caws status --visual to view project health'));
|
|
488
|
+
console.log(chalk.blue(' - Run: caws validate to check working spec'));
|
|
489
|
+
console.log(chalk.blue(' - Optional: Create .caws/policy.yaml for custom budgets'));
|
|
490
490
|
console.log(
|
|
491
|
-
chalk.blue('
|
|
491
|
+
chalk.blue(' - Start implementing: caws iterate --current-state "Ready to begin"')
|
|
492
492
|
);
|
|
493
493
|
}
|
|
494
494
|
} catch (error) {
|
|
495
|
-
console.error(chalk.red('\
|
|
496
|
-
console.error(chalk.yellow('\
|
|
495
|
+
console.error(chalk.red('\nError running diagnosis:'), error.message);
|
|
496
|
+
console.error(chalk.yellow('\nTry: caws status for basic health check'));
|
|
497
497
|
process.exit(1);
|
|
498
498
|
}
|
|
499
499
|
}
|
|
@@ -21,11 +21,11 @@ const { initializeGlobalSetup } = require('../config');
|
|
|
21
21
|
*/
|
|
22
22
|
async function evaluateCommand(specFile = '.caws/working-spec.yaml', options = {}) {
|
|
23
23
|
try {
|
|
24
|
-
console.log('
|
|
24
|
+
console.log('Detecting CAWS setup...');
|
|
25
25
|
const setup = initializeGlobalSetup();
|
|
26
26
|
|
|
27
27
|
if (setup.hasWorkingSpec) {
|
|
28
|
-
console.log(
|
|
28
|
+
console.log(`Detected ${setup.setupType} CAWS setup`);
|
|
29
29
|
console.log(` Capabilities: ${setup.capabilities.join(', ')}`);
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -33,16 +33,16 @@ async function evaluateCommand(specFile = '.caws/working-spec.yaml', options = {
|
|
|
33
33
|
const specPath = path.isAbsolute(specFile) ? specFile : path.join(process.cwd(), specFile);
|
|
34
34
|
|
|
35
35
|
if (!fs.existsSync(specPath)) {
|
|
36
|
-
console.error(chalk.red(`\
|
|
37
|
-
console.error(chalk.yellow('
|
|
36
|
+
console.error(chalk.red(`\nWorking spec not found: ${specFile}`));
|
|
37
|
+
console.error(chalk.yellow('Run: caws init to create a working spec'));
|
|
38
38
|
process.exit(1);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
const specContent = fs.readFileSync(specPath, 'utf8');
|
|
42
42
|
const spec = yaml.load(specContent);
|
|
43
43
|
|
|
44
|
-
console.log(chalk.blue('\
|
|
45
|
-
console.log('
|
|
44
|
+
console.log(chalk.blue('\nEvaluating CAWS Quality Standards\n'));
|
|
45
|
+
console.log('-'.repeat(60));
|
|
46
46
|
|
|
47
47
|
// Evaluation results
|
|
48
48
|
const results = {
|
|
@@ -181,9 +181,9 @@ async function evaluateCommand(specFile = '.caws/working-spec.yaml', options = {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
// Display results
|
|
184
|
-
console.log('\
|
|
184
|
+
console.log('\nQuality Checks:\n');
|
|
185
185
|
results.checks.forEach((check) => {
|
|
186
|
-
const icon = check.status === 'pass' ? '
|
|
186
|
+
const icon = check.status === 'pass' ? '' : check.status === 'partial' ? '' : '';
|
|
187
187
|
const detail = check.detail ? ` (${check.detail})` : '';
|
|
188
188
|
console.log(
|
|
189
189
|
`${icon} ${check.name}: ${check.points}/${results.maxScore / results.checks.length}${detail}`
|
|
@@ -203,33 +203,33 @@ async function evaluateCommand(specFile = '.caws/working-spec.yaml', options = {
|
|
|
203
203
|
? 'D'
|
|
204
204
|
: 'F';
|
|
205
205
|
|
|
206
|
-
console.log('\n' + '
|
|
206
|
+
console.log('\n' + '-'.repeat(60));
|
|
207
207
|
console.log(
|
|
208
208
|
chalk.bold(
|
|
209
|
-
`\
|
|
209
|
+
`\nOverall Score: ${results.score}/${results.maxScore} (${percentage}%) - Grade: ${grade}\n`
|
|
210
210
|
)
|
|
211
211
|
);
|
|
212
212
|
|
|
213
213
|
// Display warnings
|
|
214
214
|
if (results.warnings.length > 0) {
|
|
215
|
-
console.log(chalk.yellow('
|
|
215
|
+
console.log(chalk.yellow('Warnings:\n'));
|
|
216
216
|
results.warnings.forEach((warning) => {
|
|
217
|
-
console.log(chalk.yellow(`
|
|
217
|
+
console.log(chalk.yellow(` - ${warning}`));
|
|
218
218
|
});
|
|
219
219
|
console.log();
|
|
220
220
|
}
|
|
221
221
|
|
|
222
222
|
// Display recommendations
|
|
223
223
|
if (results.recommendations.length > 0) {
|
|
224
|
-
console.log(chalk.blue('
|
|
224
|
+
console.log(chalk.blue('Recommendations:\n'));
|
|
225
225
|
results.recommendations.forEach((rec) => {
|
|
226
|
-
console.log(chalk.blue(`
|
|
226
|
+
console.log(chalk.blue(` - ${rec}`));
|
|
227
227
|
});
|
|
228
228
|
console.log();
|
|
229
229
|
}
|
|
230
230
|
|
|
231
231
|
// Risk tier specific guidance
|
|
232
|
-
console.log(chalk.bold(`\
|
|
232
|
+
console.log(chalk.bold(`\nRisk Tier ${spec.risk_tier} Requirements:\n`));
|
|
233
233
|
|
|
234
234
|
const tierRequirements = {
|
|
235
235
|
1: {
|
|
@@ -258,7 +258,7 @@ async function evaluateCommand(specFile = '.caws/working-spec.yaml', options = {
|
|
|
258
258
|
console.log(` Contract Tests: ${req.contracts}`);
|
|
259
259
|
console.log(` Code Review: ${req.review}`);
|
|
260
260
|
|
|
261
|
-
console.log(chalk.blue('\
|
|
261
|
+
console.log(chalk.blue('\nNext Steps:\n'));
|
|
262
262
|
console.log(' 1. Address warnings and recommendations above');
|
|
263
263
|
console.log(' 2. Implement acceptance criteria with tests');
|
|
264
264
|
console.log(' 3. Run: caws validate to check spec validity');
|
|
@@ -268,16 +268,16 @@ async function evaluateCommand(specFile = '.caws/working-spec.yaml', options = {
|
|
|
268
268
|
// Exit with appropriate code
|
|
269
269
|
if (percentage < 70) {
|
|
270
270
|
console.log(
|
|
271
|
-
chalk.red('\
|
|
271
|
+
chalk.red('\nQuality score below 70% - improvements needed before proceeding\n')
|
|
272
272
|
);
|
|
273
273
|
process.exit(1);
|
|
274
274
|
} else if (percentage < 90) {
|
|
275
|
-
console.log(chalk.yellow('\
|
|
275
|
+
console.log(chalk.yellow('\nQuality score acceptable but improvements recommended\n'));
|
|
276
276
|
} else {
|
|
277
|
-
console.log(chalk.green('\
|
|
277
|
+
console.log(chalk.green('\nExcellent quality score - ready to proceed!\n'));
|
|
278
278
|
}
|
|
279
279
|
} catch (error) {
|
|
280
|
-
console.error(chalk.red(`\
|
|
280
|
+
console.error(chalk.red(`\nEvaluation failed: ${error.message}`));
|
|
281
281
|
if (options.verbose) {
|
|
282
282
|
console.error(error.stack);
|
|
283
283
|
}
|