@paths.design/caws-cli 7.0.1 → 7.0.3
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/dist/budget-derivation.js +5 -4
- package/dist/commands/diagnose.js +26 -20
- package/dist/commands/init.js +72 -5
- package/dist/commands/specs.js +40 -1
- package/dist/commands/status.js +2 -2
- package/dist/commands/templates.js +10 -0
- package/dist/commands/tool.js +2 -3
- package/dist/commands/validate.js +12 -0
- package/dist/config/index.js +17 -8
- package/dist/generators/working-spec.js +42 -9
- package/dist/index.js +3 -1
- package/dist/scaffold/cursor-hooks.js +10 -2
- package/dist/scaffold/git-hooks.js +189 -32
- package/dist/scaffold/index.js +105 -17
- package/dist/templates/.caws/tools/README.md +20 -0
- package/dist/templates/.cursor/README.md +311 -0
- package/dist/templates/.cursor/hooks/audit.sh +55 -0
- package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
- package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
- package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
- package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
- package/dist/templates/.cursor/hooks/format.sh +38 -0
- package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
- package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
- package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
- package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
- package/dist/templates/.cursor/hooks.json +59 -0
- package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
- package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
- package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
- package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
- package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
- package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
- package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
- package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
- package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
- package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
- package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
- package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
- package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
- package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
- package/dist/templates/.cursor/rules/README.md +148 -0
- package/dist/templates/.github/copilot/instructions.md +311 -0
- package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
- package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
- package/dist/templates/.vscode/launch.json +56 -0
- package/dist/templates/.vscode/settings.json +93 -0
- package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
- package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
- package/dist/templates/OIDC_SETUP.md +300 -0
- package/dist/templates/agents.md +1047 -0
- package/dist/templates/codemod/README.md +1 -0
- package/dist/templates/codemod/test.js +93 -0
- package/dist/templates/docs/README.md +150 -0
- package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
- package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
- package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
- package/dist/tool-loader.js +6 -1
- package/dist/tool-validator.js +8 -2
- package/dist/utils/detection.js +34 -6
- package/dist/utils/git-lock.js +118 -0
- package/dist/utils/gitignore-updater.js +148 -0
- package/dist/utils/quality-gates.js +47 -7
- package/dist/utils/spec-resolver.js +23 -3
- package/dist/utils/yaml-validation.js +155 -0
- package/dist/validation/spec-validation.js +105 -2
- package/package.json +2 -2
- package/templates/.caws/schemas/waivers.schema.json +30 -0
- package/templates/.caws/schemas/working-spec.schema.json +133 -0
- package/templates/.caws/templates/working-spec.template.yml +74 -0
- package/templates/.caws/tools/README.md +20 -0
- package/templates/.caws/tools/scope-guard.js +208 -0
- package/templates/.caws/tools-allow.json +331 -0
- package/templates/.caws/waivers.yml +19 -0
- package/templates/.cursor/hooks/scope-guard.sh +2 -2
- package/templates/.cursor/hooks/validate-spec.sh +42 -7
- package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
- package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
- package/templates/apps/tools/caws/README.md +0 -463
- package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
- package/templates/apps/tools/caws/attest.js +0 -357
- package/templates/apps/tools/caws/ci-optimizer.js +0 -642
- package/templates/apps/tools/caws/config.ts +0 -245
- package/templates/apps/tools/caws/cross-functional.js +0 -876
- package/templates/apps/tools/caws/dashboard.js +0 -1112
- package/templates/apps/tools/caws/flake-detector.ts +0 -362
- package/templates/apps/tools/caws/gates.js +0 -198
- package/templates/apps/tools/caws/gates.ts +0 -271
- package/templates/apps/tools/caws/language-adapters.ts +0 -381
- package/templates/apps/tools/caws/language-support.d.ts +0 -367
- package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
- package/templates/apps/tools/caws/language-support.js +0 -585
- package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
- package/templates/apps/tools/caws/legacy-assessor.js +0 -764
- package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
- package/templates/apps/tools/caws/perf-budgets.ts +0 -349
- package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
- package/templates/apps/tools/caws/property-testing.js +0 -707
- package/templates/apps/tools/caws/provenance.d.ts +0 -14
- package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
- package/templates/apps/tools/caws/provenance.js +0 -132
- package/templates/apps/tools/caws/provenance.js.backup +0 -73
- package/templates/apps/tools/caws/provenance.ts +0 -211
- package/templates/apps/tools/caws/security-provenance.ts +0 -483
- package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
- package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
- package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
- package/templates/apps/tools/caws/shared/types.ts +0 -444
- package/templates/apps/tools/caws/shared/validator.ts +0 -305
- package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
- package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
- package/templates/apps/tools/caws/test-quality.js +0 -578
- package/templates/apps/tools/caws/validate.js +0 -76
- package/templates/apps/tools/caws/validate.ts +0 -228
- package/templates/apps/tools/caws/waivers.js +0 -344
- /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
|
@@ -196,10 +196,11 @@ async function deriveBudget(spec, projectRoot = process.cwd(), options = {}) {
|
|
|
196
196
|
' This may be a path resolution or caching issue\n'
|
|
197
197
|
);
|
|
198
198
|
} else {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
199
|
+
// Policy.yaml is optional - defaults work fine, so don't warn unnecessarily
|
|
200
|
+
// Only show info message if user explicitly wants to see it
|
|
201
|
+
if (options.showPolicyInfo !== false) {
|
|
202
|
+
// Silent by default - policy.yaml is optional
|
|
203
|
+
}
|
|
203
204
|
}
|
|
204
205
|
}
|
|
205
206
|
|
|
@@ -240,41 +240,44 @@ async function checkTestFiles() {
|
|
|
240
240
|
* @returns {Promise<Object>} Check result
|
|
241
241
|
*/
|
|
242
242
|
async function checkCAWSTools() {
|
|
243
|
-
|
|
243
|
+
// Check new location first, then legacy location for backward compatibility
|
|
244
|
+
const toolsPath = '.caws/tools';
|
|
245
|
+
const legacyToolsPath = 'apps/tools/caws';
|
|
244
246
|
|
|
245
|
-
if (!(await fs.pathExists(toolsPath))) {
|
|
247
|
+
if (!(await fs.pathExists(toolsPath)) && !(await fs.pathExists(legacyToolsPath))) {
|
|
246
248
|
return {
|
|
247
|
-
passed:
|
|
248
|
-
severity: '
|
|
249
|
-
message: 'CAWS tools directory not found',
|
|
250
|
-
fix: '
|
|
249
|
+
passed: true,
|
|
250
|
+
severity: 'info',
|
|
251
|
+
message: 'CAWS tools directory not found (optional - use CLI commands instead)',
|
|
252
|
+
fix: 'Core functionality available via: caws validate, caws quality-gates, caws provenance',
|
|
251
253
|
autoFixable: false,
|
|
252
254
|
};
|
|
253
255
|
}
|
|
254
256
|
|
|
255
|
-
//
|
|
256
|
-
const
|
|
257
|
-
|
|
257
|
+
// Tools directory exists - check for specialized tools (not core CLI duplicates)
|
|
258
|
+
const specializedTools = ['flake-detector.ts', 'spec-test-mapper.ts', 'perf-budgets.ts'];
|
|
259
|
+
const foundTools = [];
|
|
258
260
|
|
|
259
|
-
for (const tool of
|
|
260
|
-
if (
|
|
261
|
-
|
|
261
|
+
for (const tool of specializedTools) {
|
|
262
|
+
if (await fs.pathExists(path.join(toolsPath, tool))) {
|
|
263
|
+
foundTools.push(tool);
|
|
262
264
|
}
|
|
263
265
|
}
|
|
264
266
|
|
|
265
|
-
if (
|
|
267
|
+
if (foundTools.length === 0) {
|
|
266
268
|
return {
|
|
267
|
-
passed:
|
|
268
|
-
severity: '
|
|
269
|
-
message:
|
|
270
|
-
fix: '
|
|
269
|
+
passed: true,
|
|
270
|
+
severity: 'info',
|
|
271
|
+
message: 'No specialized tools found (optional - use CLI commands for core functionality)',
|
|
272
|
+
fix: 'Core functionality available via: caws validate, caws quality-gates, caws provenance',
|
|
271
273
|
autoFixable: false,
|
|
272
274
|
};
|
|
273
275
|
}
|
|
274
276
|
|
|
275
277
|
return {
|
|
276
278
|
passed: true,
|
|
277
|
-
message:
|
|
279
|
+
message: `Found ${foundTools.length} specialized tool(s): ${foundTools.join(', ')}`,
|
|
280
|
+
note: 'Core functionality (validate, quality-gates, provenance) available via CLI commands',
|
|
278
281
|
};
|
|
279
282
|
}
|
|
280
283
|
|
|
@@ -481,9 +484,12 @@ async function diagnoseCommand(options = {}) {
|
|
|
481
484
|
|
|
482
485
|
if (issueCount === 0) {
|
|
483
486
|
console.log(chalk.blue('📚 Next steps:'));
|
|
484
|
-
console.log(chalk.blue(' • Run: caws status to view project health'));
|
|
487
|
+
console.log(chalk.blue(' • Run: caws status --visual to view project health'));
|
|
485
488
|
console.log(chalk.blue(' • Run: caws validate to check working spec'));
|
|
486
|
-
console.log(chalk.blue(' •
|
|
489
|
+
console.log(chalk.blue(' • Optional: Create .caws/policy.yaml for custom budgets'));
|
|
490
|
+
console.log(
|
|
491
|
+
chalk.blue(' • Start implementing: caws iterate --current-state "Ready to begin"')
|
|
492
|
+
);
|
|
487
493
|
}
|
|
488
494
|
} catch (error) {
|
|
489
495
|
console.error(chalk.red('\n❌ Error running diagnosis:'), error.message);
|
package/dist/commands/init.js
CHANGED
|
@@ -17,6 +17,7 @@ const { generateWorkingSpec } = require('../generators/working-spec');
|
|
|
17
17
|
const { finalizeProject } = require('../utils/finalization');
|
|
18
18
|
const { scaffoldCursorHooks } = require('../scaffold/cursor-hooks');
|
|
19
19
|
const { scaffoldIDEIntegrations } = require('../scaffold/index');
|
|
20
|
+
const { updateGitignore } = require('../utils/gitignore-updater');
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* Initialize a new project with CAWS
|
|
@@ -361,6 +362,18 @@ async function initProject(projectName, options) {
|
|
|
361
362
|
await fs.writeFile(path.join('.caws', 'working-spec.yaml'), specContent);
|
|
362
363
|
console.log(chalk.green('✅ Created .caws/working-spec.yaml'));
|
|
363
364
|
|
|
365
|
+
// Optionally create policy.yaml (optional - defaults work fine)
|
|
366
|
+
const policyPath = path.join('.caws', 'policy.yaml');
|
|
367
|
+
if (!fs.existsSync(policyPath)) {
|
|
368
|
+
const { PolicyManager } = require('../policy/PolicyManager');
|
|
369
|
+
const policyManager = new PolicyManager();
|
|
370
|
+
const defaultPolicy = policyManager.getDefaultPolicy();
|
|
371
|
+
const yaml = require('js-yaml');
|
|
372
|
+
const policyContent = yaml.dump(defaultPolicy, { indent: 2 });
|
|
373
|
+
await fs.writeFile(policyPath, policyContent);
|
|
374
|
+
console.log(chalk.green('✅ Created .caws/policy.yaml (optional - defaults work fine)'));
|
|
375
|
+
}
|
|
376
|
+
|
|
364
377
|
// Generate additional files if requested
|
|
365
378
|
if (answers.generateExamples) {
|
|
366
379
|
console.log(chalk.blue('📝 Generating example files...'));
|
|
@@ -409,6 +422,17 @@ Happy coding! 🎯
|
|
|
409
422
|
console.log(chalk.blue('🎨 Setting up IDE integrations...'));
|
|
410
423
|
await scaffoldIDEIntegrations(process.cwd(), { force: false });
|
|
411
424
|
|
|
425
|
+
// Update .gitignore to exclude CAWS local runtime files
|
|
426
|
+
console.log(chalk.blue('📝 Updating .gitignore...'));
|
|
427
|
+
const gitignoreUpdated = await updateGitignore(process.cwd());
|
|
428
|
+
if (gitignoreUpdated) {
|
|
429
|
+
console.log(chalk.green('✅ Updated .gitignore to exclude CAWS local runtime files'));
|
|
430
|
+
console.log(
|
|
431
|
+
chalk.gray(' Tracked: Specs, policy, waivers, provenance, plans (shared with team)')
|
|
432
|
+
);
|
|
433
|
+
console.log(chalk.gray(' Ignored: Agent runtime, temp files, logs (local-only)'));
|
|
434
|
+
}
|
|
435
|
+
|
|
412
436
|
// Finalize project
|
|
413
437
|
await finalizeProject(projectName, options, answers);
|
|
414
438
|
} else {
|
|
@@ -456,7 +480,7 @@ Happy coding! 🎯
|
|
|
456
480
|
experimentalSandbox: '',
|
|
457
481
|
aiConfidence: 0.8,
|
|
458
482
|
uncertaintyAreas: '',
|
|
459
|
-
complexityFactors: ''
|
|
483
|
+
complexityFactors: '',
|
|
460
484
|
};
|
|
461
485
|
|
|
462
486
|
const specContent = generateWorkingSpec(defaultAnswers);
|
|
@@ -464,6 +488,18 @@ Happy coding! 🎯
|
|
|
464
488
|
await fs.writeFile(path.join('.caws', 'working-spec.yaml'), specContent);
|
|
465
489
|
console.log(chalk.green('✅ Created .caws/working-spec.yaml'));
|
|
466
490
|
|
|
491
|
+
// Optionally create policy.yaml (optional - defaults work fine)
|
|
492
|
+
const policyPath = path.join('.caws', 'policy.yaml');
|
|
493
|
+
if (!fs.existsSync(policyPath)) {
|
|
494
|
+
const { PolicyManager } = require('../policy/PolicyManager');
|
|
495
|
+
const policyManager = new PolicyManager();
|
|
496
|
+
const defaultPolicy = policyManager.getDefaultPolicy();
|
|
497
|
+
const yaml = require('js-yaml');
|
|
498
|
+
const policyContent = yaml.dump(defaultPolicy, { indent: 2 });
|
|
499
|
+
await fs.writeFile(policyPath, policyContent);
|
|
500
|
+
console.log(chalk.green('✅ Created .caws/policy.yaml (optional - defaults work fine)'));
|
|
501
|
+
}
|
|
502
|
+
|
|
467
503
|
// Setup Cursor hooks by default in non-interactive mode
|
|
468
504
|
console.log(chalk.blue('🎯 Setting up Cursor hooks...'));
|
|
469
505
|
await scaffoldCursorHooks(process.cwd());
|
|
@@ -472,6 +508,17 @@ Happy coding! 🎯
|
|
|
472
508
|
console.log(chalk.blue('🎨 Setting up IDE integrations...'));
|
|
473
509
|
await scaffoldIDEIntegrations(process.cwd(), { force: false });
|
|
474
510
|
|
|
511
|
+
// Update .gitignore to exclude CAWS local runtime files
|
|
512
|
+
console.log(chalk.blue('📝 Updating .gitignore...'));
|
|
513
|
+
const gitignoreUpdated = await updateGitignore(process.cwd());
|
|
514
|
+
if (gitignoreUpdated) {
|
|
515
|
+
console.log(chalk.green('✅ Updated .gitignore to exclude CAWS local runtime files'));
|
|
516
|
+
console.log(
|
|
517
|
+
chalk.gray(' Tracked: Specs, policy, waivers, provenance, plans (shared with team)')
|
|
518
|
+
);
|
|
519
|
+
console.log(chalk.gray(' Ignored: Agent runtime, temp files, logs (local-only)'));
|
|
520
|
+
}
|
|
521
|
+
|
|
475
522
|
// Finalize project
|
|
476
523
|
await finalizeProject(projectName, options, defaultAnswers);
|
|
477
524
|
}
|
|
@@ -481,17 +528,37 @@ Happy coding! 🎯
|
|
|
481
528
|
console.log(chalk.blue('\nNext steps:'));
|
|
482
529
|
console.log('1. Review .caws/working-spec.yaml');
|
|
483
530
|
console.log('2. Customize the specification for your needs');
|
|
484
|
-
|
|
531
|
+
|
|
532
|
+
// Show contract requirements if Tier 1 or 2
|
|
533
|
+
// Use answers if available (interactive mode), otherwise default to 2
|
|
534
|
+
const riskTier = answers?.riskTier || 2;
|
|
535
|
+
if (riskTier === 1 || riskTier === 2) {
|
|
536
|
+
console.log(chalk.yellow('\n⚠️ Important: Contract Requirements'));
|
|
537
|
+
console.log(` Tier ${riskTier} changes require at least one contract.`);
|
|
538
|
+
console.log(' For infrastructure/setup work, add a minimal contract:');
|
|
539
|
+
console.log(chalk.gray(' contracts:'));
|
|
540
|
+
console.log(chalk.gray(' - type: "project_setup"'));
|
|
541
|
+
console.log(chalk.gray(' path: ".caws/working-spec.yaml"'));
|
|
542
|
+
console.log(chalk.gray(' description: "Project-level CAWS configuration"'));
|
|
543
|
+
console.log(' Or use "chore" mode for maintenance work (mode: chore)');
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
console.log('\n📋 Recommended Setup Workflow:');
|
|
547
|
+
console.log(' 1. Review .caws/working-spec.yaml');
|
|
548
|
+
console.log(' 2. Run: caws scaffold (adds tools and templates)');
|
|
549
|
+
console.log(' 3. Run: caws validate (verify setup)');
|
|
550
|
+
console.log(' 4. Run: caws diagnose (check health)');
|
|
551
|
+
console.log(' 5. Optional: Create .caws/policy.yaml for custom budgets');
|
|
485
552
|
if (answers?.useCursorHooks || options.interactive === false) {
|
|
486
|
-
console.log('
|
|
553
|
+
console.log(' 6. Restart Cursor IDE to activate quality gates');
|
|
487
554
|
}
|
|
488
|
-
console.log('
|
|
555
|
+
console.log('\n💡 Quick start: caws scaffold && caws validate && caws diagnose');
|
|
489
556
|
} catch (error) {
|
|
490
557
|
console.error(chalk.red('❌ Error during initialization:'), error.message);
|
|
491
558
|
if (error.stack) {
|
|
492
559
|
console.error(chalk.gray(error.stack));
|
|
493
560
|
}
|
|
494
|
-
|
|
561
|
+
|
|
495
562
|
// Cleanup on error (only for new directory creation)
|
|
496
563
|
if (projectName && projectName !== '.' && fs.existsSync(projectName)) {
|
|
497
564
|
try {
|
package/dist/commands/specs.js
CHANGED
|
@@ -202,7 +202,46 @@ async function createSpec(id, options = {}) {
|
|
|
202
202
|
const filePath = path.join(SPECS_DIR, fileName);
|
|
203
203
|
|
|
204
204
|
// Write spec file
|
|
205
|
-
|
|
205
|
+
const yamlContent = yaml.dump(specContent, { indent: 2 });
|
|
206
|
+
await fs.writeFile(filePath, yamlContent);
|
|
207
|
+
|
|
208
|
+
// Validate written file (YAML syntax and structure)
|
|
209
|
+
try {
|
|
210
|
+
const writtenContent = await fs.readFile(filePath, 'utf8');
|
|
211
|
+
const parsed = yaml.load(writtenContent);
|
|
212
|
+
|
|
213
|
+
// Validate YAML syntax was preserved
|
|
214
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
215
|
+
await fs.remove(filePath);
|
|
216
|
+
throw new Error('Failed to parse written spec file - invalid YAML structure');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Validate spec structure using CAWS validation
|
|
220
|
+
const { validateWorkingSpec } = require('../validation/spec-validation');
|
|
221
|
+
const validation = validateWorkingSpec(parsed);
|
|
222
|
+
|
|
223
|
+
if (!validation.valid) {
|
|
224
|
+
await fs.remove(filePath);
|
|
225
|
+
const errorMessages = validation.errors
|
|
226
|
+
.map((e) => `${e.instancePath}: ${e.message}`)
|
|
227
|
+
.join('; ');
|
|
228
|
+
throw new Error(`Spec validation failed: ${errorMessages}`);
|
|
229
|
+
}
|
|
230
|
+
} catch (error) {
|
|
231
|
+
// Clean up invalid file if it exists
|
|
232
|
+
if (await fs.pathExists(filePath)) {
|
|
233
|
+
await fs.remove(filePath);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Re-throw with helpful message
|
|
237
|
+
if (error.message.includes('YAMLException') || error.message.includes('yaml')) {
|
|
238
|
+
throw new Error(
|
|
239
|
+
`Failed to create valid spec: YAML syntax error. ${error.message}\n` +
|
|
240
|
+
'💡 Consider using the interactive mode: caws specs create <id> --interactive'
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
throw error;
|
|
244
|
+
}
|
|
206
245
|
|
|
207
246
|
// Update registry
|
|
208
247
|
const registry = await loadSpecsRegistry();
|
package/dist/commands/status.js
CHANGED
|
@@ -182,10 +182,10 @@ async function loadWaiverStatus() {
|
|
|
182
182
|
*/
|
|
183
183
|
async function checkQualityGates() {
|
|
184
184
|
// For now, return a placeholder
|
|
185
|
-
//
|
|
185
|
+
// Quality gates are available via CLI or MCP
|
|
186
186
|
return {
|
|
187
187
|
checked: false,
|
|
188
|
-
message: 'Run:
|
|
188
|
+
message: 'Run: caws quality-gates or use MCP tool caws_quality_gates_run for full gate status',
|
|
189
189
|
};
|
|
190
190
|
}
|
|
191
191
|
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
const fs = require('fs-extra');
|
|
8
8
|
const path = require('path');
|
|
9
9
|
const chalk = require('chalk');
|
|
10
|
+
const { findPackageRoot } = require('../utils/detection');
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Built-in template definitions
|
|
@@ -64,11 +65,20 @@ const BUILTIN_TEMPLATES = {
|
|
|
64
65
|
|
|
65
66
|
/**
|
|
66
67
|
* Get template directory path
|
|
68
|
+
* Works in both development and global install scenarios
|
|
67
69
|
* @returns {string|null} Template directory path or null
|
|
68
70
|
*/
|
|
69
71
|
function getTemplateDir() {
|
|
72
|
+
// Find package root using shared utility
|
|
73
|
+
const packageRoot = findPackageRoot(__dirname);
|
|
74
|
+
|
|
70
75
|
const possiblePaths = [
|
|
76
|
+
// First: Try templates relative to package root (works in dev and global install)
|
|
77
|
+
path.join(packageRoot, 'templates'),
|
|
78
|
+
// Fallback: Try relative to current file location (for development)
|
|
71
79
|
path.join(__dirname, '../../templates'),
|
|
80
|
+
path.join(__dirname, '../templates'),
|
|
81
|
+
// Legacy fallbacks
|
|
72
82
|
path.join(process.cwd(), 'packages/caws-cli/templates'),
|
|
73
83
|
path.join(process.cwd(), 'templates'),
|
|
74
84
|
];
|
package/dist/commands/tool.js
CHANGED
|
@@ -23,9 +23,8 @@ async function initializeToolSystem() {
|
|
|
23
23
|
if (toolLoader) return toolLoader;
|
|
24
24
|
|
|
25
25
|
try {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
26
|
+
// ToolLoader now checks .caws/tools first, then falls back to legacy location
|
|
27
|
+
toolLoader = new ToolLoader();
|
|
29
28
|
|
|
30
29
|
toolValidator = new ToolValidator();
|
|
31
30
|
|
|
@@ -194,6 +194,18 @@ async function validateCommand(specFile, options = {}) {
|
|
|
194
194
|
if (error.suggestion) {
|
|
195
195
|
console.log(` ${chalk.blue('💡 ' + error.suggestion)}`);
|
|
196
196
|
}
|
|
197
|
+
if (error.example) {
|
|
198
|
+
console.log(` ${chalk.gray('Example:')}`);
|
|
199
|
+
if (error.example.contracts) {
|
|
200
|
+
error.example.contracts.forEach((contract) => {
|
|
201
|
+
console.log(` ${chalk.gray('- type: ' + contract.type)}`);
|
|
202
|
+
console.log(` ${chalk.gray('path: ' + contract.path)}`);
|
|
203
|
+
if (contract.description) {
|
|
204
|
+
console.log(` ${chalk.gray('description: ' + contract.description)}`);
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
197
209
|
});
|
|
198
210
|
|
|
199
211
|
// Show warnings
|
package/dist/config/index.js
CHANGED
|
@@ -49,15 +49,19 @@ function initializeGlobalSetup() {
|
|
|
49
49
|
function loadProvenanceTools() {
|
|
50
50
|
if (provenanceTools) return provenanceTools; // Already loaded
|
|
51
51
|
|
|
52
|
-
//
|
|
52
|
+
// Provenance tools are now handled by CLI command (caws provenance)
|
|
53
|
+
// Legacy tool loading removed - use CLI instead
|
|
54
|
+
// Try multiple possible locations for provenance tools (legacy support)
|
|
53
55
|
const possiblePaths = [
|
|
54
|
-
// 1.
|
|
55
|
-
path.join(
|
|
56
|
-
// 2.
|
|
56
|
+
// 1. New location (if someone manually adds it)
|
|
57
|
+
path.join(process.cwd(), '.caws/tools/provenance.js'),
|
|
58
|
+
// 2. Legacy location (for backward compatibility)
|
|
57
59
|
path.join(process.cwd(), 'apps/tools/caws/provenance.js'),
|
|
58
|
-
// 3.
|
|
60
|
+
// 3. Bundled templates in CLI package (legacy)
|
|
61
|
+
path.join(__dirname, '../../templates/.caws/tools/provenance.js'),
|
|
62
|
+
// 4. Template package in monorepo (legacy)
|
|
59
63
|
path.join(__dirname, '../../../caws-template/apps/tools/caws/provenance.js'),
|
|
60
|
-
//
|
|
64
|
+
// 5. Detected setup template directory
|
|
61
65
|
null, // Will be set from setup if available
|
|
62
66
|
];
|
|
63
67
|
|
|
@@ -65,7 +69,7 @@ function loadProvenanceTools() {
|
|
|
65
69
|
try {
|
|
66
70
|
const setup = cawsSetup || initializeGlobalSetup();
|
|
67
71
|
if (setup?.hasTemplateDir && setup?.templateDir) {
|
|
68
|
-
possiblePaths[
|
|
72
|
+
possiblePaths[4] = path.join(setup.templateDir, '.caws/tools/provenance.js');
|
|
69
73
|
}
|
|
70
74
|
} catch (setupError) {
|
|
71
75
|
// Continue without detected setup
|
|
@@ -97,8 +101,13 @@ function initializeLanguageSupport() {
|
|
|
97
101
|
if (languageSupport) return languageSupport;
|
|
98
102
|
|
|
99
103
|
try {
|
|
100
|
-
//
|
|
104
|
+
// Language support tools removed - use CLI instead
|
|
105
|
+
// Try multiple possible locations for language support (legacy support)
|
|
101
106
|
const possiblePaths = [
|
|
107
|
+
// New location (if someone manually adds it)
|
|
108
|
+
path.join(process.cwd(), '.caws/tools/language-support.js'),
|
|
109
|
+
// Legacy locations
|
|
110
|
+
path.join(process.cwd(), 'apps/tools/caws/language-support.js'),
|
|
102
111
|
path.join(__dirname, '../../../caws-template/apps/tools/caws/language-support.js'),
|
|
103
112
|
path.join(__dirname, '../../../../caws-template/apps/tools/caws/language-support.js'),
|
|
104
113
|
path.join(process.cwd(), 'packages/caws-template/apps/tools/caws/language-support.js'),
|
|
@@ -42,16 +42,28 @@ function generateWorkingSpec(answers) {
|
|
|
42
42
|
.split(',')
|
|
43
43
|
.map((s) => s.trim())
|
|
44
44
|
.filter((s) => s),
|
|
45
|
-
out: (answers.scopeOut || 'node_modules/, dist/')
|
|
45
|
+
out: (answers.scopeOut || 'node_modules/, dist/, build/')
|
|
46
46
|
.split(',')
|
|
47
47
|
.map((s) => s.trim())
|
|
48
|
-
.filter((s) => s)
|
|
48
|
+
.filter((s) => s)
|
|
49
|
+
// Remove glob patterns - scope.out should only contain directory paths
|
|
50
|
+
.filter((s) => !s.includes('*') && !s.includes('?'))
|
|
51
|
+
// Ensure paths end with / for directories or are explicit file paths
|
|
52
|
+
.map((s) => {
|
|
53
|
+
// If it's a directory pattern without trailing slash, add it
|
|
54
|
+
if (!s.includes('.') && !s.endsWith('/')) {
|
|
55
|
+
return s + '/';
|
|
56
|
+
}
|
|
57
|
+
return s;
|
|
58
|
+
}),
|
|
49
59
|
},
|
|
50
60
|
invariants: (answers.projectInvariants || 'System maintains data consistency')
|
|
51
61
|
.split('\n')
|
|
52
62
|
.map((i) => i.trim())
|
|
53
63
|
.filter((i) => i),
|
|
54
|
-
acceptance: (
|
|
64
|
+
acceptance: (
|
|
65
|
+
answers.acceptanceCriteria || 'Given current state, when action occurs, then expected result'
|
|
66
|
+
)
|
|
55
67
|
.split('\n')
|
|
56
68
|
.filter((a) => a.trim())
|
|
57
69
|
.map((criteria, index) => {
|
|
@@ -97,12 +109,33 @@ function generateWorkingSpec(answers) {
|
|
|
97
109
|
.map((s) => s.trim())
|
|
98
110
|
.filter((s) => s),
|
|
99
111
|
},
|
|
100
|
-
contracts:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
112
|
+
contracts: (() => {
|
|
113
|
+
// If contract type/path provided, use it
|
|
114
|
+
if (answers.contractType && answers.contractPath) {
|
|
115
|
+
return [
|
|
116
|
+
{
|
|
117
|
+
type: answers.contractType,
|
|
118
|
+
path: answers.contractPath,
|
|
119
|
+
},
|
|
120
|
+
];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// For Tier 1 & 2, provide minimal project_setup contract if none specified
|
|
124
|
+
const riskTier = answers.riskTier || 2;
|
|
125
|
+
if (riskTier === 1 || riskTier === 2) {
|
|
126
|
+
return [
|
|
127
|
+
{
|
|
128
|
+
type: 'project_setup',
|
|
129
|
+
path: '.caws/working-spec.yaml',
|
|
130
|
+
description:
|
|
131
|
+
'Project-level CAWS configuration. Feature-specific contracts will be added as features are developed.',
|
|
132
|
+
},
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Tier 3 doesn't require contracts
|
|
137
|
+
return [];
|
|
138
|
+
})(),
|
|
106
139
|
observability: {
|
|
107
140
|
logs: (answers.observabilityLogs || '')
|
|
108
141
|
.split(',')
|
package/dist/index.js
CHANGED
|
@@ -138,7 +138,7 @@ program
|
|
|
138
138
|
.option('--json', 'Output machine-readable JSON to stdout', false)
|
|
139
139
|
.option(
|
|
140
140
|
'--gates <gates>',
|
|
141
|
-
'Run only specific gates (comma-separated: naming,code_freeze,duplication,god_objects,documentation)',
|
|
141
|
+
'Run only specific gates (comma-separated: naming,code_freeze,duplication,god_objects,hidden-todo,documentation,placeholders)',
|
|
142
142
|
''
|
|
143
143
|
)
|
|
144
144
|
.option('--fix', 'Attempt automatic fixes (experimental)', false)
|
|
@@ -168,7 +168,9 @@ VALID GATES:
|
|
|
168
168
|
code_freeze Enforce code freeze compliance
|
|
169
169
|
duplication Detect functional duplication
|
|
170
170
|
god_objects Prevent oversized files
|
|
171
|
+
hidden-todo Detect hidden incomplete implementations
|
|
171
172
|
documentation Check documentation quality
|
|
173
|
+
placeholders Placeholder governance (explicit degradations)
|
|
172
174
|
|
|
173
175
|
EXAMPLES:
|
|
174
176
|
# Run all gates in development mode
|
|
@@ -9,7 +9,7 @@ const path = require('path');
|
|
|
9
9
|
const chalk = require('chalk');
|
|
10
10
|
|
|
11
11
|
// Import detection utilities
|
|
12
|
-
const { detectCAWSSetup } = require('../utils/detection');
|
|
12
|
+
const { detectCAWSSetup, findPackageRoot } = require('../utils/detection');
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Scaffold Cursor hooks for a CAWS project
|
|
@@ -28,9 +28,17 @@ async function scaffoldCursorHooks(projectDir, levels = ['safety', 'quality', 's
|
|
|
28
28
|
|
|
29
29
|
// Determine template directory - prefer bundled templates
|
|
30
30
|
const setup = detectCAWSSetup(projectDir);
|
|
31
|
-
|
|
31
|
+
|
|
32
|
+
// Find package root using shared utility
|
|
33
|
+
const packageRoot = findPackageRoot(__dirname);
|
|
34
|
+
|
|
35
|
+
// Try templates relative to package root first (works in both dev and global install)
|
|
36
|
+
const bundledTemplateDir = path.join(packageRoot, 'templates');
|
|
37
|
+
const fallbackTemplateDir = path.join(__dirname, '../../templates');
|
|
32
38
|
const templateDir = fs.existsSync(bundledTemplateDir)
|
|
33
39
|
? bundledTemplateDir
|
|
40
|
+
: fs.existsSync(fallbackTemplateDir)
|
|
41
|
+
? fallbackTemplateDir
|
|
34
42
|
: setup.templateDir || path.resolve(__dirname, '../templates');
|
|
35
43
|
|
|
36
44
|
const cursorTemplateDir = path.join(templateDir, '.cursor');
|