@paths.design/caws-cli 3.1.0 → 3.2.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 (94) hide show
  1. package/README.md +295 -150
  2. package/dist/budget-derivation.d.ts +35 -0
  3. package/dist/budget-derivation.d.ts.map +1 -0
  4. package/dist/budget-derivation.js +204 -0
  5. package/dist/cicd-optimizer.d.ts +142 -0
  6. package/dist/cicd-optimizer.d.ts.map +1 -0
  7. package/dist/cicd-optimizer.js +504 -0
  8. package/dist/commands/burnup.d.ts +6 -0
  9. package/dist/commands/burnup.d.ts.map +1 -0
  10. package/dist/commands/burnup.js +90 -0
  11. package/dist/commands/init.d.ts +5 -0
  12. package/dist/commands/init.d.ts.map +1 -0
  13. package/dist/commands/init.js +514 -0
  14. package/dist/commands/provenance.d.ts +32 -0
  15. package/dist/commands/provenance.d.ts.map +1 -0
  16. package/dist/commands/provenance.js +979 -0
  17. package/dist/commands/tool.d.ts +13 -0
  18. package/dist/commands/tool.d.ts.map +1 -0
  19. package/dist/commands/tool.js +138 -0
  20. package/dist/commands/validate.d.ts +7 -0
  21. package/dist/commands/validate.d.ts.map +1 -0
  22. package/dist/commands/validate.js +80 -0
  23. package/dist/config/index.d.ts +29 -0
  24. package/dist/config/index.d.ts.map +1 -0
  25. package/dist/config/index.js +132 -0
  26. package/dist/error-handler.d.ts +50 -0
  27. package/dist/error-handler.d.ts.map +1 -0
  28. package/dist/error-handler.js +253 -0
  29. package/dist/generators/working-spec.d.ts +13 -0
  30. package/dist/generators/working-spec.d.ts.map +1 -0
  31. package/dist/generators/working-spec.js +204 -0
  32. package/dist/index.d.ts +3 -12
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +193 -2983
  35. package/dist/scaffold/cursor-hooks.d.ts +7 -0
  36. package/dist/scaffold/cursor-hooks.d.ts.map +1 -0
  37. package/dist/scaffold/cursor-hooks.js +152 -0
  38. package/dist/scaffold/git-hooks.d.ts +20 -0
  39. package/dist/scaffold/git-hooks.d.ts.map +1 -0
  40. package/dist/scaffold/git-hooks.js +417 -0
  41. package/dist/scaffold/index.d.ts +20 -0
  42. package/dist/scaffold/index.d.ts.map +1 -0
  43. package/dist/scaffold/index.js +486 -0
  44. package/dist/test-analysis.d.ts +182 -0
  45. package/dist/test-analysis.d.ts.map +1 -0
  46. package/dist/test-analysis.js +580 -0
  47. package/dist/tool-interface.d.ts +236 -0
  48. package/dist/tool-interface.d.ts.map +1 -0
  49. package/dist/tool-interface.js +314 -0
  50. package/dist/tool-loader.d.ts +77 -0
  51. package/dist/tool-loader.d.ts.map +1 -0
  52. package/dist/tool-loader.js +298 -0
  53. package/dist/tool-validator.d.ts +72 -0
  54. package/dist/tool-validator.d.ts.map +1 -0
  55. package/dist/tool-validator.js +387 -0
  56. package/dist/utils/detection.d.ts +7 -0
  57. package/dist/utils/detection.d.ts.map +1 -0
  58. package/dist/utils/detection.js +174 -0
  59. package/dist/utils/finalization.d.ts +17 -0
  60. package/dist/utils/finalization.d.ts.map +1 -0
  61. package/dist/utils/finalization.js +229 -0
  62. package/dist/utils/project-analysis.d.ts +14 -0
  63. package/dist/utils/project-analysis.d.ts.map +1 -0
  64. package/dist/utils/project-analysis.js +105 -0
  65. package/dist/validation/spec-validation.d.ts +29 -0
  66. package/dist/validation/spec-validation.d.ts.map +1 -0
  67. package/dist/validation/spec-validation.js +376 -0
  68. package/dist/waivers-manager.d.ts +167 -0
  69. package/dist/waivers-manager.d.ts.map +1 -0
  70. package/dist/waivers-manager.js +549 -0
  71. package/package.json +10 -12
  72. package/templates/.cursor/README.md +311 -0
  73. package/templates/.cursor/hooks/audit.sh +55 -0
  74. package/templates/.cursor/hooks/block-dangerous.sh +77 -0
  75. package/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  76. package/templates/.cursor/hooks/caws-scope-guard.sh +74 -0
  77. package/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  78. package/templates/.cursor/hooks/format.sh +38 -0
  79. package/templates/.cursor/hooks/naming-check.sh +64 -0
  80. package/templates/.cursor/hooks/scan-secrets.sh +46 -0
  81. package/templates/.cursor/hooks/scope-guard.sh +52 -0
  82. package/templates/.cursor/hooks/validate-spec.sh +38 -0
  83. package/templates/.cursor/hooks.json +59 -0
  84. package/templates/.github/copilot/instructions.md +311 -0
  85. package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  86. package/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  87. package/templates/.vscode/launch.json +56 -0
  88. package/templates/.vscode/settings.json +93 -0
  89. package/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  90. package/templates/apps/tools/caws/README.md +1 -1
  91. package/templates/apps/tools/caws/schemas/working-spec.schema.json +21 -3
  92. package/templates/codemod/test.js +93 -1
  93. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  94. package/templates/apps/tools/caws/provenance.js.backup +0 -73
@@ -0,0 +1,229 @@
1
+ /**
2
+ * @fileoverview Project Finalization Utilities
3
+ * Functions for finalizing CAWS project setup
4
+ * @author @darianrosebrook
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('path');
9
+ const chalk = require('chalk');
10
+
11
+ // CLI version from package.json
12
+ const CLI_VERSION = require('../../package.json').version;
13
+
14
+ // Import scaffold utilities
15
+ const { scaffoldCursorHooks } = require('../scaffold/cursor-hooks');
16
+
17
+ // Dependencies injected via setFinalizationDependencies()
18
+ let languageSupport = null;
19
+ let loadProvenanceTools = null;
20
+
21
+ /**
22
+ * Set dependencies for finalization utilities
23
+ * @param {Object} deps - Dependencies object
24
+ */
25
+ function setFinalizationDependencies(deps) {
26
+ languageSupport = deps.languageSupport;
27
+ loadProvenanceTools = deps.loadProvenanceTools;
28
+ }
29
+
30
+ /**
31
+ * Generate provenance manifest and git initialization (for both modes)
32
+ * @param {string} projectName - Project name
33
+ * @param {Object} options - Command options
34
+ * @param {Object} answers - User answers
35
+ */
36
+ async function finalizeProject(projectName, options, answers) {
37
+ try {
38
+ // Detect and configure language support
39
+ if (languageSupport) {
40
+ console.log(chalk.cyan('🔍 Detecting project language...'));
41
+ const detectedLanguage = languageSupport.detectProjectLanguage();
42
+
43
+ if (detectedLanguage !== 'unknown') {
44
+ console.log(chalk.green(`✅ Detected language: ${detectedLanguage}`));
45
+
46
+ // Generate language-specific configuration
47
+ try {
48
+ const langConfig = languageSupport.generateLanguageConfig(
49
+ detectedLanguage,
50
+ '.caws/language-config.json'
51
+ );
52
+
53
+ console.log(chalk.green('✅ Generated language-specific configuration'));
54
+ console.log(` Language: ${langConfig.name}`);
55
+ console.log(` Tier: ${langConfig.tier}`);
56
+ console.log(
57
+ ` Thresholds: Branch ≥${langConfig.thresholds.min_branch * 100}%, Mutation ≥${langConfig.thresholds.min_mutation * 100}%`
58
+ );
59
+ } catch (langError) {
60
+ console.warn(chalk.yellow('⚠️ Could not generate language config:'), langError.message);
61
+ }
62
+ } else {
63
+ console.log(
64
+ chalk.blue('ℹ️ Could not detect project language - using default configuration')
65
+ );
66
+ }
67
+ }
68
+
69
+ // Setup Cursor hooks if enabled
70
+ if (answers && answers.enableCursorHooks) {
71
+ console.log(chalk.cyan('📌 Setting up Cursor hooks...'));
72
+ await scaffoldCursorHooks(
73
+ process.cwd(),
74
+ answers.cursorHookLevels || ['safety', 'quality', 'scope', 'audit']
75
+ );
76
+ }
77
+
78
+ // Generate provenance manifest
79
+ console.log(chalk.cyan('📦 Generating provenance manifest...'));
80
+
81
+ const provenanceData = {
82
+ agent: 'caws-cli',
83
+ model: 'cli-interactive',
84
+ modelHash: CLI_VERSION,
85
+ toolAllowlist: [
86
+ 'node',
87
+ 'npm',
88
+ 'git',
89
+ 'fs-extra',
90
+ 'inquirer',
91
+ 'commander',
92
+ 'js-yaml',
93
+ 'ajv',
94
+ 'chalk',
95
+ ],
96
+ prompts: Object.keys(answers),
97
+ commit: null, // Will be set after git init
98
+ artifacts: ['.caws/working-spec.yaml'],
99
+ results: {
100
+ project_id: answers.projectId,
101
+ project_title: answers.projectTitle,
102
+ risk_tier: answers.riskTier,
103
+ mode: answers.projectMode,
104
+ change_budget: {
105
+ max_files: answers.maxFiles,
106
+ max_loc: answers.maxLoc,
107
+ },
108
+ },
109
+ approvals: [],
110
+ };
111
+
112
+ // Generate provenance if tools are available
113
+ const tools = loadProvenanceTools && loadProvenanceTools();
114
+ if (
115
+ tools &&
116
+ typeof tools.generateProvenance === 'function' &&
117
+ typeof tools.saveProvenance === 'function'
118
+ ) {
119
+ const provenance = tools.generateProvenance(provenanceData);
120
+ await tools.saveProvenance(provenance, '.agent/provenance.json');
121
+ console.log(chalk.green('✅ Provenance manifest generated'));
122
+ } else {
123
+ console.log(
124
+ chalk.yellow('⚠️ Provenance tools not available - skipping manifest generation')
125
+ );
126
+ }
127
+
128
+ // Initialize git repository
129
+ if (options.git) {
130
+ try {
131
+ console.log(chalk.cyan('🔧 Initializing git repository...'));
132
+
133
+ // Check if git is available
134
+ try {
135
+ require('child_process').execSync('git --version', { stdio: 'ignore' });
136
+ } catch (error) {
137
+ console.warn(chalk.yellow('⚠️ Git not found. Skipping git initialization.'));
138
+ console.warn(chalk.blue('💡 Install git to enable automatic repository setup.'));
139
+ return;
140
+ }
141
+
142
+ // Configure git author information
143
+ const gitConfig = answers.git_config || {};
144
+ const authorName = process.env.GIT_AUTHOR_NAME || gitConfig.author_name;
145
+ const authorEmail = process.env.GIT_AUTHOR_EMAIL || gitConfig.author_email;
146
+
147
+ if (authorName && authorEmail) {
148
+ require('child_process').execSync(`git config user.name "${authorName}"`, {
149
+ stdio: 'inherit',
150
+ });
151
+ require('child_process').execSync(`git config user.email "${authorEmail}"`, {
152
+ stdio: 'inherit',
153
+ });
154
+ console.log(chalk.green(`✅ Git configured: ${authorName} <${authorEmail}>`));
155
+ }
156
+
157
+ require('child_process').execSync('git init', { stdio: 'inherit' });
158
+ require('child_process').execSync('git add .', { stdio: 'inherit' });
159
+ require('child_process').execSync('git commit -m "Initial CAWS project setup"', {
160
+ stdio: 'inherit',
161
+ });
162
+ console.log(chalk.green('✅ Git repository initialized'));
163
+
164
+ // Update provenance with commit hash
165
+ const commitHash = require('child_process')
166
+ .execSync('git rev-parse HEAD', { encoding: 'utf8' })
167
+ .trim();
168
+ const currentProvenance = JSON.parse(fs.readFileSync('.agent/provenance.json', 'utf8'));
169
+ currentProvenance.commit = commitHash;
170
+ currentProvenance.hash = require('crypto')
171
+ .createHash('sha256')
172
+ .update(JSON.stringify(currentProvenance, Object.keys(currentProvenance).sort()))
173
+ .digest('hex');
174
+ await fs.writeFile('.agent/provenance.json', JSON.stringify(currentProvenance, null, 2));
175
+
176
+ console.log(chalk.green('✅ Provenance updated with commit hash'));
177
+ } catch (error) {
178
+ console.warn(
179
+ chalk.yellow('⚠️ Failed to initialize git repository:'),
180
+ error?.message || String(error)
181
+ );
182
+ console.warn(chalk.blue('💡 You can initialize git manually later with:'));
183
+ console.warn(" git init && git add . && git commit -m 'Initial CAWS project setup'");
184
+ }
185
+ }
186
+ } catch (error) {
187
+ console.error(
188
+ chalk.red('❌ Error during project finalization:'),
189
+ error?.message || String(error)
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Display success message after project initialization
196
+ */
197
+ function continueToSuccess() {
198
+ const isCurrentDir =
199
+ process.cwd() ===
200
+ path.resolve(process.argv[3] === '.' ? process.cwd() : process.argv[3] || 'caws-project');
201
+
202
+ console.log(chalk.green('\n🎉 CAWS project initialized successfully!'));
203
+
204
+ if (isCurrentDir) {
205
+ console.log(
206
+ `📁 ${chalk.cyan('Initialized in current directory')}: ${path.resolve(process.cwd())}`
207
+ );
208
+ console.log(chalk.gray(' (CAWS files added to your existing project)'));
209
+ } else {
210
+ console.log(`📁 ${chalk.cyan('Project location')}: ${path.resolve(process.cwd())}`);
211
+ console.log(chalk.gray(' (New subdirectory created with CAWS structure)'));
212
+ }
213
+
214
+ console.log(chalk.bold('\nNext steps:'));
215
+ console.log('1. Customize .caws/working-spec.yaml');
216
+ console.log('2. Review added CAWS tools and documentation');
217
+ if (!isCurrentDir) {
218
+ console.log('3. Move CAWS files to your main project if needed');
219
+ }
220
+ console.log('4. npm install (if using Node.js)');
221
+ console.log('5. Set up your CI/CD pipeline');
222
+ console.log(chalk.blue('\nFor help: caws --help'));
223
+ }
224
+
225
+ module.exports = {
226
+ finalizeProject,
227
+ continueToSuccess,
228
+ setFinalizationDependencies,
229
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Detect project type from existing files and structure
3
+ * @param {string} cwd - Current working directory
4
+ * @returns {string} Project type
5
+ */
6
+ export function detectProjectType(cwd?: string): string;
7
+ /**
8
+ * Detect if current directory appears to be a project that should be initialized directly
9
+ * @param {string} projectName - Project name from command line
10
+ * @param {string} currentDir - Current directory path
11
+ * @returns {boolean} Whether to init in current directory
12
+ */
13
+ export function shouldInitInCurrentDirectory(projectName: string, currentDir: string): boolean;
14
+ //# sourceMappingURL=project-analysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-analysis.d.ts","sourceRoot":"","sources":["../../src/utils/project-analysis.js"],"names":[],"mappings":"AASA;;;;GAIG;AACH,wCAHW,MAAM,GACJ,MAAM,CAmDlB;AAED;;;;;GAKG;AACH,0DAJW,MAAM,cACN,MAAM,GACJ,OAAO,CA8BnB"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @fileoverview Project Analysis Utilities
3
+ * Functions for analyzing project types and structure
4
+ * @author @darianrosebrook
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('path');
9
+
10
+ /**
11
+ * Detect project type from existing files and structure
12
+ * @param {string} cwd - Current working directory
13
+ * @returns {string} Project type
14
+ */
15
+ function detectProjectType(cwd = process.cwd()) {
16
+ const files = fs.readdirSync(cwd);
17
+
18
+ // Check for various project indicators
19
+ const hasPackageJson = files.includes('package.json');
20
+ const hasPnpm = files.includes('pnpm-workspace.yaml');
21
+ const hasYarn = files.includes('yarn.lock');
22
+
23
+ let packageJson = {};
24
+ if (hasPackageJson) {
25
+ try {
26
+ packageJson = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
27
+ } catch (e) {
28
+ // Ignore parse errors
29
+ }
30
+ }
31
+
32
+ // VS Code Extension detection
33
+ const isVscodeExtension =
34
+ packageJson.engines?.vscode ||
35
+ packageJson.contributes ||
36
+ packageJson.activationEvents ||
37
+ packageJson.main?.includes('extension.js');
38
+
39
+ // Monorepo detection
40
+ const isMonorepo = hasPnpm || hasYarn || files.includes('packages') || files.includes('apps');
41
+
42
+ // Library detection
43
+ const isLibrary = packageJson.main || packageJson.module || packageJson.exports;
44
+
45
+ // CLI detection
46
+ const isCli = packageJson.bin || packageJson.name?.startsWith('@') === false;
47
+
48
+ // API detection
49
+ const isApi =
50
+ packageJson.scripts?.start ||
51
+ packageJson.dependencies?.express ||
52
+ packageJson.dependencies?.fastify ||
53
+ packageJson.dependencies?.['@types/express'];
54
+
55
+ // Determine primary type
56
+ if (isVscodeExtension) return 'extension';
57
+ if (isMonorepo) return 'monorepo';
58
+ if (isApi) return 'api';
59
+ if (isLibrary) return 'library';
60
+ if (isCli) return 'cli';
61
+
62
+ // Default fallback
63
+ return 'application';
64
+ }
65
+
66
+ /**
67
+ * Detect if current directory appears to be a project that should be initialized directly
68
+ * @param {string} projectName - Project name from command line
69
+ * @param {string} currentDir - Current directory path
70
+ * @returns {boolean} Whether to init in current directory
71
+ */
72
+ function shouldInitInCurrentDirectory(projectName, currentDir) {
73
+ // If explicitly '.', always init in current directory
74
+ if (projectName === '.') return true;
75
+
76
+ // Check for common project indicators
77
+ const projectIndicators = [
78
+ 'package.json',
79
+ 'tsconfig.json',
80
+ 'jest.config.js',
81
+ 'eslint.config.js',
82
+ 'README.md',
83
+ 'src/',
84
+ 'lib/',
85
+ 'app/',
86
+ 'packages/',
87
+ '.git/',
88
+ 'node_modules/', // Even if empty, suggests intent to be a project
89
+ ];
90
+
91
+ const files = fs.readdirSync(currentDir);
92
+ const hasProjectIndicators = projectIndicators.some((indicator) => {
93
+ if (indicator.endsWith('/')) {
94
+ return files.includes(indicator.slice(0, -1));
95
+ }
96
+ return files.includes(indicator);
97
+ });
98
+
99
+ return hasProjectIndicators;
100
+ }
101
+
102
+ module.exports = {
103
+ detectProjectType,
104
+ shouldInitInCurrentDirectory,
105
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Basic validation of working spec
3
+ * @param {Object} spec - Working spec object
4
+ * @param {Object} options - Validation options
5
+ * @returns {Object} Validation result
6
+ */
7
+ export function validateWorkingSpec(spec: any, _options?: {}): any;
8
+ /**
9
+ * Enhanced validation with suggestions and auto-fix
10
+ * @param {Object} spec - Working spec object
11
+ * @param {Object} options - Validation options
12
+ * @returns {Object} Enhanced validation result
13
+ */
14
+ export function validateWorkingSpecWithSuggestions(spec: any, options?: any): any;
15
+ /**
16
+ * Get suggestion for a missing field
17
+ * @param {string} field - Field name
18
+ * @param {Object} _spec - Spec object (for context)
19
+ * @returns {string} Suggestion text
20
+ */
21
+ export function getFieldSuggestion(field: string, _spec: any): string;
22
+ /**
23
+ * Check if a field can be auto-fixed
24
+ * @param {string} field - Field name
25
+ * @param {Object} _spec - Spec object (for context)
26
+ * @returns {boolean} Whether field can be auto-fixed
27
+ */
28
+ export function canAutoFixField(field: string, _spec: any): boolean;
29
+ //# sourceMappingURL=spec-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec-validation.d.ts","sourceRoot":"","sources":["../../src/validation/spec-validation.js"],"names":[],"mappings":"AAQA;;;;;GAKG;AACH,mEA8HC;AAED;;;;;GAKG;AACH,kFAyLC;AAED;;;;;GAKG;AACH,0CAJW,MAAM,eAEJ,MAAM,CAkBlB;AAED;;;;;GAKG;AACH,uCAJW,MAAM,eAEJ,OAAO,CAKnB"}