@paths.design/caws-cli 3.3.1 ā 3.5.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/diagnose.d.ts.map +1 -1
- package/dist/commands/diagnose.js +39 -4
- package/dist/commands/evaluate.d.ts +8 -0
- package/dist/commands/evaluate.d.ts.map +1 -0
- package/dist/commands/evaluate.js +288 -0
- package/dist/commands/iterate.d.ts +8 -0
- package/dist/commands/iterate.d.ts.map +1 -0
- package/dist/commands/iterate.js +341 -0
- package/dist/commands/quality-monitor.d.ts +17 -0
- package/dist/commands/quality-monitor.d.ts.map +1 -0
- package/dist/commands/quality-monitor.js +265 -0
- package/dist/commands/status.d.ts +6 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +120 -20
- package/dist/commands/troubleshoot.d.ts +8 -0
- package/dist/commands/troubleshoot.d.ts.map +1 -0
- package/dist/commands/troubleshoot.js +104 -0
- package/dist/commands/waivers.d.ts +8 -0
- package/dist/commands/waivers.d.ts.map +1 -0
- package/dist/commands/waivers.js +293 -0
- package/dist/commands/workflow.d.ts +85 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +243 -0
- package/dist/error-handler.d.ts +91 -2
- package/dist/error-handler.d.ts.map +1 -1
- package/dist/error-handler.js +362 -16
- package/dist/index.js +95 -0
- package/dist/scaffold/git-hooks.d.ts.map +1 -1
- package/dist/scaffold/git-hooks.js +27 -6
- package/dist/utils/typescript-detector.d.ts +31 -0
- package/dist/utils/typescript-detector.d.ts.map +1 -1
- package/dist/utils/typescript-detector.js +245 -7
- package/package.json +2 -1
- package/templates/agents.md +6 -5
- package/templates/apps/tools/caws/gates.ts +34 -0
- package/templates/apps/tools/caws/shared/gate-checker.ts +265 -13
- package/templates/apps/tools/caws/templates/working-spec.template.yml +14 -0
- package/dist/index-new.d.ts +0 -5
- package/dist/index-new.d.ts.map +0 -1
- package/dist/index-new.js +0 -317
- package/dist/index.js.backup +0 -4711
- package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
- package/templates/apps/tools/caws/provenance.js.backup +0 -73
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CAWS Iterate Command
|
|
3
|
+
*
|
|
4
|
+
* Provides iterative development guidance based on current progress
|
|
5
|
+
* and working spec state.
|
|
6
|
+
*
|
|
7
|
+
* @author @darianrosebrook
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const yaml = require('js-yaml');
|
|
13
|
+
const chalk = require('chalk');
|
|
14
|
+
const { initializeGlobalSetup } = require('../config');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Iterate command handler
|
|
18
|
+
*
|
|
19
|
+
* @param {string} specFile - Path to working spec file
|
|
20
|
+
* @param {object} options - Command options
|
|
21
|
+
*/
|
|
22
|
+
async function iterateCommand(specFile = '.caws/working-spec.yaml', options = {}) {
|
|
23
|
+
try {
|
|
24
|
+
console.log('š Detecting CAWS setup...');
|
|
25
|
+
const setup = initializeGlobalSetup();
|
|
26
|
+
|
|
27
|
+
if (setup.hasWorkingSpec) {
|
|
28
|
+
console.log(`ā
Detected ${setup.setupType} CAWS setup`);
|
|
29
|
+
console.log(` Capabilities: ${setup.capabilities.join(', ')}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Load working spec
|
|
33
|
+
const specPath = path.isAbsolute(specFile) ? specFile : path.join(process.cwd(), specFile);
|
|
34
|
+
|
|
35
|
+
if (!fs.existsSync(specPath)) {
|
|
36
|
+
console.error(chalk.red(`\nā Working spec not found: ${specFile}`));
|
|
37
|
+
console.error(chalk.yellow('š” Run: caws init to create a working spec'));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const specContent = fs.readFileSync(specPath, 'utf8');
|
|
42
|
+
const spec = yaml.load(specContent);
|
|
43
|
+
|
|
44
|
+
// Parse current state from options
|
|
45
|
+
const currentState = options.currentState ? JSON.parse(options.currentState) : {};
|
|
46
|
+
const stateDescription = currentState.description || 'Starting implementation';
|
|
47
|
+
|
|
48
|
+
console.log(chalk.blue('\nš Iterative Development Guidance\n'));
|
|
49
|
+
console.log('ā'.repeat(60));
|
|
50
|
+
console.log(chalk.bold(`\nProject: ${spec.title}`));
|
|
51
|
+
console.log(`ID: ${spec.id} | Tier: ${spec.risk_tier} | Mode: ${spec.mode}`);
|
|
52
|
+
console.log(`Current State: ${stateDescription}\n`);
|
|
53
|
+
|
|
54
|
+
// Analyze progress based on mode
|
|
55
|
+
const guidance = generateGuidance(spec, currentState, options);
|
|
56
|
+
|
|
57
|
+
// Display guidance
|
|
58
|
+
console.log(chalk.blue('š Current Phase:\n'));
|
|
59
|
+
console.log(` ${guidance.phase}\n`);
|
|
60
|
+
|
|
61
|
+
console.log(chalk.blue('ā
Completed Steps:\n'));
|
|
62
|
+
guidance.completed.forEach((step) => {
|
|
63
|
+
console.log(chalk.green(` ā ${step}`));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
console.log(chalk.blue('\nšÆ Next Actions:\n'));
|
|
67
|
+
guidance.nextActions.forEach((action, index) => {
|
|
68
|
+
console.log(chalk.yellow(` ${index + 1}. ${action}`));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
if (guidance.blockers.length > 0) {
|
|
72
|
+
console.log(chalk.red('\nā ļø Blockers:\n'));
|
|
73
|
+
guidance.blockers.forEach((blocker) => {
|
|
74
|
+
console.log(chalk.red(` ā ļø ${blocker}`));
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(chalk.blue('\nš” Recommendations:\n'));
|
|
79
|
+
guidance.recommendations.forEach((rec) => {
|
|
80
|
+
console.log(chalk.blue(` ⢠${rec}`));
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
// Acceptance criteria checklist with detailed progress
|
|
84
|
+
if (spec.acceptance && spec.acceptance.length > 0) {
|
|
85
|
+
console.log(chalk.blue('\nš Acceptance Criteria Progress:\n'));
|
|
86
|
+
|
|
87
|
+
let totalTestsWritten = 0;
|
|
88
|
+
let totalTestsPassing = 0;
|
|
89
|
+
let totalCoverage = 0;
|
|
90
|
+
let criteriaWithProgress = 0;
|
|
91
|
+
|
|
92
|
+
spec.acceptance.forEach((criterion, _index) => {
|
|
93
|
+
// Support both old format (boolean completed) and new format (detailed progress)
|
|
94
|
+
let status = 'ā¬';
|
|
95
|
+
let progressInfo = '';
|
|
96
|
+
|
|
97
|
+
if (criterion.status) {
|
|
98
|
+
// New detailed format
|
|
99
|
+
switch (criterion.status) {
|
|
100
|
+
case 'completed':
|
|
101
|
+
status = 'ā
';
|
|
102
|
+
break;
|
|
103
|
+
case 'in_progress':
|
|
104
|
+
status = 'š';
|
|
105
|
+
break;
|
|
106
|
+
case 'pending':
|
|
107
|
+
default:
|
|
108
|
+
status = 'ā¬';
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Show detailed progress if available
|
|
113
|
+
if (criterion.tests) {
|
|
114
|
+
const written = criterion.tests.written || 0;
|
|
115
|
+
const passing = criterion.tests.passing || 0;
|
|
116
|
+
progressInfo = ` (${passing}/${written} tests passing`;
|
|
117
|
+
|
|
118
|
+
if (criterion.coverage !== undefined) {
|
|
119
|
+
progressInfo += `, ${criterion.coverage.toFixed(1)}% coverage`;
|
|
120
|
+
}
|
|
121
|
+
progressInfo += ')';
|
|
122
|
+
|
|
123
|
+
totalTestsWritten += written;
|
|
124
|
+
totalTestsPassing += passing;
|
|
125
|
+
if (criterion.coverage !== undefined) {
|
|
126
|
+
totalCoverage += criterion.coverage;
|
|
127
|
+
criteriaWithProgress++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (criterion.last_updated) {
|
|
132
|
+
const lastUpdate = new Date(criterion.last_updated).toLocaleDateString();
|
|
133
|
+
progressInfo += ` - updated ${lastUpdate}`;
|
|
134
|
+
}
|
|
135
|
+
} else if (criterion.completed) {
|
|
136
|
+
// Backward compatibility with old boolean format
|
|
137
|
+
status = 'ā
';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.log(` ${status} ${criterion.id}: ${criterion.then}`);
|
|
141
|
+
if (progressInfo) {
|
|
142
|
+
console.log(chalk.gray(` ${progressInfo}`));
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Calculate overall progress
|
|
147
|
+
const completed = spec.acceptance.filter(
|
|
148
|
+
(a) => a.status === 'completed' || a.completed
|
|
149
|
+
).length;
|
|
150
|
+
const inProgress = spec.acceptance.filter((a) => a.status === 'in_progress').length;
|
|
151
|
+
const total = spec.acceptance.length;
|
|
152
|
+
const completionProgress = Math.round((completed / total) * 100);
|
|
153
|
+
|
|
154
|
+
console.log(
|
|
155
|
+
chalk.bold(
|
|
156
|
+
`\n Overall Progress: ${completed}/${total} completed (${completionProgress}%)`
|
|
157
|
+
)
|
|
158
|
+
);
|
|
159
|
+
if (inProgress > 0) {
|
|
160
|
+
console.log(chalk.yellow(` In Progress: ${inProgress} criteria`));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Show test progress if available
|
|
164
|
+
if (totalTestsWritten > 0) {
|
|
165
|
+
const testProgress = Math.round((totalTestsPassing / totalTestsWritten) * 100);
|
|
166
|
+
console.log(
|
|
167
|
+
` Test Progress: ${totalTestsPassing}/${totalTestsWritten} tests passing (${testProgress}%)`
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Show coverage progress if available
|
|
172
|
+
if (criteriaWithProgress > 0) {
|
|
173
|
+
const avgCoverage = totalCoverage / criteriaWithProgress;
|
|
174
|
+
console.log(` Average Coverage: ${avgCoverage.toFixed(1)}%`);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Quality gates reminder
|
|
179
|
+
console.log(chalk.blue('\nš Quality Gates (Risk Tier ' + spec.risk_tier + '):\n'));
|
|
180
|
+
const gates = getQualityGates(spec.risk_tier);
|
|
181
|
+
gates.forEach((gate) => {
|
|
182
|
+
console.log(` ā” ${gate}`);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
console.log(chalk.blue('\nš Useful Commands:\n'));
|
|
186
|
+
console.log(' caws evaluate - Check quality score');
|
|
187
|
+
console.log(' caws validate - Validate working spec');
|
|
188
|
+
console.log(' caws status - View project health');
|
|
189
|
+
console.log(' caws diagnose - Run health checks');
|
|
190
|
+
console.log(' npm test - Run test suite');
|
|
191
|
+
console.log(' npm run coverage - Check test coverage\n');
|
|
192
|
+
} catch (error) {
|
|
193
|
+
console.error(chalk.red(`\nā Iteration guidance failed: ${error.message}`));
|
|
194
|
+
if (options.verbose) {
|
|
195
|
+
console.error(error.stack);
|
|
196
|
+
}
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Generate guidance based on spec and current state
|
|
203
|
+
*/
|
|
204
|
+
function generateGuidance(spec, _currentState, _options) {
|
|
205
|
+
const mode = spec.mode;
|
|
206
|
+
const riskTier = spec.risk_tier;
|
|
207
|
+
|
|
208
|
+
// Default guidance structure
|
|
209
|
+
const guidance = {
|
|
210
|
+
phase: 'Implementation',
|
|
211
|
+
completed: [],
|
|
212
|
+
nextActions: [],
|
|
213
|
+
blockers: [],
|
|
214
|
+
recommendations: [],
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// Mode-specific guidance
|
|
218
|
+
if (mode === 'feature') {
|
|
219
|
+
guidance.phase = 'Feature Development';
|
|
220
|
+
guidance.completed = ['Working specification created', 'Acceptance criteria defined'];
|
|
221
|
+
guidance.nextActions = [
|
|
222
|
+
'Write failing tests for first acceptance criterion',
|
|
223
|
+
'Implement minimum code to pass tests',
|
|
224
|
+
'Refactor and ensure all tests pass',
|
|
225
|
+
'Move to next acceptance criterion',
|
|
226
|
+
];
|
|
227
|
+
guidance.recommendations = [
|
|
228
|
+
'Follow TDD cycle: Red ā Green ā Refactor',
|
|
229
|
+
'Keep changes within scope boundaries',
|
|
230
|
+
'Update working spec as requirements evolve',
|
|
231
|
+
`Maintain ${riskTier === 1 ? '90%+' : riskTier === 2 ? '80%+' : '70%+'} test coverage`,
|
|
232
|
+
];
|
|
233
|
+
} else if (mode === 'refactor') {
|
|
234
|
+
guidance.phase = 'Refactoring';
|
|
235
|
+
guidance.completed = ['Working specification created', 'Baseline tests established'];
|
|
236
|
+
guidance.nextActions = [
|
|
237
|
+
'Ensure all existing tests pass',
|
|
238
|
+
'Make small, incremental refactoring changes',
|
|
239
|
+
'Run tests after each change',
|
|
240
|
+
'Update documentation as needed',
|
|
241
|
+
];
|
|
242
|
+
guidance.recommendations = [
|
|
243
|
+
'No behavior changes - tests must still pass',
|
|
244
|
+
'Use codemod scripts for large-scale changes',
|
|
245
|
+
'Generate semantic diff report',
|
|
246
|
+
'Keep commits small and atomic',
|
|
247
|
+
];
|
|
248
|
+
guidance.blockers = [
|
|
249
|
+
!spec.contracts?.length ? 'No contracts defined to prove unchanged behavior' : null,
|
|
250
|
+
].filter(Boolean);
|
|
251
|
+
} else if (mode === 'fix') {
|
|
252
|
+
guidance.phase = 'Bug Fix';
|
|
253
|
+
guidance.completed = ['Working specification created', 'Bug reproduced'];
|
|
254
|
+
guidance.nextActions = [
|
|
255
|
+
'Write failing test that reproduces the bug',
|
|
256
|
+
'Implement minimal fix',
|
|
257
|
+
'Verify test passes',
|
|
258
|
+
'Add regression tests',
|
|
259
|
+
];
|
|
260
|
+
guidance.recommendations = [
|
|
261
|
+
'Keep fix scope minimal',
|
|
262
|
+
'Document root cause in working spec',
|
|
263
|
+
'Add edge case tests to prevent recurrence',
|
|
264
|
+
'Consider if similar bugs exist elsewhere',
|
|
265
|
+
];
|
|
266
|
+
} else if (mode === 'doc') {
|
|
267
|
+
guidance.phase = 'Documentation';
|
|
268
|
+
guidance.completed = ['Working specification created'];
|
|
269
|
+
guidance.nextActions = [
|
|
270
|
+
'Update README with current information',
|
|
271
|
+
'Add code examples and usage snippets',
|
|
272
|
+
'Update API documentation',
|
|
273
|
+
'Review and update troubleshooting guides',
|
|
274
|
+
];
|
|
275
|
+
guidance.recommendations = [
|
|
276
|
+
'Use Mermaid for diagrams',
|
|
277
|
+
'Include code examples that actually work',
|
|
278
|
+
'Keep docs in sync with code',
|
|
279
|
+
'Add links to related documentation',
|
|
280
|
+
];
|
|
281
|
+
} else if (mode === 'chore') {
|
|
282
|
+
guidance.phase = 'Maintenance';
|
|
283
|
+
guidance.completed = ['Working specification created'];
|
|
284
|
+
guidance.nextActions = [
|
|
285
|
+
'Update dependencies to latest versions',
|
|
286
|
+
'Run tests to ensure compatibility',
|
|
287
|
+
'Update CI/CD configurations',
|
|
288
|
+
'Commit changes with descriptive message',
|
|
289
|
+
];
|
|
290
|
+
guidance.recommendations = [
|
|
291
|
+
'Review changelogs for breaking changes',
|
|
292
|
+
'Test locally before committing',
|
|
293
|
+
'Update lockfiles',
|
|
294
|
+
'Document any configuration changes',
|
|
295
|
+
];
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Check for common blockers
|
|
299
|
+
if (!fs.existsSync(path.join(process.cwd(), 'package.json'))) {
|
|
300
|
+
guidance.blockers.push('No package.json found');
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (spec.change_budget && !spec.change_budget.max_files) {
|
|
304
|
+
guidance.blockers.push('Change budget not defined');
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return guidance;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Get quality gates for risk tier
|
|
312
|
+
*/
|
|
313
|
+
function getQualityGates(riskTier) {
|
|
314
|
+
const gates = {
|
|
315
|
+
1: [
|
|
316
|
+
'Branch coverage ā„ 90%',
|
|
317
|
+
'Mutation score ā„ 70%',
|
|
318
|
+
'All contract tests passing',
|
|
319
|
+
'Manual code review completed',
|
|
320
|
+
'No SAST/secret scan violations',
|
|
321
|
+
'Performance budgets met',
|
|
322
|
+
],
|
|
323
|
+
2: [
|
|
324
|
+
'Branch coverage ā„ 80%',
|
|
325
|
+
'Mutation score ā„ 50%',
|
|
326
|
+
'Contract tests passing (if external APIs)',
|
|
327
|
+
'E2E smoke tests passing',
|
|
328
|
+
'No security violations',
|
|
329
|
+
],
|
|
330
|
+
3: [
|
|
331
|
+
'Branch coverage ā„ 70%',
|
|
332
|
+
'Mutation score ā„ 30%',
|
|
333
|
+
'Integration happy-path tests passing',
|
|
334
|
+
'Linting passing',
|
|
335
|
+
],
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
return gates[riskTier] || gates[2];
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
module.exports = { iterateCommand };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quality monitor command handler
|
|
3
|
+
*
|
|
4
|
+
* @param {string} action - Type of action to monitor
|
|
5
|
+
* @param {object} options - Command options
|
|
6
|
+
*/
|
|
7
|
+
export function qualityMonitorCommand(action: string, options?: object): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Analyze quality impact of an action
|
|
10
|
+
*
|
|
11
|
+
* @param {string} action - Type of action (file_saved, code_edited, test_run)
|
|
12
|
+
* @param {array} files - Files affected by the action
|
|
13
|
+
* @param {object} context - Additional context information
|
|
14
|
+
* @returns {object} Quality analysis
|
|
15
|
+
*/
|
|
16
|
+
export function analyzeQualityImpact(action: string, files?: any[], context?: object): object;
|
|
17
|
+
//# sourceMappingURL=quality-monitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quality-monitor.d.ts","sourceRoot":"","sources":["../../src/commands/quality-monitor.js"],"names":[],"mappings":"AAoIA;;;;;GAKG;AACH,8CAHW,MAAM,YACN,MAAM,iBA2HhB;AArPD;;;;;;;GAOG;AACH,6CALW,MAAM,2BAEN,MAAM,GACJ,MAAM,CA8GlB"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CAWS Quality Monitor Command
|
|
3
|
+
*
|
|
4
|
+
* Monitors code quality impact in real-time based on development actions.
|
|
5
|
+
* Provides actionable recommendations for maintaining quality standards.
|
|
6
|
+
*
|
|
7
|
+
* @author @darianrosebrook
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const chalk = require('chalk');
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
const yaml = require('js-yaml');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Analyze quality impact of an action
|
|
17
|
+
*
|
|
18
|
+
* @param {string} action - Type of action (file_saved, code_edited, test_run)
|
|
19
|
+
* @param {array} files - Files affected by the action
|
|
20
|
+
* @param {object} context - Additional context information
|
|
21
|
+
* @returns {object} Quality analysis
|
|
22
|
+
*/
|
|
23
|
+
function analyzeQualityImpact(action, files = [], context = {}) {
|
|
24
|
+
const analysis = {
|
|
25
|
+
action,
|
|
26
|
+
files_affected: files?.length || 0,
|
|
27
|
+
quality_impact: 'unknown',
|
|
28
|
+
recommendations: [],
|
|
29
|
+
risk_level: 'low',
|
|
30
|
+
timestamp: new Date().toISOString(),
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Analyze based on action type
|
|
34
|
+
switch (action) {
|
|
35
|
+
case 'file_saved':
|
|
36
|
+
analysis.quality_impact = 'code_change';
|
|
37
|
+
analysis.recommendations = [
|
|
38
|
+
'Run CAWS validation: caws evaluate',
|
|
39
|
+
'Check for linting issues',
|
|
40
|
+
'Verify test coverage if applicable',
|
|
41
|
+
];
|
|
42
|
+
break;
|
|
43
|
+
|
|
44
|
+
case 'code_edited':
|
|
45
|
+
analysis.quality_impact = 'implementation_change';
|
|
46
|
+
analysis.recommendations = [
|
|
47
|
+
'Run unit tests for affected files',
|
|
48
|
+
'Check CAWS quality gates',
|
|
49
|
+
'Update documentation if public APIs changed',
|
|
50
|
+
];
|
|
51
|
+
analysis.risk_level = files?.length > 5 ? 'medium' : 'low';
|
|
52
|
+
|
|
53
|
+
// Add file-specific recommendations
|
|
54
|
+
if (files.length > 0) {
|
|
55
|
+
const hasTests = files.some((f) => f.includes('test') || f.includes('spec'));
|
|
56
|
+
const hasConfig = files.some((f) => f.includes('config') || f.includes('.json'));
|
|
57
|
+
|
|
58
|
+
if (hasTests) {
|
|
59
|
+
analysis.recommendations.push('Run full test suite to ensure consistency');
|
|
60
|
+
}
|
|
61
|
+
if (hasConfig) {
|
|
62
|
+
analysis.risk_level = 'high';
|
|
63
|
+
analysis.recommendations.unshift('Configuration changed - validate carefully');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
break;
|
|
67
|
+
|
|
68
|
+
case 'test_run':
|
|
69
|
+
analysis.quality_impact = 'validation_complete';
|
|
70
|
+
analysis.recommendations = [
|
|
71
|
+
'Review test results',
|
|
72
|
+
'Address any failing tests',
|
|
73
|
+
'Update CAWS working spec if needed',
|
|
74
|
+
];
|
|
75
|
+
break;
|
|
76
|
+
|
|
77
|
+
default:
|
|
78
|
+
analysis.quality_impact = 'unknown_action';
|
|
79
|
+
analysis.recommendations = ['Run CAWS evaluation to assess impact'];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Load working spec to check risk tier
|
|
83
|
+
try {
|
|
84
|
+
const specPath = path.join(process.cwd(), '.caws/working-spec.yaml');
|
|
85
|
+
if (fs.existsSync(specPath)) {
|
|
86
|
+
const spec = yaml.load(fs.readFileSync(specPath, 'utf8'));
|
|
87
|
+
const projectTier = spec.risk_tier;
|
|
88
|
+
|
|
89
|
+
analysis.project_tier = projectTier;
|
|
90
|
+
|
|
91
|
+
// Add context-specific recommendations for high-risk projects
|
|
92
|
+
if (projectTier <= 2) {
|
|
93
|
+
analysis.recommendations.unshift(
|
|
94
|
+
'High-risk project (Tier ' + projectTier + '): Run comprehensive validation'
|
|
95
|
+
);
|
|
96
|
+
if (analysis.risk_level === 'low') {
|
|
97
|
+
analysis.risk_level = 'medium';
|
|
98
|
+
} else if (analysis.risk_level === 'medium') {
|
|
99
|
+
analysis.risk_level = 'high';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Add tier-specific quality gates
|
|
104
|
+
if (projectTier === 1) {
|
|
105
|
+
analysis.quality_gates = [
|
|
106
|
+
'Branch coverage ā„ 90%',
|
|
107
|
+
'Mutation score ā„ 70%',
|
|
108
|
+
'All contract tests passing',
|
|
109
|
+
'Manual code review required',
|
|
110
|
+
];
|
|
111
|
+
} else if (projectTier === 2) {
|
|
112
|
+
analysis.quality_gates = [
|
|
113
|
+
'Branch coverage ā„ 80%',
|
|
114
|
+
'Mutation score ā„ 50%',
|
|
115
|
+
'Contract tests passing (if applicable)',
|
|
116
|
+
];
|
|
117
|
+
} else {
|
|
118
|
+
analysis.quality_gates = ['Branch coverage ā„ 70%', 'Mutation score ā„ 30%'];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} catch (error) {
|
|
122
|
+
// Ignore if we can't load spec
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Add context-based recommendations
|
|
126
|
+
if (context.project_tier) {
|
|
127
|
+
analysis.project_tier = context.project_tier;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return analysis;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Quality monitor command handler
|
|
135
|
+
*
|
|
136
|
+
* @param {string} action - Type of action to monitor
|
|
137
|
+
* @param {object} options - Command options
|
|
138
|
+
*/
|
|
139
|
+
async function qualityMonitorCommand(action, options = {}) {
|
|
140
|
+
try {
|
|
141
|
+
// Parse files if provided
|
|
142
|
+
let files = [];
|
|
143
|
+
if (options.files) {
|
|
144
|
+
files =
|
|
145
|
+
typeof options.files === 'string'
|
|
146
|
+
? options.files.split(',').map((f) => f.trim())
|
|
147
|
+
: options.files;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Parse context if provided
|
|
151
|
+
let context = {};
|
|
152
|
+
if (options.context) {
|
|
153
|
+
try {
|
|
154
|
+
context =
|
|
155
|
+
typeof options.context === 'string' ? JSON.parse(options.context) : options.context;
|
|
156
|
+
} catch (e) {
|
|
157
|
+
console.warn(chalk.yellow('ā ļø Invalid context JSON, ignoring'));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Validate action
|
|
162
|
+
const validActions = ['file_saved', 'code_edited', 'test_run'];
|
|
163
|
+
if (!validActions.includes(action)) {
|
|
164
|
+
console.error(chalk.red(`\nā Invalid action: ${action}`));
|
|
165
|
+
console.log(chalk.blue('\nš” Valid actions:'));
|
|
166
|
+
validActions.forEach((a) => {
|
|
167
|
+
console.log(chalk.blue(` ⢠${a}`));
|
|
168
|
+
});
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Analyze quality impact
|
|
173
|
+
const analysis = analyzeQualityImpact(action, files, context);
|
|
174
|
+
|
|
175
|
+
// Display results
|
|
176
|
+
console.log(chalk.bold('\nš CAWS Quality Monitor\n'));
|
|
177
|
+
console.log('ā'.repeat(60));
|
|
178
|
+
|
|
179
|
+
// Action info
|
|
180
|
+
console.log(chalk.bold(`\nAction: ${action}`));
|
|
181
|
+
console.log(chalk.gray(`Time: ${new Date(analysis.timestamp).toLocaleString()}`));
|
|
182
|
+
|
|
183
|
+
if (analysis.files_affected > 0) {
|
|
184
|
+
console.log(chalk.bold(`\nFiles Affected: ${analysis.files_affected}`));
|
|
185
|
+
if (files.length > 0 && files.length <= 10) {
|
|
186
|
+
files.forEach((file) => {
|
|
187
|
+
console.log(chalk.gray(` ⢠${file}`));
|
|
188
|
+
});
|
|
189
|
+
} else if (files.length > 10) {
|
|
190
|
+
files.slice(0, 10).forEach((file) => {
|
|
191
|
+
console.log(chalk.gray(` ⢠${file}`));
|
|
192
|
+
});
|
|
193
|
+
console.log(chalk.gray(` ... and ${files.length - 10} more`));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Quality impact
|
|
198
|
+
const impactColor =
|
|
199
|
+
analysis.quality_impact === 'validation_complete'
|
|
200
|
+
? chalk.green
|
|
201
|
+
: analysis.quality_impact === 'code_change'
|
|
202
|
+
? chalk.yellow
|
|
203
|
+
: chalk.blue;
|
|
204
|
+
|
|
205
|
+
console.log(chalk.bold('\nš Quality Impact:'));
|
|
206
|
+
console.log(impactColor(` ${analysis.quality_impact}`));
|
|
207
|
+
|
|
208
|
+
// Risk level
|
|
209
|
+
const riskColor =
|
|
210
|
+
analysis.risk_level === 'high'
|
|
211
|
+
? chalk.red
|
|
212
|
+
: analysis.risk_level === 'medium'
|
|
213
|
+
? chalk.yellow
|
|
214
|
+
: chalk.green;
|
|
215
|
+
|
|
216
|
+
console.log(chalk.bold('\nā ļø Risk Level:'));
|
|
217
|
+
console.log(riskColor(` ${analysis.risk_level.toUpperCase()}`));
|
|
218
|
+
|
|
219
|
+
// Project tier
|
|
220
|
+
if (analysis.project_tier) {
|
|
221
|
+
console.log(chalk.bold(`\nšÆ Project Tier: ${analysis.project_tier}`));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Quality gates
|
|
225
|
+
if (analysis.quality_gates && analysis.quality_gates.length > 0) {
|
|
226
|
+
console.log(chalk.bold('\nšŖ Quality Gates to Check:\n'));
|
|
227
|
+
analysis.quality_gates.forEach((gate) => {
|
|
228
|
+
console.log(chalk.gray(` ā” ${gate}`));
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Recommendations
|
|
233
|
+
console.log(chalk.bold('\nš” Recommendations:\n'));
|
|
234
|
+
analysis.recommendations.forEach((rec, idx) => {
|
|
235
|
+
const icon = idx === 0 ? 'ā”' : ' ā¢';
|
|
236
|
+
console.log(chalk.blue(` ${icon} ${rec}`));
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
// Suggested commands
|
|
240
|
+
console.log(chalk.bold('\nš Suggested Commands:\n'));
|
|
241
|
+
switch (action) {
|
|
242
|
+
case 'file_saved':
|
|
243
|
+
case 'code_edited':
|
|
244
|
+
console.log(chalk.gray(' caws evaluate - Check quality score'));
|
|
245
|
+
console.log(chalk.gray(' caws validate - Run validation'));
|
|
246
|
+
console.log(chalk.gray(' caws diagnose - Health check'));
|
|
247
|
+
break;
|
|
248
|
+
case 'test_run':
|
|
249
|
+
console.log(chalk.gray(' caws status - Project status'));
|
|
250
|
+
console.log(chalk.gray(' caws iterate - Next steps'));
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.log('\n' + 'ā'.repeat(60) + '\n');
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error(chalk.red(`\nā Quality monitoring failed: ${error.message}`));
|
|
257
|
+
console.error(chalk.gray(error.stack));
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
module.exports = {
|
|
263
|
+
qualityMonitorCommand,
|
|
264
|
+
analyzeQualityImpact,
|
|
265
|
+
};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Status command handler
|
|
3
3
|
* @param {Object} options - Command options
|
|
4
4
|
*/
|
|
5
|
-
export function statusCommand(options?: any): Promise<
|
|
5
|
+
export function statusCommand(options?: any): Promise<any>;
|
|
6
6
|
/**
|
|
7
7
|
* Load working specification
|
|
8
8
|
* @param {string} specPath - Path to working spec
|
|
@@ -19,6 +19,11 @@ export function checkGitHooks(): Promise<any>;
|
|
|
19
19
|
* @returns {Promise<Object>} Provenance status
|
|
20
20
|
*/
|
|
21
21
|
export function loadProvenanceChain(): Promise<any>;
|
|
22
|
+
/**
|
|
23
|
+
* Load waiver status
|
|
24
|
+
* @returns {Promise<Object>} Waiver status
|
|
25
|
+
*/
|
|
26
|
+
export function loadWaiverStatus(): Promise<any>;
|
|
22
27
|
/**
|
|
23
28
|
* Check quality gates status (simplified)
|
|
24
29
|
* @returns {Promise<Object>} Quality gates status
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.js"],"names":[],"mappings":"AAuUA;;;GAGG;AACH,2DAiCC;AAhWD;;;;GAIG;AACH,2CAHW,MAAM,GACJ,OAAO,CAAC,MAAO,IAAI,CAAC,CAahC;AAED;;;GAGG;AACH,iCAFa,OAAO,KAAQ,CAgC3B;AAED;;;GAGG;AACH,uCAFa,OAAO,KAAQ,CA+B3B;AAED;;;GAGG;AACH,oCAFa,OAAO,KAAQ,CA0D3B;AAED;;;GAGG;AACH,qCAFa,OAAO,KAAQ,CAS3B;AAwBD;;;GAGG;AACH,+CAgGC;AAED;;;;GAIG;AACH,gDAFa,MAAM,EAAE,CAsBpB"}
|