@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.
- package/README.md +5 -6
- package/dist/commands/archive.d.ts +1 -1
- package/dist/commands/archive.d.ts.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +185 -39
- package/dist/commands/mode.d.ts +2 -1
- package/dist/commands/mode.d.ts.map +1 -1
- package/dist/commands/provenance.d.ts.map +1 -1
- package/dist/commands/specs.d.ts.map +1 -1
- package/dist/commands/worktree.d.ts +7 -0
- package/dist/commands/worktree.d.ts.map +1 -0
- package/dist/commands/worktree.js +136 -0
- package/dist/config/lite-scope.d.ts +33 -0
- package/dist/config/lite-scope.d.ts.map +1 -0
- package/dist/config/lite-scope.js +158 -0
- package/dist/config/modes.d.ts +90 -51
- package/dist/config/modes.d.ts.map +1 -1
- package/dist/config/modes.js +26 -0
- package/dist/error-handler.d.ts +3 -16
- package/dist/error-handler.d.ts.map +1 -1
- package/dist/generators/jest-config-generator.d.ts +32 -0
- package/dist/generators/jest-config-generator.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/scaffold/claude-hooks.d.ts +28 -0
- package/dist/scaffold/claude-hooks.d.ts.map +1 -0
- package/dist/scaffold/claude-hooks.js +28 -0
- package/dist/scaffold/index.d.ts +2 -0
- package/dist/scaffold/index.d.ts.map +1 -1
- package/dist/scaffold/index.js +90 -88
- package/dist/templates/.caws/schemas/scope.schema.json +52 -0
- package/dist/templates/.caws/schemas/working-spec.schema.json +1 -1
- package/dist/templates/.caws/schemas/worktrees.schema.json +36 -0
- package/dist/templates/.claude/hooks/block-dangerous.sh +33 -0
- package/dist/templates/.claude/hooks/lite-sprawl-check.sh +117 -0
- package/dist/templates/.claude/hooks/scope-guard.sh +93 -6
- package/dist/templates/.claude/hooks/simplification-guard.sh +92 -0
- package/dist/templates/.cursor/README.md +0 -3
- package/dist/templates/.github/copilot-instructions.md +82 -0
- package/dist/templates/.junie/guidelines.md +73 -0
- package/dist/templates/.vscode/launch.json +0 -27
- package/dist/templates/.windsurf/rules/caws-quality-standards.md +54 -0
- package/dist/templates/CLAUDE.md +101 -0
- package/dist/templates/agents.md +73 -1016
- package/dist/templates/docs/README.md +5 -5
- package/dist/test-analysis.d.ts +50 -1
- package/dist/test-analysis.d.ts.map +1 -1
- package/dist/utils/error-categories.d.ts +52 -0
- package/dist/utils/error-categories.d.ts.map +1 -0
- package/dist/utils/gitignore-updater.d.ts +1 -1
- package/dist/utils/gitignore-updater.d.ts.map +1 -1
- package/dist/utils/gitignore-updater.js +4 -0
- package/dist/utils/ide-detection.js +133 -0
- package/dist/utils/quality-gates-utils.d.ts +49 -0
- package/dist/utils/quality-gates-utils.d.ts.map +1 -0
- package/dist/utils/typescript-detector.d.ts +8 -5
- package/dist/utils/typescript-detector.d.ts.map +1 -1
- package/dist/validation/spec-validation.d.ts.map +1 -1
- package/dist/worktree/worktree-manager.d.ts +54 -0
- package/dist/worktree/worktree-manager.d.ts.map +1 -0
- package/dist/worktree/worktree-manager.js +378 -0
- package/package.json +5 -1
- package/templates/.caws/schemas/scope.schema.json +52 -0
- package/templates/.caws/schemas/working-spec.schema.json +1 -1
- package/templates/.caws/schemas/worktrees.schema.json +36 -0
- package/templates/.claude/hooks/block-dangerous.sh +33 -0
- package/templates/.claude/hooks/lite-sprawl-check.sh +117 -0
- package/templates/.claude/hooks/scope-guard.sh +93 -6
- package/templates/.claude/hooks/simplification-guard.sh +92 -0
- package/templates/.cursor/README.md +0 -3
- package/templates/.github/copilot-instructions.md +82 -0
- package/templates/.junie/guidelines.md +73 -0
- package/templates/.vscode/launch.json +0 -27
- package/templates/.windsurf/rules/caws-quality-standards.md +54 -0
- package/templates/AGENTS.md +104 -0
- package/templates/CLAUDE.md +101 -0
- package/templates/docs/README.md +5 -5
- package/templates/.github/copilot/instructions.md +0 -311
- 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
|
|
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
|
|
162
|
-
│ (Agent Bridge) │
|
|
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(
|
|
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
|
|
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":"
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.js"],"names":[],"mappings":"AAwBA;;GAEG;AACH,2EA6mBC"}
|
package/dist/commands/init.js
CHANGED
|
@@ -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, '
|
|
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
|
|
150
|
+
// Copy AGENTS.md guide if templates are available
|
|
141
151
|
if (originalTemplateDir) {
|
|
142
152
|
try {
|
|
143
|
-
const agentsMdSource = path.join(originalTemplateDir, '
|
|
144
|
-
let targetFile = '
|
|
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: '
|
|
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('
|
|
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('
|
|
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(
|
|
184
|
+
console.log(chalk.green(`Added ${targetFile} guide`));
|
|
182
185
|
}
|
|
183
186
|
}
|
|
184
187
|
} catch (templateError) {
|
|
185
|
-
console.warn(chalk.yellow('
|
|
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: '
|
|
341
|
-
name: '
|
|
342
|
-
message: '
|
|
343
|
-
|
|
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
|
|
416
|
-
|
|
417
|
-
|
|
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
|
-
|
|
422
|
-
|
|
423
|
-
|
|
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
|
|
504
|
-
|
|
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
|
-
|
|
508
|
-
|
|
509
|
-
|
|
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
|
-
|
|
553
|
-
|
|
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) {
|
package/dist/commands/mode.d.ts
CHANGED
|
@@ -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":"
|
|
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":"
|
|
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":"
|
|
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 @@
|
|
|
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"}
|