@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
@@ -1,305 +0,0 @@
1
- /**
2
- * CAWS Validator
3
- * Shared validation utilities for working specs, provenance, and other data
4
- *
5
- * @author @darianrosebrook
6
- */
7
-
8
- import * as fs from 'fs';
9
- import * as path from 'path';
10
- import Ajv from 'ajv';
11
- import yaml from 'js-yaml';
12
- import { ValidationResult, ContractValidationResult } from './types.js';
13
- import { CawsBaseTool } from './base-tool.js';
14
-
15
- export class CawsValidator extends CawsBaseTool {
16
- private ajv: Ajv;
17
-
18
- constructor() {
19
- super();
20
- this.ajv = new Ajv({
21
- allErrors: true,
22
- strict: false,
23
- allowUnionTypes: true,
24
- });
25
- }
26
-
27
- /**
28
- * Validate a working spec file
29
- */
30
- validateWorkingSpec(specPath: string): ValidationResult {
31
- try {
32
- // Read the working spec file
33
- const specContent = fs.readFileSync(specPath, 'utf-8');
34
- let spec: any;
35
-
36
- // Try to parse as YAML first, then JSON
37
- try {
38
- spec = yaml.load(specContent);
39
- } catch {
40
- try {
41
- spec = JSON.parse(specContent);
42
- } catch {
43
- return {
44
- passed: false,
45
- score: 0,
46
- details: {},
47
- errors: ['Invalid JSON/YAML format in working spec'],
48
- };
49
- }
50
- }
51
-
52
- // Load schema if available
53
- const schemaPath = path.join(this.getCawsDirectory(), 'schemas/working-spec.schema.json');
54
-
55
- if (fs.existsSync(schemaPath)) {
56
- const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
57
- const schema = JSON.parse(schemaContent);
58
-
59
- // Validate against schema
60
- const validate = this.ajv.compile(schema);
61
- const valid = validate(spec);
62
-
63
- if (!valid) {
64
- return {
65
- passed: false,
66
- errors: validate.errors?.map((err) => `${err.instancePath}: ${err.message}`) || [],
67
- score: 0,
68
- details: {},
69
- };
70
- }
71
- }
72
-
73
- // Additional business logic validations
74
- const warnings: string[] = [];
75
-
76
- // Check risk tier thresholds
77
- if (spec.risk_tier === 1 && spec.acceptance?.length < 5) {
78
- warnings.push('Tier 1 specs should have at least 5 acceptance criteria');
79
- }
80
-
81
- if (spec.risk_tier === 2 && spec.contracts?.length === 0) {
82
- warnings.push('Tier 2 specs should have contract definitions');
83
- }
84
-
85
- // Check for required non-functional requirements
86
- const requiredNonFunctional = ['perf'];
87
- const missingNonFunctional = requiredNonFunctional.filter(
88
- (req) => !spec.non_functional?.[req]
89
- );
90
-
91
- if (missingNonFunctional.length > 0) {
92
- warnings.push(`Missing non-functional requirements: ${missingNonFunctional.join(', ')}`);
93
- }
94
-
95
- return {
96
- passed: true,
97
- score: 1,
98
- details: {},
99
- warnings: warnings.length > 0 ? warnings : undefined,
100
- };
101
- } catch (error) {
102
- return {
103
- passed: false,
104
- score: 0,
105
- details: {},
106
- errors: [`Validation failed: ${error}`],
107
- };
108
- }
109
- }
110
-
111
- /**
112
- * Validate a provenance file
113
- */
114
- validateProvenance(provenancePath: string): ValidationResult {
115
- try {
116
- const provenanceContent = fs.readFileSync(provenancePath, 'utf-8');
117
- const provenance = JSON.parse(provenanceContent);
118
-
119
- // Basic structure validation
120
- const requiredFields = ['agent', 'model', 'commit', 'artifacts', 'results', 'approvals'];
121
- const missingFields = requiredFields.filter((field) => !provenance[field]);
122
-
123
- if (missingFields.length > 0) {
124
- return {
125
- passed: false,
126
- score: 0,
127
- details: {},
128
- errors: [`Missing required fields: ${missingFields.join(', ')}`],
129
- };
130
- }
131
-
132
- // Validate results structure
133
- const requiredResults = ['coverage_branch', 'mutation_score', 'tests_passed'];
134
- const missingResults = requiredResults.filter(
135
- (field) => typeof provenance.results[field] !== 'number'
136
- );
137
-
138
- if (missingResults.length > 0) {
139
- return {
140
- passed: false,
141
- score: 0,
142
- details: {},
143
- errors: [`Missing numeric results: ${missingResults.join(', ')}`],
144
- };
145
- }
146
-
147
- return {
148
- passed: true,
149
- score: 1,
150
- details: {},
151
- };
152
- } catch (error) {
153
- return {
154
- passed: false,
155
- score: 0,
156
- details: {},
157
- errors: [`Provenance validation failed: ${error}`],
158
- };
159
- }
160
- }
161
-
162
- /**
163
- * Validate a JSON file against a schema
164
- */
165
- validateJsonAgainstSchema(jsonPath: string, schemaPath: string): ValidationResult {
166
- try {
167
- // Read JSON file
168
- const jsonContent = fs.readFileSync(jsonPath, 'utf-8');
169
- const jsonData = JSON.parse(jsonContent);
170
-
171
- // Read schema file
172
- const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
173
- const schema = JSON.parse(schemaContent);
174
-
175
- // Validate
176
- const validate = this.ajv.compile(schema);
177
- const valid = validate(jsonData);
178
-
179
- if (!valid) {
180
- return {
181
- passed: false,
182
- score: 0,
183
- details: {},
184
- errors: validate.errors?.map((err) => `${err.instancePath}: ${err.message}`) || [],
185
- };
186
- }
187
-
188
- return {
189
- passed: true,
190
- score: 1,
191
- details: {},
192
- };
193
- } catch (error) {
194
- return {
195
- passed: false,
196
- score: 0,
197
- details: {},
198
- errors: [`Schema validation failed: ${error}`],
199
- };
200
- }
201
- }
202
-
203
- /**
204
- * Validate a YAML file against a schema
205
- */
206
- validateYamlAgainstSchema(yamlPath: string, schemaPath: string): ValidationResult {
207
- try {
208
- // Read YAML file
209
- const yamlContent = fs.readFileSync(yamlPath, 'utf-8');
210
- const yamlData = yaml.load(yamlContent);
211
-
212
- // Read schema file
213
- const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
214
- const schema = JSON.parse(schemaContent);
215
-
216
- // Validate
217
- const validate = this.ajv.compile(schema);
218
- const valid = validate(yamlData);
219
-
220
- if (!valid) {
221
- return {
222
- passed: false,
223
- score: 0,
224
- details: {},
225
- errors: validate.errors?.map((err) => `${err.instancePath}: ${err.message}`) || [],
226
- };
227
- }
228
-
229
- return {
230
- passed: true,
231
- score: 1,
232
- details: {},
233
- };
234
- } catch (error) {
235
- return {
236
- passed: false,
237
- score: 0,
238
- details: {},
239
- errors: [`YAML schema validation failed: ${error}`],
240
- };
241
- }
242
- }
243
-
244
- /**
245
- * Validate file exists and is readable
246
- */
247
- validateFileExists(filePath: string): ValidationResult {
248
- try {
249
- if (!fs.existsSync(filePath)) {
250
- return {
251
- passed: false,
252
- score: 0,
253
- details: {},
254
- errors: [`File not found: ${filePath}`],
255
- };
256
- }
257
-
258
- // Try to read the file
259
- fs.accessSync(filePath, fs.constants.R_OK);
260
- return {
261
- passed: true,
262
- score: 1,
263
- details: {},
264
- };
265
- } catch {
266
- return {
267
- passed: false,
268
- score: 0,
269
- details: {},
270
- errors: [`File not readable: ${filePath}`],
271
- };
272
- }
273
- }
274
-
275
- /**
276
- * Validate directory exists and is writable
277
- */
278
- validateDirectoryExists(dirPath: string): ValidationResult {
279
- try {
280
- if (!fs.existsSync(dirPath)) {
281
- return {
282
- passed: false,
283
- score: 0,
284
- details: {},
285
- errors: [`Directory not found: ${dirPath}`],
286
- };
287
- }
288
-
289
- // Try to write to the directory
290
- fs.accessSync(dirPath, fs.constants.W_OK);
291
- return {
292
- passed: true,
293
- score: 1,
294
- details: {},
295
- };
296
- } catch {
297
- return {
298
- passed: false,
299
- score: 0,
300
- details: {},
301
- errors: [`Directory not writable: ${dirPath}`],
302
- };
303
- }
304
- }
305
- }
@@ -1,174 +0,0 @@
1
- /**
2
- * CAWS Waivers Manager
3
- * TypeScript wrapper for waivers management functionality
4
- *
5
- * @author @darianrosebrook
6
- */
7
-
8
- import * as fs from 'fs';
9
- import * as path from 'path';
10
- import yaml from 'js-yaml';
11
- import { WaiverConfig } from './types.js';
12
- import { CawsBaseTool } from './base-tool.js';
13
-
14
- export class WaiversManager extends CawsBaseTool {
15
- private readonly waiversPath: string;
16
-
17
- constructor(waiversPath?: string) {
18
- super();
19
- this.waiversPath = waiversPath || path.join(this.getCawsDirectory(), 'waivers.yml');
20
- }
21
-
22
- /**
23
- * Load waivers configuration
24
- */
25
- private loadWaiversConfig(): { waivers: WaiverConfig[] } {
26
- try {
27
- if (!fs.existsSync(this.waiversPath)) {
28
- return { waivers: [] };
29
- }
30
-
31
- const content = fs.readFileSync(this.waiversPath, 'utf8');
32
- return yaml.load(content) as { waivers: WaiverConfig[] };
33
- } catch (error) {
34
- this.logError(`Error loading waivers config: ${error}`);
35
- return { waivers: [] };
36
- }
37
- }
38
-
39
- /**
40
- * Save waivers configuration
41
- */
42
- private saveWaiversConfig(config: { waivers: WaiverConfig[] }): void {
43
- try {
44
- const yamlContent = yaml.dump(config, { indent: 2 });
45
- fs.writeFileSync(this.waiversPath, yamlContent);
46
- this.logSuccess(`Waivers configuration saved to ${this.waiversPath}`);
47
- } catch (error) {
48
- this.logError(`Error saving waivers config: ${error}`);
49
- throw error;
50
- }
51
- }
52
-
53
- /**
54
- * Get all waivers for a specific gate
55
- */
56
- async getWaiversByGate(gate: string): Promise<WaiverConfig[]> {
57
- const config = this.loadWaiversConfig();
58
- const now = new Date();
59
-
60
- return config.waivers.filter((waiver) => {
61
- // Check if waiver covers this gate
62
- if (waiver.gate !== gate) {
63
- return false;
64
- }
65
-
66
- // Check if waiver is still active
67
- const expiresAt = new Date(waiver.expiry);
68
- if (now > expiresAt) {
69
- return false;
70
- }
71
-
72
- return waiver.status === 'active';
73
- });
74
- }
75
-
76
- /**
77
- * Check waiver status
78
- */
79
- async checkWaiverStatus(waiverId: string): Promise<{
80
- active: boolean;
81
- waiver?: WaiverConfig;
82
- reason?: string;
83
- }> {
84
- const config = this.loadWaiversConfig();
85
- const now = new Date();
86
-
87
- const waiver = config.waivers.find((w) => w.created_at === waiverId);
88
-
89
- if (!waiver) {
90
- return { active: false, reason: 'Waiver not found' };
91
- }
92
-
93
- const expiresAt = new Date(waiver.expiry);
94
- if (now > expiresAt) {
95
- return { active: false, waiver, reason: 'Waiver expired' };
96
- }
97
-
98
- if (waiver.status !== 'active') {
99
- return { active: false, waiver, reason: `Waiver status: ${waiver.status}` };
100
- }
101
-
102
- return { active: true, waiver };
103
- }
104
-
105
- /**
106
- * Create a new waiver
107
- */
108
- async createWaiver(waiver: Omit<WaiverConfig, 'created_at'>): Promise<void> {
109
- const config = this.loadWaiversConfig();
110
-
111
- const newWaiver: WaiverConfig = {
112
- ...waiver,
113
- created_at: new Date().toISOString(),
114
- };
115
-
116
- config.waivers.push(newWaiver);
117
- this.saveWaiversConfig(config);
118
- }
119
-
120
- /**
121
- * Revoke a waiver
122
- */
123
- async revokeWaiver(gate: string, owner: string): Promise<void> {
124
- const config = this.loadWaiversConfig();
125
-
126
- const waiver = config.waivers.find(
127
- (w) => w.gate === gate && w.owner === owner && w.status === 'active'
128
- );
129
-
130
- if (waiver) {
131
- waiver.status = 'revoked';
132
- this.saveWaiversConfig(config);
133
- this.logSuccess(`Revoked waiver for gate: ${gate}`);
134
- } else {
135
- this.logWarning(`No active waiver found for gate: ${gate}`);
136
- }
137
- }
138
-
139
- /**
140
- * Cleanup expired waivers
141
- */
142
- async cleanupExpiredWaivers(): Promise<number> {
143
- const config = this.loadWaiversConfig();
144
- const now = new Date();
145
-
146
- const activeWaivers = config.waivers.filter((waiver) => {
147
- const expiresAt = new Date(waiver.expiry);
148
- return now <= expiresAt;
149
- });
150
-
151
- const removedCount = config.waivers.length - activeWaivers.length;
152
-
153
- if (removedCount > 0) {
154
- config.waivers = activeWaivers;
155
- this.saveWaiversConfig(config);
156
- this.logSuccess(`Cleaned up ${removedCount} expired waiver(s)`);
157
- }
158
-
159
- return removedCount;
160
- }
161
-
162
- /**
163
- * List all active waivers
164
- */
165
- async listActiveWaivers(): Promise<WaiverConfig[]> {
166
- const config = this.loadWaiversConfig();
167
- const now = new Date();
168
-
169
- return config.waivers.filter((waiver) => {
170
- const expiresAt = new Date(waiver.expiry);
171
- return now <= expiresAt && waiver.status === 'active';
172
- });
173
- }
174
- }