@paths.design/caws-cli 3.0.0 → 3.1.1

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 (95) 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 +22 -0
  15. package/dist/commands/provenance.d.ts.map +1 -0
  16. package/dist/commands/provenance.js +594 -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-new.d.ts +5 -0
  33. package/dist/index-new.d.ts.map +1 -0
  34. package/dist/index-new.js +317 -0
  35. package/dist/index.d.ts +3 -12
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +100 -1659
  38. package/dist/index.js.backup +4711 -0
  39. package/dist/scaffold/cursor-hooks.d.ts +7 -0
  40. package/dist/scaffold/cursor-hooks.d.ts.map +1 -0
  41. package/dist/scaffold/cursor-hooks.js +152 -0
  42. package/dist/scaffold/index.d.ts +20 -0
  43. package/dist/scaffold/index.d.ts.map +1 -0
  44. package/dist/scaffold/index.js +486 -0
  45. package/dist/test-analysis.d.ts +182 -0
  46. package/dist/test-analysis.d.ts.map +1 -0
  47. package/dist/test-analysis.js +580 -0
  48. package/dist/tool-interface.d.ts +236 -0
  49. package/dist/tool-interface.d.ts.map +1 -0
  50. package/dist/tool-interface.js +314 -0
  51. package/dist/tool-loader.d.ts +77 -0
  52. package/dist/tool-loader.d.ts.map +1 -0
  53. package/dist/tool-loader.js +298 -0
  54. package/dist/tool-validator.d.ts +72 -0
  55. package/dist/tool-validator.d.ts.map +1 -0
  56. package/dist/tool-validator.js +387 -0
  57. package/dist/utils/detection.d.ts +7 -0
  58. package/dist/utils/detection.d.ts.map +1 -0
  59. package/dist/utils/detection.js +174 -0
  60. package/dist/utils/finalization.d.ts +17 -0
  61. package/dist/utils/finalization.d.ts.map +1 -0
  62. package/dist/utils/finalization.js +229 -0
  63. package/dist/utils/project-analysis.d.ts +14 -0
  64. package/dist/utils/project-analysis.d.ts.map +1 -0
  65. package/dist/utils/project-analysis.js +105 -0
  66. package/dist/validation/spec-validation.d.ts +29 -0
  67. package/dist/validation/spec-validation.d.ts.map +1 -0
  68. package/dist/validation/spec-validation.js +376 -0
  69. package/dist/waivers-manager.d.ts +167 -0
  70. package/dist/waivers-manager.d.ts.map +1 -0
  71. package/dist/waivers-manager.js +549 -0
  72. package/package.json +10 -12
  73. package/templates/.cursor/README.md +311 -0
  74. package/templates/.cursor/hooks/audit.sh +55 -0
  75. package/templates/.cursor/hooks/block-dangerous.sh +77 -0
  76. package/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  77. package/templates/.cursor/hooks/caws-scope-guard.sh +74 -0
  78. package/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  79. package/templates/.cursor/hooks/format.sh +38 -0
  80. package/templates/.cursor/hooks/naming-check.sh +64 -0
  81. package/templates/.cursor/hooks/scan-secrets.sh +46 -0
  82. package/templates/.cursor/hooks/scope-guard.sh +52 -0
  83. package/templates/.cursor/hooks/validate-spec.sh +38 -0
  84. package/templates/.cursor/hooks.json +59 -0
  85. package/templates/.github/copilot/instructions.md +311 -0
  86. package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  87. package/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  88. package/templates/.vscode/launch.json +56 -0
  89. package/templates/.vscode/settings.json +93 -0
  90. package/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  91. package/templates/apps/tools/caws/README.md +1 -1
  92. package/templates/apps/tools/caws/prompt-lint.js.backup +274 -0
  93. package/templates/apps/tools/caws/provenance.js.backup +73 -0
  94. package/templates/apps/tools/caws/schemas/working-spec.schema.json +21 -3
  95. package/templates/codemod/test.js +93 -1
@@ -0,0 +1,387 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @fileoverview CAWS Tool Validator - Security validation for dynamically loaded tools
5
+ * Validates tools against allowlists, scans for security violations, and ensures safe execution
6
+ * @author @darianrosebrook
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const path = require('path');
11
+ const crypto = require('crypto');
12
+
13
+ /**
14
+ * Tool Validator - Security validation and allowlist enforcement
15
+ */
16
+ class ToolValidator {
17
+ constructor(options = {}) {
18
+ this.options = {
19
+ allowlistPath:
20
+ options.allowlistPath || path.join(process.cwd(), 'apps/tools/caws/tools-allow.json'),
21
+ strictMode: options.strictMode !== false,
22
+ maxFileSize: options.maxFileSize || 1024 * 1024, // 1MB
23
+ ...options,
24
+ };
25
+
26
+ this.allowlist = null;
27
+ this.validationCache = new Map();
28
+ }
29
+
30
+ /**
31
+ * Load and parse the tools allowlist
32
+ * @returns {Promise<Array<string>>} Array of allowed commands/patterns
33
+ */
34
+ async loadAllowlist() {
35
+ if (this.allowlist) return this.allowlist;
36
+
37
+ try {
38
+ if (!fs.existsSync(this.options.allowlistPath)) {
39
+ throw new Error(`Allowlist file not found: ${this.options.allowlistPath}`);
40
+ }
41
+
42
+ const content = await fs.promises.readFile(this.options.allowlistPath, 'utf8');
43
+ this.allowlist = JSON.parse(content);
44
+
45
+ if (!Array.isArray(this.allowlist)) {
46
+ throw new Error('Allowlist must be an array of strings');
47
+ }
48
+
49
+ return this.allowlist;
50
+ } catch (error) {
51
+ throw new Error(`Failed to load allowlist: ${error.message}`);
52
+ }
53
+ }
54
+
55
+ /**
56
+ * Validate a tool against security requirements
57
+ * @param {Object} tool - Tool object with module and metadata
58
+ * @returns {Promise<Object>} Validation result
59
+ */
60
+ async validateTool(tool) {
61
+ const toolId = tool.metadata?.id || path.basename(tool.path, '.js');
62
+ const cacheKey = crypto
63
+ .createHash('md5')
64
+ .update(toolId + tool.loadedAt)
65
+ .digest('hex');
66
+
67
+ // Check cache first
68
+ if (this.validationCache.has(cacheKey)) {
69
+ return this.validationCache.get(cacheKey);
70
+ }
71
+
72
+ const result = {
73
+ valid: true,
74
+ checks: [],
75
+ warnings: [],
76
+ errors: [],
77
+ score: 100,
78
+ };
79
+
80
+ try {
81
+ // Load allowlist if not loaded
82
+ await this.loadAllowlist();
83
+
84
+ // Run all validation checks
85
+ const checks = await Promise.allSettled([
86
+ this.checkFileSecurity(tool),
87
+ this.checkCodeSecurity(tool),
88
+ this.checkInterfaceCompliance(tool),
89
+ this.checkMetadataValidity(tool),
90
+ this.checkDependencySafety(tool),
91
+ ]);
92
+
93
+ // Process check results
94
+ checks.forEach((check, index) => {
95
+ const checkName = [
96
+ 'fileSecurity',
97
+ 'codeSecurity',
98
+ 'interfaceCompliance',
99
+ 'metadataValidity',
100
+ 'dependencySafety',
101
+ ][index];
102
+
103
+ if (check.status === 'fulfilled') {
104
+ const checkResult = check.value;
105
+ result.checks.push({
106
+ name: checkName,
107
+ passed: checkResult.passed,
108
+ message: checkResult.message,
109
+ severity: checkResult.severity || 'info',
110
+ });
111
+
112
+ if (!checkResult.passed) {
113
+ result.valid = false;
114
+ if (checkResult.severity === 'error') {
115
+ result.errors.push(checkResult.message);
116
+ result.score -= 20;
117
+ } else {
118
+ result.warnings.push(checkResult.message);
119
+ result.score -= 5;
120
+ }
121
+ }
122
+ } else {
123
+ result.checks.push({
124
+ name: checkName,
125
+ passed: false,
126
+ message: `Check failed: ${check.reason.message}`,
127
+ severity: 'error',
128
+ });
129
+ result.valid = false;
130
+ result.errors.push(check.reason.message);
131
+ result.score -= 20;
132
+ }
133
+ });
134
+
135
+ // Cache result
136
+ this.validationCache.set(cacheKey, result);
137
+ } catch (error) {
138
+ result.valid = false;
139
+ result.errors.push(`Validation failed: ${error.message}`);
140
+ result.score = 0;
141
+ }
142
+
143
+ return result;
144
+ }
145
+
146
+ /**
147
+ * Check file-level security
148
+ * @private
149
+ * @param {Object} tool - Tool object
150
+ */
151
+ async checkFileSecurity(tool) {
152
+ const issues = [];
153
+
154
+ try {
155
+ const stats = await fs.promises.stat(tool.path);
156
+
157
+ // Check file size
158
+ if (stats.size > this.options.maxFileSize) {
159
+ issues.push(`File too large: ${stats.size} bytes > ${this.options.maxFileSize} bytes`);
160
+ }
161
+
162
+ // Check file permissions (should be readable)
163
+ const mode = stats.mode;
164
+ if (!(mode & parseInt('0444', 8))) {
165
+ // Owner, group, others can read
166
+ issues.push('File permissions too restrictive');
167
+ }
168
+
169
+ // Check if file is executable (should not be)
170
+ if (mode & parseInt('0111', 8)) {
171
+ // Execute permissions
172
+ issues.push('Tool file should not have execute permissions');
173
+ }
174
+ } catch (error) {
175
+ issues.push(`File access error: ${error.message}`);
176
+ }
177
+
178
+ return {
179
+ passed: issues.length === 0,
180
+ message: issues.length > 0 ? issues.join('; ') : 'File security check passed',
181
+ severity: issues.length > 0 ? 'error' : 'info',
182
+ };
183
+ }
184
+
185
+ /**
186
+ * Check code-level security
187
+ * @private
188
+ * @param {Object} tool - Tool object
189
+ */
190
+ async checkCodeSecurity(tool) {
191
+ const issues = [];
192
+
193
+ try {
194
+ const content = await fs.promises.readFile(tool.path, 'utf8');
195
+
196
+ // Check for dangerous patterns
197
+ const dangerousPatterns = [
198
+ { pattern: /require\(['"`]child_process['"`]\)/g, message: 'Direct child_process usage' },
199
+ { pattern: /require\(['"`]fs['"`]\)\.writeFileSync/g, message: 'Synchronous file writing' },
200
+ { pattern: /process\.exit\(/g, message: 'Process termination' },
201
+ { pattern: /eval\(/g, message: 'Code evaluation' },
202
+ { pattern: /Function\(['"`]/g, message: 'Dynamic function creation' },
203
+ { pattern: /require\(['"`]\.\./g, message: 'Directory traversal in require' },
204
+ ];
205
+
206
+ dangerousPatterns.forEach(({ pattern, message }) => {
207
+ const matches = content.match(pattern);
208
+ if (matches) {
209
+ issues.push(`${message} (${matches.length} occurrences)`);
210
+ }
211
+ });
212
+
213
+ // Check for secrets (basic pattern matching)
214
+ const secretPatterns = [
215
+ /password\s*[=:]\s*['"`][^'"]{8,}['"`]/gi,
216
+ /token\s*[=:]\s*['"`][^'"]{20,}['"`]/gi,
217
+ /key\s*[=:]\s*['"`][^'"]{16,}['"`]/gi,
218
+ /secret\s*[=:]\s*['"`][^'"]{16,}['"`]/gi,
219
+ ];
220
+
221
+ secretPatterns.forEach((pattern) => {
222
+ if (content.match(pattern)) {
223
+ issues.push('Potential hardcoded secrets detected');
224
+ }
225
+ });
226
+ } catch (error) {
227
+ issues.push(`Code analysis error: ${error.message}`);
228
+ }
229
+
230
+ return {
231
+ passed: issues.length === 0,
232
+ message:
233
+ issues.length > 0 ? `Security issues: ${issues.join('; ')}` : 'Code security check passed',
234
+ severity: issues.length > 0 ? 'error' : 'info',
235
+ };
236
+ }
237
+
238
+ /**
239
+ * Check interface compliance
240
+ * @private
241
+ * @param {Object} tool - Tool object
242
+ */
243
+ async checkInterfaceCompliance(tool) {
244
+ const requiredMethods = ['execute', 'getMetadata'];
245
+ const missingMethods = [];
246
+
247
+ requiredMethods.forEach((method) => {
248
+ if (typeof tool.module[method] !== 'function') {
249
+ missingMethods.push(method);
250
+ }
251
+ });
252
+
253
+ return {
254
+ passed: missingMethods.length === 0,
255
+ message:
256
+ missingMethods.length > 0
257
+ ? `Missing required methods: ${missingMethods.join(', ')}`
258
+ : 'Interface compliance check passed',
259
+ severity: missingMethods.length > 0 ? 'error' : 'info',
260
+ };
261
+ }
262
+
263
+ /**
264
+ * Check metadata validity
265
+ * @private
266
+ * @param {Object} tool - Tool object
267
+ */
268
+ async checkMetadataValidity(tool) {
269
+ const metadata = tool.metadata || {};
270
+ const requiredFields = ['id', 'name', 'version'];
271
+ const missingFields = [];
272
+ const invalidFields = [];
273
+
274
+ // Check required fields
275
+ requiredFields.forEach((field) => {
276
+ if (!metadata[field]) {
277
+ missingFields.push(field);
278
+ }
279
+ });
280
+
281
+ // Validate field types and formats
282
+ if (metadata.id && typeof metadata.id !== 'string') {
283
+ invalidFields.push('id must be string');
284
+ }
285
+ if (metadata.name && typeof metadata.name !== 'string') {
286
+ invalidFields.push('name must be string');
287
+ }
288
+ if (metadata.version && typeof metadata.version !== 'string') {
289
+ invalidFields.push('version must be string');
290
+ }
291
+ if (metadata.capabilities && !Array.isArray(metadata.capabilities)) {
292
+ invalidFields.push('capabilities must be array');
293
+ }
294
+
295
+ const issues = [...missingFields.map((f) => `missing ${f}`), ...invalidFields];
296
+
297
+ return {
298
+ passed: issues.length === 0,
299
+ message:
300
+ issues.length > 0
301
+ ? `Metadata issues: ${issues.join(', ')}`
302
+ : 'Metadata validity check passed',
303
+ severity: issues.length > 0 ? 'error' : 'info',
304
+ };
305
+ }
306
+
307
+ /**
308
+ * Check dependency safety
309
+ * @private
310
+ * @param {Object} tool - Tool object
311
+ */
312
+ async checkDependencySafety(tool) {
313
+ const metadata = tool.metadata || {};
314
+ const issues = [];
315
+
316
+ if (metadata.dependencies) {
317
+ if (!Array.isArray(metadata.dependencies)) {
318
+ issues.push('dependencies must be array');
319
+ } else {
320
+ // Check for potentially unsafe dependencies
321
+ const unsafeDeps = ['child_process', 'fs-extra', 'execa', 'shelljs'];
322
+ const foundUnsafe = metadata.dependencies.filter((dep) =>
323
+ unsafeDeps.some((unsafe) => dep.includes(unsafe))
324
+ );
325
+
326
+ if (foundUnsafe.length > 0) {
327
+ issues.push(`Potentially unsafe dependencies: ${foundUnsafe.join(', ')}`);
328
+ }
329
+ }
330
+ }
331
+
332
+ return {
333
+ passed: issues.length === 0,
334
+ message:
335
+ issues.length > 0
336
+ ? `Dependency issues: ${issues.join('; ')}`
337
+ : 'Dependency safety check passed',
338
+ severity: issues.length > 0 ? 'warning' : 'info',
339
+ };
340
+ }
341
+
342
+ /**
343
+ * Validate a command against the allowlist
344
+ * @param {string} command - Command to validate
345
+ * @returns {boolean} True if command is allowed
346
+ */
347
+ async validateCommand(command) {
348
+ const allowlist = await this.loadAllowlist();
349
+
350
+ // Check exact matches first
351
+ if (allowlist.includes(command)) {
352
+ return true;
353
+ }
354
+
355
+ // Check pattern matches
356
+ return allowlist.some((allowed) => {
357
+ if (allowed.includes('*')) {
358
+ // Simple wildcard matching
359
+ const regex = new RegExp(allowed.replace(/\*/g, '.*'));
360
+ return regex.test(command);
361
+ }
362
+ return false;
363
+ });
364
+ }
365
+
366
+ /**
367
+ * Clear validation cache
368
+ */
369
+ clearCache() {
370
+ this.validationCache.clear();
371
+ }
372
+
373
+ /**
374
+ * Get validator statistics
375
+ * @returns {Object} Statistics object
376
+ */
377
+ getStats() {
378
+ return {
379
+ allowlistLoaded: this.allowlist !== null,
380
+ allowlistSize: this.allowlist?.length || 0,
381
+ cacheSize: this.validationCache.size,
382
+ strictMode: this.options.strictMode,
383
+ };
384
+ }
385
+ }
386
+
387
+ module.exports = ToolValidator;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Detect CAWS setup in a directory
3
+ * @param {string} cwd - Current working directory
4
+ * @returns {Object} Setup information
5
+ */
6
+ export function detectCAWSSetup(cwd?: string): any;
7
+ //# sourceMappingURL=detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detection.d.ts","sourceRoot":"","sources":["../../src/utils/detection.js"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,sCAHW,MAAM,OA6JhB"}
@@ -0,0 +1,174 @@
1
+ /**
2
+ * @fileoverview CAWS Setup Detection Utilities
3
+ * Functions for detecting and analyzing CAWS project setups
4
+ * @author @darianrosebrook
5
+ */
6
+
7
+ const fs = require('fs-extra');
8
+ const path = require('path');
9
+ const chalk = require('chalk');
10
+
11
+ /**
12
+ * Detect CAWS setup in a directory
13
+ * @param {string} cwd - Current working directory
14
+ * @returns {Object} Setup information
15
+ */
16
+ function detectCAWSSetup(cwd = process.cwd()) {
17
+ // Skip logging for version/help commands
18
+ const isQuietCommand =
19
+ process.argv.includes('--version') ||
20
+ process.argv.includes('-V') ||
21
+ process.argv.includes('--help');
22
+
23
+ if (!isQuietCommand) {
24
+ console.log(chalk.blue('🔍 Detecting CAWS setup...'));
25
+ }
26
+
27
+ // Check for existing CAWS setup
28
+ const cawsDir = path.join(cwd, '.caws');
29
+ const hasCAWSDir = fs.existsSync(cawsDir);
30
+
31
+ if (!hasCAWSDir) {
32
+ if (!isQuietCommand) {
33
+ console.log(chalk.gray('ℹ️ No .caws directory found - new project setup'));
34
+ }
35
+ return {
36
+ type: 'new',
37
+ hasCAWSDir: false,
38
+ cawsDir: null,
39
+ capabilities: [],
40
+ hasTemplateDir: false,
41
+ templateDir: null,
42
+ };
43
+ }
44
+
45
+ // Analyze existing setup
46
+ const files = fs.readdirSync(cawsDir);
47
+ const hasWorkingSpec = fs.existsSync(path.join(cawsDir, 'working-spec.yaml'));
48
+ const hasValidateScript = fs.existsSync(path.join(cawsDir, 'validate.js'));
49
+ const hasPolicy = fs.existsSync(path.join(cawsDir, 'policy'));
50
+ const hasSchemas = fs.existsSync(path.join(cawsDir, 'schemas'));
51
+ const hasTemplates = fs.existsSync(path.join(cawsDir, 'templates'));
52
+
53
+ // Check for multiple spec files (enhanced project pattern)
54
+ const specFiles = files.filter((f) => f.endsWith('-spec.yaml'));
55
+ const hasMultipleSpecs = specFiles.length > 1;
56
+
57
+ // Check for tools directory (enhanced setup)
58
+ const toolsDir = path.join(cwd, 'apps/tools/caws');
59
+ const hasTools = fs.existsSync(toolsDir);
60
+
61
+ // Determine setup type
62
+ let setupType = 'basic';
63
+ let capabilities = [];
64
+
65
+ if (hasMultipleSpecs && hasWorkingSpec) {
66
+ setupType = 'enhanced';
67
+ capabilities.push('multiple-specs', 'working-spec', 'domain-specific');
68
+ } else if (hasWorkingSpec) {
69
+ setupType = 'standard';
70
+ capabilities.push('working-spec');
71
+ }
72
+
73
+ if (hasValidateScript) {
74
+ capabilities.push('validation');
75
+ }
76
+ if (hasPolicy) {
77
+ capabilities.push('policies');
78
+ }
79
+ if (hasSchemas) {
80
+ capabilities.push('schemas');
81
+ }
82
+ if (hasTemplates) {
83
+ capabilities.push('templates');
84
+ }
85
+ if (hasTools) {
86
+ capabilities.push('tools');
87
+ }
88
+
89
+ if (!isQuietCommand) {
90
+ console.log(chalk.green(`✅ Detected ${setupType} CAWS setup`));
91
+ console.log(chalk.gray(` Capabilities: ${capabilities.join(', ')}`));
92
+ }
93
+
94
+ // Check for template directory - try multiple possible locations
95
+ let templateDir = null;
96
+ const possibleTemplatePaths = [
97
+ // FIRST: Try bundled templates (for npm-installed CLI)
98
+ { path: path.resolve(__dirname, '../templates'), source: 'bundled with CLI' },
99
+ { path: path.resolve(__dirname, 'templates'), source: 'bundled with CLI (fallback)' },
100
+ // Try relative to current working directory (for monorepo setups)
101
+ { path: path.resolve(cwd, '../caws-template'), source: 'monorepo parent directory' },
102
+ { path: path.resolve(cwd, '../../caws-template'), source: 'monorepo grandparent' },
103
+ { path: path.resolve(cwd, '../../../caws-template'), source: 'workspace root' },
104
+ { path: path.resolve(cwd, 'packages/caws-template'), source: 'packages/ subdirectory' },
105
+ { path: path.resolve(cwd, 'caws-template'), source: 'caws-template/ subdirectory' },
106
+ // Try relative to CLI location (for installed CLI)
107
+ { path: path.resolve(__dirname, '../caws-template'), source: 'CLI installation' },
108
+ { path: path.resolve(__dirname, '../../caws-template'), source: 'CLI parent directory' },
109
+ { path: path.resolve(__dirname, '../../../caws-template'), source: 'CLI workspace root' },
110
+ // Try absolute paths for CI environments
111
+ { path: path.resolve(process.cwd(), 'packages/caws-template'), source: 'current packages/' },
112
+ { path: path.resolve(process.cwd(), '../packages/caws-template'), source: 'parent packages/' },
113
+ {
114
+ path: path.resolve(process.cwd(), '../../packages/caws-template'),
115
+ source: 'grandparent packages/',
116
+ },
117
+ {
118
+ path: path.resolve(process.cwd(), '../../../packages/caws-template'),
119
+ source: 'workspace packages/',
120
+ },
121
+ // Try from workspace root
122
+ { path: path.resolve(process.cwd(), 'caws-template'), source: 'workspace caws-template/' },
123
+ // Try various other common locations
124
+ {
125
+ path: '/home/runner/work/coding-agent-working-standard/coding-agent-working-standard/packages/caws-template',
126
+ source: 'GitHub Actions CI',
127
+ },
128
+ { path: '/workspace/packages/caws-template', source: 'Docker workspace' },
129
+ { path: '/caws/packages/caws-template', source: 'Container workspace' },
130
+ ];
131
+
132
+ for (const { path: testPath, source } of possibleTemplatePaths) {
133
+ if (fs.existsSync(testPath)) {
134
+ templateDir = testPath;
135
+ if (!isQuietCommand) {
136
+ console.log(`✅ Found CAWS templates in ${source}:`);
137
+ console.log(` ${chalk.gray(testPath)}`);
138
+ }
139
+ break;
140
+ }
141
+ }
142
+
143
+ if (!templateDir && !isQuietCommand) {
144
+ console.warn(chalk.yellow('⚠️ CAWS templates not found in standard locations'));
145
+ console.warn(chalk.blue('💡 This may limit available scaffolding features'));
146
+ console.warn(
147
+ chalk.blue('💡 For full functionality, ensure caws-template package is available')
148
+ );
149
+ }
150
+
151
+ const hasTemplateDir = templateDir !== null;
152
+
153
+ return {
154
+ type: setupType,
155
+ hasCAWSDir: true,
156
+ cawsDir,
157
+ hasWorkingSpec,
158
+ hasMultipleSpecs,
159
+ hasValidateScript,
160
+ hasPolicy,
161
+ hasSchemas,
162
+ hasTemplates,
163
+ hasTools,
164
+ hasTemplateDir,
165
+ templateDir,
166
+ capabilities,
167
+ isEnhanced: setupType === 'enhanced',
168
+ isAdvanced: hasTools || hasValidateScript,
169
+ };
170
+ }
171
+
172
+ module.exports = {
173
+ detectCAWSSetup,
174
+ };
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Generate provenance manifest and git initialization (for both modes)
3
+ * @param {string} projectName - Project name
4
+ * @param {Object} options - Command options
5
+ * @param {Object} answers - User answers
6
+ */
7
+ export function finalizeProject(projectName: string, options: any, answers: any): Promise<void>;
8
+ /**
9
+ * Display success message after project initialization
10
+ */
11
+ export function continueToSuccess(): void;
12
+ /**
13
+ * Set dependencies for finalization utilities
14
+ * @param {Object} deps - Dependencies object
15
+ */
16
+ export function setFinalizationDependencies(deps: any): void;
17
+ //# sourceMappingURL=finalization.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finalization.d.ts","sourceRoot":"","sources":["../../src/utils/finalization.js"],"names":[],"mappings":"AA6BA;;;;;GAKG;AACH,6CAJW,MAAM,6CAgKhB;AAED;;GAEG;AACH,0CA0BC;AA1MD;;;GAGG;AACH,6DAGC"}