@paths.design/caws-cli 3.3.0 → 3.4.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.
Files changed (38) hide show
  1. package/dist/commands/diagnose.d.ts.map +1 -1
  2. package/dist/commands/diagnose.js +39 -4
  3. package/dist/commands/evaluate.d.ts +8 -0
  4. package/dist/commands/evaluate.d.ts.map +1 -0
  5. package/dist/commands/evaluate.js +288 -0
  6. package/dist/commands/iterate.d.ts +8 -0
  7. package/dist/commands/iterate.d.ts.map +1 -0
  8. package/dist/commands/iterate.js +341 -0
  9. package/dist/commands/quality-monitor.d.ts +17 -0
  10. package/dist/commands/quality-monitor.d.ts.map +1 -0
  11. package/dist/commands/quality-monitor.js +265 -0
  12. package/dist/commands/status.d.ts +6 -1
  13. package/dist/commands/status.d.ts.map +1 -1
  14. package/dist/commands/status.js +120 -20
  15. package/dist/commands/troubleshoot.d.ts +8 -0
  16. package/dist/commands/troubleshoot.d.ts.map +1 -0
  17. package/dist/commands/troubleshoot.js +104 -0
  18. package/dist/commands/waivers.d.ts +8 -0
  19. package/dist/commands/waivers.d.ts.map +1 -0
  20. package/dist/commands/waivers.js +293 -0
  21. package/dist/commands/workflow.d.ts +85 -0
  22. package/dist/commands/workflow.d.ts.map +1 -0
  23. package/dist/commands/workflow.js +243 -0
  24. package/dist/error-handler.d.ts +91 -2
  25. package/dist/error-handler.d.ts.map +1 -1
  26. package/dist/error-handler.js +362 -16
  27. package/dist/index.js +95 -0
  28. package/dist/scaffold/index.d.ts.map +1 -1
  29. package/dist/scaffold/index.js +13 -0
  30. package/dist/utils/typescript-detector.d.ts +31 -0
  31. package/dist/utils/typescript-detector.d.ts.map +1 -1
  32. package/dist/utils/typescript-detector.js +245 -7
  33. package/package.json +5 -4
  34. package/templates/OIDC_SETUP.md +300 -0
  35. package/templates/agents.md +912 -686
  36. package/templates/apps/tools/caws/gates.ts +34 -0
  37. package/templates/apps/tools/caws/shared/gate-checker.ts +265 -13
  38. package/templates/apps/tools/caws/templates/working-spec.template.yml +14 -0
@@ -1 +1 @@
1
- {"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/commands/diagnose.js"],"names":[],"mappings":"AAoZA;;;GAGG;AACH,8DAiDC;AApMD;;;GAGG;AACH,gCAFa,OAAO,KAAQ,CAkD3B;AAED;;;GAGG;AACH,wCAFW,KAAQ,QA4BlB;AAED;;;;GAIG;AACH,wCAHW,KAAQ,GACN,OAAO,KAAQ,CAoD3B;AAnYD;;;GAGG;AACH,oCAFa,OAAO,KAAQ,CA2C3B;AAED;;;GAGG;AACH,iCAFa,OAAO,KAAQ,CAiB3B;AAED;;;GAGG;AACH,iCAFa,OAAO,KAAQ,CA0C3B;AAED;;;GAGG;AACH,yCAFa,OAAO,KAAQ,CA6C3B;AAED;;;GAGG;AACH,kCAFa,OAAO,KAAQ,CAoC3B;AAED;;;GAGG;AACH,kCAFa,OAAO,KAAQ,CAuC3B"}
1
+ {"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/commands/diagnose.js"],"names":[],"mappings":"AAubA;;;GAGG;AACH,8DAiDC;AApND;;;GAGG;AACH,gCAFa,OAAO,KAAQ,CAkD3B;AAED;;;GAGG;AACH,wCAFW,KAAQ,QA4ClB;AAED;;;;GAIG;AACH,wCAHW,KAAQ,GACN,OAAO,KAAQ,CAoD3B;AAtaD;;;GAGG;AACH,oCAFa,OAAO,KAAQ,CA2C3B;AAED;;;GAGG;AACH,iCAFa,OAAO,KAAQ,CAiB3B;AAED;;;GAGG;AACH,iCAFa,OAAO,KAAQ,CA0C3B;AAED;;;GAGG;AACH,yCAFa,OAAO,KAAQ,CAgE3B;AAED;;;GAGG;AACH,kCAFa,OAAO,KAAQ,CAoC3B;AAED;;;GAGG;AACH,kCAFa,OAAO,KAAQ,CAuC3B"}
@@ -142,11 +142,17 @@ async function checkTypeScriptConfig() {
142
142
  };
143
143
  }
144
144
 
145
+ // If we have workspaces, provide context about where the TypeScript setup was found
146
+ let messageSuffix = '';
147
+ if (tsConfig.workspaceInfo.hasWorkspaces && tsConfig.workspaceInfo.primaryWorkspace) {
148
+ messageSuffix = ` (detected in workspace: ${tsConfig.workspaceInfo.primaryWorkspace})`;
149
+ }
150
+
145
151
  if (tsConfig.needsJestConfig) {
146
152
  return {
147
153
  passed: false,
148
154
  severity: 'medium',
149
- message: 'TypeScript project missing Jest configuration',
155
+ message: `TypeScript project missing Jest configuration${messageSuffix}`,
150
156
  fix: 'Auto-configure Jest for TypeScript',
151
157
  autoFixable: true,
152
158
  autoFix: async () => {
@@ -161,18 +167,31 @@ async function checkTypeScriptConfig() {
161
167
  }
162
168
 
163
169
  if (tsConfig.needsTsJest) {
170
+ const workspaceContext = tsConfig.workspaceInfo.primaryWorkspace
171
+ ? ` (in workspace: ${tsConfig.workspaceInfo.primaryWorkspace})`
172
+ : '';
173
+
164
174
  return {
165
175
  passed: false,
166
176
  severity: 'high',
167
- message: 'TypeScript + Jest detected but missing ts-jest',
168
- fix: 'Install ts-jest: npm install --save-dev ts-jest',
177
+ message: `TypeScript + Jest detected but missing ts-jest${workspaceContext}`,
178
+ fix: `Install ts-jest in ${tsConfig.workspaceInfo.primaryWorkspace || 'root'}: npm install --save-dev ts-jest`,
169
179
  autoFixable: false,
180
+ details: {
181
+ searchedLocations: tsConfig.workspaceInfo.primaryWorkspace
182
+ ? [`${tsConfig.workspaceInfo.primaryWorkspace}/package.json`]
183
+ : ['package.json'],
184
+ frameworkDetected: tsConfig.testFramework.framework,
185
+ hasJest: tsConfig.testFramework.hasJest,
186
+ hasTsJest: tsConfig.testFramework.hasTsJest,
187
+ workspacesChecked: tsConfig.workspaceInfo.allWorkspaces,
188
+ },
170
189
  };
171
190
  }
172
191
 
173
192
  return {
174
193
  passed: true,
175
- message: 'TypeScript configuration is correct',
194
+ message: `TypeScript configuration is correct${messageSuffix}`,
176
195
  };
177
196
  }
178
197
 
@@ -341,6 +360,22 @@ function displayResults(results) {
341
360
  console.log(chalk.green(' ✨ Auto-fix available'));
342
361
  }
343
362
 
363
+ // Show additional details if available
364
+ if (issue.details) {
365
+ console.log(chalk.gray(' Details:'));
366
+ if (issue.details.searchedLocations) {
367
+ console.log(chalk.gray(` Searched: ${issue.details.searchedLocations.join(', ')}`));
368
+ }
369
+ if (issue.details.frameworkDetected) {
370
+ console.log(chalk.gray(` Framework: ${issue.details.frameworkDetected}`));
371
+ }
372
+ if (issue.details.workspacesChecked && issue.details.workspacesChecked.length > 0) {
373
+ console.log(
374
+ chalk.gray(` Workspaces checked: ${issue.details.workspacesChecked.join(', ')}`)
375
+ );
376
+ }
377
+ }
378
+
344
379
  console.log('');
345
380
  });
346
381
  }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Evaluate command handler
3
+ *
4
+ * @param {string} specFile - Path to working spec file
5
+ * @param {object} options - Command options
6
+ */
7
+ export function evaluateCommand(specFile?: string, options?: object): Promise<void>;
8
+ //# sourceMappingURL=evaluate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/commands/evaluate.js"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,2CAHW,MAAM,YACN,MAAM,iBA0QhB"}
@@ -0,0 +1,288 @@
1
+ /**
2
+ * CAWS Evaluate Command
3
+ *
4
+ * Evaluates work against CAWS quality standards and provides
5
+ * actionable feedback on meeting acceptance criteria.
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
+ * Evaluate command handler
18
+ *
19
+ * @param {string} specFile - Path to working spec file
20
+ * @param {object} options - Command options
21
+ */
22
+ async function evaluateCommand(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
+ console.log(chalk.blue('\nšŸ“Š Evaluating CAWS Quality Standards\n'));
45
+ console.log('─'.repeat(60));
46
+
47
+ // Evaluation results
48
+ const results = {
49
+ score: 0,
50
+ maxScore: 0,
51
+ checks: [],
52
+ recommendations: [],
53
+ warnings: [],
54
+ };
55
+
56
+ // 1. Check working spec validity
57
+ results.maxScore += 10;
58
+ if (spec.id && spec.title && spec.risk_tier && spec.mode) {
59
+ results.score += 10;
60
+ results.checks.push({ name: 'Working Spec Structure', status: 'pass', points: 10 });
61
+ } else {
62
+ results.checks.push({ name: 'Working Spec Structure', status: 'fail', points: 0 });
63
+ results.warnings.push('Working spec missing required fields');
64
+ }
65
+
66
+ // 2. Check acceptance criteria
67
+ results.maxScore += 15;
68
+ if (spec.acceptance && spec.acceptance.length > 0) {
69
+ const validCriteria = spec.acceptance.filter((a) => a.id && a.given && a.when && a.then);
70
+ const criteriaScore = Math.floor((validCriteria.length / spec.acceptance.length) * 15);
71
+ results.score += criteriaScore;
72
+ results.checks.push({
73
+ name: 'Acceptance Criteria',
74
+ status: criteriaScore === 15 ? 'pass' : 'partial',
75
+ points: criteriaScore,
76
+ detail: `${validCriteria.length}/${spec.acceptance.length} complete`,
77
+ });
78
+
79
+ if (criteriaScore < 15) {
80
+ results.recommendations.push(
81
+ 'Complete all acceptance criteria with Given-When-Then format'
82
+ );
83
+ }
84
+ } else {
85
+ results.checks.push({ name: 'Acceptance Criteria', status: 'fail', points: 0 });
86
+ results.warnings.push('No acceptance criteria defined');
87
+ }
88
+
89
+ // 3. Check scope definition
90
+ results.maxScore += 10;
91
+ if (spec.scope && spec.scope.in && spec.scope.in.length > 0) {
92
+ results.score += 10;
93
+ results.checks.push({ name: 'Scope Definition', status: 'pass', points: 10 });
94
+ } else {
95
+ results.checks.push({ name: 'Scope Definition', status: 'fail', points: 0 });
96
+ results.warnings.push('Scope not clearly defined');
97
+ }
98
+
99
+ // 4. Check change budget
100
+ results.maxScore += 10;
101
+ if (spec.change_budget && spec.change_budget.max_files && spec.change_budget.max_loc) {
102
+ results.score += 10;
103
+ results.checks.push({ name: 'Change Budget', status: 'pass', points: 10 });
104
+ } else {
105
+ results.checks.push({ name: 'Change Budget', status: 'fail', points: 0 });
106
+ results.recommendations.push('Define change budget (max_files, max_loc)');
107
+ }
108
+
109
+ // 5. Check invariants
110
+ results.maxScore += 10;
111
+ if (spec.invariants && spec.invariants.length > 0) {
112
+ results.score += 10;
113
+ results.checks.push({ name: 'System Invariants', status: 'pass', points: 10 });
114
+ } else {
115
+ results.checks.push({ name: 'System Invariants', status: 'partial', points: 5 });
116
+ results.recommendations.push('Define system invariants to maintain');
117
+ }
118
+
119
+ // 6. Check non-functional requirements
120
+ results.maxScore += 15;
121
+ let nfrScore = 0;
122
+ if (spec.non_functional) {
123
+ if (spec.non_functional.a11y && spec.non_functional.a11y.length > 0) nfrScore += 5;
124
+ if (spec.non_functional.perf && spec.non_functional.perf.api_p95_ms) nfrScore += 5;
125
+ if (spec.non_functional.security && spec.non_functional.security.length > 0) nfrScore += 5;
126
+ }
127
+ results.score += nfrScore;
128
+ results.checks.push({
129
+ name: 'Non-Functional Requirements',
130
+ status: nfrScore === 15 ? 'pass' : 'partial',
131
+ points: nfrScore,
132
+ });
133
+
134
+ if (nfrScore < 15) {
135
+ results.recommendations.push('Define a11y, performance, and security requirements');
136
+ }
137
+
138
+ // 7. Check rollback plan
139
+ results.maxScore += 10;
140
+ if (spec.rollback && spec.rollback.length > 0) {
141
+ results.score += 10;
142
+ results.checks.push({ name: 'Rollback Plan', status: 'pass', points: 10 });
143
+ } else {
144
+ results.checks.push({ name: 'Rollback Plan', status: 'fail', points: 0 });
145
+ results.recommendations.push('Document rollback procedures');
146
+ }
147
+
148
+ // 8. Check observability
149
+ results.maxScore += 10;
150
+ if (
151
+ spec.observability &&
152
+ (spec.observability.logs?.length > 0 ||
153
+ spec.observability.metrics?.length > 0 ||
154
+ spec.observability.traces?.length > 0)
155
+ ) {
156
+ results.score += 10;
157
+ results.checks.push({ name: 'Observability', status: 'pass', points: 10 });
158
+ } else {
159
+ results.checks.push({ name: 'Observability', status: 'partial', points: 3 });
160
+ results.recommendations.push('Define logging, metrics, and tracing strategy');
161
+ }
162
+
163
+ // 9. Risk tier appropriateness
164
+ results.maxScore += 10;
165
+ const hasCriticalScope = spec.blast_radius?.modules?.some(
166
+ (m) => m.includes('auth') || m.includes('payment') || m.includes('billing')
167
+ );
168
+ const hasDataMigration = spec.blast_radius?.data_migration === true;
169
+
170
+ if (hasCriticalScope || hasDataMigration) {
171
+ if (spec.risk_tier === 1) {
172
+ results.score += 10;
173
+ results.checks.push({ name: 'Risk Tier Appropriateness', status: 'pass', points: 10 });
174
+ } else {
175
+ results.checks.push({ name: 'Risk Tier Appropriateness', status: 'fail', points: 0 });
176
+ results.warnings.push(`Risk tier ${spec.risk_tier} may be too low for critical changes`);
177
+ }
178
+ } else {
179
+ results.score += 10;
180
+ results.checks.push({ name: 'Risk Tier Appropriateness', status: 'pass', points: 10 });
181
+ }
182
+
183
+ // Display results
184
+ console.log('\nšŸ“‹ Quality Checks:\n');
185
+ results.checks.forEach((check) => {
186
+ const icon = check.status === 'pass' ? 'āœ…' : check.status === 'partial' ? 'āš ļø' : 'āŒ';
187
+ const detail = check.detail ? ` (${check.detail})` : '';
188
+ console.log(
189
+ `${icon} ${check.name}: ${check.points}/${results.maxScore / results.checks.length}${detail}`
190
+ );
191
+ });
192
+
193
+ // Calculate percentage
194
+ const percentage = Math.round((results.score / results.maxScore) * 100);
195
+ const grade =
196
+ percentage >= 90
197
+ ? 'A'
198
+ : percentage >= 80
199
+ ? 'B'
200
+ : percentage >= 70
201
+ ? 'C'
202
+ : percentage >= 60
203
+ ? 'D'
204
+ : 'F';
205
+
206
+ console.log('\n' + '─'.repeat(60));
207
+ console.log(
208
+ chalk.bold(
209
+ `\nšŸ“Š Overall Score: ${results.score}/${results.maxScore} (${percentage}%) - Grade: ${grade}\n`
210
+ )
211
+ );
212
+
213
+ // Display warnings
214
+ if (results.warnings.length > 0) {
215
+ console.log(chalk.yellow('āš ļø Warnings:\n'));
216
+ results.warnings.forEach((warning) => {
217
+ console.log(chalk.yellow(` • ${warning}`));
218
+ });
219
+ console.log();
220
+ }
221
+
222
+ // Display recommendations
223
+ if (results.recommendations.length > 0) {
224
+ console.log(chalk.blue('šŸ’” Recommendations:\n'));
225
+ results.recommendations.forEach((rec) => {
226
+ console.log(chalk.blue(` • ${rec}`));
227
+ });
228
+ console.log();
229
+ }
230
+
231
+ // Risk tier specific guidance
232
+ console.log(chalk.bold(`\nšŸŽÆ Risk Tier ${spec.risk_tier} Requirements:\n`));
233
+
234
+ const tierRequirements = {
235
+ 1: {
236
+ coverage: '90%+',
237
+ mutation: '70%+',
238
+ contracts: 'Required',
239
+ review: 'Manual code review required',
240
+ },
241
+ 2: {
242
+ coverage: '80%+',
243
+ mutation: '50%+',
244
+ contracts: 'Required for external APIs',
245
+ review: 'Optional',
246
+ },
247
+ 3: {
248
+ coverage: '70%+',
249
+ mutation: '30%+',
250
+ contracts: 'Optional',
251
+ review: 'Optional',
252
+ },
253
+ };
254
+
255
+ const req = tierRequirements[spec.risk_tier] || tierRequirements[2];
256
+ console.log(` Branch Coverage: ${req.coverage}`);
257
+ console.log(` Mutation Score: ${req.mutation}`);
258
+ console.log(` Contract Tests: ${req.contracts}`);
259
+ console.log(` Code Review: ${req.review}`);
260
+
261
+ console.log(chalk.blue('\nšŸ“š Next Steps:\n'));
262
+ console.log(' 1. Address warnings and recommendations above');
263
+ console.log(' 2. Implement acceptance criteria with tests');
264
+ console.log(' 3. Run: caws validate to check spec validity');
265
+ console.log(' 4. Run: caws diagnose for health checks');
266
+ console.log(' 5. Ensure test coverage meets risk tier requirements');
267
+
268
+ // Exit with appropriate code
269
+ if (percentage < 70) {
270
+ console.log(
271
+ chalk.red('\nāš ļø Quality score below 70% - improvements needed before proceeding\n')
272
+ );
273
+ process.exit(1);
274
+ } else if (percentage < 90) {
275
+ console.log(chalk.yellow('\nāš ļø Quality score acceptable but improvements recommended\n'));
276
+ } else {
277
+ console.log(chalk.green('\nāœ… Excellent quality score - ready to proceed!\n'));
278
+ }
279
+ } catch (error) {
280
+ console.error(chalk.red(`\nāŒ Evaluation failed: ${error.message}`));
281
+ if (options.verbose) {
282
+ console.error(error.stack);
283
+ }
284
+ process.exit(1);
285
+ }
286
+ }
287
+
288
+ module.exports = { evaluateCommand };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Iterate command handler
3
+ *
4
+ * @param {string} specFile - Path to working spec file
5
+ * @param {object} options - Command options
6
+ */
7
+ export function iterateCommand(specFile?: string, options?: object): Promise<void>;
8
+ //# sourceMappingURL=iterate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iterate.d.ts","sourceRoot":"","sources":["../../src/commands/iterate.js"],"names":[],"mappings":"AAeA;;;;;GAKG;AACH,0CAHW,MAAM,YACN,MAAM,iBAmLhB"}