@paths.design/caws-cli 7.0.1 → 7.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +26 -20
  3. package/dist/commands/init.js +72 -5
  4. package/dist/commands/specs.js +40 -1
  5. package/dist/commands/status.js +2 -2
  6. package/dist/commands/templates.js +10 -0
  7. package/dist/commands/tool.js +2 -3
  8. package/dist/commands/validate.js +12 -0
  9. package/dist/config/index.js +17 -8
  10. package/dist/generators/working-spec.js +42 -9
  11. package/dist/index.js +3 -1
  12. package/dist/scaffold/cursor-hooks.js +10 -2
  13. package/dist/scaffold/git-hooks.js +189 -32
  14. package/dist/scaffold/index.js +105 -17
  15. package/dist/templates/.caws/tools/README.md +20 -0
  16. package/dist/templates/.cursor/README.md +311 -0
  17. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  18. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  19. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  20. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  21. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  22. package/dist/templates/.cursor/hooks/format.sh +38 -0
  23. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  24. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  25. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  26. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  27. package/dist/templates/.cursor/hooks.json +59 -0
  28. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  29. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  30. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  31. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  32. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  33. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  34. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  35. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  36. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  37. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  38. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  39. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  40. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  41. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  42. package/dist/templates/.cursor/rules/README.md +148 -0
  43. package/dist/templates/.github/copilot/instructions.md +311 -0
  44. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  45. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  46. package/dist/templates/.vscode/launch.json +56 -0
  47. package/dist/templates/.vscode/settings.json +93 -0
  48. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  49. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  50. package/dist/templates/OIDC_SETUP.md +300 -0
  51. package/dist/templates/agents.md +1047 -0
  52. package/dist/templates/codemod/README.md +1 -0
  53. package/dist/templates/codemod/test.js +93 -0
  54. package/dist/templates/docs/README.md +150 -0
  55. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  56. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  57. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  58. package/dist/tool-loader.js +6 -1
  59. package/dist/tool-validator.js +8 -2
  60. package/dist/utils/detection.js +34 -6
  61. package/dist/utils/git-lock.js +118 -0
  62. package/dist/utils/gitignore-updater.js +148 -0
  63. package/dist/utils/quality-gates.js +47 -7
  64. package/dist/utils/spec-resolver.js +23 -3
  65. package/dist/utils/yaml-validation.js +155 -0
  66. package/dist/validation/spec-validation.js +105 -2
  67. package/package.json +2 -2
  68. package/templates/.caws/schemas/waivers.schema.json +30 -0
  69. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  70. package/templates/.caws/templates/working-spec.template.yml +74 -0
  71. package/templates/.caws/tools/README.md +20 -0
  72. package/templates/.caws/tools/scope-guard.js +208 -0
  73. package/templates/.caws/tools-allow.json +331 -0
  74. package/templates/.caws/waivers.yml +19 -0
  75. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  76. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  77. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  78. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  79. package/templates/apps/tools/caws/README.md +0 -463
  80. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  81. package/templates/apps/tools/caws/attest.js +0 -357
  82. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  83. package/templates/apps/tools/caws/config.ts +0 -245
  84. package/templates/apps/tools/caws/cross-functional.js +0 -876
  85. package/templates/apps/tools/caws/dashboard.js +0 -1112
  86. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  87. package/templates/apps/tools/caws/gates.js +0 -198
  88. package/templates/apps/tools/caws/gates.ts +0 -271
  89. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  90. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  91. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  92. package/templates/apps/tools/caws/language-support.js +0 -585
  93. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  94. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  95. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  96. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  97. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  98. package/templates/apps/tools/caws/property-testing.js +0 -707
  99. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  100. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  101. package/templates/apps/tools/caws/provenance.js +0 -132
  102. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  103. package/templates/apps/tools/caws/provenance.ts +0 -211
  104. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  105. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  106. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  107. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  108. package/templates/apps/tools/caws/shared/types.ts +0 -444
  109. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  110. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  111. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  112. package/templates/apps/tools/caws/test-quality.js +0 -578
  113. package/templates/apps/tools/caws/validate.js +0 -76
  114. package/templates/apps/tools/caws/validate.ts +0 -228
  115. package/templates/apps/tools/caws/waivers.js +0 -344
  116. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  117. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  118. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  119. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  120. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  121. /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
@@ -1,228 +0,0 @@
1
- #!/usr/bin/env tsx
2
-
3
- /**
4
- * CAWS Validation Tool
5
- * CLI wrapper for CawsValidator with schema validation
6
- *
7
- * @author @darianrosebrook
8
- */
9
-
10
- import * as path from 'path';
11
- import { CawsValidator } from './shared/validator.js';
12
- import { ValidationResult } from './shared/types.js';
13
-
14
- class ValidateCLI {
15
- private validator: CawsValidator;
16
-
17
- constructor() {
18
- this.validator = new CawsValidator();
19
- }
20
-
21
- /**
22
- * Validate a working specification file
23
- */
24
- validateWorkingSpec(specPath: string): ValidationResult {
25
- try {
26
- const result = this.validator.validateWorkingSpec(specPath);
27
-
28
- if (result.passed) {
29
- console.log('✅ Working specification is valid');
30
- console.log(` Score: ${(result.score * 100).toFixed(0)}%`);
31
-
32
- if (result.warnings && result.warnings.length > 0) {
33
- console.log('\n⚠️ Warnings:');
34
- result.warnings.forEach((warning) => console.log(` - ${warning}`));
35
- }
36
-
37
- if (result.details) {
38
- console.log('\n📊 Details:');
39
- if (result.details.risk_tier) {
40
- console.log(` Tier: ${result.details.risk_tier}`);
41
- }
42
- if (result.details.acceptance_count) {
43
- console.log(` Acceptance Criteria: ${result.details.acceptance_count}`);
44
- }
45
- if (result.details.contract_count) {
46
- console.log(` Contracts: ${result.details.contract_count}`);
47
- }
48
- }
49
- } else {
50
- console.error('❌ Working specification is invalid:');
51
- if (result.errors && result.errors.length > 0) {
52
- result.errors.forEach((error) => console.error(` - ${error}`));
53
- }
54
- }
55
-
56
- return result;
57
- } catch (error) {
58
- console.error(`❌ Validation failed: ${error}`);
59
- return {
60
- passed: false,
61
- errors: [`Validation error: ${error}`],
62
- score: 0,
63
- details: {},
64
- };
65
- }
66
- }
67
-
68
- /**
69
- * Validate a provenance file
70
- */
71
- validateProvenance(provenancePath: string): ValidationResult {
72
- try {
73
- const result = this.validator.validateProvenance(provenancePath);
74
-
75
- if (result.passed) {
76
- console.log('✅ Provenance file is valid');
77
- console.log(` Score: ${(result.score * 100).toFixed(0)}%`);
78
-
79
- if (result.details) {
80
- console.log('\n📊 Provenance Details:');
81
- if (result.details.agent) {
82
- console.log(` Agent: ${result.details.agent}`);
83
- }
84
- if (result.details.model) {
85
- console.log(` Model: ${result.details.model}`);
86
- }
87
- if (result.details.commit) {
88
- console.log(` Commit: ${result.details.commit}`);
89
- }
90
- }
91
- } else {
92
- console.error('❌ Provenance file is invalid:');
93
- if (result.errors && result.errors.length > 0) {
94
- result.errors.forEach((error) => console.error(` - ${error}`));
95
- }
96
- }
97
-
98
- return result;
99
- } catch (error) {
100
- console.error(`❌ Provenance validation failed: ${error}`);
101
- return {
102
- passed: false,
103
- errors: [`Validation error: ${error}`],
104
- score: 0,
105
- details: {},
106
- };
107
- }
108
- }
109
-
110
- /**
111
- * Validate a JSON file against a schema
112
- */
113
- validateJsonSchema(jsonPath: string, schemaPath: string): ValidationResult {
114
- try {
115
- const result = this.validator.validateJsonAgainstSchema(jsonPath, schemaPath);
116
-
117
- if (result.passed) {
118
- console.log('✅ JSON file is valid against schema');
119
- } else {
120
- console.error('❌ JSON file is invalid:');
121
- if (result.errors && result.errors.length > 0) {
122
- result.errors.forEach((error) => console.error(` - ${error}`));
123
- }
124
- }
125
-
126
- return result;
127
- } catch (error) {
128
- console.error(`❌ Schema validation failed: ${error}`);
129
- return {
130
- passed: false,
131
- errors: [`Validation error: ${error}`],
132
- score: 0,
133
- details: {},
134
- };
135
- }
136
- }
137
-
138
- /**
139
- * Validate a YAML file against a schema
140
- */
141
- validateYamlSchema(yamlPath: string, schemaPath: string): ValidationResult {
142
- try {
143
- const result = this.validator.validateYamlAgainstSchema(yamlPath, schemaPath);
144
-
145
- if (result.passed) {
146
- console.log('✅ YAML file is valid against schema');
147
- } else {
148
- console.error('❌ YAML file is invalid:');
149
- if (result.errors && result.errors.length > 0) {
150
- result.errors.forEach((error) => console.error(` - ${error}`));
151
- }
152
- }
153
-
154
- return result;
155
- } catch (error) {
156
- console.error(`❌ Schema validation failed: ${error}`);
157
- return {
158
- passed: false,
159
- errors: [`Validation error: ${error}`],
160
- score: 0,
161
- details: {},
162
- };
163
- }
164
- }
165
- }
166
-
167
- // Main CLI handler
168
- if (import.meta.url === `file://${process.argv[1]}`) {
169
- const command = process.argv[2];
170
- const cli = new ValidateCLI();
171
-
172
- switch (command) {
173
- case 'spec': {
174
- const specPath = process.argv[3] || '.caws/working-spec.yaml';
175
- const result = cli.validateWorkingSpec(specPath);
176
- process.exit(result.passed ? 0 : 1);
177
- }
178
-
179
- case 'provenance': {
180
- const provenancePath = process.argv[3] || '.agent/provenance.json';
181
- const result = cli.validateProvenance(provenancePath);
182
- process.exit(result.passed ? 0 : 1);
183
- }
184
-
185
- case 'json': {
186
- const jsonPath = process.argv[3];
187
- const schemaPath = process.argv[4];
188
-
189
- if (!jsonPath || !schemaPath) {
190
- console.error('Usage: validate.ts json <json-file> <schema-file>');
191
- process.exit(1);
192
- }
193
-
194
- const result = cli.validateJsonSchema(jsonPath, schemaPath);
195
- process.exit(result.passed ? 0 : 1);
196
- }
197
-
198
- case 'yaml': {
199
- const yamlPath = process.argv[3];
200
- const schemaPath = process.argv[4];
201
-
202
- if (!yamlPath || !schemaPath) {
203
- console.error('Usage: validate.ts yaml <yaml-file> <schema-file>');
204
- process.exit(1);
205
- }
206
-
207
- const result = cli.validateYamlSchema(yamlPath, schemaPath);
208
- process.exit(result.passed ? 0 : 1);
209
- }
210
-
211
- default:
212
- console.log('CAWS Validation Tool');
213
- console.log('');
214
- console.log('Commands:');
215
- console.log(' spec [path] - Validate working specification');
216
- console.log(' provenance [path] - Validate provenance file');
217
- console.log(' json <file> <schema> - Validate JSON against schema');
218
- console.log(' yaml <file> <schema> - Validate YAML against schema');
219
- console.log('');
220
- console.log('Examples:');
221
- console.log(' validate.ts spec .caws/working-spec.yaml');
222
- console.log(' validate.ts provenance .agent/provenance.json');
223
- console.log(' validate.ts yaml .caws/waivers.yml schemas/waivers.schema.json');
224
- process.exit(1);
225
- }
226
- }
227
-
228
- export { ValidateCLI };
@@ -1,344 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * @fileoverview CAWS Waivers Management Tool
5
- * Manages time-boxed waivers for quality gates
6
- * @author @darianrosebrook
7
- */
8
-
9
- const fs = require('fs');
10
- const yaml = require('js-yaml');
11
-
12
- /**
13
- * Waiver reasons enum
14
- */
15
- const WAIVER_REASONS = {
16
- URGENT_FIX: 'urgent_fix',
17
- EXPERIMENTAL: 'experimental',
18
- LEGACY_CODE: 'legacy_code',
19
- RESOURCE_CONSTRAINTS: 'resource_constraints',
20
- OTHER: 'other',
21
- };
22
-
23
- /**
24
- * Waivable gates
25
- */
26
- const WAIVABLE_GATES = ['coverage', 'mutation', 'contracts', 'manual_review', 'trust_score'];
27
-
28
- /**
29
- * Load waivers configuration
30
- * @param {string} waiversPath - Path to waivers.yml file
31
- * @returns {Object} Parsed waivers configuration
32
- */
33
- function loadWaiversConfig(waiversPath = '.caws/waivers.yml') {
34
- try {
35
- if (!fs.existsSync(waiversPath)) {
36
- return { waivers: [] };
37
- }
38
-
39
- const content = fs.readFileSync(waiversPath, 'utf8');
40
- return yaml.load(content);
41
- } catch (error) {
42
- console.error('❌ Error loading waivers config:', error.message);
43
- return { waivers: [] };
44
- }
45
- }
46
-
47
- /**
48
- * Save waivers configuration
49
- * @param {Object} config - Waivers configuration
50
- * @param {string} waiversPath - Path to save waivers.yml file
51
- */
52
- function saveWaiversConfig(config, waiversPath = '.caws/waivers.yml') {
53
- try {
54
- const yamlContent = yaml.dump(config, { indent: 2 });
55
- fs.writeFileSync(waiversPath, yamlContent);
56
- console.log(`✅ Waivers configuration saved to ${waiversPath}`);
57
- } catch (error) {
58
- console.error('❌ Error saving waivers config:', error.message);
59
- process.exit(1);
60
- }
61
- }
62
-
63
- /**
64
- * Find active waivers for a project and gate
65
- * @param {string} projectId - Project identifier
66
- * @param {string} gate - Gate to check
67
- * @param {string} waiversPath - Path to waivers.yml file
68
- * @returns {Array} Active waivers
69
- */
70
- function findActiveWaivers(projectId, gate, waiversPath = '.caws/waivers.yml') {
71
- const config = loadWaiversConfig(waiversPath);
72
- const now = new Date();
73
-
74
- return config.waivers.filter((waiver) => {
75
- const expiresAt = new Date(waiver.expires_at);
76
-
77
- // Filter out expired waivers
78
- if (now > expiresAt) {
79
- console.warn(`⚠️ Waiver ${waiver.id} has expired (${waiver.expires_at})`);
80
- return false;
81
- }
82
-
83
- // Check if project specific
84
- if (waiver.projects && waiver.projects.length > 0) {
85
- if (!waiver.projects.includes(projectId)) {
86
- return false;
87
- }
88
- }
89
-
90
- // Check if gate is waived
91
- return waiver.gates.includes(gate);
92
- });
93
- }
94
-
95
- /**
96
- * Create a new waiver
97
- * @param {Object} options - Waiver options
98
- */
99
- function createWaiver(options) {
100
- const {
101
- id,
102
- description,
103
- gates,
104
- reason,
105
- approver,
106
- expiresInDays = 7,
107
- projects = [],
108
- maxTrustScore = 79,
109
- } = options;
110
-
111
- // Validate inputs
112
- if (!id || !description || !gates || !reason || !approver) {
113
- console.error('❌ Missing required waiver fields');
114
- process.exit(1);
115
- }
116
-
117
- // Validate gates
118
- const invalidGates = gates.filter((gate) => !WAIVABLE_GATES.includes(gate));
119
- if (invalidGates.length > 0) {
120
- console.error(`❌ Invalid gates: ${invalidGates.join(', ')}`);
121
- console.error(`💡 Valid gates: ${WAIVABLE_GATES.join(', ')}`);
122
- process.exit(1);
123
- }
124
-
125
- // Validate reason
126
- if (!Object.values(WAIVER_REASONS).includes(reason)) {
127
- console.error(`❌ Invalid reason: ${reason}`);
128
- console.error(`💡 Valid reasons: ${Object.values(WAIVER_REASONS).join(', ')}`);
129
- process.exit(1);
130
- }
131
-
132
- const expiresAt = new Date();
133
- expiresAt.setDate(expiresAt.getDate() + expiresInDays);
134
-
135
- const waiver = {
136
- id,
137
- description,
138
- gates,
139
- reason,
140
- approver,
141
- expires_at: expiresAt.toISOString(),
142
- projects,
143
- max_trust_score: maxTrustScore,
144
- };
145
-
146
- // Load existing waivers
147
- const config = loadWaiversConfig();
148
-
149
- // Check for duplicate ID
150
- const existingWaiver = config.waivers.find((w) => w.id === id);
151
- if (existingWaiver) {
152
- console.error(`❌ Waiver with ID ${id} already exists`);
153
- process.exit(1);
154
- }
155
-
156
- // Add new waiver
157
- config.waivers.push(waiver);
158
-
159
- // Save configuration
160
- saveWaiversConfig(config);
161
-
162
- console.log(`✅ Created waiver ${id}`);
163
- console.log(` Description: ${description}`);
164
- console.log(` Gates: ${gates.join(', ')}`);
165
- console.log(` Reason: ${reason}`);
166
- console.log(` Expires: ${expiresAt.toISOString()}`);
167
- if (projects.length > 0) {
168
- console.log(` Projects: ${projects.join(', ')}`);
169
- }
170
- console.log(` Max Trust Score: ${maxTrustScore}`);
171
- }
172
-
173
- /**
174
- * List all waivers
175
- * @param {string} waiversPath - Path to waivers.yml file
176
- */
177
- function listWaivers(waiversPath = '.caws/waivers.yml') {
178
- const config = loadWaiversConfig(waiversPath);
179
-
180
- if (config.waivers.length === 0) {
181
- console.log('ℹ️ No waivers configured');
182
- return;
183
- }
184
-
185
- console.log('📋 Active Waivers:');
186
- const now = new Date();
187
-
188
- config.waivers.forEach((waiver) => {
189
- const expiresAt = new Date(waiver.expires_at);
190
- const isExpired = now > expiresAt;
191
- const status = isExpired ? '🔴 EXPIRED' : '🟢 ACTIVE';
192
- const daysLeft = Math.ceil((expiresAt - now) / (1000 * 60 * 60 * 24));
193
-
194
- console.log(`\n${status} Waiver: ${waiver.id}`);
195
- console.log(` Description: ${waiver.description}`);
196
- console.log(` Gates: ${waiver.gates.join(', ')}`);
197
- console.log(` Reason: ${waiver.reason}`);
198
- console.log(` Approver: ${waiver.approver}`);
199
- console.log(` Expires: ${waiver.expires_at} (${daysLeft} days)`);
200
- if (waiver.projects && waiver.projects.length > 0) {
201
- console.log(` Projects: ${waiver.projects.join(', ')}`);
202
- }
203
- if (waiver.max_trust_score) {
204
- console.log(` Max Trust Score: ${waiver.max_trust_score}`);
205
- }
206
- });
207
- }
208
-
209
- /**
210
- * Remove expired waivers
211
- * @param {string} waiversPath - Path to waivers.yml file
212
- */
213
- function cleanupExpiredWaivers(waiversPath = '.caws/waivers.yml') {
214
- const config = loadWaiversConfig(waiversPath);
215
- const now = new Date();
216
-
217
- const activeWaivers = config.waivers.filter((waiver) => {
218
- const expiresAt = new Date(waiver.expires_at);
219
- return now <= expiresAt;
220
- });
221
-
222
- const removedCount = config.waivers.length - activeWaivers.length;
223
-
224
- if (removedCount > 0) {
225
- config.waivers = activeWaivers;
226
- saveWaiversConfig(config);
227
- console.log(`✅ Cleaned up ${removedCount} expired waiver(s)`);
228
- } else {
229
- console.log('ℹ️ No expired waivers to clean up');
230
- }
231
- }
232
-
233
- /**
234
- * Check if a specific gate is waived for a project
235
- * @param {string} projectId - Project identifier
236
- * @param {string} gate - Gate to check
237
- * @param {string} waiversPath - Path to waivers.yml file
238
- * @returns {Object} Waiver status information
239
- */
240
- function checkWaiverStatus(projectId, gate, waiversPath = '.caws/waivers.yml') {
241
- const activeWaivers = findActiveWaivers(projectId, gate, waiversPath);
242
-
243
- if (activeWaivers.length === 0) {
244
- return {
245
- waived: false,
246
- reason: null,
247
- maxTrustScore: 100,
248
- };
249
- }
250
-
251
- // Find the most restrictive waiver (lowest max trust score)
252
- const applicableWaiver = activeWaivers.reduce((mostRestrictive, waiver) => {
253
- if (
254
- !mostRestrictive ||
255
- (waiver.max_trust_score && waiver.max_trust_score < mostRestrictive.max_trust_score)
256
- ) {
257
- return waiver;
258
- }
259
- return mostRestrictive;
260
- }, null);
261
-
262
- return {
263
- waived: true,
264
- reason: applicableWaiver.reason,
265
- maxTrustScore: applicableWaiver.max_trust_score || 79,
266
- waiverId: applicableWaiver.id,
267
- expiresAt: applicableWaiver.expires_at,
268
- };
269
- }
270
-
271
- // CLI interface
272
- if (require.main === module) {
273
- const command = process.argv[2];
274
-
275
- switch (command) {
276
- case 'create':
277
- createWaiver({
278
- id: process.argv[3],
279
- description: process.argv[4],
280
- gates: process.argv[5]?.split(',') || [],
281
- reason: process.argv[6],
282
- approver: process.argv[7],
283
- expiresInDays: parseInt(process.argv[8]) || 7,
284
- projects: process.argv[9]?.split(',') || [],
285
- maxTrustScore: parseInt(process.argv[10]) || 79,
286
- });
287
- break;
288
-
289
- case 'list':
290
- listWaivers();
291
- break;
292
-
293
- case 'cleanup':
294
- cleanupExpiredWaivers();
295
- break;
296
-
297
- case 'check':
298
- const projectId = process.argv[3];
299
- const gate = process.argv[4];
300
- if (!projectId || !gate) {
301
- console.error('❌ Usage: node waivers.js check <project-id> <gate>');
302
- process.exit(1);
303
- }
304
- const status = checkWaiverStatus(projectId, gate);
305
- console.log(`Waiver status for ${gate} on project ${projectId}:`);
306
- console.log(` Waived: ${status.waived}`);
307
- if (status.waived) {
308
- console.log(` Reason: ${status.reason}`);
309
- console.log(` Max Trust Score: ${status.maxTrustScore}`);
310
- console.log(` Waiver ID: ${status.waiverId}`);
311
- console.log(` Expires: ${status.expiresAt}`);
312
- }
313
- break;
314
-
315
- default:
316
- console.log('CAWS Waivers Management Tool');
317
- console.log('Usage:');
318
- console.log(
319
- ' node waivers.js create <id> <description> <gates> <reason> <approver> [expires-days] [projects] [max-trust-score]'
320
- );
321
- console.log(' node waivers.js list');
322
- console.log(' node waivers.js cleanup');
323
- console.log(' node waivers.js check <project-id> <gate>');
324
- console.log('');
325
- console.log('Examples:');
326
- console.log(
327
- ' node waivers.js create HOTFIX-001 "Urgent security fix" "mutation,coverage" urgent_fix "senior-dev" 3'
328
- );
329
- console.log(' node waivers.js check FEAT-1234 mutation');
330
- process.exit(1);
331
- }
332
- }
333
-
334
- module.exports = {
335
- loadWaiversConfig,
336
- saveWaiversConfig,
337
- findActiveWaivers,
338
- checkWaiverStatus,
339
- createWaiver,
340
- listWaivers,
341
- cleanupExpiredWaivers,
342
- WAIVER_REASONS,
343
- WAIVABLE_GATES,
344
- };