@paths.design/caws-cli 7.0.2 → 8.0.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 (217) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +24 -19
  3. package/dist/commands/init.js +51 -4
  4. package/dist/commands/quality-gates.js +147 -9
  5. package/dist/commands/specs.js +148 -14
  6. package/dist/commands/status.js +2 -2
  7. package/dist/commands/tool.js +2 -4
  8. package/dist/config/index.js +17 -8
  9. package/dist/generators/working-spec.js +19 -6
  10. package/dist/scaffold/git-hooks.js +245 -46
  11. package/dist/scaffold/index.js +53 -7
  12. package/dist/templates/.caws/tools/README.md +21 -0
  13. package/dist/templates/.cursor/README.md +311 -0
  14. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  15. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  16. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  17. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  18. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  19. package/dist/templates/.cursor/hooks/format.sh +38 -0
  20. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  21. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  22. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  23. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  24. package/dist/templates/.cursor/hooks.json +59 -0
  25. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  26. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  27. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  28. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  29. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  30. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  31. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  32. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  33. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  34. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  35. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  36. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  37. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  38. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  39. package/dist/templates/.cursor/rules/README.md +148 -0
  40. package/dist/templates/.github/copilot/instructions.md +311 -0
  41. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  42. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  43. package/dist/templates/.vscode/launch.json +56 -0
  44. package/dist/templates/.vscode/settings.json +93 -0
  45. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  46. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  47. package/dist/templates/OIDC_SETUP.md +300 -0
  48. package/dist/templates/agents.md +1047 -0
  49. package/dist/templates/codemod/README.md +1 -0
  50. package/dist/templates/codemod/test.js +93 -0
  51. package/dist/templates/docs/README.md +150 -0
  52. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  53. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  54. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  55. package/dist/tool-loader.js +6 -1
  56. package/dist/tool-validator.js +8 -2
  57. package/dist/utils/detection.js +4 -3
  58. package/dist/utils/git-lock.js +119 -0
  59. package/dist/utils/gitignore-updater.js +148 -0
  60. package/dist/utils/project-analysis.js +176 -16
  61. package/dist/utils/quality-gates.js +48 -7
  62. package/dist/utils/spec-resolver.js +27 -3
  63. package/dist/utils/yaml-validation.js +156 -0
  64. package/dist/validation/spec-validation.js +81 -2
  65. package/package.json +2 -2
  66. package/templates/.caws/schemas/waivers.schema.json +30 -0
  67. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  68. package/templates/.caws/templates/working-spec.template.yml +74 -0
  69. package/templates/.caws/tools/README.md +21 -0
  70. package/templates/.caws/tools/scope-guard.js +208 -0
  71. package/templates/.caws/tools-allow.json +331 -0
  72. package/templates/.caws/waivers.yml +19 -0
  73. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  74. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  75. package/dist/budget-derivation.d.ts +0 -74
  76. package/dist/budget-derivation.d.ts.map +0 -1
  77. package/dist/cicd-optimizer.d.ts +0 -142
  78. package/dist/cicd-optimizer.d.ts.map +0 -1
  79. package/dist/commands/archive.d.ts +0 -50
  80. package/dist/commands/archive.d.ts.map +0 -1
  81. package/dist/commands/burnup.d.ts +0 -6
  82. package/dist/commands/burnup.d.ts.map +0 -1
  83. package/dist/commands/diagnose.d.ts +0 -52
  84. package/dist/commands/diagnose.d.ts.map +0 -1
  85. package/dist/commands/evaluate.d.ts +0 -8
  86. package/dist/commands/evaluate.d.ts.map +0 -1
  87. package/dist/commands/init.d.ts +0 -5
  88. package/dist/commands/init.d.ts.map +0 -1
  89. package/dist/commands/iterate.d.ts +0 -8
  90. package/dist/commands/iterate.d.ts.map +0 -1
  91. package/dist/commands/mode.d.ts +0 -24
  92. package/dist/commands/mode.d.ts.map +0 -1
  93. package/dist/commands/plan.d.ts +0 -49
  94. package/dist/commands/plan.d.ts.map +0 -1
  95. package/dist/commands/provenance.d.ts +0 -32
  96. package/dist/commands/provenance.d.ts.map +0 -1
  97. package/dist/commands/quality-gates.d.ts +0 -52
  98. package/dist/commands/quality-gates.d.ts.map +0 -1
  99. package/dist/commands/quality-monitor.d.ts +0 -17
  100. package/dist/commands/quality-monitor.d.ts.map +0 -1
  101. package/dist/commands/specs.d.ts +0 -71
  102. package/dist/commands/specs.d.ts.map +0 -1
  103. package/dist/commands/status.d.ts +0 -44
  104. package/dist/commands/status.d.ts.map +0 -1
  105. package/dist/commands/templates.d.ts +0 -74
  106. package/dist/commands/templates.d.ts.map +0 -1
  107. package/dist/commands/tool.d.ts +0 -13
  108. package/dist/commands/tool.d.ts.map +0 -1
  109. package/dist/commands/troubleshoot.d.ts +0 -8
  110. package/dist/commands/troubleshoot.d.ts.map +0 -1
  111. package/dist/commands/tutorial.d.ts +0 -55
  112. package/dist/commands/tutorial.d.ts.map +0 -1
  113. package/dist/commands/validate.d.ts +0 -15
  114. package/dist/commands/validate.d.ts.map +0 -1
  115. package/dist/commands/waivers.d.ts +0 -8
  116. package/dist/commands/waivers.d.ts.map +0 -1
  117. package/dist/commands/workflow.d.ts +0 -85
  118. package/dist/commands/workflow.d.ts.map +0 -1
  119. package/dist/config/index.d.ts +0 -29
  120. package/dist/config/index.d.ts.map +0 -1
  121. package/dist/config/modes.d.ts +0 -225
  122. package/dist/config/modes.d.ts.map +0 -1
  123. package/dist/constants/spec-types.d.ts +0 -41
  124. package/dist/constants/spec-types.d.ts.map +0 -1
  125. package/dist/error-handler.d.ts +0 -164
  126. package/dist/error-handler.d.ts.map +0 -1
  127. package/dist/generators/jest-config.d.ts +0 -32
  128. package/dist/generators/jest-config.d.ts.map +0 -1
  129. package/dist/generators/working-spec.d.ts +0 -13
  130. package/dist/generators/working-spec.d.ts.map +0 -1
  131. package/dist/index-new.d.ts +0 -5
  132. package/dist/index-new.d.ts.map +0 -1
  133. package/dist/index-new.js +0 -317
  134. package/dist/index.d.ts +0 -5
  135. package/dist/index.d.ts.map +0 -1
  136. package/dist/index.js.backup +0 -4711
  137. package/dist/minimal-cli.d.ts +0 -3
  138. package/dist/minimal-cli.d.ts.map +0 -1
  139. package/dist/policy/PolicyManager.d.ts +0 -104
  140. package/dist/policy/PolicyManager.d.ts.map +0 -1
  141. package/dist/scaffold/cursor-hooks.d.ts +0 -7
  142. package/dist/scaffold/cursor-hooks.d.ts.map +0 -1
  143. package/dist/scaffold/git-hooks.d.ts +0 -20
  144. package/dist/scaffold/git-hooks.d.ts.map +0 -1
  145. package/dist/scaffold/index.d.ts +0 -20
  146. package/dist/scaffold/index.d.ts.map +0 -1
  147. package/dist/spec/SpecFileManager.d.ts +0 -146
  148. package/dist/spec/SpecFileManager.d.ts.map +0 -1
  149. package/dist/test-analysis.d.ts +0 -182
  150. package/dist/test-analysis.d.ts.map +0 -1
  151. package/dist/tool-interface.d.ts +0 -236
  152. package/dist/tool-interface.d.ts.map +0 -1
  153. package/dist/tool-loader.d.ts +0 -77
  154. package/dist/tool-loader.d.ts.map +0 -1
  155. package/dist/tool-validator.d.ts +0 -72
  156. package/dist/tool-validator.d.ts.map +0 -1
  157. package/dist/utils/detection.d.ts +0 -7
  158. package/dist/utils/detection.d.ts.map +0 -1
  159. package/dist/utils/finalization.d.ts +0 -17
  160. package/dist/utils/finalization.d.ts.map +0 -1
  161. package/dist/utils/project-analysis.d.ts +0 -14
  162. package/dist/utils/project-analysis.d.ts.map +0 -1
  163. package/dist/utils/quality-gates.d.ts +0 -49
  164. package/dist/utils/quality-gates.d.ts.map +0 -1
  165. package/dist/utils/spec-resolver.d.ts +0 -88
  166. package/dist/utils/spec-resolver.d.ts.map +0 -1
  167. package/dist/utils/typescript-detector.d.ts +0 -63
  168. package/dist/utils/typescript-detector.d.ts.map +0 -1
  169. package/dist/validation/spec-validation.d.ts +0 -43
  170. package/dist/validation/spec-validation.d.ts.map +0 -1
  171. package/dist/waivers-manager.d.ts +0 -167
  172. package/dist/waivers-manager.d.ts.map +0 -1
  173. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  174. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  175. package/templates/apps/tools/caws/README.md +0 -463
  176. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  177. package/templates/apps/tools/caws/attest.js +0 -357
  178. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  179. package/templates/apps/tools/caws/config.ts +0 -245
  180. package/templates/apps/tools/caws/cross-functional.js +0 -876
  181. package/templates/apps/tools/caws/dashboard.js +0 -1112
  182. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  183. package/templates/apps/tools/caws/gates.js +0 -198
  184. package/templates/apps/tools/caws/gates.ts +0 -271
  185. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  186. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  187. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  188. package/templates/apps/tools/caws/language-support.js +0 -585
  189. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  190. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  191. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  192. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  193. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  194. package/templates/apps/tools/caws/property-testing.js +0 -707
  195. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  196. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  197. package/templates/apps/tools/caws/provenance.js +0 -132
  198. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  199. package/templates/apps/tools/caws/provenance.ts +0 -211
  200. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  201. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  202. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  203. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  204. package/templates/apps/tools/caws/shared/types.ts +0 -444
  205. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  206. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  207. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  208. package/templates/apps/tools/caws/test-quality.js +0 -578
  209. package/templates/apps/tools/caws/validate.js +0 -76
  210. package/templates/apps/tools/caws/validate.ts +0 -228
  211. package/templates/apps/tools/caws/waivers.js +0 -344
  212. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  213. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  214. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  215. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  216. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  217. /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
@@ -1,764 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * @fileoverview CAWS Legacy Codebase Assessment Tool
5
- * Evaluates existing projects and provides incremental adoption roadmap for CAWS
6
- * @author @darianrosebrook
7
- */
8
-
9
- const fs = require('fs');
10
- const path = require('path');
11
-
12
- /**
13
- * Assessment categories and their scoring criteria
14
- */
15
- const ASSESSMENT_CATEGORIES = {
16
- TESTING: {
17
- name: 'Testing Infrastructure',
18
- weight: 0.25,
19
- indicators: {
20
- testFiles: { weight: 0.3, description: 'Presence of test files' },
21
- testCoverage: { weight: 0.25, description: 'Code coverage metrics' },
22
- testTypes: { weight: 0.2, description: 'Unit, integration, and E2E tests' },
23
- testQuality: { weight: 0.15, description: 'Test structure and assertions' },
24
- testAutomation: { weight: 0.1, description: 'CI/CD integration' },
25
- },
26
- },
27
- DOCUMENTATION: {
28
- name: 'Documentation Quality',
29
- weight: 0.2,
30
- indicators: {
31
- readmeQuality: { weight: 0.3, description: 'README completeness' },
32
- codeComments: { weight: 0.25, description: 'Inline documentation' },
33
- apiDocs: { weight: 0.2, description: 'API documentation' },
34
- architectureDocs: { weight: 0.15, description: 'Architecture documentation' },
35
- changelog: { weight: 0.1, description: 'Change tracking' },
36
- },
37
- },
38
- CODE_QUALITY: {
39
- name: 'Code Quality',
40
- weight: 0.2,
41
- indicators: {
42
- linting: { weight: 0.25, description: 'Linting configuration' },
43
- formatting: { weight: 0.2, description: 'Code formatting standards' },
44
- complexity: { weight: 0.2, description: 'Cyclomatic complexity' },
45
- dependencies: { weight: 0.2, description: 'Dependency management' },
46
- security: { weight: 0.15, description: 'Security scanning' },
47
- },
48
- },
49
- PROJECT_STRUCTURE: {
50
- name: 'Project Structure',
51
- weight: 0.15,
52
- indicators: {
53
- organization: { weight: 0.3, description: 'Logical file organization' },
54
- buildConfig: { weight: 0.25, description: 'Build configuration' },
55
- packageManagement: { weight: 0.2, description: 'Package management' },
56
- ciCd: { weight: 0.15, description: 'CI/CD configuration' },
57
- versionControl: { weight: 0.1, description: 'Version control setup' },
58
- },
59
- },
60
- PROCESS_MATURITY: {
61
- name: 'Process Maturity',
62
- weight: 0.2,
63
- indicators: {
64
- branchingStrategy: { weight: 0.25, description: 'Branching and merging strategy' },
65
- codeReview: { weight: 0.25, description: 'Code review process' },
66
- releaseProcess: { weight: 0.2, description: 'Release management' },
67
- issueTracking: { weight: 0.15, description: 'Issue tracking' },
68
- teamCollaboration: { weight: 0.15, description: 'Team collaboration tools' },
69
- },
70
- },
71
- };
72
-
73
- /**
74
- * Assess a project directory for CAWS readiness
75
- * @param {string} projectDir - Project directory path
76
- * @returns {Object} Assessment results
77
- */
78
- function assessProject(projectDir = process.cwd()) {
79
- console.log(`šŸ” Assessing project for CAWS adoption: ${projectDir}`);
80
-
81
- const assessment = {
82
- projectInfo: getProjectInfo(projectDir),
83
- scores: {},
84
- recommendations: [],
85
- adoptionRoadmap: [],
86
- riskProfile: {},
87
- };
88
-
89
- // Calculate scores for each category
90
- Object.keys(ASSESSMENT_CATEGORIES).forEach((category) => {
91
- assessment.scores[category] = calculateCategoryScore(projectDir, category);
92
- });
93
-
94
- // Calculate overall readiness score
95
- assessment.overallScore = calculateOverallScore(assessment.scores);
96
-
97
- // Generate recommendations
98
- assessment.recommendations = generateRecommendations(assessment.scores);
99
-
100
- // Generate adoption roadmap
101
- assessment.adoptionRoadmap = generateAdoptionRoadmap(assessment.scores);
102
-
103
- // Assess risk profile
104
- assessment.riskProfile = assessRiskProfile(projectDir, assessment.scores);
105
-
106
- return assessment;
107
- }
108
-
109
- /**
110
- * Get basic project information
111
- */
112
- function getProjectInfo(projectDir) {
113
- const info = {
114
- name: path.basename(projectDir),
115
- path: projectDir,
116
- languages: [],
117
- packageManager: null,
118
- frameworks: [],
119
- size: { files: 0, lines: 0, directories: 0 },
120
- };
121
-
122
- // Detect languages and frameworks
123
- try {
124
- const files = fs.readdirSync(projectDir, { recursive: true });
125
-
126
- files.forEach((file) => {
127
- const filePath = path.join(projectDir, file);
128
- const stat = fs.statSync(filePath);
129
-
130
- if (stat.isFile()) {
131
- info.size.files++;
132
- if (file.endsWith('.js') || file.endsWith('.ts')) {
133
- info.languages.push('javascript');
134
- if (file.includes('react') || file.includes('vue') || file.includes('angular')) {
135
- info.frameworks.push('frontend');
136
- }
137
- } else if (file.endsWith('.py')) {
138
- info.languages.push('python');
139
- } else if (file.endsWith('.java')) {
140
- info.languages.push('java');
141
- } else if (file.endsWith('.go')) {
142
- info.languages.push('go');
143
- } else if (file.endsWith('.rs')) {
144
- info.languages.push('rust');
145
- }
146
- } else if (stat.isDirectory()) {
147
- info.size.directories++;
148
- }
149
- });
150
-
151
- // Remove duplicates
152
- info.languages = [...new Set(info.languages)];
153
- info.frameworks = [...new Set(info.frameworks)];
154
-
155
- // Detect package manager
156
- if (fs.existsSync(path.join(projectDir, 'package.json'))) {
157
- info.packageManager = 'npm';
158
- } else if (fs.existsSync(path.join(projectDir, 'requirements.txt'))) {
159
- info.packageManager = 'pip';
160
- } else if (fs.existsSync(path.join(projectDir, 'pom.xml'))) {
161
- info.packageManager = 'maven';
162
- } else if (fs.existsSync(path.join(projectDir, 'go.mod'))) {
163
- info.packageManager = 'go modules';
164
- } else if (fs.existsSync(path.join(projectDir, 'Cargo.toml'))) {
165
- info.packageManager = 'cargo';
166
- }
167
- } catch (error) {
168
- console.warn('āš ļø Error gathering project info:', error.message);
169
- }
170
-
171
- return info;
172
- }
173
-
174
- /**
175
- * Calculate score for a specific category
176
- */
177
- function calculateCategoryScore(projectDir, category) {
178
- const categoryInfo = ASSESSMENT_CATEGORIES[category];
179
- let totalScore = 0;
180
-
181
- Object.keys(categoryInfo.indicators).forEach((indicator) => {
182
- const indicatorInfo = categoryInfo.indicators[indicator];
183
- const score = calculateIndicatorScore(projectDir, category, indicator);
184
- const weightedScore = score * indicatorInfo.weight;
185
- totalScore += weightedScore;
186
- });
187
-
188
- return Math.round(totalScore * 100);
189
- }
190
-
191
- /**
192
- * Calculate score for a specific indicator
193
- */
194
- function calculateIndicatorScore(projectDir, category, indicator) {
195
- switch (category) {
196
- case 'TESTING':
197
- return calculateTestingScore(projectDir, indicator);
198
- case 'DOCUMENTATION':
199
- return calculateDocumentationScore(projectDir, indicator);
200
- case 'CODE_QUALITY':
201
- return calculateCodeQualityScore(projectDir, indicator);
202
- case 'PROJECT_STRUCTURE':
203
- return calculateProjectStructureScore(projectDir, indicator);
204
- case 'PROCESS_MATURITY':
205
- return calculateProcessMaturityScore(projectDir, indicator);
206
- default:
207
- return 0.5; // Neutral score
208
- }
209
- }
210
-
211
- /**
212
- * Calculate testing-related scores
213
- */
214
- function calculateTestingScore(projectDir, indicator) {
215
- const testDir = path.join(projectDir, 'tests') || path.join(projectDir, 'test');
216
-
217
- switch (indicator) {
218
- case 'testFiles':
219
- if (fs.existsSync(testDir)) {
220
- const testFiles = fs
221
- .readdirSync(testDir)
222
- .filter((f) => f.includes('test') || f.includes('spec'));
223
- return Math.min(testFiles.length / 10, 1); // Scale based on number of test files
224
- }
225
- return 0;
226
-
227
- case 'testCoverage':
228
- // Check for coverage configuration
229
- const coverageFiles = [
230
- '.nycrc',
231
- 'jest.config.js',
232
- 'coverage.json',
233
- 'sonar-project.properties',
234
- ];
235
- const hasCoverage = coverageFiles.some((file) => fs.existsSync(path.join(projectDir, file)));
236
- return hasCoverage ? 1 : 0;
237
-
238
- case 'testTypes':
239
- if (fs.existsSync(testDir)) {
240
- const files = fs.readdirSync(testDir);
241
- let types = 0;
242
- if (files.some((f) => f.includes('unit'))) types += 0.3;
243
- if (files.some((f) => f.includes('integration'))) types += 0.3;
244
- if (files.some((f) => f.includes('e2e'))) types += 0.4;
245
- return Math.min(types, 1);
246
- }
247
- return 0;
248
-
249
- case 'testQuality':
250
- // Basic check for test structure
251
- if (fs.existsSync(testDir)) {
252
- const testContent = fs
253
- .readdirSync(testDir)
254
- .filter((f) => f.endsWith('.js') || f.endsWith('.ts'))
255
- .map((f) => fs.readFileSync(path.join(testDir, f), 'utf8'))
256
- .join('');
257
-
258
- const hasAssertions = /\b(expect|assert|should)\b/.test(testContent);
259
- const hasDescribe = /\bdescribe\b/.test(testContent);
260
- return hasAssertions && hasDescribe ? 0.8 : 0.3;
261
- }
262
- return 0;
263
-
264
- case 'testAutomation':
265
- const hasCI =
266
- fs.existsSync(path.join(projectDir, '.github/workflows')) ||
267
- fs.existsSync(path.join(projectDir, '.gitlab-ci.yml')) ||
268
- fs.existsSync(path.join(projectDir, 'Jenkinsfile'));
269
- return hasCI ? 1 : 0;
270
-
271
- default:
272
- return 0.5;
273
- }
274
- }
275
-
276
- /**
277
- * Calculate documentation-related scores
278
- */
279
- function calculateDocumentationScore(projectDir, indicator) {
280
- switch (indicator) {
281
- case 'readmeQuality':
282
- const readmePath = path.join(projectDir, 'README.md');
283
- if (fs.existsSync(readmePath)) {
284
- const readme = fs.readFileSync(readmePath, 'utf8');
285
- const score =
286
- (readme.length > 500 ? 0.4 : 0) +
287
- (readme.includes('#') ? 0.2 : 0) +
288
- (readme.includes('install') || readme.includes('setup') ? 0.2 : 0) +
289
- (readme.includes('usage') || readme.includes('example') ? 0.2 : 0);
290
- return Math.min(score, 1);
291
- }
292
- return 0;
293
-
294
- case 'codeComments':
295
- // Basic check for comment density
296
- const sourceFiles = getSourceFiles(projectDir);
297
- if (sourceFiles.length === 0) return 0.5;
298
-
299
- const totalLines = sourceFiles.reduce((sum, file) => {
300
- return sum + fs.readFileSync(file, 'utf8').split('\n').length;
301
- }, 0);
302
-
303
- const commentLines = sourceFiles.reduce((sum, file) => {
304
- const content = fs.readFileSync(file, 'utf8');
305
- return (
306
- sum +
307
- (content.match(/\/\//g) || []).length +
308
- (content.match(/\/\*/g) || []).length +
309
- (content.match(/#/g) || []).length
310
- );
311
- }, 0);
312
-
313
- const commentRatio = commentLines / totalLines;
314
- return Math.min(commentRatio * 5, 1); // Scale comment ratio
315
-
316
- case 'apiDocs':
317
- const hasApiDocs =
318
- fs.existsSync(path.join(projectDir, 'docs/api')) ||
319
- fs.existsSync(path.join(projectDir, 'docs/API.md'));
320
- return hasApiDocs ? 1 : 0;
321
-
322
- case 'architectureDocs':
323
- const hasArchDocs =
324
- fs.existsSync(path.join(projectDir, 'docs/architecture')) ||
325
- fs.existsSync(path.join(projectDir, 'ARCHITECTURE.md'));
326
- return hasArchDocs ? 1 : 0;
327
-
328
- case 'changelog':
329
- const hasChangelog =
330
- fs.existsSync(path.join(projectDir, 'CHANGELOG.md')) ||
331
- fs.existsSync(path.join(projectDir, 'HISTORY.md'));
332
- return hasChangelog ? 1 : 0;
333
-
334
- default:
335
- return 0.5;
336
- }
337
- }
338
-
339
- /**
340
- * Calculate code quality scores
341
- */
342
- function calculateCodeQualityScore(projectDir, indicator) {
343
- switch (indicator) {
344
- case 'linting':
345
- const lintingFiles = ['.eslintrc', '.prettierrc', 'tsconfig.json', '.editorconfig'];
346
- const hasLinting = lintingFiles.some((file) => fs.existsSync(path.join(projectDir, file)));
347
- return hasLinting ? 1 : 0;
348
-
349
- case 'formatting':
350
- // Check if formatting tools are likely configured
351
- return 0.7; // Assume some formatting exists
352
-
353
- case 'complexity':
354
- // Basic complexity check (could be enhanced with actual analysis)
355
- return 0.6; // Neutral score
356
-
357
- case 'dependencies':
358
- const hasPackageFile =
359
- fs.existsSync(path.join(projectDir, 'package.json')) ||
360
- fs.existsSync(path.join(projectDir, 'requirements.txt')) ||
361
- fs.existsSync(path.join(projectDir, 'pom.xml'));
362
- return hasPackageFile ? 1 : 0;
363
-
364
- case 'security':
365
- const hasSecurity =
366
- fs.existsSync(path.join(projectDir, '.github/workflows')) &&
367
- fs
368
- .readdirSync(path.join(projectDir, '.github/workflows'))
369
- .some((f) => f.includes('security') || f.includes('audit'));
370
- return hasSecurity ? 1 : 0;
371
-
372
- default:
373
- return 0.5;
374
- }
375
- }
376
-
377
- /**
378
- * Calculate project structure scores
379
- */
380
- function calculateProjectStructureScore(projectDir, indicator) {
381
- switch (indicator) {
382
- case 'organization':
383
- const srcDir =
384
- fs.existsSync(path.join(projectDir, 'src')) || fs.existsSync(path.join(projectDir, 'lib'));
385
- return srcDir ? 1 : 0.5;
386
-
387
- case 'buildConfig':
388
- const buildFiles = ['package.json', 'Makefile', 'CMakeLists.txt', 'build.gradle'];
389
- const hasBuild = buildFiles.some((file) => fs.existsSync(path.join(projectDir, file)));
390
- return hasBuild ? 1 : 0;
391
-
392
- case 'packageManagement':
393
- const packageFiles = ['package.json', 'requirements.txt', 'pom.xml', 'go.mod', 'Cargo.toml'];
394
- const hasPackage = packageFiles.some((file) => fs.existsSync(path.join(projectDir, file)));
395
- return hasPackage ? 1 : 0;
396
-
397
- case 'ciCd':
398
- const hasCI =
399
- fs.existsSync(path.join(projectDir, '.github')) ||
400
- fs.existsSync(path.join(projectDir, '.gitlab-ci.yml'));
401
- return hasCI ? 1 : 0;
402
-
403
- case 'versionControl':
404
- // Check for .git directory (basic check)
405
- return fs.existsSync(path.join(projectDir, '.git')) ? 1 : 0;
406
-
407
- default:
408
- return 0.5;
409
- }
410
- }
411
-
412
- /**
413
- * Calculate process maturity scores
414
- */
415
- function calculateProcessMaturityScore(projectDir, indicator) {
416
- switch (indicator) {
417
- case 'branchingStrategy':
418
- // Check for branch protection or common branching files
419
- const hasBranches =
420
- fs.existsSync(path.join(projectDir, '.github/workflows')) &&
421
- fs
422
- .readdirSync(path.join(projectDir, '.github/workflows'))
423
- .some((f) => f.includes('branch') || f.includes('merge'));
424
- return hasBranches ? 0.8 : 0.3;
425
-
426
- case 'codeReview':
427
- const hasPRTemplate = fs.existsSync(
428
- path.join(projectDir, '.github/PULL_REQUEST_TEMPLATE.md')
429
- );
430
- return hasPRTemplate ? 0.9 : 0.4;
431
-
432
- case 'releaseProcess':
433
- const hasReleaseWorkflow =
434
- fs.existsSync(path.join(projectDir, '.github/workflows')) &&
435
- fs
436
- .readdirSync(path.join(projectDir, '.github/workflows'))
437
- .some((f) => f.includes('release') || f.includes('publish'));
438
- return hasReleaseWorkflow ? 1 : 0;
439
-
440
- case 'issueTracking':
441
- const hasIssueTemplate = fs.existsSync(path.join(projectDir, '.github/ISSUE_TEMPLATE'));
442
- return hasIssueTemplate ? 0.8 : 0.2;
443
-
444
- case 'teamCollaboration':
445
- const hasContributing = fs.existsSync(path.join(projectDir, 'CONTRIBUTING.md'));
446
- return hasContributing ? 0.7 : 0.3;
447
-
448
- default:
449
- return 0.5;
450
- }
451
- }
452
-
453
- /**
454
- * Get source files for analysis
455
- */
456
- function getSourceFiles(projectDir) {
457
- const sourceFiles = [];
458
-
459
- function scanDirectory(dir) {
460
- try {
461
- const files = fs.readdirSync(dir);
462
-
463
- files.forEach((file) => {
464
- const filePath = path.join(dir, file);
465
- const stat = fs.statSync(filePath);
466
-
467
- if (
468
- stat.isDirectory() &&
469
- !file.startsWith('.') &&
470
- file !== 'node_modules' &&
471
- file !== 'target'
472
- ) {
473
- scanDirectory(filePath);
474
- } else if (stat.isFile() && /\.(js|ts|py|java|go|rs)$/.test(file)) {
475
- sourceFiles.push(filePath);
476
- }
477
- });
478
- } catch (error) {
479
- // Skip directories we can't read
480
- }
481
- }
482
-
483
- scanDirectory(projectDir);
484
- return sourceFiles;
485
- }
486
-
487
- /**
488
- * Calculate overall readiness score
489
- */
490
- function calculateOverallScore(categoryScores) {
491
- let totalScore = 0;
492
-
493
- Object.keys(categoryScores).forEach((category) => {
494
- totalScore += categoryScores[category] * ASSESSMENT_CATEGORIES[category].weight;
495
- });
496
-
497
- return Math.round(totalScore);
498
- }
499
-
500
- /**
501
- * Generate recommendations based on scores
502
- */
503
- function generateRecommendations(scores) {
504
- const recommendations = [];
505
-
506
- Object.keys(scores).forEach((category) => {
507
- const score = scores[category];
508
- const categoryInfo = ASSESSMENT_CATEGORIES[category];
509
-
510
- if (score < 40) {
511
- recommendations.push({
512
- category: categoryInfo.name,
513
- priority: 'high',
514
- message: `${categoryInfo.name} needs significant improvement (Score: ${score}/100)`,
515
- suggestions: getCategorySuggestions(category, 'high'),
516
- });
517
- } else if (score < 70) {
518
- recommendations.push({
519
- category: categoryInfo.name,
520
- priority: 'medium',
521
- message: `${categoryInfo.name} has room for improvement (Score: ${score}/100)`,
522
- suggestions: getCategorySuggestions(category, 'medium'),
523
- });
524
- }
525
- });
526
-
527
- return recommendations;
528
- }
529
-
530
- /**
531
- * Get category-specific suggestions
532
- */
533
- function getCategorySuggestions(category, priority) {
534
- const suggestions = {
535
- TESTING: {
536
- high: [
537
- 'Add comprehensive unit test suite',
538
- 'Implement integration tests for critical paths',
539
- 'Set up test automation in CI/CD',
540
- 'Add test coverage reporting',
541
- ],
542
- medium: [
543
- 'Improve test coverage for existing code',
544
- 'Add more edge case testing',
545
- 'Implement automated test execution',
546
- ],
547
- },
548
- DOCUMENTATION: {
549
- high: [
550
- 'Create comprehensive README with setup instructions',
551
- 'Add inline code documentation',
552
- 'Document API endpoints and usage',
553
- 'Create architecture documentation',
554
- ],
555
- medium: ['Enhance existing documentation', 'Add code examples', 'Document recent changes'],
556
- },
557
- CODE_QUALITY: {
558
- high: [
559
- 'Set up linting and code formatting',
560
- 'Implement code quality gates',
561
- 'Add security scanning',
562
- 'Manage technical debt',
563
- ],
564
- medium: [
565
- 'Improve code formatting consistency',
566
- 'Add static code analysis',
567
- 'Update dependencies regularly',
568
- ],
569
- },
570
- };
571
-
572
- return suggestions[category]?.[priority] || ['Improve this area'];
573
- }
574
-
575
- /**
576
- * Generate phased adoption roadmap
577
- */
578
- function generateAdoptionRoadmap(scores) {
579
- const phases = [
580
- {
581
- name: 'Foundation Setup',
582
- duration: '2-4 weeks',
583
- prerequisites: ['Basic project structure', 'Development environment'],
584
- tasks: [
585
- 'Set up CAWS CLI and basic configuration',
586
- 'Create initial working spec template',
587
- 'Establish basic linting and formatting',
588
- 'Set up version control and CI basics',
589
- ],
590
- success_criteria: 'CAWS CLI operational, basic quality gates in place',
591
- },
592
- {
593
- name: 'Testing Infrastructure',
594
- duration: '4-6 weeks',
595
- prerequisites: ['Foundation setup complete'],
596
- tasks: [
597
- 'Implement comprehensive test suite',
598
- 'Add test coverage reporting',
599
- 'Set up mutation testing',
600
- 'Integrate tests into CI/CD',
601
- ],
602
- success_criteria: 'Test coverage >70%, automated testing operational',
603
- },
604
- {
605
- name: 'Documentation & Quality',
606
- duration: '3-5 weeks',
607
- prerequisites: ['Testing infrastructure complete'],
608
- tasks: [
609
- 'Complete project documentation',
610
- 'Implement advanced quality gates',
611
- 'Add contract testing',
612
- 'Set up monitoring and observability',
613
- ],
614
- success_criteria: 'Full CAWS compliance, comprehensive documentation',
615
- },
616
- ];
617
-
618
- // Adjust phases based on current scores
619
- return phases.map((phase, index) => ({
620
- ...phase,
621
- priority: index + 1,
622
- estimated_effort: scores[Object.keys(scores)[index]] < 50 ? 'high' : 'medium',
623
- }));
624
- }
625
-
626
- /**
627
- * Assess risk profile of the project
628
- */
629
- function assessRiskProfile(projectDir, scores) {
630
- const profile = {
631
- overall_risk: 'medium',
632
- risk_factors: [],
633
- recommended_tier: 2,
634
- };
635
-
636
- // Determine risk based on scores
637
- const avgScore = Object.values(scores).reduce((a, b) => a + b, 0) / Object.keys(scores).length;
638
-
639
- if (avgScore < 40) {
640
- profile.overall_risk = 'high';
641
- profile.risk_factors.push('Low test coverage and documentation');
642
- profile.risk_factors.push('Missing quality gates');
643
- profile.recommended_tier = 1;
644
- } else if (avgScore < 70) {
645
- profile.overall_risk = 'medium';
646
- profile.risk_factors.push('Inconsistent testing practices');
647
- profile.risk_factors.push('Documentation gaps');
648
- profile.recommended_tier = 2;
649
- } else {
650
- profile.overall_risk = 'low';
651
- profile.risk_factors.push('Good foundation for quality practices');
652
- profile.recommended_tier = 3;
653
- }
654
-
655
- // Add specific risk factors
656
- if (scores.TESTING < 30) {
657
- profile.risk_factors.push('Critical: Minimal testing infrastructure');
658
- }
659
- if (scores.DOCUMENTATION < 30) {
660
- profile.risk_factors.push('High: Poor documentation quality');
661
- }
662
- if (scores.CODE_QUALITY < 40) {
663
- profile.risk_factors.push('Medium: Code quality needs improvement');
664
- }
665
-
666
- return profile;
667
- }
668
-
669
- // CLI interface
670
- if (require.main === module) {
671
- const command = process.argv[2];
672
- const projectDir = process.argv[3] || process.cwd();
673
-
674
- switch (command) {
675
- case 'assess':
676
- console.log(`šŸ” Assessing CAWS readiness for project: ${projectDir}`);
677
-
678
- const assessment = assessProject(projectDir);
679
-
680
- console.log('\nšŸ“Š CAWS Readiness Assessment Results:');
681
- console.log(`šŸ† Overall Score: ${assessment.overallScore}/100`);
682
-
683
- console.log('\nšŸ“ˆ Category Scores:');
684
- Object.keys(assessment.scores).forEach((category) => {
685
- const score = assessment.scores[category];
686
- const categoryInfo = ASSESSMENT_CATEGORIES[category];
687
- const status =
688
- score >= 80
689
- ? 'āœ… Excellent'
690
- : score >= 60
691
- ? '🟢 Good'
692
- : score >= 40
693
- ? '🟔 Fair'
694
- : 'šŸ”“ Poor';
695
- console.log(`${status} ${categoryInfo.name}: ${score}/100`);
696
- });
697
-
698
- console.log('\nšŸ“‹ Project Information:');
699
- console.log(` Languages: ${assessment.projectInfo.languages.join(', ')}`);
700
- console.log(` Package Manager: ${assessment.projectInfo.packageManager || 'Not detected'}`);
701
- console.log(
702
- ` Frameworks: ${assessment.projectInfo.frameworks.join(', ') || 'None detected'}`
703
- );
704
- console.log(
705
- ` Project Size: ${assessment.projectInfo.size.files} files, ${assessment.projectInfo.size.directories} directories`
706
- );
707
-
708
- if (assessment.recommendations.length > 0) {
709
- console.log('\nšŸ’” Priority Recommendations:');
710
- assessment.recommendations.forEach((rec, index) => {
711
- console.log(`\n${index + 1}. [${rec.priority.toUpperCase()}] ${rec.category}`);
712
- console.log(` ${rec.message}`);
713
- rec.suggestions.forEach((suggestion) => {
714
- console.log(` • ${suggestion}`);
715
- });
716
- });
717
- }
718
-
719
- console.log('\nšŸ—“ļø Adoption Roadmap:');
720
- assessment.adoptionRoadmap.forEach((phase, index) => {
721
- console.log(`\n${index + 1}. ${phase.name} (${phase.duration})`);
722
- console.log(` Priority: ${phase.priority} | Effort: ${phase.estimated_effort}`);
723
- console.log(` Tasks: ${phase.tasks.join(', ')}`);
724
- console.log(` Success: ${phase.success_criteria}`);
725
- });
726
-
727
- console.log('\nāš ļø Risk Profile:');
728
- console.log(` Overall Risk: ${assessment.riskProfile.overall_risk}`);
729
- console.log(` Recommended Tier: ${assessment.riskProfile.recommended_tier}`);
730
- assessment.riskProfile.risk_factors.forEach((factor) => {
731
- console.log(` • ${factor}`);
732
- });
733
-
734
- console.log('\nšŸŽÆ Next Steps:');
735
- console.log(' 1. Start with Foundation setup tasks');
736
- console.log(' 2. Address high-priority recommendations first');
737
- console.log(' 3. Set up CAWS CLI and create initial working spec');
738
- console.log(' 4. Gradually implement testing and quality improvements');
739
-
740
- break;
741
-
742
- default:
743
- console.log('CAWS Legacy Codebase Assessment Tool');
744
- console.log('Usage:');
745
- console.log(' node legacy-assessor.js assess [project-directory]');
746
- console.log('');
747
- console.log('Assessment Categories:');
748
- Object.values(ASSESSMENT_CATEGORIES).forEach((category) => {
749
- console.log(` - ${category.name} (${Math.round(category.weight * 100)}% weight)`);
750
- });
751
- console.log('');
752
- console.log('Examples:');
753
- console.log(' node legacy-assessor.js assess .');
754
- console.log(' node legacy-assessor.js assess /path/to/project');
755
- process.exit(1);
756
- }
757
- }
758
-
759
- module.exports = {
760
- assessProject,
761
- ASSESSMENT_CATEGORIES,
762
- generateRecommendations,
763
- generateAdoptionRoadmap,
764
- };