@paths.design/caws-cli 8.1.0 → 8.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 (78) hide show
  1. package/README.md +5 -6
  2. package/dist/commands/archive.d.ts +1 -1
  3. package/dist/commands/archive.d.ts.map +1 -1
  4. package/dist/commands/init.d.ts.map +1 -1
  5. package/dist/commands/init.js +185 -39
  6. package/dist/commands/mode.d.ts +2 -1
  7. package/dist/commands/mode.d.ts.map +1 -1
  8. package/dist/commands/provenance.d.ts.map +1 -1
  9. package/dist/commands/specs.d.ts.map +1 -1
  10. package/dist/commands/worktree.d.ts +7 -0
  11. package/dist/commands/worktree.d.ts.map +1 -0
  12. package/dist/commands/worktree.js +136 -0
  13. package/dist/config/lite-scope.d.ts +33 -0
  14. package/dist/config/lite-scope.d.ts.map +1 -0
  15. package/dist/config/lite-scope.js +158 -0
  16. package/dist/config/modes.d.ts +90 -51
  17. package/dist/config/modes.d.ts.map +1 -1
  18. package/dist/config/modes.js +26 -0
  19. package/dist/error-handler.d.ts +3 -16
  20. package/dist/error-handler.d.ts.map +1 -1
  21. package/dist/generators/jest-config-generator.d.ts +32 -0
  22. package/dist/generators/jest-config-generator.d.ts.map +1 -0
  23. package/dist/index.js +36 -0
  24. package/dist/scaffold/claude-hooks.d.ts +28 -0
  25. package/dist/scaffold/claude-hooks.d.ts.map +1 -0
  26. package/dist/scaffold/claude-hooks.js +28 -0
  27. package/dist/scaffold/index.d.ts +2 -0
  28. package/dist/scaffold/index.d.ts.map +1 -1
  29. package/dist/scaffold/index.js +90 -88
  30. package/dist/templates/.caws/schemas/scope.schema.json +52 -0
  31. package/dist/templates/.caws/schemas/working-spec.schema.json +1 -1
  32. package/dist/templates/.caws/schemas/worktrees.schema.json +36 -0
  33. package/dist/templates/.claude/hooks/block-dangerous.sh +33 -0
  34. package/dist/templates/.claude/hooks/lite-sprawl-check.sh +117 -0
  35. package/dist/templates/.claude/hooks/scope-guard.sh +93 -6
  36. package/dist/templates/.claude/hooks/simplification-guard.sh +92 -0
  37. package/dist/templates/.cursor/README.md +0 -3
  38. package/dist/templates/.github/copilot-instructions.md +82 -0
  39. package/dist/templates/.junie/guidelines.md +73 -0
  40. package/dist/templates/.vscode/launch.json +0 -27
  41. package/dist/templates/.windsurf/rules/caws-quality-standards.md +54 -0
  42. package/dist/templates/CLAUDE.md +101 -0
  43. package/dist/templates/agents.md +73 -1016
  44. package/dist/templates/docs/README.md +5 -5
  45. package/dist/test-analysis.d.ts +50 -1
  46. package/dist/test-analysis.d.ts.map +1 -1
  47. package/dist/utils/error-categories.d.ts +52 -0
  48. package/dist/utils/error-categories.d.ts.map +1 -0
  49. package/dist/utils/gitignore-updater.d.ts +1 -1
  50. package/dist/utils/gitignore-updater.d.ts.map +1 -1
  51. package/dist/utils/gitignore-updater.js +4 -0
  52. package/dist/utils/ide-detection.js +133 -0
  53. package/dist/utils/quality-gates-utils.d.ts +49 -0
  54. package/dist/utils/quality-gates-utils.d.ts.map +1 -0
  55. package/dist/utils/typescript-detector.d.ts +8 -5
  56. package/dist/utils/typescript-detector.d.ts.map +1 -1
  57. package/dist/validation/spec-validation.d.ts.map +1 -1
  58. package/dist/worktree/worktree-manager.d.ts +54 -0
  59. package/dist/worktree/worktree-manager.d.ts.map +1 -0
  60. package/dist/worktree/worktree-manager.js +378 -0
  61. package/package.json +5 -1
  62. package/templates/.caws/schemas/scope.schema.json +52 -0
  63. package/templates/.caws/schemas/working-spec.schema.json +1 -1
  64. package/templates/.caws/schemas/worktrees.schema.json +36 -0
  65. package/templates/.claude/hooks/block-dangerous.sh +33 -0
  66. package/templates/.claude/hooks/lite-sprawl-check.sh +117 -0
  67. package/templates/.claude/hooks/scope-guard.sh +93 -6
  68. package/templates/.claude/hooks/simplification-guard.sh +92 -0
  69. package/templates/.cursor/README.md +0 -3
  70. package/templates/.github/copilot-instructions.md +82 -0
  71. package/templates/.junie/guidelines.md +73 -0
  72. package/templates/.vscode/launch.json +0 -27
  73. package/templates/.windsurf/rules/caws-quality-standards.md +54 -0
  74. package/templates/AGENTS.md +104 -0
  75. package/templates/CLAUDE.md +101 -0
  76. package/templates/docs/README.md +5 -5
  77. package/templates/.github/copilot/instructions.md +0 -311
  78. package/templates/agents.md +0 -1047
package/README.md CHANGED
@@ -13,7 +13,7 @@ The CAWS CLI serves as the central control point for:
13
13
  - **Agent Integration**: Programmatic APIs for AI agents to evaluate and guide development
14
14
  - **Waiver Management**: Fast-lane escape hatches with full audit trails
15
15
  - **CI/CD Optimization**: Pipeline generation and optimization tools
16
- - **Experimental Features**: Dry-run capabilities for cutting-edge functionality
16
+ - **Experimental Features**: Dry-run capabilities for experimental functionality
17
17
 
18
18
  ## Installation
19
19
 
@@ -157,15 +157,14 @@ caws-cli/
157
157
  │ │
158
158
  └───────────────────────┘
159
159
 
160
- ┌─────────────────┐ ┌──────────────────┐
161
- │ caws-mcp-server │────│ caws-vscode-ext
162
- │ (Agent Bridge) │ │ (IDE Integration)
163
- └─────────────────┘ └──────────────────┘
160
+ ┌─────────────────┐
161
+ │ caws-mcp-server │
162
+ │ (Agent Bridge) │
163
+ └─────────────────┘
164
164
  ```
165
165
 
166
166
  - **caws-template**: Provides the tools and configurations that CLI manages
167
167
  - **caws-mcp-server**: Exposes CLI functionality to AI agents via MCP protocol
168
- - **caws-vscode-extension**: Provides IDE integration using CLI capabilities
169
168
 
170
169
  ### Quality Gates Integration
171
170
 
@@ -22,7 +22,7 @@ export function validateAcceptanceCriteria(workingSpec: any): Promise<any>;
22
22
  * @param {string} changeId - Change identifier
23
23
  * @returns {Promise<Object>} Quality gate result
24
24
  */
25
- export function validateQualityGates(changeId: string): Promise<any>;
25
+ export function validateQualityGates(_changeId: any): Promise<any>;
26
26
  /**
27
27
  * Generate change summary for archival
28
28
  * @param {Object} change - Change data
@@ -1 +1 @@
1
- {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/commands/archive.js"],"names":[],"mappings":"AA0VA;;;;GAIG;AACH,yCAHW,MAAM,+BAqGhB;AAjbD;;;;GAIG;AACH,qCAHW,MAAM,GACJ,OAAO,CAAC,MAAO,IAAI,CAAC,CAgChC;AAED;;;;GAIG;AACH,8DAFa,OAAO,KAAQ,CA8B3B;AAED;;;;;GAKG;AACH,+CAHW,MAAM,GACJ,OAAO,KAAQ,CAmH3B;AAED;;;;GAIG;AACH,oDAFa,OAAO,CAAC,MAAM,CAAC,CAgC3B;AAED;;;;GAIG;AACH,4CAFa,OAAO,CAAC,IAAI,CAAC,CAazB;AAED;;;;GAIG;AACH,+CAFa,OAAO,CAAC,IAAI,CAAC,CAoCzB;AAED;;;;;GAKG;AACH,6FAiCC"}
1
+ {"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../src/commands/archive.js"],"names":[],"mappings":"AA0VA;;;;GAIG;AACH,yCAHW,MAAM,+BAqGhB;AAjbD;;;;GAIG;AACH,qCAHW,MAAM,GACJ,OAAO,CAAC,MAAO,IAAI,CAAC,CAgChC;AAED;;;;GAIG;AACH,8DAFa,OAAO,KAAQ,CA8B3B;AAED;;;;;GAKG;AACH,sDAFa,OAAO,KAAQ,CAmH3B;AAED;;;;GAIG;AACH,oDAFa,OAAO,CAAC,MAAM,CAAC,CAgC3B;AAED;;;;GAIG;AACH,4CAFa,OAAO,CAAC,IAAI,CAAC,CAazB;AAED;;;;GAIG;AACH,+CAFa,OAAO,CAAC,IAAI,CAAC,CAoCzB;AAED;;;;;GAKG;AACH,6FAiCC"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.js"],"names":[],"mappings":"AAqBA;;GAEG;AACH,2EAwiBC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.js"],"names":[],"mappings":"AAwBA;;GAEG;AACH,2EA6mBC"}
@@ -18,6 +18,15 @@ const { finalizeProject } = require('../utils/finalization');
18
18
  const { scaffoldCursorHooks } = require('../scaffold/cursor-hooks');
19
19
  const { scaffoldIDEIntegrations } = require('../scaffold/index');
20
20
  const { updateGitignore } = require('../utils/gitignore-updater');
21
+ const { getLiteScopeDefaults } = require('../config/lite-scope');
22
+ const { scaffoldClaudeHooks } = require('../scaffold/claude-hooks');
23
+ const { setCurrentMode } = require('../config/modes');
24
+ const {
25
+ IDE_REGISTRY,
26
+ detectActiveIDEs,
27
+ getRecommendedIDEs,
28
+ parseIDESelection,
29
+ } = require('../utils/ide-detection');
21
30
 
22
31
  /**
23
32
  * Initialize a new project with CAWS
@@ -115,8 +124,9 @@ async function initProject(projectName, options) {
115
124
  const cawsSetup = detectCAWSSetup(targetDir);
116
125
  const originalTemplateDir = cawsSetup?.hasTemplateDir ? cawsSetup.templateDir : null;
117
126
 
118
- // Check for existing agents.md/caws.md in target directory
119
- const existingAgentsMd = fs.existsSync(path.join(targetDir, 'agents.md'));
127
+ // Check for existing AGENTS.md/agents.md/caws.md in target directory
128
+ const existingAgentsMd = fs.existsSync(path.join(targetDir, 'AGENTS.md')) ||
129
+ fs.existsSync(path.join(targetDir, 'agents.md'));
120
130
  const existingCawsMd = fs.existsSync(path.join(targetDir, 'caws.md'));
121
131
 
122
132
  // Create project directory and change to it (unless already in current directory)
@@ -137,55 +147,45 @@ async function initProject(projectName, options) {
137
147
  await fs.ensureDir('.agent');
138
148
  console.log(chalk.blue('ℹ️ Created basic CAWS structure'));
139
149
 
140
- // Copy agents.md guide if templates are available
150
+ // Copy AGENTS.md guide if templates are available
141
151
  if (originalTemplateDir) {
142
152
  try {
143
- const agentsMdSource = path.join(originalTemplateDir, 'agents.md');
144
- let targetFile = 'agents.md';
153
+ const agentsMdSource = path.join(originalTemplateDir, 'AGENTS.md');
154
+ let targetFile = 'AGENTS.md';
145
155
 
146
156
  if (fs.existsSync(agentsMdSource)) {
147
- // Use the pre-checked values for conflicts
148
157
  if (existingAgentsMd) {
149
- // Conflict: user already has agents.md
150
158
  if (options.interactive && !options.nonInteractive) {
151
- // Interactive mode: ask user
152
159
  const overwriteAnswer = await inquirer.prompt([
153
160
  {
154
161
  type: 'confirm',
155
162
  name: 'overwrite',
156
- message: '⚠️ agents.md already exists. Overwrite with CAWS guide?',
163
+ message: 'AGENTS.md already exists. Overwrite with CAWS guide?',
157
164
  default: false,
158
165
  },
159
166
  ]);
160
167
 
161
- if (overwriteAnswer.overwrite) {
162
- targetFile = 'agents.md';
163
- } else {
168
+ if (!overwriteAnswer.overwrite) {
164
169
  targetFile = 'caws.md';
165
170
  }
166
171
  } else {
167
- // Non-interactive mode: use caws.md instead
168
172
  targetFile = 'caws.md';
169
- console.log(chalk.blue('ℹ️ agents.md exists, using caws.md for CAWS guide'));
173
+ console.log(chalk.blue('AGENTS.md exists, using caws.md for CAWS guide'));
170
174
  }
171
175
  }
172
176
 
173
- // If caws.md also exists and that's our target, skip
174
177
  if (targetFile === 'caws.md' && existingCawsMd) {
175
178
  console.log(
176
- chalk.yellow('⚠️ Both agents.md and caws.md exist, skipping guide copy')
179
+ chalk.yellow('Both AGENTS.md and caws.md exist, skipping guide copy')
177
180
  );
178
181
  } else {
179
182
  const agentsMdDest = path.join(process.cwd(), targetFile);
180
183
  await fs.copyFile(agentsMdSource, agentsMdDest);
181
- console.log(chalk.green(`✅ Added ${targetFile} guide`));
184
+ console.log(chalk.green(`Added ${targetFile} guide`));
182
185
  }
183
186
  }
184
187
  } catch (templateError) {
185
- console.warn(chalk.yellow('⚠️ Could not copy agents guide:'), templateError.message);
186
- console.warn(
187
- chalk.blue('💡 You can manually copy the guide from the caws-template package')
188
- );
188
+ console.warn(chalk.yellow('Could not copy agents guide:'), templateError.message);
189
189
  }
190
190
  }
191
191
  } else {
@@ -193,12 +193,92 @@ async function initProject(projectName, options) {
193
193
  console.log(chalk.green('✅ CAWS project detected - skipping template copy'));
194
194
  }
195
195
 
196
+ // Handle lite mode init path
197
+ if (options.mode === 'lite') {
198
+ console.log(chalk.magenta('🛡️ CAWS Lite Mode — guardrails without YAML specs'));
199
+
200
+ // Detect allowed directories
201
+ const detectedDirs = [];
202
+ const commonDirs = ['src/', 'lib/', 'app/', 'tests/', 'test/', 'docs/'];
203
+ for (const dir of commonDirs) {
204
+ if (fs.existsSync(path.join(process.cwd(), dir.replace(/\/$/, '')))) {
205
+ detectedDirs.push(dir);
206
+ }
207
+ }
208
+
209
+ let allowedDirs = detectedDirs.length > 0 ? detectedDirs : ['src/', 'tests/', 'docs/'];
210
+
211
+ if (options.interactive && !options.nonInteractive) {
212
+ const liteAnswers = await inquirer.prompt([
213
+ {
214
+ type: 'input',
215
+ name: 'projectName',
216
+ message: '📝 Project name:',
217
+ default: path.basename(process.cwd()),
218
+ },
219
+ {
220
+ type: 'input',
221
+ name: 'allowedDirs',
222
+ message: '📁 Allowed directories (comma-separated):',
223
+ default: allowedDirs.join(', '),
224
+ },
225
+ ]);
226
+ allowedDirs = liteAnswers.allowedDirs.split(',').map((d) => d.trim()).filter(Boolean);
227
+ }
228
+
229
+ // Generate .caws/scope.json
230
+ await fs.ensureDir('.caws');
231
+ const scopeConfig = getLiteScopeDefaults();
232
+ scopeConfig.allowedDirectories = allowedDirs;
233
+ await fs.writeFile(
234
+ path.join('.caws', 'scope.json'),
235
+ JSON.stringify(scopeConfig, null, 2)
236
+ );
237
+ console.log(chalk.green('✅ Created .caws/scope.json'));
238
+
239
+ // Set mode to lite
240
+ await setCurrentMode('lite');
241
+ console.log(chalk.green('✅ Set mode to lite in .caws/mode.json'));
242
+
243
+ // Scaffold hooks: block-dangerous + scope-guard + lite-sprawl-check + simplification-guard
244
+ const liteIDEs = options.ide ? parseIDESelection(options.ide) : ['claude'];
245
+ if (liteIDEs.includes('claude')) {
246
+ console.log(chalk.blue('🔧 Setting up lite-mode hooks...'));
247
+ await scaffoldClaudeHooks(process.cwd(), ['safety', 'scope', 'lite']);
248
+ }
249
+
250
+ // Update .gitignore
251
+ console.log(chalk.blue('📝 Updating .gitignore...'));
252
+ await updateGitignore(process.cwd());
253
+
254
+ // Success
255
+ console.log(chalk.green('\n🎉 CAWS Lite mode initialized!'));
256
+ console.log(chalk.blue('\nGuardrails active:'));
257
+ console.log(' - Destructive command blocking (git push --force, rm -rf, etc.)');
258
+ console.log(' - Scope fencing (edits outside allowed directories require confirmation)');
259
+ console.log(' - File sprawl detection (banned patterns like *-enhanced.*, *-final.*)');
260
+ console.log(' - Simplification guard (prevents stubbing out implementations)');
261
+ console.log(chalk.blue('\nNext steps:'));
262
+ console.log(' 1. Review .caws/scope.json and customize for your project');
263
+ console.log(' 2. Start coding — hooks will protect against common AI mistakes');
264
+ console.log(' 3. Use `caws worktree create <name>` for isolated agent workspaces');
265
+ return;
266
+ }
267
+
196
268
  // Handle interactive wizard or template-based setup
197
269
  if (options.interactive && !options.nonInteractive) {
198
270
  console.log(chalk.cyan('🎯 CAWS Interactive Setup Wizard'));
199
271
  console.log(chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));
200
272
  console.log(chalk.gray('This wizard will guide you through creating a CAWS working spec\n'));
201
273
 
274
+ // Detect active IDEs for pre-selecting the IDE prompt
275
+ const detectedIDEs = detectActiveIDEs();
276
+ const recommendedIDEs = getRecommendedIDEs();
277
+ if (detectedIDEs.length > 0) {
278
+ console.log(chalk.blue(`Detected IDE: ${detectedIDEs.map((id) => IDE_REGISTRY[id].name).join(', ')}`));
279
+ console.log(chalk.gray(' (Pre-selected based on your environment)\n'));
280
+ }
281
+
202
282
  // Detect project type
203
283
  const detectedType = detectProjectType(process.cwd());
204
284
  console.log(chalk.blue(`📦 Detected project type: ${chalk.cyan(detectedType)}`));
@@ -337,10 +417,65 @@ async function initProject(projectName, options) {
337
417
  },
338
418
  },
339
419
  {
340
- type: 'confirm',
341
- name: 'useCursorHooks',
342
- message: '🎯 Enable Cursor IDE hooks for real-time quality gates?',
343
- default: true,
420
+ type: 'checkbox',
421
+ name: 'selectedIDEs',
422
+ message: 'Which IDE integrations do you want to install?',
423
+ choices: [
424
+ {
425
+ name: `Cursor (hooks, rules, audit) - AI-first IDE`,
426
+ value: 'cursor',
427
+ checked: options.ide
428
+ ? parseIDESelection(options.ide).includes('cursor')
429
+ : recommendedIDEs.includes('cursor'),
430
+ },
431
+ {
432
+ name: `Claude Code (safety hooks, settings)`,
433
+ value: 'claude',
434
+ checked: options.ide
435
+ ? parseIDESelection(options.ide).includes('claude')
436
+ : recommendedIDEs.includes('claude'),
437
+ },
438
+ {
439
+ name: `VS Code (settings, debug configs)`,
440
+ value: 'vscode',
441
+ checked: options.ide
442
+ ? parseIDESelection(options.ide).includes('vscode')
443
+ : recommendedIDEs.includes('vscode'),
444
+ },
445
+ {
446
+ name: `IntelliJ IDEA (run configurations)`,
447
+ value: 'intellij',
448
+ checked: options.ide
449
+ ? parseIDESelection(options.ide).includes('intellij')
450
+ : recommendedIDEs.includes('intellij'),
451
+ },
452
+ {
453
+ name: `Windsurf (CAWS workflow)`,
454
+ value: 'windsurf',
455
+ checked: options.ide
456
+ ? parseIDESelection(options.ide).includes('windsurf')
457
+ : recommendedIDEs.includes('windsurf'),
458
+ },
459
+ {
460
+ name: `GitHub Copilot (instructions)`,
461
+ value: 'copilot',
462
+ checked: options.ide
463
+ ? parseIDESelection(options.ide).includes('copilot')
464
+ : recommendedIDEs.includes('copilot'),
465
+ },
466
+ {
467
+ name: `JetBrains Junie (AI agent guidelines)`,
468
+ value: 'junie',
469
+ checked: options.ide
470
+ ? parseIDESelection(options.ide).includes('junie')
471
+ : recommendedIDEs.includes('junie'),
472
+ },
473
+ new inquirer.Separator(),
474
+ {
475
+ name: 'All IDEs (install everything)',
476
+ value: 'all',
477
+ },
478
+ ],
344
479
  },
345
480
  {
346
481
  type: 'confirm',
@@ -412,15 +547,20 @@ Happy coding! 🎯
412
547
  console.log(chalk.green('✅ Created test and docs directories'));
413
548
  }
414
549
 
415
- // Setup Cursor hooks if requested
416
- if (answers.useCursorHooks) {
417
- console.log(chalk.blue('🎯 Setting up Cursor hooks...'));
550
+ // Setup selected IDE integrations
551
+ const selectedIDEs = parseIDESelection(answers.selectedIDEs || []);
552
+
553
+ if (selectedIDEs.includes('cursor')) {
554
+ console.log(chalk.blue('Setting up Cursor hooks...'));
418
555
  await scaffoldCursorHooks(process.cwd());
419
556
  }
420
557
 
421
- // Setup IDE integrations for comprehensive development experience
422
- console.log(chalk.blue('🎨 Setting up IDE integrations...'));
423
- await scaffoldIDEIntegrations(process.cwd(), { force: false });
558
+ if (selectedIDEs.length > 0) {
559
+ console.log(chalk.blue('Setting up IDE integrations...'));
560
+ await scaffoldIDEIntegrations(process.cwd(), { force: false, ides: selectedIDEs });
561
+ } else {
562
+ console.log(chalk.gray('Skipping IDE setup (none selected, run `caws scaffold --ide <ides>` later)'));
563
+ }
424
564
 
425
565
  // Update .gitignore to exclude CAWS local runtime files
426
566
  console.log(chalk.blue('📝 Updating .gitignore...'));
@@ -500,13 +640,18 @@ Happy coding! 🎯
500
640
  console.log(chalk.green('✅ Created .caws/policy.yaml (optional - defaults work fine)'));
501
641
  }
502
642
 
503
- // Setup Cursor hooks by default in non-interactive mode
504
- console.log(chalk.blue('🎯 Setting up Cursor hooks...'));
505
- await scaffoldCursorHooks(process.cwd());
643
+ // Setup IDE integrations based on --ide flag or auto-detection
644
+ const selectedIDEs = options.ide ? parseIDESelection(options.ide) : getRecommendedIDEs();
506
645
 
507
- // Setup IDE integrations by default in non-interactive mode
508
- console.log(chalk.blue('🎨 Setting up IDE integrations...'));
509
- await scaffoldIDEIntegrations(process.cwd(), { force: false });
646
+ if (selectedIDEs.includes('cursor')) {
647
+ console.log(chalk.blue('Setting up Cursor hooks...'));
648
+ await scaffoldCursorHooks(process.cwd());
649
+ }
650
+
651
+ if (selectedIDEs.length > 0) {
652
+ console.log(chalk.blue(`Setting up IDE integrations: ${selectedIDEs.map((id) => IDE_REGISTRY[id].name).join(', ')}...`));
653
+ await scaffoldIDEIntegrations(process.cwd(), { force: false, ides: selectedIDEs });
654
+ }
510
655
 
511
656
  // Update .gitignore to exclude CAWS local runtime files
512
657
  console.log(chalk.blue('📝 Updating .gitignore...'));
@@ -549,8 +694,9 @@ Happy coding! 🎯
549
694
  console.log(' 3. Run: caws validate (verify setup)');
550
695
  console.log(' 4. Run: caws diagnose (check health)');
551
696
  console.log(' 5. Optional: Create .caws/policy.yaml for custom budgets');
552
- if (answers?.useCursorHooks || options.interactive === false) {
553
- console.log(' 6. Restart Cursor IDE to activate quality gates');
697
+ const finalIDEs = answers?.selectedIDEs || [];
698
+ if (finalIDEs.includes('cursor') || finalIDEs.includes('claude') || options.interactive === false) {
699
+ console.log(' 6. Restart your IDE to activate quality gates');
554
700
  }
555
701
  console.log('\n💡 Quick start: caws scaffold && caws validate && caws diagnose');
556
702
  } catch (error) {
@@ -8,8 +8,9 @@ import { getCurrentMode } from "../config/modes";
8
8
  import { setCurrentMode } from "../config/modes";
9
9
  /**
10
10
  * Display current mode status
11
+ * @param {string} currentMode - The current mode to display
11
12
  */
12
- export function displayCurrentMode(): void;
13
+ export function displayCurrentMode(currentMode: string): void;
13
14
  /**
14
15
  * Display mode details
15
16
  * @param {string} mode - Mode to display
@@ -1 +1 @@
1
- {"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../src/commands/mode.js"],"names":[],"mappings":"AAuHA;;;;GAIG;AACH,oCAHW,MAAM,+BAgIhB;;;AAvOD;;GAEG;AACH,2CAOC;AAED;;;GAGG;AACH,yCAFW,MAAM,QA+ChB;AAED;;;GAGG;AACH,4CAFa,OAAO,CAAC,MAAM,CAAC,CAkC3B"}
1
+ {"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../src/commands/mode.js"],"names":[],"mappings":"AA0IA;;;;GAIG;AACH,oCAHW,MAAM,+BAuHhB;;;AAjPD;;;GAGG;AACH,gDAFW,MAAM,QA2BhB;AAED;;;GAGG;AACH,yCAFW,MAAM,QA+ChB;AAED;;;GAGG;AACH,4CAFa,OAAO,CAAC,MAAM,CAAC,CAkC3B"}
@@ -1 +1 @@
1
- {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../../src/commands/provenance.js"],"names":[],"mappings":"AAYA;;;;GAIG;AACH,8CAHW,MAAM,8BA+BhB;AAED;;;GAGG;AACH,8DA4EC;AAED;;;GAGG;AACH,4DAyEC;AAED;;;GAGG;AACH,8DA8CC;AA6iBD;;;GAGG;AACH,4DAmEC;AAzcD;;;GAGG;AACH,0DAwEC"}
1
+ {"version":3,"file":"provenance.d.ts","sourceRoot":"","sources":["../../src/commands/provenance.js"],"names":[],"mappings":"AA2CA;;;;GAIG;AACH,8CAHW,MAAM,8BA+BhB;AAED;;;GAGG;AACH,8DAuEC;AAED;;;GAGG;AACH,4DAyEC;AAED;;;GAGG;AACH,8DA8CC;AAgnBD;;;GAGG;AACH,4DAmEC;AA/cD;;;GAGG;AACH,0DAwEC"}
@@ -1 +1 @@
1
- {"version":3,"file":"specs.d.ts","sourceRoot":"","sources":["../../src/commands/specs.js"],"names":[],"mappings":"AAipBA;;;;GAIG;AACH,qCAHW,MAAM,+BA+LhB;AA3zBD;;;GAGG;AACH,qCAFa,OAAO,KAAQ,CAqB3B;AAED;;;;GAIG;AACH,kDAFa,OAAO,CAAC,IAAI,CAAC,CAMzB;AAED;;;GAGG;AACH,iCAFa,OAAO,OAAO,CAmC1B;AAED;;;;;GAKG;AACH,+BAJW,MAAM,kBAEJ,OAAO,KAAQ,CAkO3B;AAED;;;;GAIG;AACH,6BAHW,MAAM,GACJ,OAAO,CAAC,MAAO,IAAI,CAAC,CAiBhC;AAED;;;;;GAKG;AACH,+BAJW,MAAM,kBAEJ,OAAO,CAAC,OAAO,CAAC,CA6B5B;AAED;;;;GAIG;AACH,+BAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAmB5B;AAED;;;GAGG;AACH,sDA2CC;AAED;;;GAGG;AACH,oDAoCC;AAoHD;;;GAGG;AACH,yCAFa,OAAO,CAAC,MAAM,CAAC,CAqC3B;AA9nBD;;GAEG;AACH,wBAAkB,aAAa,CAAC;AAChC,6BAAuB,2BAA2B,CAAC"}
1
+ {"version":3,"file":"specs.d.ts","sourceRoot":"","sources":["../../src/commands/specs.js"],"names":[],"mappings":"AAm0BA;;;;GAIG;AACH,qCAHW,MAAM,+BA+LhB;AA7+BD;;;GAGG;AACH,qCAFa,OAAO,KAAQ,CAqB3B;AAED;;;;GAIG;AACH,kDAFa,OAAO,CAAC,IAAI,CAAC,CAMzB;AAED;;;GAGG;AACH,iCAFa,OAAO,OAAO,CAmC1B;AAED;;;;;GAKG;AACH,+BAJW,MAAM,kBAEJ,OAAO,KAAQ,CAkO3B;AAED;;;;GAIG;AACH,6BAHW,MAAM,GACJ,OAAO,CAAC,MAAO,IAAI,CAAC,CAiBhC;AAED;;;;;GAKG;AACH,+BAJW,MAAM,kBAEJ,OAAO,CAAC,OAAO,CAAC,CA6B5B;AAiID;;;;GAIG;AACH,+BAHW,MAAM,GACJ,OAAO,CAAC,OAAO,CAAC,CAmB5B;AAED;;;GAGG;AACH,sDA2CC;AAED;;;GAGG;AACH,oDAoCC;AAuKD;;;GAGG;AACH,yCAFa,OAAO,CAAC,MAAM,CAAC,CAqC3B;AAhzBD;;GAEG;AACH,wBAAkB,aAAa,CAAC;AAChC,6BAAuB,2BAA2B,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Handle worktree subcommands
3
+ * @param {string} subcommand - Subcommand name
4
+ * @param {Object} options - Command options
5
+ */
6
+ export function worktreeCommand(subcommand: string, options?: any): Promise<void>;
7
+ //# sourceMappingURL=worktree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/commands/worktree.js"],"names":[],"mappings":"AAcA;;;;GAIG;AACH,4CAHW,MAAM,gCAuBhB"}
@@ -0,0 +1,136 @@
1
+ /**
2
+ * @fileoverview CAWS Worktree CLI Command
3
+ * Manages git worktrees for agent scope isolation
4
+ * @author @darianrosebrook
5
+ */
6
+
7
+ const chalk = require('chalk');
8
+ const {
9
+ createWorktree,
10
+ listWorktrees,
11
+ destroyWorktree,
12
+ pruneWorktrees,
13
+ } = require('../worktree/worktree-manager');
14
+
15
+ /**
16
+ * Handle worktree subcommands
17
+ * @param {string} subcommand - Subcommand name
18
+ * @param {Object} options - Command options
19
+ */
20
+ async function worktreeCommand(subcommand, options = {}) {
21
+ try {
22
+ switch (subcommand) {
23
+ case 'create':
24
+ return handleCreate(options);
25
+ case 'list':
26
+ return handleList();
27
+ case 'destroy':
28
+ return handleDestroy(options);
29
+ case 'prune':
30
+ return handlePrune(options);
31
+ default:
32
+ console.error(chalk.red(`Unknown worktree subcommand: ${subcommand}`));
33
+ console.log(chalk.blue('Available: create, list, destroy, prune'));
34
+ process.exit(1);
35
+ }
36
+ } catch (error) {
37
+ console.error(chalk.red(`❌ ${error.message}`));
38
+ process.exit(1);
39
+ }
40
+ }
41
+
42
+ function handleCreate(options) {
43
+ const { name, scope, baseBranch, specId } = options;
44
+
45
+ if (!name) {
46
+ console.error(chalk.red('❌ Worktree name is required'));
47
+ console.log(chalk.blue('Usage: caws worktree create <name> [--scope "src/auth/**"]'));
48
+ process.exit(1);
49
+ }
50
+
51
+ console.log(chalk.cyan(`🌿 Creating worktree: ${name}`));
52
+
53
+ const entry = createWorktree(name, { scope, baseBranch, specId });
54
+
55
+ console.log(chalk.green(`✅ Worktree created`));
56
+ console.log(chalk.gray(` Path: ${entry.path}`));
57
+ console.log(chalk.gray(` Branch: ${entry.branch}`));
58
+ if (entry.scope) console.log(chalk.gray(` Scope: ${entry.scope}`));
59
+ if (entry.specId) console.log(chalk.gray(` Spec: ${entry.specId}`));
60
+ console.log(chalk.blue(`\n💡 cd ${entry.path} to start working in the isolated worktree`));
61
+ }
62
+
63
+ function handleList() {
64
+ const entries = listWorktrees();
65
+
66
+ if (entries.length === 0) {
67
+ console.log(chalk.gray('No worktrees registered.'));
68
+ console.log(chalk.blue('Create one with: caws worktree create <name>'));
69
+ return;
70
+ }
71
+
72
+ console.log(chalk.bold.cyan('🌿 CAWS Worktrees'));
73
+ console.log(chalk.cyan('━'.repeat(70)));
74
+ console.log(
75
+ chalk.bold(
76
+ 'Name'.padEnd(20) +
77
+ 'Status'.padEnd(12) +
78
+ 'Branch'.padEnd(20) +
79
+ 'Scope'
80
+ )
81
+ );
82
+ console.log(chalk.gray('─'.repeat(70)));
83
+
84
+ for (const entry of entries) {
85
+ const statusColor =
86
+ entry.status === 'active'
87
+ ? chalk.green
88
+ : entry.status === 'destroyed'
89
+ ? chalk.gray
90
+ : chalk.yellow;
91
+
92
+ console.log(
93
+ entry.name.padEnd(20) +
94
+ statusColor(entry.status.padEnd(12)) +
95
+ (entry.branch || '').padEnd(20) +
96
+ (entry.scope || '-')
97
+ );
98
+ }
99
+
100
+ console.log('');
101
+ }
102
+
103
+ function handleDestroy(options) {
104
+ const { name, deleteBranch, force } = options;
105
+
106
+ if (!name) {
107
+ console.error(chalk.red('❌ Worktree name is required'));
108
+ console.log(chalk.blue('Usage: caws worktree destroy <name> [--delete-branch] [--force]'));
109
+ process.exit(1);
110
+ }
111
+
112
+ console.log(chalk.cyan(`🗑️ Destroying worktree: ${name}`));
113
+ destroyWorktree(name, { deleteBranch, force });
114
+ console.log(chalk.green(`✅ Worktree '${name}' destroyed`));
115
+ if (deleteBranch) {
116
+ console.log(chalk.gray(' Branch also deleted'));
117
+ }
118
+ }
119
+
120
+ function handlePrune(options) {
121
+ const maxAge = options.maxAge !== undefined ? parseInt(options.maxAge, 10) : 30;
122
+
123
+ console.log(chalk.cyan(`🧹 Pruning worktrees (max age: ${maxAge} days)`));
124
+ const pruned = pruneWorktrees({ maxAgeDays: maxAge });
125
+
126
+ if (pruned.length === 0) {
127
+ console.log(chalk.gray('Nothing to prune.'));
128
+ } else {
129
+ console.log(chalk.green(`✅ Pruned ${pruned.length} worktree(s):`));
130
+ for (const entry of pruned) {
131
+ console.log(chalk.gray(` - ${entry.name} (created ${entry.createdAt})`));
132
+ }
133
+ }
134
+ }
135
+
136
+ module.exports = { worktreeCommand };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Load lite scope configuration from .caws/scope.json
3
+ * @param {string} [projectRoot] - Project root directory (defaults to cwd)
4
+ * @returns {Object} Scope configuration (defaults if file not found)
5
+ */
6
+ export function loadLiteScope(projectRoot?: string): any;
7
+ /**
8
+ * Check if a file path is allowed by the scope configuration
9
+ * @param {string} filePath - Relative file path to check
10
+ * @param {Object} [scope] - Scope configuration (loads from disk if not provided)
11
+ * @param {string} [projectRoot] - Project root directory
12
+ * @returns {boolean} Whether the path is allowed
13
+ */
14
+ export function isPathAllowed(filePath: string, scope?: any, projectRoot?: string): boolean;
15
+ /**
16
+ * Check if a filename or path matches any banned pattern
17
+ * @param {string} filePath - File path to check
18
+ * @param {Object} [scope] - Scope configuration (loads from disk if not provided)
19
+ * @param {string} [projectRoot] - Project root directory
20
+ * @returns {{ matched: boolean, pattern: string|null, category: string|null }} Match result
21
+ */
22
+ export function matchesBannedPattern(filePath: string, scope?: any, projectRoot?: string): {
23
+ matched: boolean;
24
+ pattern: string | null;
25
+ category: string | null;
26
+ };
27
+ /**
28
+ * Default scope configuration for lite mode
29
+ * @returns {Object} Default scope.json contents
30
+ */
31
+ export function getLiteScopeDefaults(): any;
32
+ export const SCOPE_FILE: ".caws/scope.json";
33
+ //# sourceMappingURL=lite-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lite-scope.d.ts","sourceRoot":"","sources":["../../src/config/lite-scope.js"],"names":[],"mappings":"AA8BA;;;;GAIG;AACH,4CAHW,MAAM,OAgChB;AAED;;;;;;GAMG;AACH,wCALW,MAAM,6BAEN,MAAM,GACJ,OAAO,CAiCnB;AAED;;;;;;GAMG;AACH,+CALW,MAAM,6BAEN,MAAM,GACJ;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,GAAC,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAC,IAAI,CAAA;CAAE,CAsC7E;AAzID;;;GAGG;AACH,4CAYC;AAlBD,yBAAmB,kBAAkB,CAAC"}