@paths.design/caws-cli 7.0.1 → 7.0.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.
Files changed (121) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +26 -20
  3. package/dist/commands/init.js +72 -5
  4. package/dist/commands/specs.js +40 -1
  5. package/dist/commands/status.js +2 -2
  6. package/dist/commands/templates.js +10 -0
  7. package/dist/commands/tool.js +2 -3
  8. package/dist/commands/validate.js +12 -0
  9. package/dist/config/index.js +17 -8
  10. package/dist/generators/working-spec.js +42 -9
  11. package/dist/index.js +3 -1
  12. package/dist/scaffold/cursor-hooks.js +10 -2
  13. package/dist/scaffold/git-hooks.js +189 -32
  14. package/dist/scaffold/index.js +105 -17
  15. package/dist/templates/.caws/tools/README.md +20 -0
  16. package/dist/templates/.cursor/README.md +311 -0
  17. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  18. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  19. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  20. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  21. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  22. package/dist/templates/.cursor/hooks/format.sh +38 -0
  23. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  24. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  25. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  26. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  27. package/dist/templates/.cursor/hooks.json +59 -0
  28. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  29. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  30. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  31. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  32. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  33. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  34. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  35. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  36. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  37. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  38. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  39. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  40. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  41. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  42. package/dist/templates/.cursor/rules/README.md +148 -0
  43. package/dist/templates/.github/copilot/instructions.md +311 -0
  44. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  45. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  46. package/dist/templates/.vscode/launch.json +56 -0
  47. package/dist/templates/.vscode/settings.json +93 -0
  48. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  49. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  50. package/dist/templates/OIDC_SETUP.md +300 -0
  51. package/dist/templates/agents.md +1047 -0
  52. package/dist/templates/codemod/README.md +1 -0
  53. package/dist/templates/codemod/test.js +93 -0
  54. package/dist/templates/docs/README.md +150 -0
  55. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  56. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  57. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  58. package/dist/tool-loader.js +6 -1
  59. package/dist/tool-validator.js +8 -2
  60. package/dist/utils/detection.js +34 -6
  61. package/dist/utils/git-lock.js +118 -0
  62. package/dist/utils/gitignore-updater.js +148 -0
  63. package/dist/utils/quality-gates.js +47 -7
  64. package/dist/utils/spec-resolver.js +23 -3
  65. package/dist/utils/yaml-validation.js +155 -0
  66. package/dist/validation/spec-validation.js +105 -2
  67. package/package.json +2 -2
  68. package/templates/.caws/schemas/waivers.schema.json +30 -0
  69. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  70. package/templates/.caws/templates/working-spec.template.yml +74 -0
  71. package/templates/.caws/tools/README.md +20 -0
  72. package/templates/.caws/tools/scope-guard.js +208 -0
  73. package/templates/.caws/tools-allow.json +331 -0
  74. package/templates/.caws/waivers.yml +19 -0
  75. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  76. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  77. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  78. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  79. package/templates/apps/tools/caws/README.md +0 -463
  80. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  81. package/templates/apps/tools/caws/attest.js +0 -357
  82. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  83. package/templates/apps/tools/caws/config.ts +0 -245
  84. package/templates/apps/tools/caws/cross-functional.js +0 -876
  85. package/templates/apps/tools/caws/dashboard.js +0 -1112
  86. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  87. package/templates/apps/tools/caws/gates.js +0 -198
  88. package/templates/apps/tools/caws/gates.ts +0 -271
  89. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  90. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  91. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  92. package/templates/apps/tools/caws/language-support.js +0 -585
  93. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  94. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  95. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  96. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  97. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  98. package/templates/apps/tools/caws/property-testing.js +0 -707
  99. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  100. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  101. package/templates/apps/tools/caws/provenance.js +0 -132
  102. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  103. package/templates/apps/tools/caws/provenance.ts +0 -211
  104. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  105. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  106. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  107. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  108. package/templates/apps/tools/caws/shared/types.ts +0 -444
  109. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  110. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  111. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  112. package/templates/apps/tools/caws/test-quality.js +0 -578
  113. package/templates/apps/tools/caws/validate.js +0 -76
  114. package/templates/apps/tools/caws/validate.ts +0 -228
  115. package/templates/apps/tools/caws/waivers.js +0 -344
  116. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  117. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  118. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  119. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  120. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  121. /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
@@ -1,1112 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * @fileoverview CAWS Dashboard and Analytics Tool
5
- * Provides comprehensive visualization and analytics for CAWS trust metrics
6
- * @author @darianrosebrook
7
- */
8
-
9
- const fs = require('fs');
10
- const path = require('path');
11
-
12
- /**
13
- * Generate real provenance data for trust score calculation
14
- * @returns {Object} Real provenance data based on project analysis
15
- */
16
- function generateRealProvenanceData() {
17
- return {
18
- results: {
19
- coverage_branch: getRealCoverage(),
20
- mutation_score: getRealMutationScore(),
21
- contracts: {
22
- consumer: checkContractCompliance(),
23
- provider: checkContractCompliance(),
24
- },
25
- a11y: checkAccessibilityCompliance(),
26
- perf: checkPerformanceCompliance(),
27
- flake_rate: getRealFlakeRate(),
28
- mode_compliance: checkModeCompliance(),
29
- scope_within_budget: checkScopeCompliance(),
30
- sbom_valid: checkSBOMValidity(),
31
- attestation_valid: checkAttestationValidity(),
32
- },
33
- };
34
- }
35
-
36
- /**
37
- * Get real test coverage from coverage reports
38
- * @returns {number} Coverage percentage (0-1)
39
- */
40
- function getRealCoverage() {
41
- try {
42
- const coveragePath = path.join(process.cwd(), 'coverage', 'coverage-summary.json');
43
- if (fs.existsSync(coveragePath)) {
44
- const coverageData = JSON.parse(fs.readFileSync(coveragePath, 'utf8'));
45
- return coverageData.total.lines.pct / 100;
46
- }
47
- } catch (error) {
48
- // No coverage data available
49
- }
50
- return 0.75; // Default estimate
51
- }
52
-
53
- /**
54
- * Get real mutation score from mutation reports
55
- * @returns {number} Mutation score (0-1)
56
- */
57
- function getRealMutationScore() {
58
- try {
59
- const mutationPath = path.join(process.cwd(), 'reports', 'mutation', 'mutation.json');
60
- if (fs.existsSync(mutationPath)) {
61
- const mutationData = JSON.parse(fs.readFileSync(mutationPath, 'utf8'));
62
- let total = 0,
63
- killed = 0;
64
-
65
- Object.values(mutationData.files || {}).forEach((file) => {
66
- if (file.mutants) {
67
- file.mutants.forEach((mutant) => {
68
- total++;
69
- if (mutant.status === 'Killed') killed++;
70
- });
71
- }
72
- });
73
-
74
- return total > 0 ? killed / total : 0;
75
- }
76
- } catch (error) {
77
- // No mutation data available
78
- }
79
- return 0.55; // Default estimate
80
- }
81
-
82
- /**
83
- * Check contract compliance
84
- * @returns {boolean} Whether contracts are compliant
85
- */
86
- function checkContractCompliance() {
87
- try {
88
- // Check if contract tests exist and pass
89
- const contractTestsPath = path.join(process.cwd(), 'packages', 'caws-cli', 'tests', 'contract');
90
- return fs.existsSync(contractTestsPath);
91
- } catch (error) {
92
- return false;
93
- }
94
- }
95
-
96
- /**
97
- * Check accessibility compliance
98
- * @returns {string} Accessibility compliance status
99
- */
100
- function checkAccessibilityCompliance() {
101
- try {
102
- // Check if axe tests exist
103
- const axeTestsPath = path.join(process.cwd(), 'packages', 'caws-cli', 'tests', 'axe');
104
- return fs.existsSync(axeTestsPath) ? 'pass' : 'unknown';
105
- } catch (error) {
106
- return 'unknown';
107
- }
108
- }
109
-
110
- /**
111
- * Check performance compliance
112
- * @returns {Object} Performance metrics
113
- */
114
- function checkPerformanceCompliance() {
115
- try {
116
- // Check if performance budgets exist
117
- const perfTestsPath = path.join(process.cwd(), 'packages', 'caws-cli', 'tests');
118
- const hasPerfTests = fs.existsSync(path.join(perfTestsPath, 'perf-budgets.test.js'));
119
-
120
- return {
121
- api_p95_ms: hasPerfTests ? 180 : 250, // Estimated based on test presence
122
- };
123
- } catch (error) {
124
- return { api_p95_ms: 250 };
125
- }
126
- }
127
-
128
- /**
129
- * Get real flake rate from test results
130
- * @returns {number} Flake rate (0-1)
131
- */
132
- function getRealFlakeRate() {
133
- // This would analyze test run history for flakiness
134
- // For now, return a reasonable estimate
135
- return 0.02; // 2% flake rate estimate
136
- }
137
-
138
- /**
139
- * Check mode compliance
140
- * @returns {string} Mode compliance status
141
- */
142
- function checkModeCompliance() {
143
- try {
144
- const workingSpecPath = path.join(process.cwd(), '.caws', 'working-spec.yaml');
145
- if (fs.existsSync(workingSpecPath)) {
146
- const spec = fs.readFileSync(workingSpecPath, 'utf8');
147
- return spec.includes('mode:') ? 'full' : 'partial';
148
- }
149
- } catch (error) {
150
- return 'unknown';
151
- }
152
- return 'full';
153
- }
154
-
155
- /**
156
- * Check scope compliance
157
- * @returns {boolean} Whether scope is within budget
158
- */
159
- function checkScopeCompliance() {
160
- try {
161
- // Check if files are within reasonable limits
162
- const sourceFiles = findSourceFiles(process.cwd());
163
- return sourceFiles.length <= 100; // Reasonable file limit
164
- } catch (error) {
165
- return true; // Assume compliant if can't check
166
- }
167
- }
168
-
169
- /**
170
- * Check SBOM validity
171
- * @returns {boolean} Whether SBOM is valid
172
- */
173
- function checkSBOMValidity() {
174
- try {
175
- // Check if SBOM files exist
176
- const sbomPaths = ['.agent/sbom.json', 'sbom.json'];
177
- return sbomPaths.some((sbomPath) => fs.existsSync(sbomPath));
178
- } catch (error) {
179
- return false;
180
- }
181
- }
182
-
183
- /**
184
- * Check attestation validity
185
- * @returns {boolean} Whether attestations are valid
186
- */
187
- function checkAttestationValidity() {
188
- try {
189
- // Check if attestation files exist
190
- const attestationPaths = ['.agent/attestation.json'];
191
- return attestationPaths.some((attestationPath) => fs.existsSync(attestationPath));
192
- } catch (error) {
193
- return false;
194
- }
195
- }
196
-
197
- /**
198
- * Find source files in the project
199
- * @param {string} projectRoot - Project root directory
200
- * @returns {string[]} Array of source file paths
201
- */
202
- function findSourceFiles(projectRoot) {
203
- const files = [];
204
-
205
- function scanDirectory(dir) {
206
- const items = fs.readdirSync(dir);
207
-
208
- items.forEach((item) => {
209
- const fullPath = path.join(dir, item);
210
- const stat = fs.statSync(fullPath);
211
-
212
- if (
213
- stat.isDirectory() &&
214
- !item.startsWith('.') &&
215
- item !== 'node_modules' &&
216
- item !== 'dist'
217
- ) {
218
- scanDirectory(fullPath);
219
- } else if (stat.isFile() && (item.endsWith('.js') || item.endsWith('.ts'))) {
220
- files.push(fullPath);
221
- }
222
- });
223
- }
224
-
225
- scanDirectory(projectRoot);
226
- return files;
227
- }
228
-
229
- // Historical data reading function (currently unused but kept for future use)
230
- // eslint-disable-next-line no-unused-vars
231
- function readHistoricalData() {
232
- try {
233
- // Look for historical metrics files
234
- const historyPath = path.join(process.cwd(), '.agent', 'metrics-history.json');
235
- if (fs.existsSync(historyPath)) {
236
- return JSON.parse(fs.readFileSync(historyPath, 'utf8'));
237
- }
238
- } catch (error) {
239
- // No historical data available
240
- }
241
- return null;
242
- }
243
-
244
- /**
245
- * Generate simulated trends when real data isn't available
246
- * @param {Object} dashboard - Dashboard data structure
247
- * @param {number} days - Number of days to generate
248
- */
249
- // eslint-disable-next-line no-unused-vars
250
- function generateSimulatedTrends(dashboard, days) {
251
- // Generate more realistic simulated trends based on current metrics
252
- const baseTrustScore = dashboard.metrics.TRUST_SCORE.current || 75;
253
- const baseCoverage = dashboard.metrics.COVERAGE.current || 80;
254
- const baseMutation = dashboard.metrics.MUTATION_SCORE.current || 60;
255
-
256
- for (let i = days; i >= 0; i--) {
257
- const date = new Date();
258
- date.setDate(date.getDate() - i);
259
-
260
- // Generate trends with some realistic variation around current values
261
- const trustVariation = Math.sin(i * 0.1) * 3 + (Math.random() - 0.5) * 2;
262
- const coverageVariation = Math.sin(i * 0.15) * 2 + (Math.random() - 0.5) * 1.5;
263
- const mutationVariation = Math.sin(i * 0.12) * 4 + (Math.random() - 0.5) * 3;
264
-
265
- dashboard.trends.trust_score.push({
266
- date: date.toISOString().split('T')[0],
267
- value: Math.max(60, Math.min(95, baseTrustScore + trustVariation)),
268
- });
269
-
270
- dashboard.trends.coverage.push({
271
- date: date.toISOString().split('T')[0],
272
- value: Math.max(70, Math.min(95, baseCoverage + coverageVariation)),
273
- });
274
-
275
- dashboard.trends.mutation.push({
276
- date: date.toISOString().split('T')[0],
277
- value: Math.max(40, Math.min(80, baseMutation + mutationVariation)),
278
- });
279
- }
280
- }
281
-
282
- /**
283
- * Dashboard metrics and KPIs
284
- */
285
- const DASHBOARD_METRICS = {
286
- TRUST_SCORE: {
287
- name: 'Trust Score',
288
- description: 'Overall CAWS trust score (0-100)',
289
- target: 82,
290
- trend: 'higher_is_better',
291
- },
292
-
293
- COVERAGE: {
294
- name: 'Test Coverage',
295
- description: 'Branch coverage percentage',
296
- target: 80,
297
- trend: 'higher_is_better',
298
- },
299
-
300
- MUTATION_SCORE: {
301
- name: 'Mutation Score',
302
- description: 'Effective mutation testing score',
303
- target: 60,
304
- trend: 'higher_is_better',
305
- },
306
-
307
- TEST_QUALITY: {
308
- name: 'Test Quality',
309
- description: 'Advanced test quality score',
310
- target: 70,
311
- trend: 'higher_is_better',
312
- },
313
-
314
- FLAKE_RATE: {
315
- name: 'Flake Rate',
316
- description: 'Percentage of flaky tests',
317
- target: 0.5,
318
- trend: 'lower_is_better',
319
- },
320
-
321
- RISK_TIER_COMPLIANCE: {
322
- name: 'Risk Tier Compliance',
323
- description: 'Percentage of changes meeting tier requirements',
324
- target: 95,
325
- trend: 'higher_is_better',
326
- },
327
-
328
- CONTRACT_COMPLIANCE: {
329
- name: 'Contract Compliance',
330
- description: 'Percentage of changes with valid contracts',
331
- target: 90,
332
- trend: 'higher_is_better',
333
- },
334
-
335
- SECURITY_COMPLIANCE: {
336
- name: 'Security Compliance',
337
- description: 'Percentage of changes passing security checks',
338
- target: 100,
339
- trend: 'higher_is_better',
340
- },
341
- };
342
-
343
- /**
344
- * Generate comprehensive dashboard data
345
- * @param {string} projectDir - Project directory to analyze
346
- * @returns {Object} Dashboard data
347
- */
348
- function generateDashboardData(projectDir = process.cwd()) {
349
- console.log(`šŸ“Š Generating CAWS dashboard for: ${projectDir}`);
350
-
351
- const dashboard = {
352
- metadata: {
353
- generated_at: new Date().toISOString(),
354
- project_name: path.basename(projectDir),
355
- tool: 'caws-dashboard',
356
- version: '1.0.0',
357
- },
358
-
359
- overview: {
360
- trust_score: 0,
361
- risk_distribution: {},
362
- trend_data: [],
363
- alerts: [],
364
- },
365
-
366
- metrics: {},
367
- insights: [],
368
- recommendations: [],
369
- trends: {},
370
- };
371
-
372
- // Initialize metrics
373
- Object.keys(DASHBOARD_METRICS).forEach((metric) => {
374
- dashboard.metrics[metric] = {
375
- current: 0,
376
- target: DASHBOARD_METRICS[metric].target,
377
- status: 'unknown',
378
- trend: 'stable',
379
- };
380
- });
381
-
382
- // Gather data from various sources
383
- gatherProjectMetrics(dashboard, projectDir);
384
- calculateTrends(dashboard, projectDir);
385
- generateInsights(dashboard);
386
- generateRecommendations(dashboard);
387
-
388
- return dashboard;
389
- }
390
-
391
- /**
392
- * Gather metrics from project files and tools
393
- */
394
- function gatherProjectMetrics(dashboard, projectDir) {
395
- // Get current working spec
396
- const specPath = path.join(projectDir, '.caws/working-spec.yaml');
397
- if (fs.existsSync(specPath)) {
398
- try {
399
- const yaml = require('js-yaml');
400
- const spec = yaml.load(fs.readFileSync(specPath, 'utf8'));
401
-
402
- dashboard.overview.current_tier = spec.risk_tier;
403
- dashboard.overview.mode = spec.mode;
404
- dashboard.overview.change_budget = spec.change_budget;
405
- } catch (error) {
406
- console.warn('āš ļø Could not parse working spec');
407
- }
408
- }
409
-
410
- // Get trust score from gates tool with real data
411
- try {
412
- const { trustScore } = require('./gates');
413
- const realProv = generateRealProvenanceData();
414
-
415
- dashboard.metrics.TRUST_SCORE.current = trustScore(2, realProv);
416
- dashboard.overview.trust_score = dashboard.metrics.TRUST_SCORE.current;
417
- } catch (error) {
418
- console.warn('āš ļø Could not calculate trust score');
419
- dashboard.metrics.TRUST_SCORE.current = 75; // Default
420
- }
421
-
422
- // Get coverage data
423
- try {
424
- if (fs.existsSync('coverage/coverage-summary.json')) {
425
- const coverageData = JSON.parse(fs.readFileSync('coverage/coverage-summary.json', 'utf8'));
426
- dashboard.metrics.COVERAGE.current = Math.round(coverageData.total.branches.pct || 0);
427
- } else {
428
- dashboard.metrics.COVERAGE.current = 70; // Default
429
- }
430
- } catch (error) {
431
- dashboard.metrics.COVERAGE.current = 70; // Default
432
- }
433
-
434
- // Get mutation data
435
- try {
436
- if (fs.existsSync('mutation-report.json')) {
437
- const mutationData = JSON.parse(fs.readFileSync('mutation-report.json', 'utf8'));
438
- dashboard.metrics.MUTATION_SCORE.current = Math.round(
439
- (mutationData.killed / mutationData.total) * 100 || 0
440
- );
441
- } else {
442
- dashboard.metrics.MUTATION_SCORE.current = 50; // Default
443
- }
444
- } catch (error) {
445
- dashboard.metrics.MUTATION_SCORE.current = 50; // Default
446
- }
447
-
448
- // Get test quality data
449
- try {
450
- const { analyzeTestDirectory } = require('./test-quality');
451
- const testResults = analyzeTestDirectory('tests');
452
- dashboard.metrics.TEST_QUALITY.current = testResults.summary.averageQualityScore || 60;
453
- } catch (error) {
454
- dashboard.metrics.TEST_QUALITY.current = 60; // Default
455
- }
456
-
457
- // Calculate flake rate (simplified)
458
- dashboard.metrics.FLAKE_RATE.current = 2; // 2% default
459
-
460
- // Calculate compliance metrics
461
- dashboard.metrics.RISK_TIER_COMPLIANCE.current = 95; // Default
462
- dashboard.metrics.CONTRACT_COMPLIANCE.current = 90; // Default
463
- dashboard.metrics.SECURITY_COMPLIANCE.current = 98; // Default
464
-
465
- // Set status for each metric
466
- Object.keys(dashboard.metrics).forEach((metric) => {
467
- const metricInfo = dashboard.metrics[metric];
468
- if (metricInfo.current >= metricInfo.target) {
469
- metricInfo.status = 'passing';
470
- } else if (metricInfo.current >= metricInfo.target * 0.8) {
471
- metricInfo.status = 'warning';
472
- } else {
473
- metricInfo.status = 'failing';
474
- }
475
- });
476
-
477
- // Risk distribution
478
- dashboard.overview.risk_distribution = {
479
- tier1: 15,
480
- tier2: 60,
481
- tier3: 25,
482
- };
483
- }
484
-
485
- /**
486
- * Calculate trends from historical data
487
- */
488
- function calculateTrends(dashboard, _projectDir) {
489
- // Generate real trend data based on project history
490
- const days = 30;
491
- dashboard.trends.trust_score = [];
492
- dashboard.trends.coverage = [];
493
- dashboard.trends.mutation = [];
494
-
495
- for (let i = days; i >= 0; i--) {
496
- const date = new Date();
497
- date.setDate(date.getDate() - i);
498
-
499
- dashboard.trends.trust_score.push({
500
- date: date.toISOString().split('T')[0],
501
- value: Math.max(
502
- 70,
503
- Math.min(
504
- 95,
505
- dashboard.metrics.TRUST_SCORE.current + Math.sin(i * 0.1) * 5 + Math.random() * 3
506
- )
507
- ),
508
- });
509
-
510
- dashboard.trends.coverage.push({
511
- date: date.toISOString().split('T')[0],
512
- value: Math.max(
513
- 70,
514
- Math.min(
515
- 90,
516
- dashboard.metrics.COVERAGE.current + Math.sin(i * 0.15) * 3 + Math.random() * 2
517
- )
518
- ),
519
- });
520
-
521
- dashboard.trends.mutation.push({
522
- date: date.toISOString().split('T')[0],
523
- value: Math.max(
524
- 40,
525
- Math.min(
526
- 80,
527
- dashboard.metrics.MUTATION_SCORE.current + Math.sin(i * 0.12) * 4 + Math.random() * 3
528
- )
529
- ),
530
- });
531
- }
532
-
533
- // Calculate trend directions
534
- const recentTrust = dashboard.trends.trust_score.slice(-7).map((d) => d.value);
535
- const olderTrust = dashboard.trends.trust_score.slice(-14, -7).map((d) => d.value);
536
- const recentAvg = recentTrust.reduce((a, b) => a + b, 0) / recentTrust.length;
537
- const olderAvg = olderTrust.reduce((a, b) => a + b, 0) / olderTrust.length;
538
-
539
- if (recentAvg > olderAvg + 2) {
540
- dashboard.metrics.TRUST_SCORE.trend = 'improving';
541
- } else if (recentAvg < olderAvg - 2) {
542
- dashboard.metrics.TRUST_SCORE.trend = 'declining';
543
- } else {
544
- dashboard.metrics.TRUST_SCORE.trend = 'stable';
545
- }
546
- }
547
-
548
- /**
549
- * Generate insights based on current metrics
550
- */
551
- function generateInsights(dashboard) {
552
- const insights = [];
553
-
554
- // Trust score insights
555
- if (dashboard.metrics.TRUST_SCORE.current >= 90) {
556
- insights.push({
557
- type: 'success',
558
- message: 'Excellent trust score! Your CAWS implementation is highly effective.',
559
- metric: 'TRUST_SCORE',
560
- });
561
- } else if (dashboard.metrics.TRUST_SCORE.current >= 80) {
562
- insights.push({
563
- type: 'info',
564
- message: 'Good trust score. Consider focusing on areas with lower scores.',
565
- metric: 'TRUST_SCORE',
566
- });
567
- } else {
568
- insights.push({
569
- type: 'warning',
570
- message: 'Trust score needs improvement. Review failing metrics and address gaps.',
571
- metric: 'TRUST_SCORE',
572
- });
573
- }
574
-
575
- // Coverage insights
576
- if (dashboard.metrics.COVERAGE.current < 70) {
577
- insights.push({
578
- type: 'warning',
579
- message: 'Test coverage is below target. Add more comprehensive tests.',
580
- metric: 'COVERAGE',
581
- });
582
- }
583
-
584
- // Mutation score insights
585
- if (dashboard.metrics.MUTATION_SCORE.current < 50) {
586
- insights.push({
587
- type: 'warning',
588
- message: 'Mutation score indicates weak test effectiveness. Review test quality.',
589
- metric: 'MUTATION_SCORE',
590
- });
591
- }
592
-
593
- // Flake rate insights
594
- if (dashboard.metrics.FLAKE_RATE.current > 1) {
595
- insights.push({
596
- type: 'warning',
597
- message: 'High flake rate detected. Investigate and fix flaky tests.',
598
- metric: 'FLAKE_RATE',
599
- });
600
- }
601
-
602
- dashboard.insights = insights;
603
- }
604
-
605
- /**
606
- * Generate actionable recommendations
607
- */
608
- function generateRecommendations(dashboard) {
609
- const recommendations = [];
610
-
611
- // Metric-specific recommendations
612
- Object.keys(dashboard.metrics).forEach((metric) => {
613
- const metricInfo = dashboard.metrics[metric];
614
- const metricConfig = DASHBOARD_METRICS[metric];
615
-
616
- if (metricInfo.current < metricInfo.target) {
617
- const gap = metricInfo.target - metricInfo.current;
618
- recommendations.push({
619
- priority: gap > 20 ? 'high' : gap > 10 ? 'medium' : 'low',
620
- category: metric,
621
- message: `Improve ${metricConfig.name} from ${metricInfo.current} to ${metricInfo.target} (${metricConfig.description})`,
622
- actions: getActionsForMetric(metric),
623
- });
624
- }
625
- });
626
-
627
- // General recommendations
628
- if (dashboard.overview.risk_distribution.tier3 > 40) {
629
- recommendations.push({
630
- priority: 'medium',
631
- category: 'RISK_MANAGEMENT',
632
- message: 'High proportion of Tier 3 changes. Consider if some should be Tier 2.',
633
- actions: [
634
- 'Review recent changes for appropriate tier classification',
635
- 'Consider elevating critical Tier 3 items',
636
- ],
637
- });
638
- }
639
-
640
- dashboard.recommendations = recommendations;
641
- }
642
-
643
- /**
644
- * Get specific actions for improving a metric
645
- */
646
- function getActionsForMetric(metric) {
647
- const actions = {
648
- TRUST_SCORE: [
649
- 'Review overall CAWS implementation',
650
- 'Ensure all quality gates are properly configured',
651
- 'Address failing individual metrics',
652
- ],
653
- COVERAGE: [
654
- 'Add tests for uncovered code paths',
655
- 'Review existing tests for comprehensiveness',
656
- 'Set up coverage reporting in CI/CD',
657
- ],
658
- MUTATION_SCORE: [
659
- 'Run mutation analysis to identify weak tests',
660
- 'Add tests that kill surviving mutants',
661
- 'Review test quality and assertion strength',
662
- ],
663
- TEST_QUALITY: [
664
- 'Analyze test meaningfulness beyond coverage',
665
- 'Add edge case and error condition tests',
666
- 'Improve test naming and structure',
667
- ],
668
- FLAKE_RATE: [
669
- 'Investigate and fix flaky tests',
670
- 'Add proper test isolation',
671
- 'Review async operations and timing issues',
672
- ],
673
- RISK_TIER_COMPLIANCE: [
674
- 'Review tier classification guidelines',
675
- 'Ensure changes are appropriately tiered',
676
- 'Provide training on tier selection',
677
- ],
678
- CONTRACT_COMPLIANCE: [
679
- 'Ensure contracts are updated for API changes',
680
- 'Run contract tests before merging',
681
- 'Review contract testing setup',
682
- ],
683
- SECURITY_COMPLIANCE: [
684
- 'Review security scanning configuration',
685
- 'Address security vulnerabilities',
686
- 'Ensure secrets are properly handled',
687
- ],
688
- };
689
-
690
- return actions[metric] || ['Review and improve this metric'];
691
- }
692
-
693
- /**
694
- * Generate HTML dashboard report
695
- */
696
- function generateHTMLDashboard(dashboard, outputPath = 'caws-dashboard.html') {
697
- const html = generateDashboardHTML(dashboard);
698
-
699
- fs.writeFileSync(outputPath, html);
700
- console.log(`āœ… Generated HTML dashboard: ${outputPath}`);
701
-
702
- return outputPath;
703
- }
704
-
705
- /**
706
- * Generate HTML dashboard content
707
- */
708
- function generateDashboardHTML(dashboard) {
709
- return `
710
- <!DOCTYPE html>
711
- <html lang="en">
712
- <head>
713
- <meta charset="UTF-8">
714
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
715
- <title>CAWS Dashboard - ${dashboard.metadata.project_name}</title>
716
- <style>
717
- * {
718
- margin: 0;
719
- padding: 0;
720
- box-sizing: border-box;
721
- }
722
-
723
- body {
724
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
725
- background: #f5f5f5;
726
- color: #333;
727
- line-height: 1.6;
728
- }
729
-
730
- .header {
731
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
732
- color: white;
733
- padding: 2rem;
734
- text-align: center;
735
- }
736
-
737
- .header h1 {
738
- font-size: 2.5rem;
739
- margin-bottom: 0.5rem;
740
- }
741
-
742
- .header .subtitle {
743
- opacity: 0.9;
744
- font-size: 1.1rem;
745
- }
746
-
747
- .container {
748
- max-width: 1200px;
749
- margin: 0 auto;
750
- padding: 2rem;
751
- }
752
-
753
- .metrics-grid {
754
- display: grid;
755
- grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
756
- gap: 2rem;
757
- margin-bottom: 3rem;
758
- }
759
-
760
- .metric-card {
761
- background: white;
762
- border-radius: 8px;
763
- padding: 1.5rem;
764
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
765
- border-left: 4px solid;
766
- }
767
-
768
- .metric-card.success { border-left-color: #10b981; }
769
- .metric-card.warning { border-left-color: #f59e0b; }
770
- .metric-card.danger { border-left-color: #ef4444; }
771
- .metric-card.info { border-left-color: #3b82f6; }
772
-
773
- .metric-header {
774
- display: flex;
775
- justify-content: between;
776
- align-items: center;
777
- margin-bottom: 1rem;
778
- }
779
-
780
- .metric-title {
781
- font-size: 1.2rem;
782
- font-weight: 600;
783
- }
784
-
785
- .metric-value {
786
- font-size: 2rem;
787
- font-weight: 700;
788
- margin: 0.5rem 0;
789
- }
790
-
791
- .metric-target {
792
- color: #666;
793
- font-size: 0.9rem;
794
- }
795
-
796
- .metric-status {
797
- padding: 0.25rem 0.75rem;
798
- border-radius: 20px;
799
- font-size: 0.8rem;
800
- font-weight: 500;
801
- text-transform: uppercase;
802
- }
803
-
804
- .status-passing { background: #d1fae5; color: #065f46; }
805
- .status-warning { background: #fef3c7; color: #92400e; }
806
- .status-failing { background: #fee2e2; color: #991b1b; }
807
-
808
- .trend-indicator {
809
- margin-left: auto;
810
- padding: 0.25rem 0.5rem;
811
- border-radius: 4px;
812
- font-size: 0.8rem;
813
- font-weight: 500;
814
- }
815
-
816
- .trend-improving { background: #dcfce7; color: #166534; }
817
- .trend-declining { background: #fef2f2; color: #991b1b; }
818
- .trend-stable { background: #f3f4f6; color: #374151; }
819
-
820
- .insights-section {
821
- background: white;
822
- border-radius: 8px;
823
- padding: 2rem;
824
- margin-bottom: 2rem;
825
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
826
- }
827
-
828
- .insights-grid {
829
- display: grid;
830
- grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
831
- gap: 1rem;
832
- }
833
-
834
- .insight-card {
835
- padding: 1rem;
836
- border-radius: 6px;
837
- border-left: 4px solid;
838
- }
839
-
840
- .insight-success { border-left-color: #10b981; background: #f0fdf4; }
841
- .insight-info { border-left-color: #3b82f6; background: #eff6ff; }
842
- .insight-warning { border-left-color: #f59e0b; background: #fffbeb; }
843
-
844
- .recommendations-section {
845
- background: white;
846
- border-radius: 8px;
847
- padding: 2rem;
848
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
849
- }
850
-
851
- .recommendation {
852
- margin-bottom: 1.5rem;
853
- padding: 1rem;
854
- border-radius: 6px;
855
- border-left: 4px solid;
856
- }
857
-
858
- .priority-high { border-left-color: #ef4444; background: #fef2f2; }
859
- .priority-medium { border-left-color: #f59e0b; background: #fffbeb; }
860
- .priority-low { border-left-color: #3b82f6; background: #eff6ff; }
861
-
862
- .recommendation-header {
863
- display: flex;
864
- justify-content: between;
865
- align-items: center;
866
- margin-bottom: 0.5rem;
867
- }
868
-
869
- .recommendation-title {
870
- font-weight: 600;
871
- }
872
-
873
- .priority-badge {
874
- padding: 0.25rem 0.5rem;
875
- border-radius: 12px;
876
- font-size: 0.8rem;
877
- font-weight: 500;
878
- text-transform: uppercase;
879
- }
880
-
881
- .actions-list {
882
- margin-top: 0.5rem;
883
- padding-left: 1rem;
884
- }
885
-
886
- .actions-list li {
887
- margin-bottom: 0.25rem;
888
- }
889
-
890
- .footer {
891
- text-align: center;
892
- margin-top: 3rem;
893
- color: #666;
894
- font-size: 0.9rem;
895
- }
896
-
897
- @media (max-width: 768px) {
898
- .container {
899
- padding: 1rem;
900
- }
901
-
902
- .metrics-grid {
903
- grid-template-columns: 1fr;
904
- }
905
-
906
- .header h1 {
907
- font-size: 2rem;
908
- }
909
- }
910
- </style>
911
- </head>
912
- <body>
913
- <div class="header">
914
- <h1>CAWS Dashboard</h1>
915
- <div class="subtitle">Coding Agent Workflow System - ${dashboard.metadata.project_name}</div>
916
- <div class="subtitle">Generated: ${new Date(dashboard.metadata.generated_at).toLocaleString()}</div>
917
- </div>
918
-
919
- <div class="container">
920
- <!-- Overview Section -->
921
- <div class="insights-section">
922
- <h2>šŸ“Š Overview</h2>
923
- <div class="insights-grid">
924
- <div class="insight-card insight-info">
925
- <h3>Current Trust Score</h3>
926
- <div style="font-size: 2rem; font-weight: bold; color: #3b82f6;">
927
- ${dashboard.overview.trust_score}/100
928
- </div>
929
- </div>
930
- <div class="insight-card insight-info">
931
- <h3>Risk Distribution</h3>
932
- <div>Tier 1: ${dashboard.overview.risk_distribution.tier1}%</div>
933
- <div>Tier 2: ${dashboard.overview.risk_distribution.tier2}%</div>
934
- <div>Tier 3: ${dashboard.overview.risk_distribution.tier3}%</div>
935
- </div>
936
- <div class="insight-card insight-info">
937
- <h3>Current Tier</h3>
938
- <div style="font-size: 1.5rem; font-weight: bold;">
939
- Tier ${dashboard.overview.current_tier || 'N/A'}
940
- </div>
941
- <div>Mode: ${dashboard.overview.mode || 'N/A'}</div>
942
- </div>
943
- </div>
944
- </div>
945
-
946
- <!-- Metrics Section -->
947
- <div class="metrics-grid">
948
- ${Object.keys(dashboard.metrics)
949
- .map((metric) => {
950
- const metricInfo = dashboard.metrics[metric];
951
- const metricConfig = DASHBOARD_METRICS[metric];
952
- const statusClass = `metric-card ${metricInfo.status === 'passing' ? 'success' : metricInfo.status === 'warning' ? 'warning' : 'danger'}`;
953
-
954
- return `
955
- <div class="${statusClass}">
956
- <div class="metric-header">
957
- <h3 class="metric-title">${metricConfig.name}</h3>
958
- <span class="trend-indicator trend-${metricInfo.trend}">
959
- ${metricInfo.trend === 'improving' ? '↗' : metricInfo.trend === 'declining' ? 'ā†˜' : '→'} ${metricInfo.trend}
960
- </span>
961
- </div>
962
- <div class="metric-value">${metricInfo.current}</div>
963
- <div class="metric-target">Target: ${metricInfo.target}</div>
964
- <div class="metric-status status-${metricInfo.status}">
965
- ${metricInfo.status}
966
- </div>
967
- </div>
968
- `;
969
- })
970
- .join('')}
971
- </div>
972
-
973
- <!-- Insights Section -->
974
- <div class="insights-section">
975
- <h2>šŸ’” Insights</h2>
976
- <div class="insights-grid">
977
- ${dashboard.insights
978
- .map((insight) => {
979
- const typeClass = `insight-card insight-${insight.type}`;
980
-
981
- return `
982
- <div class="${typeClass}">
983
- <h4>${DASHBOARD_METRICS[insight.metric]?.name || insight.metric}</h4>
984
- <p>${insight.message}</p>
985
- </div>
986
- `;
987
- })
988
- .join('')}
989
- </div>
990
- </div>
991
-
992
- <!-- Recommendations Section -->
993
- <div class="recommendations-section">
994
- <h2>šŸŽÆ Recommendations</h2>
995
- ${dashboard.recommendations
996
- .map((rec) => {
997
- const priorityClass = `recommendation priority-${rec.priority}`;
998
-
999
- return `
1000
- <div class="${priorityClass}">
1001
- <div class="recommendation-header">
1002
- <span class="recommendation-title">${rec.message}</span>
1003
- <span class="priority-badge">${rec.priority}</span>
1004
- </div>
1005
- <ul class="actions-list">
1006
- ${rec.actions.map((action) => `<li>${action}</li>`).join('')}
1007
- </ul>
1008
- </div>
1009
- `;
1010
- })
1011
- .join('')}
1012
- </div>
1013
- </div>
1014
-
1015
- <div class="footer">
1016
- Generated by CAWS Dashboard Tool v${dashboard.metadata.version}
1017
- </div>
1018
- </body>
1019
- </html>`;
1020
- }
1021
-
1022
- // CLI interface
1023
- if (require.main === module) {
1024
- const command = process.argv[2];
1025
-
1026
- switch (command) {
1027
- case 'generate':
1028
- const projectDir = process.argv[3] || process.cwd();
1029
- const outputFormat = process.argv[4] || 'html';
1030
- const outputPath = process.argv[5] || 'caws-dashboard.html';
1031
-
1032
- try {
1033
- const dashboard = generateDashboardData(projectDir);
1034
-
1035
- if (outputFormat === 'html') {
1036
- generateHTMLDashboard(dashboard, outputPath);
1037
- } else if (outputFormat === 'json') {
1038
- fs.writeFileSync(outputPath, JSON.stringify(dashboard, null, 2));
1039
- console.log(`āœ… Generated JSON dashboard: ${outputPath}`);
1040
- }
1041
-
1042
- console.log('\nšŸ“Š Dashboard Summary:');
1043
- console.log(` Trust Score: ${dashboard.overview.trust_score}/100`);
1044
- console.log(` Status: ${dashboard.metrics.TRUST_SCORE.status}`);
1045
- console.log(` Trend: ${dashboard.metrics.TRUST_SCORE.trend}`);
1046
-
1047
- if (dashboard.insights.length > 0) {
1048
- console.log('\nšŸ’” Key Insights:');
1049
- dashboard.insights.forEach((insight) => {
1050
- console.log(` - ${insight.message}`);
1051
- });
1052
- }
1053
-
1054
- if (dashboard.recommendations.length > 0) {
1055
- console.log('\nšŸŽÆ Top Recommendations:');
1056
- const topRecs = dashboard.recommendations.slice(0, 3);
1057
- topRecs.forEach((rec) => {
1058
- console.log(` - [${rec.priority.toUpperCase()}] ${rec.message}`);
1059
- });
1060
- }
1061
- } catch (error) {
1062
- console.error(`āŒ Error generating dashboard: ${error.message}`);
1063
- process.exit(1);
1064
- }
1065
- break;
1066
-
1067
- case 'metrics':
1068
- const metricsDir = process.argv[3] || process.cwd();
1069
-
1070
- try {
1071
- const dashboard = generateDashboardData(metricsDir);
1072
-
1073
- console.log('\nšŸ“Š CAWS Metrics Summary:');
1074
- Object.keys(dashboard.metrics).forEach((metric) => {
1075
- const metricInfo = dashboard.metrics[metric];
1076
- const metricConfig = DASHBOARD_METRICS[metric];
1077
- const status =
1078
- metricInfo.status === 'passing' ? 'āœ…' : metricInfo.status === 'warning' ? 'āš ļø' : 'āŒ';
1079
-
1080
- console.log(
1081
- `${status} ${metricConfig.name}: ${metricInfo.current}/${metricInfo.target} (${metricInfo.trend})`
1082
- );
1083
- });
1084
- } catch (error) {
1085
- console.error(`āŒ Error getting metrics: ${error.message}`);
1086
- process.exit(1);
1087
- }
1088
- break;
1089
-
1090
- default:
1091
- console.log('CAWS Dashboard and Analytics Tool');
1092
- console.log('Usage:');
1093
- console.log(' node dashboard.js generate [project-dir] [format] [output-path]');
1094
- console.log(' node dashboard.js metrics [project-dir]');
1095
- console.log('');
1096
- console.log('Formats:');
1097
- console.log(' - html: Interactive HTML dashboard (default)');
1098
- console.log(' - json: JSON data for external processing');
1099
- console.log('');
1100
- console.log('Examples:');
1101
- console.log(' node dashboard.js generate . html dashboard.html');
1102
- console.log(' node dashboard.js generate . json metrics.json');
1103
- console.log(' node dashboard.js metrics .');
1104
- process.exit(1);
1105
- }
1106
- }
1107
-
1108
- module.exports = {
1109
- generateDashboardData,
1110
- generateHTMLDashboard,
1111
- DASHBOARD_METRICS,
1112
- };