@paths.design/caws-cli 7.0.2 → 8.0.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 (217) 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/quality-gates.js +147 -9
  5. package/dist/commands/specs.js +148 -14
  6. package/dist/commands/status.js +2 -2
  7. package/dist/commands/tool.js +2 -4
  8. package/dist/config/index.js +17 -8
  9. package/dist/generators/working-spec.js +19 -6
  10. package/dist/scaffold/git-hooks.js +245 -46
  11. package/dist/scaffold/index.js +53 -7
  12. package/dist/templates/.caws/tools/README.md +21 -0
  13. package/dist/templates/.cursor/README.md +311 -0
  14. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  15. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  16. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  17. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  18. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  19. package/dist/templates/.cursor/hooks/format.sh +38 -0
  20. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  21. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  22. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  23. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  24. package/dist/templates/.cursor/hooks.json +59 -0
  25. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  26. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  27. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  28. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  29. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  30. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  31. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  32. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  33. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  34. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  35. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  36. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  37. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  38. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  39. package/dist/templates/.cursor/rules/README.md +148 -0
  40. package/dist/templates/.github/copilot/instructions.md +311 -0
  41. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  42. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  43. package/dist/templates/.vscode/launch.json +56 -0
  44. package/dist/templates/.vscode/settings.json +93 -0
  45. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  46. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  47. package/dist/templates/OIDC_SETUP.md +300 -0
  48. package/dist/templates/agents.md +1047 -0
  49. package/dist/templates/codemod/README.md +1 -0
  50. package/dist/templates/codemod/test.js +93 -0
  51. package/dist/templates/docs/README.md +150 -0
  52. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  53. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  54. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  55. package/dist/tool-loader.js +6 -1
  56. package/dist/tool-validator.js +8 -2
  57. package/dist/utils/detection.js +4 -3
  58. package/dist/utils/git-lock.js +119 -0
  59. package/dist/utils/gitignore-updater.js +148 -0
  60. package/dist/utils/project-analysis.js +176 -16
  61. package/dist/utils/quality-gates.js +48 -7
  62. package/dist/utils/spec-resolver.js +27 -3
  63. package/dist/utils/yaml-validation.js +156 -0
  64. package/dist/validation/spec-validation.js +81 -2
  65. package/package.json +2 -2
  66. package/templates/.caws/schemas/waivers.schema.json +30 -0
  67. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  68. package/templates/.caws/templates/working-spec.template.yml +74 -0
  69. package/templates/.caws/tools/README.md +21 -0
  70. package/templates/.caws/tools/scope-guard.js +208 -0
  71. package/templates/.caws/tools-allow.json +331 -0
  72. package/templates/.caws/waivers.yml +19 -0
  73. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  74. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  75. package/dist/budget-derivation.d.ts +0 -74
  76. package/dist/budget-derivation.d.ts.map +0 -1
  77. package/dist/cicd-optimizer.d.ts +0 -142
  78. package/dist/cicd-optimizer.d.ts.map +0 -1
  79. package/dist/commands/archive.d.ts +0 -50
  80. package/dist/commands/archive.d.ts.map +0 -1
  81. package/dist/commands/burnup.d.ts +0 -6
  82. package/dist/commands/burnup.d.ts.map +0 -1
  83. package/dist/commands/diagnose.d.ts +0 -52
  84. package/dist/commands/diagnose.d.ts.map +0 -1
  85. package/dist/commands/evaluate.d.ts +0 -8
  86. package/dist/commands/evaluate.d.ts.map +0 -1
  87. package/dist/commands/init.d.ts +0 -5
  88. package/dist/commands/init.d.ts.map +0 -1
  89. package/dist/commands/iterate.d.ts +0 -8
  90. package/dist/commands/iterate.d.ts.map +0 -1
  91. package/dist/commands/mode.d.ts +0 -24
  92. package/dist/commands/mode.d.ts.map +0 -1
  93. package/dist/commands/plan.d.ts +0 -49
  94. package/dist/commands/plan.d.ts.map +0 -1
  95. package/dist/commands/provenance.d.ts +0 -32
  96. package/dist/commands/provenance.d.ts.map +0 -1
  97. package/dist/commands/quality-gates.d.ts +0 -52
  98. package/dist/commands/quality-gates.d.ts.map +0 -1
  99. package/dist/commands/quality-monitor.d.ts +0 -17
  100. package/dist/commands/quality-monitor.d.ts.map +0 -1
  101. package/dist/commands/specs.d.ts +0 -71
  102. package/dist/commands/specs.d.ts.map +0 -1
  103. package/dist/commands/status.d.ts +0 -44
  104. package/dist/commands/status.d.ts.map +0 -1
  105. package/dist/commands/templates.d.ts +0 -74
  106. package/dist/commands/templates.d.ts.map +0 -1
  107. package/dist/commands/tool.d.ts +0 -13
  108. package/dist/commands/tool.d.ts.map +0 -1
  109. package/dist/commands/troubleshoot.d.ts +0 -8
  110. package/dist/commands/troubleshoot.d.ts.map +0 -1
  111. package/dist/commands/tutorial.d.ts +0 -55
  112. package/dist/commands/tutorial.d.ts.map +0 -1
  113. package/dist/commands/validate.d.ts +0 -15
  114. package/dist/commands/validate.d.ts.map +0 -1
  115. package/dist/commands/waivers.d.ts +0 -8
  116. package/dist/commands/waivers.d.ts.map +0 -1
  117. package/dist/commands/workflow.d.ts +0 -85
  118. package/dist/commands/workflow.d.ts.map +0 -1
  119. package/dist/config/index.d.ts +0 -29
  120. package/dist/config/index.d.ts.map +0 -1
  121. package/dist/config/modes.d.ts +0 -225
  122. package/dist/config/modes.d.ts.map +0 -1
  123. package/dist/constants/spec-types.d.ts +0 -41
  124. package/dist/constants/spec-types.d.ts.map +0 -1
  125. package/dist/error-handler.d.ts +0 -164
  126. package/dist/error-handler.d.ts.map +0 -1
  127. package/dist/generators/jest-config.d.ts +0 -32
  128. package/dist/generators/jest-config.d.ts.map +0 -1
  129. package/dist/generators/working-spec.d.ts +0 -13
  130. package/dist/generators/working-spec.d.ts.map +0 -1
  131. package/dist/index-new.d.ts +0 -5
  132. package/dist/index-new.d.ts.map +0 -1
  133. package/dist/index-new.js +0 -317
  134. package/dist/index.d.ts +0 -5
  135. package/dist/index.d.ts.map +0 -1
  136. package/dist/index.js.backup +0 -4711
  137. package/dist/minimal-cli.d.ts +0 -3
  138. package/dist/minimal-cli.d.ts.map +0 -1
  139. package/dist/policy/PolicyManager.d.ts +0 -104
  140. package/dist/policy/PolicyManager.d.ts.map +0 -1
  141. package/dist/scaffold/cursor-hooks.d.ts +0 -7
  142. package/dist/scaffold/cursor-hooks.d.ts.map +0 -1
  143. package/dist/scaffold/git-hooks.d.ts +0 -20
  144. package/dist/scaffold/git-hooks.d.ts.map +0 -1
  145. package/dist/scaffold/index.d.ts +0 -20
  146. package/dist/scaffold/index.d.ts.map +0 -1
  147. package/dist/spec/SpecFileManager.d.ts +0 -146
  148. package/dist/spec/SpecFileManager.d.ts.map +0 -1
  149. package/dist/test-analysis.d.ts +0 -182
  150. package/dist/test-analysis.d.ts.map +0 -1
  151. package/dist/tool-interface.d.ts +0 -236
  152. package/dist/tool-interface.d.ts.map +0 -1
  153. package/dist/tool-loader.d.ts +0 -77
  154. package/dist/tool-loader.d.ts.map +0 -1
  155. package/dist/tool-validator.d.ts +0 -72
  156. package/dist/tool-validator.d.ts.map +0 -1
  157. package/dist/utils/detection.d.ts +0 -7
  158. package/dist/utils/detection.d.ts.map +0 -1
  159. package/dist/utils/finalization.d.ts +0 -17
  160. package/dist/utils/finalization.d.ts.map +0 -1
  161. package/dist/utils/project-analysis.d.ts +0 -14
  162. package/dist/utils/project-analysis.d.ts.map +0 -1
  163. package/dist/utils/quality-gates.d.ts +0 -49
  164. package/dist/utils/quality-gates.d.ts.map +0 -1
  165. package/dist/utils/spec-resolver.d.ts +0 -88
  166. package/dist/utils/spec-resolver.d.ts.map +0 -1
  167. package/dist/utils/typescript-detector.d.ts +0 -63
  168. package/dist/utils/typescript-detector.d.ts.map +0 -1
  169. package/dist/validation/spec-validation.d.ts +0 -43
  170. package/dist/validation/spec-validation.d.ts.map +0 -1
  171. package/dist/waivers-manager.d.ts +0 -167
  172. package/dist/waivers-manager.d.ts.map +0 -1
  173. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  174. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  175. package/templates/apps/tools/caws/README.md +0 -463
  176. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  177. package/templates/apps/tools/caws/attest.js +0 -357
  178. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  179. package/templates/apps/tools/caws/config.ts +0 -245
  180. package/templates/apps/tools/caws/cross-functional.js +0 -876
  181. package/templates/apps/tools/caws/dashboard.js +0 -1112
  182. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  183. package/templates/apps/tools/caws/gates.js +0 -198
  184. package/templates/apps/tools/caws/gates.ts +0 -271
  185. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  186. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  187. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  188. package/templates/apps/tools/caws/language-support.js +0 -585
  189. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  190. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  191. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  192. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  193. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  194. package/templates/apps/tools/caws/property-testing.js +0 -707
  195. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  196. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  197. package/templates/apps/tools/caws/provenance.js +0 -132
  198. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  199. package/templates/apps/tools/caws/provenance.ts +0 -211
  200. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  201. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  202. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  203. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  204. package/templates/apps/tools/caws/shared/types.ts +0 -444
  205. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  206. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  207. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  208. package/templates/apps/tools/caws/test-quality.js +0 -578
  209. package/templates/apps/tools/caws/validate.js +0 -76
  210. package/templates/apps/tools/caws/validate.ts +0 -228
  211. package/templates/apps/tools/caws/waivers.js +0 -344
  212. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  213. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  214. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  215. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  216. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  217. /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
@@ -49,15 +49,19 @@ function initializeGlobalSetup() {
49
49
  function loadProvenanceTools() {
50
50
  if (provenanceTools) return provenanceTools; // Already loaded
51
51
 
52
- // Try multiple possible locations for provenance tools
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. Bundled templates in CLI package (for global installs)
55
- path.join(__dirname, '../../templates/apps/tools/caws/provenance.js'),
56
- // 2. Local project templates
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. Template package in monorepo
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
- // 4. Detected setup template directory
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[3] = path.join(setup.templateDir, 'apps/tools/caws/provenance.js');
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
- // Try multiple possible locations for language support
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: (answers.acceptanceCriteria || 'Given current state, when action occurs, then expected result')
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) => {
@@ -107,7 +119,7 @@ function generateWorkingSpec(answers) {
107
119
  },
108
120
  ];
109
121
  }
110
-
122
+
111
123
  // For Tier 1 & 2, provide minimal project_setup contract if none specified
112
124
  const riskTier = answers.riskTier || 2;
113
125
  if (riskTier === 1 || riskTier === 2) {
@@ -115,11 +127,12 @@ function generateWorkingSpec(answers) {
115
127
  {
116
128
  type: 'project_setup',
117
129
  path: '.caws/working-spec.yaml',
118
- description: 'Project-level CAWS configuration. Feature-specific contracts will be added as features are developed.',
130
+ description:
131
+ 'Project-level CAWS configuration. Feature-specific contracts will be added as features are developed.',
119
132
  },
120
133
  ];
121
134
  }
122
-
135
+
123
136
  // Tier 3 doesn't require contracts
124
137
  return [];
125
138
  })(),
@@ -6,6 +6,7 @@
6
6
 
7
7
  const fs = require('fs-extra');
8
8
  const path = require('path');
9
+ const { getTodoAnalyzerSuggestion } = require('../utils/project-analysis');
9
10
 
10
11
  /**
11
12
  * Scaffold git hooks for CAWS provenance tracking
@@ -39,7 +40,7 @@ async function scaffoldGitHooks(projectDir, options = {}) {
39
40
  name: 'pre-commit',
40
41
  description: 'Pre-commit validation and quality checks',
41
42
  enabled: validation || qualityGates,
42
- content: generatePreCommitHook({ validation, qualityGates }),
43
+ content: generatePreCommitHook({ validation, qualityGates, projectDir }),
43
44
  },
44
45
  {
45
46
  name: 'post-commit',
@@ -120,7 +121,10 @@ async function scaffoldGitHooks(projectDir, options = {}) {
120
121
  * Implements fallback chain: Node script → CLI → Python scripts → Skip gracefully
121
122
  */
122
123
  function generatePreCommitHook(options) {
123
- const { qualityGates = true, stagedOnly = true } = options;
124
+ const { qualityGates = true, stagedOnly = true, projectDir = process.cwd() } = options;
125
+
126
+ // Get language-agnostic suggestions based on runtime availability
127
+ const todoSuggestion = getTodoAnalyzerSuggestion(projectDir);
124
128
 
125
129
  return `#!/bin/bash
126
130
  # CAWS Pre-commit Hook
@@ -138,6 +142,100 @@ if [ ! -d ".caws" ]; then
138
142
  exit 0
139
143
  fi
140
144
 
145
+ # Check for git locks before proceeding
146
+ if [ -f ".git/index.lock" ]; then
147
+ LOCK_AGE=$(($(date +%s) - $(stat -f %m .git/index.lock 2>/dev/null || stat -c %Y .git/index.lock 2>/dev/null || echo 0)))
148
+ LOCK_AGE_MINUTES=$((LOCK_AGE / 60))
149
+
150
+ if [ $LOCK_AGE_MINUTES -gt 5 ]; then
151
+ echo "⚠️ Stale git lock detected (\${LOCK_AGE_MINUTES} minutes old)"
152
+ echo "💡 This may indicate a crashed git process"
153
+ echo "💡 Remove stale lock: rm .git/index.lock"
154
+ echo "⚠️ Warning: Check for running git/editor processes before removing"
155
+ exit 1
156
+ else
157
+ echo "⚠️ Git lock detected (\${LOCK_AGE_MINUTES} minutes old)"
158
+ echo "💡 Another git process may be running"
159
+ echo "💡 Wait for the other process to complete, or check for running processes"
160
+ exit 1
161
+ fi
162
+ fi
163
+
164
+ # Validate YAML syntax for all CAWS spec files
165
+ echo "🔍 Validating YAML syntax for CAWS spec files..."
166
+ YAML_VALIDATION_FAILED=false
167
+
168
+ # Find all staged .yaml/.yml files in .caws directory
169
+ STAGED_YAML_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\\.caws/.*\\.(yaml|yml)$' || true)
170
+
171
+ if [ -n "$STAGED_YAML_FILES" ]; then
172
+ # Use Node.js to validate YAML if available
173
+ if command -v node >/dev/null 2>&1; then
174
+ # Try to use CAWS CLI for validation
175
+ if command -v caws >/dev/null 2>&1; then
176
+ for file in $STAGED_YAML_FILES; do
177
+ if [ -f "$file" ]; then
178
+ # Use Node.js to validate YAML syntax
179
+ if ! node -e "
180
+ const yaml = require('js-yaml');
181
+ const fs = require('fs');
182
+ try {
183
+ const content = fs.readFileSync('$file', 'utf8');
184
+ yaml.load(content);
185
+ process.exit(0);
186
+ } catch (error) {
187
+ console.error('❌ Invalid YAML in $file');
188
+ console.error(' Error:', error.message);
189
+ if (error.mark) {
190
+ console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
191
+ if (error.mark.snippet) console.error(' ' + error.mark.snippet);
192
+ }
193
+ process.exit(1);
194
+ }
195
+ " 2>&1; then
196
+ YAML_VALIDATION_FAILED=true
197
+ fi
198
+ fi
199
+ done
200
+ else
201
+ # Fallback: use node directly with js-yaml
202
+ for file in $STAGED_YAML_FILES; do
203
+ if [ -f "$file" ]; then
204
+ if ! node -e "
205
+ const yaml = require('js-yaml');
206
+ const fs = require('fs');
207
+ try {
208
+ const content = fs.readFileSync('$file', 'utf8');
209
+ yaml.load(content);
210
+ process.exit(0);
211
+ } catch (error) {
212
+ console.error('❌ Invalid YAML in $file');
213
+ console.error(' Error:', error.message);
214
+ if (error.mark) {
215
+ console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
216
+ if (error.mark.snippet) console.error(' ' + error.mark.snippet);
217
+ }
218
+ process.exit(1);
219
+ }
220
+ " 2>&1; then
221
+ YAML_VALIDATION_FAILED=true
222
+ fi
223
+ fi
224
+ done
225
+ fi
226
+ else
227
+ echo "⚠️ Node.js not available - skipping YAML validation"
228
+ echo "💡 Install Node.js to enable YAML syntax validation"
229
+ fi
230
+ fi
231
+
232
+ if [ "$YAML_VALIDATION_FAILED" = true ]; then
233
+ echo "❌ YAML syntax validation failed - commit blocked"
234
+ echo "💡 Fix YAML syntax errors above before committing"
235
+ echo "💡 Consider using 'caws specs create <id>' instead of manual creation"
236
+ exit 1
237
+ fi
238
+
141
239
  # Fallback chain for quality gates:
142
240
  # 1. Try Node.js script (if exists)
143
241
  # 2. Try CAWS CLI
@@ -231,40 +329,50 @@ fi
231
329
  # Run hidden TODO analysis on staged files only (if available)
232
330
  if [ "$QUALITY_GATES_RAN" = true ]; then
233
331
  echo "🔍 Checking for hidden TODOs in staged files..."
234
- # Try quality gates package TODO analyzer first (published package)
235
- if [ -f "node_modules/@paths.design/quality-gates/todo-analyzer.mjs" ]; then
236
- if command -v node >/dev/null 2>&1; then
237
- if node node_modules/@paths.design/quality-gates/todo-analyzer.mjs --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
238
- echo " No critical hidden TODOs found in staged files"
239
- else
240
- echo "❌ Critical hidden TODOs detected in staged files - commit blocked"
241
- echo "💡 Fix stub implementations and placeholder code before committing"
242
- echo "📖 See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
243
- echo ""
244
- echo "🔍 Running detailed analysis on staged files..."
245
- node node_modules/@paths.design/quality-gates/todo-analyzer.mjs --staged-only --min-confidence 0.8
246
- exit 1
247
- fi
332
+
333
+ TODO_CHECK_RAN=false
334
+
335
+ # Option 1: Find TODO analyzer .mjs file (if installed locally)
336
+ if [ "$TODO_CHECK_RAN" = false ]; then
337
+ TODO_ANALYZER=""
338
+
339
+ # Try quality gates package TODO analyzer (published package)
340
+ if [ -f "node_modules/@paths.design/quality-gates/todo-analyzer.mjs" ]; then
341
+ TODO_ANALYZER="node_modules/@paths.design/quality-gates/todo-analyzer.mjs"
342
+ # Try quality gates package TODO analyzer (monorepo/local copy)
343
+ elif [ -f "node_modules/@caws/quality-gates/todo-analyzer.mjs" ]; then
344
+ TODO_ANALYZER="node_modules/@caws/quality-gates/todo-analyzer.mjs"
345
+ # Try monorepo structure (development)
346
+ elif [ -f "packages/quality-gates/todo-analyzer.mjs" ]; then
347
+ TODO_ANALYZER="packages/quality-gates/todo-analyzer.mjs"
348
+ # Try local copy in scripts directory (if scaffolded)
349
+ elif [ -f "scripts/todo-analyzer.mjs" ]; then
350
+ TODO_ANALYZER="scripts/todo-analyzer.mjs"
248
351
  fi
249
- # Try quality gates package TODO analyzer (monorepo/local copy)
250
- elif [ -f "node_modules/@caws/quality-gates/todo-analyzer.mjs" ]; then
251
- if command -v node >/dev/null 2>&1; then
252
- if node node_modules/@caws/quality-gates/todo-analyzer.mjs --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
352
+
353
+ # Run TODO analyzer if found
354
+ if [ -n "$TODO_ANALYZER" ] && command -v node >/dev/null 2>&1; then
355
+ if node "$TODO_ANALYZER" --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
253
356
  echo "✅ No critical hidden TODOs found in staged files"
357
+ TODO_CHECK_RAN=true
254
358
  else
255
359
  echo "❌ Critical hidden TODOs detected in staged files - commit blocked"
256
360
  echo "💡 Fix stub implementations and placeholder code before committing"
257
361
  echo "📖 See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
258
362
  echo ""
259
363
  echo "🔍 Running detailed analysis on staged files..."
260
- node node_modules/@caws/quality-gates/todo-analyzer.mjs --staged-only --min-confidence 0.8
364
+ node "$TODO_ANALYZER" --staged-only --min-confidence 0.8
261
365
  exit 1
262
366
  fi
263
367
  fi
264
- # Fallback to legacy Python analyzer
265
- elif command -v python3 >/dev/null 2>&1 && [ -f "scripts/v3/analysis/todo_analyzer.py" ]; then
368
+ fi
369
+
370
+ # Option 2: Fallback to legacy Python analyzer (deprecated - will be removed)
371
+ if [ "$TODO_CHECK_RAN" = false ] && command -v python3 >/dev/null 2>&1 && [ -f "scripts/v3/analysis/todo_analyzer.py" ]; then
372
+ echo "⚠️ Using legacy Python TODO analyzer (deprecated)"
266
373
  if python3 scripts/v3/analysis/todo_analyzer.py --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
267
374
  echo "✅ No critical hidden TODOs found in staged files"
375
+ TODO_CHECK_RAN=true
268
376
  else
269
377
  echo "❌ Critical hidden TODOs detected in staged files - commit blocked"
270
378
  echo "💡 Fix stub implementations and placeholder code before committing"
@@ -274,8 +382,16 @@ if [ "$QUALITY_GATES_RAN" = true ]; then
274
382
  python3 scripts/v3/analysis/todo_analyzer.py --staged-only --min-confidence 0.8
275
383
  exit 1
276
384
  fi
277
- elif command -v python3 >/dev/null 2>&1; then
278
- echo "⚠️ Python3 found but TODO analyzer not available - skipping"
385
+ fi
386
+
387
+ # Option 3: No analyzer available - show language-aware suggestions
388
+ if [ "$TODO_CHECK_RAN" = false ]; then
389
+ echo "⚠️ TODO analyzer not available - skipping hidden TODO check"
390
+ echo "💡 Available options for TODO analysis:"
391
+ ${todoSuggestion
392
+ .split('\n')
393
+ .map((line) => ` echo "${line.replace(/"/g, '\\"')}"`)
394
+ .join('\n')}
279
395
  fi
280
396
  fi
281
397
 
@@ -346,8 +462,8 @@ for arg in "$@"; do
346
462
  echo "💡 To fix issues locally:"
347
463
  echo " 1. Run: caws validate"
348
464
  echo " 2. Fix reported issues"
349
- echo " 3. Commit fixes: git commit --no-verify (allowed)"
350
- echo " 4. Push again: git push (no --no-verify)"
465
+ echo " 3. Commit fixes: git commit --no-verify \\(allowed\\)"
466
+ echo " 4. Push again: git push \\(no --no-verify\\)"
351
467
  exit 1
352
468
  fi
353
469
  done
@@ -410,13 +526,13 @@ if command -v caws >/dev/null 2>&1; then
410
526
  echo " No active waivers found"
411
527
  echo ""
412
528
  echo "💡 If this is infrastructure/setup work, you can create a waiver:"
413
- echo " caws waivers create \\"
414
- echo " --title='Initial CAWS setup' \\"
415
- echo " --reason=infrastructure_limitation \\"
416
- echo " --gates=contracts \\"
417
- echo " --expires-at='2024-12-31T23:59:59Z' \\"
418
- echo " --approved-by='@your-team' \\"
419
- echo " --impact-level=low \\"
529
+ echo " caws waivers create \\\\"
530
+ echo " --title='Initial CAWS setup' \\\\"
531
+ echo " --reason=infrastructure_limitation \\\\"
532
+ echo " --gates=contracts \\\\"
533
+ echo " --expires-at='2024-12-31T23:59:59Z' \\\\"
534
+ echo " --approved-by='@your-team' \\\\"
535
+ echo " --impact-level=low \\\\"
420
536
  echo " --mitigation-plan='Contracts will be added as features are developed'"
421
537
  fi
422
538
 
@@ -425,43 +541,121 @@ if command -v caws >/dev/null 2>&1; then
425
541
  echo "Next Steps:"
426
542
  echo " 1. Review errors above"
427
543
  echo " 2. Fix issues in .caws/working-spec.yaml"
428
- echo " 3. Run: caws validate (to verify fixes)"
429
- echo " 4. Commit fixes: git commit --no-verify (allowed)"
544
+ echo " 3. Run: caws validate \\(to verify fixes\\)"
545
+ echo " 4. Commit fixes: git commit --no-verify \\(allowed\\)"
430
546
  echo " 5. Push again: git push"
431
547
  echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
432
548
  exit 1
433
549
  fi
434
550
  fi
435
551
 
436
- # Run security checks
552
+ # Run full pre-push checks (full test suite required before push)
553
+ # Note: Pre-commit uses filtered tests for speed, but push requires full suite
554
+ echo ""
555
+ echo "⚡ Running full pre-push checks (full test suite required)..."
556
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
557
+
558
+ QUICK_CHECKS_FAILED=false
559
+
560
+ # 1. Linting (fast)
561
+ if [ -f "package.json" ]; then
562
+ if command -v npm >/dev/null 2>&1; then
563
+ if grep -q '"lint"' package.json; then
564
+ echo "🔍 Running linting..."
565
+ if npm run lint >/dev/null 2>&1; then
566
+ echo "✅ Linting passed"
567
+ else
568
+ echo "❌ Linting failed"
569
+ echo "💡 Fix lint errors: npm run lint"
570
+ QUICK_CHECKS_FAILED=true
571
+ fi
572
+ fi
573
+ fi
574
+ fi
575
+
576
+ # 2. Type checking (fast for TypeScript/JavaScript)
577
+ if [ -f "package.json" ]; then
578
+ if command -v npm >/dev/null 2>&1; then
579
+ if grep -q '"typecheck"' package.json; then
580
+ echo "🔍 Running type checking..."
581
+ if npm run typecheck >/dev/null 2>&1; then
582
+ echo "✅ Type checking passed"
583
+ else
584
+ echo "❌ Type checking failed"
585
+ echo "💡 Fix type errors: npm run typecheck"
586
+ QUICK_CHECKS_FAILED=true
587
+ fi
588
+ fi
589
+ fi
590
+ fi
591
+
592
+ # 3. Run FULL test suite (required for push) - no filtering
593
+ # Pre-commit uses filtered tests for speed, but push requires full suite
594
+ if [ -f "package.json" ]; then
595
+ if command -v npm >/dev/null 2>&1 && grep -q '"test"' package.json; then
596
+ echo "🧪 Running FULL test suite (required for push)..."
597
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
598
+ if npm test 2>&1 | tee /tmp/pre-push-test-full.log; then
599
+ echo "✅ Full test suite passed"
600
+ rm -f /tmp/pre-push-test-full.log
601
+ else
602
+ FULL_TEST_EXIT_CODE=\${PIPESTATUS[0]}
603
+ echo "❌ Full test suite failed (exit code: \${FULL_TEST_EXIT_CODE})"
604
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
605
+ echo "Test output (last 100 lines):"
606
+ tail -100 /tmp/pre-push-test-full.log 2>/dev/null || echo "No test output captured"
607
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
608
+ echo "💡 Fix test failures before pushing: npm test"
609
+ rm -f /tmp/pre-push-test-full.log
610
+ QUICK_CHECKS_FAILED=true
611
+ fi
612
+ fi
613
+ fi
614
+
615
+ # 4. Security checks (non-blocking warnings)
616
+ echo ""
437
617
  echo "🔒 Running security checks..."
438
618
  if [ -f "package.json" ]; then
439
- # Check for vulnerabilities
440
619
  if command -v npm >/dev/null 2>&1; then
441
620
  echo "🔍 Checking for vulnerabilities..."
442
621
  if npm audit --audit-level moderate >/dev/null 2>&1; then
443
622
  echo "✅ Security audit passed"
444
623
  else
445
- echo "⚠️ Security vulnerabilities found"
624
+ echo "⚠️ Security vulnerabilities found (non-blocking)"
446
625
  echo "💡 Review with: npm audit"
447
- # Don't fail on warnings, just warn
448
626
  fi
449
627
  fi
450
628
  elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
451
- # Python project security checks
452
629
  if command -v pip-audit >/dev/null 2>&1; then
453
630
  echo "🔍 Checking Python vulnerabilities..."
454
- pip-audit --desc 2>/dev/null || echo "⚠️ Install pip-audit for vulnerability checks: pip install pip-audit"
631
+ pip-audit --desc 2>/dev/null || echo "⚠️ Install pip-audit: pip install pip-audit"
455
632
  fi
456
633
  elif [ -f "Cargo.toml" ]; then
457
- # Rust project security checks
458
634
  if command -v cargo-audit >/dev/null 2>&1; then
459
635
  echo "🔍 Checking Rust vulnerabilities..."
460
- cargo audit 2>/dev/null || echo "⚠️ Install cargo-audit for vulnerability checks: cargo install cargo-audit"
636
+ cargo audit 2>/dev/null || echo "⚠️ Install cargo-audit: cargo install cargo-audit"
461
637
  fi
462
638
  fi
463
639
 
464
- echo "🎉 Pre-push checks completed!"
640
+ # Fail if any checks failed
641
+ if [ "$QUICK_CHECKS_FAILED" = true ]; then
642
+ echo ""
643
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
644
+ echo "❌ Pre-push checks failed"
645
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
646
+ echo "All checks (linting/type checking/full test suite) must pass before push."
647
+ echo ""
648
+ echo "💡 Fix failures before pushing:"
649
+ echo " - Linting: npm run lint"
650
+ echo " - Type checking: npm run typecheck"
651
+ echo " - Tests: npm test"
652
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
653
+ exit 1
654
+ fi
655
+
656
+ echo ""
657
+ echo "✅ Pre-push checks completed!"
658
+ echo "💡 All quality gates passed - ready to push"
465
659
  `;
466
660
  }
467
661
 
@@ -485,7 +679,7 @@ fi
485
679
 
486
680
  # Basic commit message validation
487
681
  if [ \${#COMMIT_MSG} -lt 10 ]; then
488
- echo "❌ Commit message too short (minimum 10 characters)"
682
+ echo "❌ Commit message too short \\(minimum 10 characters\\)"
489
683
  echo "💡 Write descriptive commit messages"
490
684
  exit 1
491
685
  fi
@@ -602,4 +796,9 @@ module.exports = {
602
796
  scaffoldGitHooks,
603
797
  removeGitHooks,
604
798
  checkGitHooksStatus,
799
+ // Export generator functions for testing
800
+ generatePrePushHook,
801
+ generatePreCommitHook,
802
+ generatePostCommitHook,
803
+ generateCommitMsgHook,
605
804
  };
@@ -14,6 +14,7 @@ const { detectsPublishing } = require('../utils/project-analysis');
14
14
 
15
15
  // Import git hooks scaffolding
16
16
  const { scaffoldGitHooks } = require('./git-hooks');
17
+ const { updateGitignore } = require('../utils/gitignore-updater');
17
18
 
18
19
  // CLI version from package.json
19
20
  const CLI_VERSION = require('../../package.json').version;
@@ -31,20 +32,20 @@ const CLI_VERSION = require('../../package.json').version;
31
32
  function findTemplateDir() {
32
33
  // Find package root using shared utility
33
34
  const packageRoot = findPackageRoot(__dirname);
34
-
35
+
35
36
  // Try templates relative to package root first (works in both dev and global install)
36
37
  const possiblePaths = [
37
38
  path.join(packageRoot, 'templates'),
38
39
  path.resolve(__dirname, '../../templates'), // Dev fallback
39
40
  path.resolve(__dirname, '../templates'), // Legacy fallback
40
41
  ];
41
-
42
+
42
43
  for (const testPath of possiblePaths) {
43
44
  if (fs.existsSync(testPath)) {
44
45
  return testPath;
45
46
  }
46
47
  }
47
-
48
+
48
49
  return null;
49
50
  }
50
51
 
@@ -301,12 +302,32 @@ async function scaffoldProject(options) {
301
302
  // Determine what enhancements to add based on setup type and options
302
303
  const enhancements = [];
303
304
 
304
- // Add CAWS tools directory structure (matches test expectations)
305
+ // Add CAWS tools to .caws/ directory (keeps all CAWS files together)
305
306
  enhancements.push({
306
- name: 'apps/tools/caws',
307
+ name: '.caws/tools',
307
308
  description: 'CAWS tools directory',
308
309
  required: true,
309
310
  });
311
+ enhancements.push({
312
+ name: '.caws/schemas',
313
+ description: 'CAWS JSON schemas',
314
+ required: true,
315
+ });
316
+ enhancements.push({
317
+ name: '.caws/templates',
318
+ description: 'CAWS templates',
319
+ required: true,
320
+ });
321
+ enhancements.push({
322
+ name: '.caws/waivers.yml',
323
+ description: 'CAWS waivers configuration',
324
+ required: false,
325
+ });
326
+ enhancements.push({
327
+ name: '.caws/tools-allow.json',
328
+ description: 'CAWS tools allowlist',
329
+ required: false,
330
+ });
310
331
 
311
332
  // Add codemods if requested or not minimal
312
333
  if (options.withCodemods || (!options.minimal && !options.withCodemods)) {
@@ -457,6 +478,19 @@ async function scaffoldProject(options) {
457
478
  console.log(
458
479
  chalk.gray(' For now, quality gates will work via CAWS CLI or local scripts')
459
480
  );
481
+
482
+ // Copy todo-analyzer.mjs locally as fallback if available
483
+ const qualityGatesPath = path.resolve(__dirname, '../../../quality-gates');
484
+ const todoAnalyzerSource = path.join(qualityGatesPath, 'todo-analyzer.mjs');
485
+ if (fs.existsSync(todoAnalyzerSource)) {
486
+ const scriptsDir = path.join(currentDir, 'scripts');
487
+ await fs.ensureDir(scriptsDir);
488
+ const todoAnalyzerDest = path.join(scriptsDir, 'todo-analyzer.mjs');
489
+ await fs.copy(todoAnalyzerSource, todoAnalyzerDest);
490
+ console.log(
491
+ chalk.green('✅ Copied todo-analyzer.mjs to scripts/ directory (local fallback)')
492
+ );
493
+ }
460
494
  }
461
495
  } else {
462
496
  // No package.json - suggest global install or manual setup
@@ -601,12 +635,14 @@ async function scaffoldProject(options) {
601
635
  try {
602
636
  // Check if the enhancement name looks like a file (has extension)
603
637
  const hasExtension = path.extname(enhancement.name).length > 0;
604
-
638
+
605
639
  if (hasExtension) {
606
640
  // Create an empty file for file-like enhancements
607
641
  await fs.ensureDir(path.dirname(destPath));
608
642
  await fs.writeFile(destPath, '');
609
- console.log(chalk.yellow(`⚠️ Created empty ${enhancement.description} (template not found)`));
643
+ console.log(
644
+ chalk.yellow(`⚠️ Created empty ${enhancement.description} (template not found)`)
645
+ );
610
646
  console.log(chalk.gray(` Template expected at: ${sourcePath}`));
611
647
  } else {
612
648
  // Create directory for directory-like enhancements
@@ -698,6 +734,16 @@ async function scaffoldProject(options) {
698
734
  console.log(chalk.yellow('\n⚠️ Force mode was used - review changes carefully'));
699
735
  }
700
736
 
737
+ // Update .gitignore to exclude CAWS local runtime files
738
+ const gitignoreUpdated = await updateGitignore(currentDir);
739
+ if (gitignoreUpdated) {
740
+ console.log(chalk.green('\n✅ Updated .gitignore to exclude CAWS local runtime files'));
741
+ console.log(
742
+ chalk.gray(' Tracked: Specs, policy, waivers, provenance, plans (shared with team)')
743
+ );
744
+ console.log(chalk.gray(' Ignored: Agent runtime, temp files, logs (local-only)'));
745
+ }
746
+
701
747
  // Save provenance manifest if tools are available
702
748
  const tools = loadProvenanceTools && loadProvenanceTools();
703
749
  if (tools && typeof tools.saveProvenance === 'function') {
@@ -0,0 +1,21 @@
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
+
21
+