@paths.design/caws-cli 7.0.2 → 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.
Files changed (117) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +24 -19
  3. package/dist/commands/init.js +51 -4
  4. package/dist/commands/specs.js +40 -1
  5. package/dist/commands/status.js +2 -2
  6. package/dist/commands/tool.js +2 -3
  7. package/dist/config/index.js +17 -8
  8. package/dist/generators/working-spec.js +19 -6
  9. package/dist/scaffold/git-hooks.js +127 -29
  10. package/dist/scaffold/index.js +53 -7
  11. package/dist/templates/.caws/tools/README.md +20 -0
  12. package/dist/templates/.cursor/README.md +311 -0
  13. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  14. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  15. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  16. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  17. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  18. package/dist/templates/.cursor/hooks/format.sh +38 -0
  19. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  20. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  21. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  22. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  23. package/dist/templates/.cursor/hooks.json +59 -0
  24. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  25. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  26. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  27. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  28. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  29. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  30. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  31. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  32. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  33. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  34. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  35. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  36. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  37. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  38. package/dist/templates/.cursor/rules/README.md +148 -0
  39. package/dist/templates/.github/copilot/instructions.md +311 -0
  40. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  41. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  42. package/dist/templates/.vscode/launch.json +56 -0
  43. package/dist/templates/.vscode/settings.json +93 -0
  44. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  45. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  46. package/dist/templates/OIDC_SETUP.md +300 -0
  47. package/dist/templates/agents.md +1047 -0
  48. package/dist/templates/codemod/README.md +1 -0
  49. package/dist/templates/codemod/test.js +93 -0
  50. package/dist/templates/docs/README.md +150 -0
  51. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  52. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  53. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  54. package/dist/tool-loader.js +6 -1
  55. package/dist/tool-validator.js +8 -2
  56. package/dist/utils/detection.js +4 -3
  57. package/dist/utils/git-lock.js +118 -0
  58. package/dist/utils/gitignore-updater.js +148 -0
  59. package/dist/utils/quality-gates.js +47 -7
  60. package/dist/utils/spec-resolver.js +23 -3
  61. package/dist/utils/yaml-validation.js +155 -0
  62. package/dist/validation/spec-validation.js +81 -2
  63. package/package.json +2 -2
  64. package/templates/.caws/schemas/waivers.schema.json +30 -0
  65. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  66. package/templates/.caws/templates/working-spec.template.yml +74 -0
  67. package/templates/.caws/tools/README.md +20 -0
  68. package/templates/.caws/tools/scope-guard.js +208 -0
  69. package/templates/.caws/tools-allow.json +331 -0
  70. package/templates/.caws/waivers.yml +19 -0
  71. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  72. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  73. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  74. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  75. package/templates/apps/tools/caws/README.md +0 -463
  76. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  77. package/templates/apps/tools/caws/attest.js +0 -357
  78. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  79. package/templates/apps/tools/caws/config.ts +0 -245
  80. package/templates/apps/tools/caws/cross-functional.js +0 -876
  81. package/templates/apps/tools/caws/dashboard.js +0 -1112
  82. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  83. package/templates/apps/tools/caws/gates.js +0 -198
  84. package/templates/apps/tools/caws/gates.ts +0 -271
  85. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  86. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  87. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  88. package/templates/apps/tools/caws/language-support.js +0 -585
  89. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  90. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  91. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  92. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  93. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  94. package/templates/apps/tools/caws/property-testing.js +0 -707
  95. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  96. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  97. package/templates/apps/tools/caws/provenance.js +0 -132
  98. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  99. package/templates/apps/tools/caws/provenance.ts +0 -211
  100. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  101. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  102. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  103. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  104. package/templates/apps/tools/caws/shared/types.ts +0 -444
  105. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  106. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  107. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  108. package/templates/apps/tools/caws/test-quality.js +0 -578
  109. package/templates/apps/tools/caws/validate.js +0 -76
  110. package/templates/apps/tools/caws/validate.ts +0 -228
  111. package/templates/apps/tools/caws/waivers.js +0 -344
  112. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  113. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  114. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  115. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  116. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  117. /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@paths.design/caws-cli",
3
- "version": "7.0.2",
3
+ "version": "7.0.3",
4
4
  "description": "CAWS CLI - Coding Agent Workflow System command line tools",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -13,7 +13,7 @@
13
13
  "templates"
14
14
  ],
15
15
  "scripts": {
16
- "build": "mkdir -p dist && cp -r src/* dist/",
16
+ "build": "mkdir -p dist && cp -r src/* dist/ && cp -r templates dist/ 2>/dev/null || true",
17
17
  "dev": "mkdir -p dist && cp -r src/* dist/ && node dist/index.js",
18
18
  "typecheck": "tsc --emitDeclarationOnly --outDir dist",
19
19
  "start": "node dist/index.js",
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "CAWS Waivers Configuration",
4
+ "type": "object",
5
+ "patternProperties": {
6
+ ".*": {
7
+ "type": "object",
8
+ "required": ["gate", "reason", "owner", "expiry"],
9
+ "properties": {
10
+ "gate": {
11
+ "type": "string",
12
+ "enum": ["coverage", "mutation", "contracts", "a11y", "perf", "security"]
13
+ },
14
+ "reason": { "type": "string", "minLength": 10 },
15
+ "owner": { "type": "string" },
16
+ "expiry": { "type": "string", "format": "date-time" },
17
+ "compensating_control": { "type": "string" },
18
+ "ticket_url": { "type": "string", "format": "uri" },
19
+ "approved_by": { "type": "string" },
20
+ "created_at": { "type": "string", "format": "date-time" },
21
+ "status": {
22
+ "type": "string",
23
+ "enum": ["active", "expired", "revoked"],
24
+ "default": "active"
25
+ }
26
+ }
27
+ }
28
+ },
29
+ "additionalProperties": false
30
+ }
@@ -0,0 +1,133 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "title": "CAWS Working Spec",
4
+ "type": "object",
5
+ "required": [
6
+ "id",
7
+ "title",
8
+ "risk_tier",
9
+ "mode",
10
+ "blast_radius",
11
+ "operational_rollback_slo",
12
+ "scope",
13
+ "invariants",
14
+ "acceptance",
15
+ "non_functional",
16
+ "contracts"
17
+ ],
18
+ "properties": {
19
+ "id": { "type": "string", "pattern": "^(PROJ|FEAT|FIX|ARCH)-\\d{4}$" },
20
+ "title": { "type": "string", "minLength": 10, "maxLength": 200 },
21
+ "risk_tier": { "type": ["integer", "string"], "enum": [1, 2, 3, "1", "2", "3"] },
22
+ "mode": { "type": "string", "enum": ["feature", "refactor", "fix", "doc", "chore"] },
23
+ "waiver_ids": {
24
+ "type": "array",
25
+ "items": { "type": "string", "pattern": "^WV-\\d{4}$" },
26
+ "description": "IDs of active waivers applying to this spec"
27
+ },
28
+ "blast_radius": {
29
+ "type": "object",
30
+ "required": ["modules"],
31
+ "properties": {
32
+ "modules": { "type": "array", "items": { "type": "string" } },
33
+ "data_migration": { "type": "boolean" }
34
+ }
35
+ },
36
+ "operational_rollback_slo": { "type": "string" },
37
+ "scope": {
38
+ "type": "object",
39
+ "required": ["in", "out"],
40
+ "properties": {
41
+ "in": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
42
+ "out": { "type": "array", "items": { "type": "string" } }
43
+ }
44
+ },
45
+ "invariants": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
46
+ "acceptance": {
47
+ "type": "array",
48
+ "minItems": 1,
49
+ "items": {
50
+ "type": "object",
51
+ "required": ["id", "given", "when", "then"],
52
+ "properties": {
53
+ "id": { "type": "string", "pattern": "^A\\d+$" },
54
+ "given": { "type": "string" },
55
+ "when": { "type": "string" },
56
+ "then": { "type": "string" }
57
+ }
58
+ }
59
+ },
60
+ "non_functional": {
61
+ "type": "object",
62
+ "properties": {
63
+ "a11y": { "type": "array", "items": { "type": "string" } },
64
+ "perf": {
65
+ "type": "object",
66
+ "properties": {
67
+ "api_p95_ms": { "type": "integer", "minimum": 1 },
68
+ "lcp_ms": { "type": "integer", "minimum": 1 }
69
+ },
70
+ "additionalProperties": false
71
+ },
72
+ "security": { "type": "array", "items": { "type": "string" } }
73
+ },
74
+ "additionalProperties": false
75
+ },
76
+ "contracts": {
77
+ "type": "array",
78
+ "minItems": 1,
79
+ "items": {
80
+ "type": "object",
81
+ "required": ["type", "path"],
82
+ "properties": {
83
+ "type": { "type": "string", "enum": ["openapi", "graphql", "proto", "pact"] },
84
+ "path": { "type": "string" }
85
+ }
86
+ }
87
+ },
88
+ "observability": {
89
+ "type": "object",
90
+ "properties": {
91
+ "logs": { "type": "array", "items": { "type": "string" } },
92
+ "metrics": { "type": "array", "items": { "type": "string" } },
93
+ "traces": { "type": "array", "items": { "type": "string" } }
94
+ }
95
+ },
96
+ "migrations": { "type": "array", "items": { "type": "string" } },
97
+ "rollback": { "type": "array", "items": { "type": "string" } },
98
+ "experiment_mode": {
99
+ "type": "boolean",
100
+ "description": "Enables experimental mode with reduced requirements"
101
+ },
102
+ "timeboxed_hours": {
103
+ "type": "integer",
104
+ "minimum": 1,
105
+ "description": "Time limit for experimental features in hours"
106
+ },
107
+ "human_override": {
108
+ "type": "object",
109
+ "properties": {
110
+ "approved_by": { "type": "string" },
111
+ "reason": { "type": "string" },
112
+ "waived_requirements": {
113
+ "type": "array",
114
+ "items": {
115
+ "type": "string",
116
+ "enum": ["mutation_testing", "contract_tests", "coverage", "manual_review"]
117
+ }
118
+ },
119
+ "expiry_date": { "type": "string", "format": "date-time" }
120
+ },
121
+ "required": ["approved_by", "reason"]
122
+ },
123
+ "ai_assessment": {
124
+ "type": "object",
125
+ "properties": {
126
+ "confidence_level": { "type": "integer", "minimum": 1, "maximum": 10 },
127
+ "uncertainty_areas": { "type": "array", "items": { "type": "string" } },
128
+ "recommended_pairing": { "type": "boolean" }
129
+ }
130
+ }
131
+ },
132
+ "additionalProperties": false
133
+ }
@@ -0,0 +1,74 @@
1
+ id: '{{FEATURE_ID}}'
2
+ title: '{{FEATURE_TITLE}}'
3
+ risk_tier: { { TIER } }
4
+ scope:
5
+ in:
6
+ - '{{SCOPE_ITEM_1}}'
7
+ - '{{SCOPE_ITEM_2}}'
8
+ out:
9
+ - '{{OUT_OF_SCOPE_ITEM_1}}'
10
+ invariants:
11
+ - '{{BUSINESS_RULE_1}}'
12
+ - '{{BUSINESS_RULE_2}}'
13
+ acceptance:
14
+ - id: A1
15
+ given: '{{GIVEN_CONDITION}}'
16
+ when: '{{WHEN_ACTION}}'
17
+ then: '{{THEN_OUTCOME}}'
18
+ status: pending # pending | in_progress | completed
19
+ # Optional: detailed progress tracking
20
+ # tests:
21
+ # written: 0
22
+ # passing: 0
23
+ # coverage: 0.0
24
+ # last_updated: '2025-10-09T14:30:00Z'
25
+ - id: A2
26
+ given: '{{GIVEN_CONDITION_2}}'
27
+ when: '{{WHEN_ACTION_2}}'
28
+ then: '{{THEN_OUTCOME_2}}'
29
+ status: pending # pending | in_progress | completed
30
+ # Optional: detailed progress tracking
31
+ # tests:
32
+ # written: 0
33
+ # passing: 0
34
+ # coverage: 0.0
35
+ # last_updated: '2025-10-09T14:30:00Z'
36
+ non_functional:
37
+ a11y:
38
+ - '{{ACCESSIBILITY_REQUIREMENT}}'
39
+ perf:
40
+ api_p95_ms: { { PERF_BUDGET } }
41
+ lcp_ms: { { LCP_BUDGET } }
42
+ security:
43
+ - '{{SECURITY_REQUIREMENT}}'
44
+ contracts:
45
+ - type: '{{CONTRACT_TYPE}}'
46
+ path: '{{CONTRACT_PATH}}'
47
+ observability:
48
+ logs:
49
+ - '{{LOG_STATEMENT}}'
50
+ metrics:
51
+ - '{{METRIC_NAME}}'
52
+ traces:
53
+ - '{{TRACE_SPAN}}'
54
+ migrations:
55
+ - '{{MIGRATION_DESCRIPTION}}'
56
+ rollback:
57
+ - '{{ROLLBACK_STRATEGY}}'
58
+ # Optional: Enable for experimental features with reduced requirements
59
+ # experiment_mode: true
60
+ # timeboxed_hours: 24
61
+
62
+ # Optional: AI confidence assessment
63
+ # ai_assessment:
64
+ # confidence_level: 8
65
+ # uncertainty_areas: ["complex business logic", "performance implications"]
66
+ # recommended_pairing: false
67
+
68
+ # Optional: Human override for special cases (hotfixes, urgent changes)
69
+ # human_override:
70
+ # approved_by: "senior-dev-username"
71
+ # reason: "Urgent production fix - bypassing mutation tests for immediate deployment"
72
+ # waived_requirements: ["mutation_testing", "manual_review"]
73
+ # expiry_date: "2025-10-01T00:00:00Z"
74
+
@@ -0,0 +1,20 @@
1
+ # CAWS Tools
2
+
3
+ This directory contains CAWS-specific tools that aren't available in the CLI.
4
+
5
+ ## scope-guard.js
6
+
7
+ Enforces that experimental code stays within designated sandbox areas. Used by Cursor hooks for scope validation.
8
+
9
+ ```bash
10
+ # Validate experimental code containment
11
+ node .caws/tools/scope-guard.js validate
12
+
13
+ # Check containment status
14
+ node .caws/tools/scope-guard.js check .caws/working-spec.yaml
15
+ ```
16
+
17
+ **Usage in Cursor Hooks:**
18
+
19
+ The `.cursor/hooks/scope-guard.sh` hook automatically uses this tool to validate file attachments against working spec scope boundaries.
20
+
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * @fileoverview CAWS Scope Guard
5
+ * Enforces that experimental code stays within designated sandbox areas
6
+ * @author @darianrosebrook
7
+ */
8
+
9
+ const fs = require('fs');
10
+ const { execSync } = require('child_process');
11
+
12
+ /**
13
+ * Check if experimental code is properly contained
14
+ * @param {string} workingSpecPath - Path to working spec file
15
+ * @returns {Object} Scope validation results
16
+ */
17
+ function checkExperimentalContainment(workingSpecPath = '.caws/working-spec.yaml') {
18
+ try {
19
+ if (!fs.existsSync(workingSpecPath)) {
20
+ console.error('❌ Working spec not found:', workingSpecPath);
21
+ return { valid: false, errors: ['Working spec not found'] };
22
+ }
23
+
24
+ const yaml = require('js-yaml');
25
+ const spec = yaml.load(fs.readFileSync(workingSpecPath, 'utf8'));
26
+
27
+ const results = {
28
+ valid: true,
29
+ errors: [],
30
+ warnings: [],
31
+ experimentalFiles: [],
32
+ nonExperimentalFiles: [],
33
+ };
34
+
35
+ // Only check if experimental mode is enabled
36
+ if (!spec.experimental_mode?.enabled) {
37
+ console.log('ℹ️ Experimental mode not enabled - skipping containment check');
38
+ return results;
39
+ }
40
+
41
+ const sandboxLocation = spec.experimental_mode.sandbox_location || 'experimental/';
42
+ console.log(`🔍 Checking containment for experimental code in: ${sandboxLocation}`);
43
+
44
+ // Get list of changed files (this would typically come from git diff)
45
+ const changedFiles = getChangedFiles();
46
+
47
+ if (changedFiles.length === 0) {
48
+ console.log('ℹ️ No files changed - skipping scope check');
49
+ return results;
50
+ }
51
+
52
+ // Check each changed file
53
+ changedFiles.forEach((file) => {
54
+ const isInSandbox =
55
+ file.startsWith(sandboxLocation) ||
56
+ file.includes(`/${sandboxLocation}`) ||
57
+ file.includes(sandboxLocation);
58
+
59
+ if (isInSandbox) {
60
+ results.experimentalFiles.push(file);
61
+ console.log(`✅ Experimental file properly contained: ${file}`);
62
+ } else {
63
+ results.nonExperimentalFiles.push(file);
64
+ results.valid = false;
65
+ results.errors.push(`Experimental code found outside sandbox: ${file}`);
66
+ console.error(`❌ Experimental code outside sandbox: ${file}`);
67
+ }
68
+ });
69
+
70
+ // Check if experimental files actually exist
71
+ results.experimentalFiles.forEach((file) => {
72
+ if (!fs.existsSync(file)) {
73
+ results.warnings.push(`Experimental file not found (may have been deleted): ${file}`);
74
+ console.warn(`⚠️ Experimental file not found: ${file}`);
75
+ }
76
+ });
77
+
78
+ return results;
79
+ } catch (error) {
80
+ console.error('❌ Error checking experimental containment:', error.message);
81
+ return { valid: false, errors: [error.message] };
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Get list of changed files from git
87
+ * @returns {Array} List of changed file paths
88
+ */
89
+ function getChangedFiles() {
90
+ try {
91
+ // Get files that are staged or modified
92
+ const staged = execSync('git diff --cached --name-only', { encoding: 'utf8' })
93
+ .split('\n')
94
+ .filter((file) => file.trim());
95
+
96
+ const modified = execSync('git diff --name-only', { encoding: 'utf8' })
97
+ .split('\n')
98
+ .filter((file) => file.trim());
99
+
100
+ // Combine and deduplicate
101
+ const allFiles = [...new Set([...staged, ...modified])];
102
+
103
+ // Filter out deleted files (they might still be in the diff)
104
+ return allFiles.filter((file) => {
105
+ try {
106
+ return fs.existsSync(file);
107
+ } catch {
108
+ return false;
109
+ }
110
+ });
111
+ } catch (error) {
112
+ console.warn('⚠️ Could not get changed files from git:', error.message);
113
+ return [];
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Validate that experimental code follows containment rules
119
+ * @param {string} workingSpecPath - Path to working spec file
120
+ */
121
+ function validateExperimentalScope(workingSpecPath = '.caws/working-spec.yaml') {
122
+ console.log('🔍 Validating experimental code containment...');
123
+
124
+ const results = checkExperimentalContainment(workingSpecPath);
125
+
126
+ if (!results.valid) {
127
+ console.error('\n❌ Experimental containment validation failed:');
128
+ results.errors.forEach((error) => {
129
+ console.error(` - ${error}`);
130
+ });
131
+
132
+ if (results.warnings.length > 0) {
133
+ console.warn('\n⚠️ Warnings:');
134
+ results.warnings.forEach((warning) => {
135
+ console.warn(` - ${warning}`);
136
+ });
137
+ }
138
+
139
+ console.error('\n💡 To fix containment issues:');
140
+ console.error(' 1. Move experimental code to the designated sandbox location');
141
+ console.error(' 2. Update the sandbox_location in your working spec');
142
+ console.error(' 3. Or disable experimental mode if this is production code');
143
+
144
+ process.exit(1);
145
+ }
146
+
147
+ if (results.warnings.length > 0) {
148
+ console.warn('\n⚠️ Experimental containment warnings:');
149
+ results.warnings.forEach((warning) => {
150
+ console.warn(` - ${warning}`);
151
+ });
152
+ }
153
+
154
+ console.log('✅ Experimental code containment validated');
155
+ console.log(` - Files in sandbox: ${results.experimentalFiles.length}`);
156
+ console.log(` - Files outside sandbox: ${results.nonExperimentalFiles.length}`);
157
+ }
158
+
159
+ // CLI interface
160
+ if (require.main === module) {
161
+ const command = process.argv[2];
162
+ const specPath = process.argv[3] || '.caws/working-spec.yaml';
163
+
164
+ switch (command) {
165
+ case 'validate':
166
+ validateExperimentalScope(specPath);
167
+ break;
168
+
169
+ case 'check':
170
+ const results = checkExperimentalContainment(specPath);
171
+ console.log('\n📊 Containment Check Results:');
172
+ console.log(` Valid: ${results.valid}`);
173
+ console.log(` Experimental files: ${results.experimentalFiles.length}`);
174
+ console.log(` Non-experimental files: ${results.nonExperimentalFiles.length}`);
175
+ console.log(` Errors: ${results.errors.length}`);
176
+ console.log(` Warnings: ${results.warnings.length}`);
177
+
178
+ if (results.errors.length > 0) {
179
+ console.log('\n❌ Errors:');
180
+ results.errors.forEach((error) => console.log(` - ${error}`));
181
+ }
182
+
183
+ if (results.warnings.length > 0) {
184
+ console.log('\n⚠️ Warnings:');
185
+ results.warnings.forEach((warning) => console.log(` - ${warning}`));
186
+ }
187
+
188
+ process.exit(results.valid ? 0 : 1);
189
+ break;
190
+
191
+ default:
192
+ console.log('CAWS Scope Guard');
193
+ console.log('Usage:');
194
+ console.log(' node scope-guard.js validate [spec-path]');
195
+ console.log(' node scope-guard.js check [spec-path]');
196
+ console.log('');
197
+ console.log('Examples:');
198
+ console.log(' node scope-guard.js validate');
199
+ console.log(' node scope-guard.js check .caws/working-spec.yaml');
200
+ process.exit(1);
201
+ }
202
+ }
203
+
204
+ module.exports = {
205
+ checkExperimentalContainment,
206
+ validateExperimentalScope,
207
+ getChangedFiles,
208
+ };