@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.
- package/dist/budget-derivation.js +5 -4
- package/dist/commands/diagnose.js +24 -19
- package/dist/commands/init.js +51 -4
- package/dist/commands/quality-gates.js +147 -9
- package/dist/commands/specs.js +148 -14
- package/dist/commands/status.js +2 -2
- package/dist/commands/tool.js +2 -4
- package/dist/config/index.js +17 -8
- package/dist/generators/working-spec.js +19 -6
- package/dist/scaffold/git-hooks.js +245 -46
- package/dist/scaffold/index.js +53 -7
- package/dist/templates/.caws/tools/README.md +21 -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 +4 -3
- package/dist/utils/git-lock.js +119 -0
- package/dist/utils/gitignore-updater.js +148 -0
- package/dist/utils/project-analysis.js +176 -16
- package/dist/utils/quality-gates.js +48 -7
- package/dist/utils/spec-resolver.js +27 -3
- package/dist/utils/yaml-validation.js +156 -0
- package/dist/validation/spec-validation.js +81 -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 +21 -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/dist/budget-derivation.d.ts +0 -74
- package/dist/budget-derivation.d.ts.map +0 -1
- package/dist/cicd-optimizer.d.ts +0 -142
- package/dist/cicd-optimizer.d.ts.map +0 -1
- package/dist/commands/archive.d.ts +0 -50
- package/dist/commands/archive.d.ts.map +0 -1
- package/dist/commands/burnup.d.ts +0 -6
- package/dist/commands/burnup.d.ts.map +0 -1
- package/dist/commands/diagnose.d.ts +0 -52
- package/dist/commands/diagnose.d.ts.map +0 -1
- package/dist/commands/evaluate.d.ts +0 -8
- package/dist/commands/evaluate.d.ts.map +0 -1
- package/dist/commands/init.d.ts +0 -5
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/iterate.d.ts +0 -8
- package/dist/commands/iterate.d.ts.map +0 -1
- package/dist/commands/mode.d.ts +0 -24
- package/dist/commands/mode.d.ts.map +0 -1
- package/dist/commands/plan.d.ts +0 -49
- package/dist/commands/plan.d.ts.map +0 -1
- package/dist/commands/provenance.d.ts +0 -32
- package/dist/commands/provenance.d.ts.map +0 -1
- package/dist/commands/quality-gates.d.ts +0 -52
- package/dist/commands/quality-gates.d.ts.map +0 -1
- package/dist/commands/quality-monitor.d.ts +0 -17
- package/dist/commands/quality-monitor.d.ts.map +0 -1
- package/dist/commands/specs.d.ts +0 -71
- package/dist/commands/specs.d.ts.map +0 -1
- package/dist/commands/status.d.ts +0 -44
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/templates.d.ts +0 -74
- package/dist/commands/templates.d.ts.map +0 -1
- package/dist/commands/tool.d.ts +0 -13
- package/dist/commands/tool.d.ts.map +0 -1
- package/dist/commands/troubleshoot.d.ts +0 -8
- package/dist/commands/troubleshoot.d.ts.map +0 -1
- package/dist/commands/tutorial.d.ts +0 -55
- package/dist/commands/tutorial.d.ts.map +0 -1
- package/dist/commands/validate.d.ts +0 -15
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/waivers.d.ts +0 -8
- package/dist/commands/waivers.d.ts.map +0 -1
- package/dist/commands/workflow.d.ts +0 -85
- package/dist/commands/workflow.d.ts.map +0 -1
- package/dist/config/index.d.ts +0 -29
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/modes.d.ts +0 -225
- package/dist/config/modes.d.ts.map +0 -1
- package/dist/constants/spec-types.d.ts +0 -41
- package/dist/constants/spec-types.d.ts.map +0 -1
- package/dist/error-handler.d.ts +0 -164
- package/dist/error-handler.d.ts.map +0 -1
- package/dist/generators/jest-config.d.ts +0 -32
- package/dist/generators/jest-config.d.ts.map +0 -1
- package/dist/generators/working-spec.d.ts +0 -13
- package/dist/generators/working-spec.d.ts.map +0 -1
- package/dist/index-new.d.ts +0 -5
- package/dist/index-new.d.ts.map +0 -1
- package/dist/index-new.js +0 -317
- package/dist/index.d.ts +0 -5
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.backup +0 -4711
- package/dist/minimal-cli.d.ts +0 -3
- package/dist/minimal-cli.d.ts.map +0 -1
- package/dist/policy/PolicyManager.d.ts +0 -104
- package/dist/policy/PolicyManager.d.ts.map +0 -1
- package/dist/scaffold/cursor-hooks.d.ts +0 -7
- package/dist/scaffold/cursor-hooks.d.ts.map +0 -1
- package/dist/scaffold/git-hooks.d.ts +0 -20
- package/dist/scaffold/git-hooks.d.ts.map +0 -1
- package/dist/scaffold/index.d.ts +0 -20
- package/dist/scaffold/index.d.ts.map +0 -1
- package/dist/spec/SpecFileManager.d.ts +0 -146
- package/dist/spec/SpecFileManager.d.ts.map +0 -1
- package/dist/test-analysis.d.ts +0 -182
- package/dist/test-analysis.d.ts.map +0 -1
- package/dist/tool-interface.d.ts +0 -236
- package/dist/tool-interface.d.ts.map +0 -1
- package/dist/tool-loader.d.ts +0 -77
- package/dist/tool-loader.d.ts.map +0 -1
- package/dist/tool-validator.d.ts +0 -72
- package/dist/tool-validator.d.ts.map +0 -1
- package/dist/utils/detection.d.ts +0 -7
- package/dist/utils/detection.d.ts.map +0 -1
- package/dist/utils/finalization.d.ts +0 -17
- package/dist/utils/finalization.d.ts.map +0 -1
- package/dist/utils/project-analysis.d.ts +0 -14
- package/dist/utils/project-analysis.d.ts.map +0 -1
- package/dist/utils/quality-gates.d.ts +0 -49
- package/dist/utils/quality-gates.d.ts.map +0 -1
- package/dist/utils/spec-resolver.d.ts +0 -88
- package/dist/utils/spec-resolver.d.ts.map +0 -1
- package/dist/utils/typescript-detector.d.ts +0 -63
- package/dist/utils/typescript-detector.d.ts.map +0 -1
- package/dist/validation/spec-validation.d.ts +0 -43
- package/dist/validation/spec-validation.d.ts.map +0 -1
- package/dist/waivers-manager.d.ts +0 -167
- package/dist/waivers-manager.d.ts.map +0 -1
- 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
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview YAML Validation Utilities
|
|
3
|
+
* Functions for validating YAML syntax and structure
|
|
4
|
+
* @author @darianrosebrook
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const yaml = require('js-yaml');
|
|
8
|
+
const fs = require('fs-extra');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Validate YAML syntax for a file
|
|
13
|
+
* @param {string} filePath - Path to YAML file
|
|
14
|
+
* @returns {Object} Validation result with valid flag and error details
|
|
15
|
+
*/
|
|
16
|
+
function validateYamlSyntax(filePath) {
|
|
17
|
+
try {
|
|
18
|
+
if (!fs.existsSync(filePath)) {
|
|
19
|
+
return {
|
|
20
|
+
valid: false,
|
|
21
|
+
error: `File not found: ${filePath}`,
|
|
22
|
+
line: null,
|
|
23
|
+
column: null,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
28
|
+
yaml.load(content); // Will throw if invalid
|
|
29
|
+
|
|
30
|
+
return { valid: true };
|
|
31
|
+
} catch (error) {
|
|
32
|
+
return {
|
|
33
|
+
valid: false,
|
|
34
|
+
error: error.message,
|
|
35
|
+
line: error.mark?.line ? error.mark.line + 1 : null, // Convert to 1-based
|
|
36
|
+
column: error.mark?.column ? error.mark.column + 1 : null, // Convert to 1-based
|
|
37
|
+
snippet: error.mark?.snippet || null,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Validate YAML syntax for multiple files
|
|
44
|
+
* @param {string[]} filePaths - Array of file paths to validate
|
|
45
|
+
* @returns {Object} Validation results with summary
|
|
46
|
+
*/
|
|
47
|
+
function validateYamlFiles(filePaths) {
|
|
48
|
+
const results = {
|
|
49
|
+
valid: true,
|
|
50
|
+
files: [],
|
|
51
|
+
errors: [],
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
for (const filePath of filePaths) {
|
|
55
|
+
const validation = validateYamlSyntax(filePath);
|
|
56
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
57
|
+
|
|
58
|
+
results.files.push({
|
|
59
|
+
path: relativePath,
|
|
60
|
+
...validation,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (!validation.valid) {
|
|
64
|
+
results.valid = false;
|
|
65
|
+
results.errors.push({
|
|
66
|
+
file: relativePath,
|
|
67
|
+
error: validation.error,
|
|
68
|
+
line: validation.line,
|
|
69
|
+
column: validation.column,
|
|
70
|
+
snippet: validation.snippet,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return results;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Find all YAML files in .caws directory
|
|
80
|
+
* @param {string} projectRoot - Project root directory
|
|
81
|
+
* @returns {string[]} Array of YAML file paths
|
|
82
|
+
*/
|
|
83
|
+
function findCawsYamlFiles(projectRoot) {
|
|
84
|
+
const cawsDir = path.join(projectRoot, '.caws');
|
|
85
|
+
const yamlFiles = [];
|
|
86
|
+
|
|
87
|
+
if (!fs.existsSync(cawsDir)) {
|
|
88
|
+
return yamlFiles;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function walkDir(dir) {
|
|
92
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
93
|
+
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
const fullPath = path.join(dir, entry.name);
|
|
96
|
+
|
|
97
|
+
if (entry.isDirectory()) {
|
|
98
|
+
walkDir(fullPath);
|
|
99
|
+
} else if (
|
|
100
|
+
entry.isFile() &&
|
|
101
|
+
(entry.name.endsWith('.yaml') || entry.name.endsWith('.yml'))
|
|
102
|
+
) {
|
|
103
|
+
yamlFiles.push(fullPath);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
walkDir(cawsDir);
|
|
109
|
+
return yamlFiles;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Validate all CAWS YAML files in project
|
|
114
|
+
* @param {string} projectRoot - Project root directory
|
|
115
|
+
* @returns {Object} Validation results
|
|
116
|
+
*/
|
|
117
|
+
function validateAllCawsYamlFiles(projectRoot) {
|
|
118
|
+
const yamlFiles = findCawsYamlFiles(projectRoot);
|
|
119
|
+
return validateYamlFiles(yamlFiles);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Format validation error for display
|
|
124
|
+
* @param {Object} error - Error object from validateYamlSyntax
|
|
125
|
+
* @param {string} filePath - File path
|
|
126
|
+
* @returns {string} Formatted error message
|
|
127
|
+
*/
|
|
128
|
+
function formatYamlError(error, filePath) {
|
|
129
|
+
const relativePath = path.relative(process.cwd(), filePath);
|
|
130
|
+
let message = `❌ Invalid YAML in ${relativePath}\n`;
|
|
131
|
+
message += ` Error: ${error.error}\n`;
|
|
132
|
+
|
|
133
|
+
if (error.line !== null) {
|
|
134
|
+
message += ` Line: ${error.line}`;
|
|
135
|
+
if (error.column !== null) {
|
|
136
|
+
message += `, Column: ${error.column}`;
|
|
137
|
+
}
|
|
138
|
+
message += '\n';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (error.snippet) {
|
|
142
|
+
message += ` ${error.snippet}\n`;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return message;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
module.exports = {
|
|
149
|
+
validateYamlSyntax,
|
|
150
|
+
validateYamlFiles,
|
|
151
|
+
findCawsYamlFiles,
|
|
152
|
+
validateAllCawsYamlFiles,
|
|
153
|
+
formatYamlError,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
|
|
@@ -238,6 +238,42 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
// Validate scope.out doesn't contain glob patterns
|
|
242
|
+
if (spec.scope && spec.scope.out && Array.isArray(spec.scope.out)) {
|
|
243
|
+
const globPatterns = spec.scope.out.filter(
|
|
244
|
+
(pattern) => pattern.includes('*') || pattern.includes('?')
|
|
245
|
+
);
|
|
246
|
+
if (globPatterns.length > 0) {
|
|
247
|
+
errors.push({
|
|
248
|
+
instancePath: '/scope/out',
|
|
249
|
+
message: `Unsupported glob patterns in scope.out: ${globPatterns.join(', ')}`,
|
|
250
|
+
suggestion:
|
|
251
|
+
'Use directory paths only (e.g., __pycache__/ instead of *.pyc or **/*.pyc). Python cache files are already covered by __pycache__/',
|
|
252
|
+
canAutoFix: true,
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Auto-fix: remove glob patterns and keep only directory paths
|
|
256
|
+
if (autoFix) {
|
|
257
|
+
const fixedOut = spec.scope.out
|
|
258
|
+
.filter((pattern) => !pattern.includes('*') && !pattern.includes('?'))
|
|
259
|
+
.map((pattern) => {
|
|
260
|
+
// Ensure directory paths end with /
|
|
261
|
+
if (!pattern.includes('.') && !pattern.endsWith('/')) {
|
|
262
|
+
return pattern + '/';
|
|
263
|
+
}
|
|
264
|
+
return pattern;
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
fixes.push({
|
|
268
|
+
field: 'scope.out',
|
|
269
|
+
value: fixedOut,
|
|
270
|
+
description: `Removed glob patterns from scope.out: ${globPatterns.join(', ')}`,
|
|
271
|
+
reason: 'Glob patterns are not supported in scope.out',
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
241
277
|
// Auto-fix missing scope.out
|
|
242
278
|
if (spec.scope && !spec.scope.out) {
|
|
243
279
|
fixes.push({
|
|
@@ -329,7 +365,7 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
|
|
|
329
365
|
const suggestion = isChoreMode
|
|
330
366
|
? 'For infrastructure/setup work, add a minimal project_setup contract or create a waiver'
|
|
331
367
|
: 'Add API contracts (OpenAPI, GraphQL, etc.) or change mode to "chore" for maintenance work';
|
|
332
|
-
|
|
368
|
+
|
|
333
369
|
errors.push({
|
|
334
370
|
instancePath: '/contracts',
|
|
335
371
|
message: `Contracts required for Tier ${spec.risk_tier} changes`,
|
|
@@ -341,7 +377,8 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
|
|
|
341
377
|
{
|
|
342
378
|
type: 'project_setup',
|
|
343
379
|
path: '.caws/working-spec.yaml',
|
|
344
|
-
description:
|
|
380
|
+
description:
|
|
381
|
+
'Project-level CAWS configuration. Feature-specific contracts will be added as features are developed.',
|
|
345
382
|
},
|
|
346
383
|
],
|
|
347
384
|
}
|
|
@@ -392,6 +429,48 @@ function validateWorkingSpecWithSuggestions(spec, options = {}) {
|
|
|
392
429
|
}
|
|
393
430
|
}
|
|
394
431
|
|
|
432
|
+
// Validate rollback format if present (for all tiers)
|
|
433
|
+
if (spec.rollback !== undefined) {
|
|
434
|
+
if (!Array.isArray(spec.rollback)) {
|
|
435
|
+
errors.push({
|
|
436
|
+
instancePath: '/rollback',
|
|
437
|
+
message: 'rollback must be an array of strings',
|
|
438
|
+
suggestion: 'Use format: ["Step 1", "Step 2", "Step 3"]',
|
|
439
|
+
canAutoFix: false,
|
|
440
|
+
});
|
|
441
|
+
} else {
|
|
442
|
+
// Check for duplicates
|
|
443
|
+
const uniqueSteps = [...new Set(spec.rollback)];
|
|
444
|
+
if (uniqueSteps.length !== spec.rollback.length) {
|
|
445
|
+
warnings.push({
|
|
446
|
+
instancePath: '/rollback',
|
|
447
|
+
message: 'Duplicate entries found in rollback array',
|
|
448
|
+
suggestion: 'Remove duplicate entries',
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
if (autoFix) {
|
|
452
|
+
fixes.push({
|
|
453
|
+
field: 'rollback',
|
|
454
|
+
value: uniqueSteps,
|
|
455
|
+
description: 'Removed duplicate rollback entries',
|
|
456
|
+
reason: 'Duplicate entries detected',
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Validate each entry is a string
|
|
462
|
+
const invalidEntries = spec.rollback.filter((entry) => typeof entry !== 'string');
|
|
463
|
+
if (invalidEntries.length > 0) {
|
|
464
|
+
errors.push({
|
|
465
|
+
instancePath: '/rollback',
|
|
466
|
+
message: `Invalid rollback entries (must be strings): ${invalidEntries.length}`,
|
|
467
|
+
suggestion: 'All rollback entries must be string descriptions',
|
|
468
|
+
canAutoFix: false,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
395
474
|
// Validate waiver_ids format if present
|
|
396
475
|
if (spec.waiver_ids) {
|
|
397
476
|
if (!Array.isArray(spec.waiver_ids)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@paths.design/caws-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
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,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
|
+
|