@paths.design/caws-cli 3.0.0 → 3.1.1
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/README.md +295 -150
- package/dist/budget-derivation.d.ts +35 -0
- package/dist/budget-derivation.d.ts.map +1 -0
- package/dist/budget-derivation.js +204 -0
- package/dist/cicd-optimizer.d.ts +142 -0
- package/dist/cicd-optimizer.d.ts.map +1 -0
- package/dist/cicd-optimizer.js +504 -0
- package/dist/commands/burnup.d.ts +6 -0
- package/dist/commands/burnup.d.ts.map +1 -0
- package/dist/commands/burnup.js +90 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +514 -0
- package/dist/commands/provenance.d.ts +22 -0
- package/dist/commands/provenance.d.ts.map +1 -0
- package/dist/commands/provenance.js +594 -0
- package/dist/commands/tool.d.ts +13 -0
- package/dist/commands/tool.d.ts.map +1 -0
- package/dist/commands/tool.js +138 -0
- package/dist/commands/validate.d.ts +7 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +80 -0
- package/dist/config/index.d.ts +29 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +132 -0
- package/dist/error-handler.d.ts +50 -0
- package/dist/error-handler.d.ts.map +1 -0
- package/dist/error-handler.js +253 -0
- package/dist/generators/working-spec.d.ts +13 -0
- package/dist/generators/working-spec.d.ts.map +1 -0
- package/dist/generators/working-spec.js +204 -0
- package/dist/index-new.d.ts +5 -0
- package/dist/index-new.d.ts.map +1 -0
- package/dist/index-new.js +317 -0
- package/dist/index.d.ts +3 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +100 -1659
- package/dist/index.js.backup +4711 -0
- package/dist/scaffold/cursor-hooks.d.ts +7 -0
- package/dist/scaffold/cursor-hooks.d.ts.map +1 -0
- package/dist/scaffold/cursor-hooks.js +152 -0
- package/dist/scaffold/index.d.ts +20 -0
- package/dist/scaffold/index.d.ts.map +1 -0
- package/dist/scaffold/index.js +486 -0
- package/dist/test-analysis.d.ts +182 -0
- package/dist/test-analysis.d.ts.map +1 -0
- package/dist/test-analysis.js +580 -0
- package/dist/tool-interface.d.ts +236 -0
- package/dist/tool-interface.d.ts.map +1 -0
- package/dist/tool-interface.js +314 -0
- package/dist/tool-loader.d.ts +77 -0
- package/dist/tool-loader.d.ts.map +1 -0
- package/dist/tool-loader.js +298 -0
- package/dist/tool-validator.d.ts +72 -0
- package/dist/tool-validator.d.ts.map +1 -0
- package/dist/tool-validator.js +387 -0
- package/dist/utils/detection.d.ts +7 -0
- package/dist/utils/detection.d.ts.map +1 -0
- package/dist/utils/detection.js +174 -0
- package/dist/utils/finalization.d.ts +17 -0
- package/dist/utils/finalization.d.ts.map +1 -0
- package/dist/utils/finalization.js +229 -0
- package/dist/utils/project-analysis.d.ts +14 -0
- package/dist/utils/project-analysis.d.ts.map +1 -0
- package/dist/utils/project-analysis.js +105 -0
- package/dist/validation/spec-validation.d.ts +29 -0
- package/dist/validation/spec-validation.d.ts.map +1 -0
- package/dist/validation/spec-validation.js +376 -0
- package/dist/waivers-manager.d.ts +167 -0
- package/dist/waivers-manager.d.ts.map +1 -0
- package/dist/waivers-manager.js +549 -0
- package/package.json +10 -12
- package/templates/.cursor/README.md +311 -0
- package/templates/.cursor/hooks/audit.sh +55 -0
- package/templates/.cursor/hooks/block-dangerous.sh +77 -0
- package/templates/.cursor/hooks/caws-quality-check.sh +52 -0
- package/templates/.cursor/hooks/caws-scope-guard.sh +74 -0
- package/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
- package/templates/.cursor/hooks/format.sh +38 -0
- package/templates/.cursor/hooks/naming-check.sh +64 -0
- package/templates/.cursor/hooks/scan-secrets.sh +46 -0
- package/templates/.cursor/hooks/scope-guard.sh +52 -0
- package/templates/.cursor/hooks/validate-spec.sh +38 -0
- package/templates/.cursor/hooks.json +59 -0
- package/templates/.github/copilot/instructions.md +311 -0
- package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
- package/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
- package/templates/.vscode/launch.json +56 -0
- package/templates/.vscode/settings.json +93 -0
- package/templates/.windsurf/workflows/caws-guided-development.md +92 -0
- package/templates/apps/tools/caws/README.md +1 -1
- package/templates/apps/tools/caws/prompt-lint.js.backup +274 -0
- package/templates/apps/tools/caws/provenance.js.backup +73 -0
- package/templates/apps/tools/caws/schemas/working-spec.schema.json +21 -3
- package/templates/codemod/test.js +93 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Budget Derivation Logic
|
|
3
|
+
* Derives budgets from policy.yaml and applies waivers
|
|
4
|
+
* @author @darianrosebrook
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const yaml = require('js-yaml');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Derive budget for a working spec based on policy and waivers
|
|
13
|
+
* @param {Object} spec - Working spec object
|
|
14
|
+
* @param {string} projectRoot - Project root directory
|
|
15
|
+
* @returns {Object} Derived budget with baseline and effective limits
|
|
16
|
+
*/
|
|
17
|
+
function deriveBudget(spec, projectRoot = process.cwd()) {
|
|
18
|
+
try {
|
|
19
|
+
// Load policy.yaml
|
|
20
|
+
const policyPath = path.join(projectRoot, '.caws', 'policy.yaml');
|
|
21
|
+
if (!fs.existsSync(policyPath)) {
|
|
22
|
+
throw new Error('Policy file not found: .caws/policy.yaml');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const policy = yaml.load(fs.readFileSync(policyPath, 'utf8'));
|
|
26
|
+
|
|
27
|
+
// Validate policy structure
|
|
28
|
+
if (!policy.risk_tiers || !policy.risk_tiers[spec.risk_tier]) {
|
|
29
|
+
throw new Error(`Risk tier ${spec.risk_tier} not defined in policy.yaml`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const tierBudget = policy.risk_tiers[spec.risk_tier];
|
|
33
|
+
const baseline = {
|
|
34
|
+
max_files: tierBudget.max_files,
|
|
35
|
+
max_loc: tierBudget.max_loc
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// Start with baseline budget
|
|
39
|
+
let effectiveBudget = { ...baseline };
|
|
40
|
+
|
|
41
|
+
// Apply waivers if any
|
|
42
|
+
if (spec.waiver_ids && Array.isArray(spec.waiver_ids)) {
|
|
43
|
+
for (const waiverId of spec.waiver_ids) {
|
|
44
|
+
const waiver = loadWaiver(waiverId, projectRoot);
|
|
45
|
+
if (waiver && waiver.status === 'active' && isWaiverValid(waiver)) {
|
|
46
|
+
// Apply additive deltas
|
|
47
|
+
if (waiver.delta) {
|
|
48
|
+
if (waiver.delta.max_files) {
|
|
49
|
+
effectiveBudget.max_files += waiver.delta.max_files;
|
|
50
|
+
}
|
|
51
|
+
if (waiver.delta.max_loc) {
|
|
52
|
+
effectiveBudget.max_loc += waiver.delta.max_loc;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
baseline,
|
|
61
|
+
effective: effectiveBudget,
|
|
62
|
+
waivers_applied: spec.waiver_ids || [],
|
|
63
|
+
derived_at: new Date().toISOString()
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw new Error(`Budget derivation failed: ${error.message}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Load a waiver by ID
|
|
73
|
+
* @param {string} waiverId - Waiver ID (e.g., WV-0001)
|
|
74
|
+
* @param {string} projectRoot - Project root directory
|
|
75
|
+
* @returns {Object|null} Waiver object or null if not found
|
|
76
|
+
*/
|
|
77
|
+
function loadWaiver(waiverId, projectRoot) {
|
|
78
|
+
try {
|
|
79
|
+
const waiverPath = path.join(projectRoot, '.caws', 'waivers', `${waiverId}.yaml`);
|
|
80
|
+
if (!fs.existsSync(waiverPath)) {
|
|
81
|
+
console.warn(`Waiver file not found: ${waiverPath}`);
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const waiver = yaml.load(fs.readFileSync(waiverPath, 'utf8'));
|
|
86
|
+
return waiver;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.warn(`Failed to load waiver ${waiverId}: ${error.message}`);
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Check if a waiver is currently valid
|
|
95
|
+
* @param {Object} waiver - Waiver object
|
|
96
|
+
* @returns {boolean} Whether waiver is valid and active
|
|
97
|
+
*/
|
|
98
|
+
function isWaiverValid(waiver) {
|
|
99
|
+
try {
|
|
100
|
+
// Check if expired
|
|
101
|
+
if (waiver.expires_at) {
|
|
102
|
+
const expiryDate = new Date(waiver.expires_at);
|
|
103
|
+
const now = new Date();
|
|
104
|
+
if (now > expiryDate) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Check status
|
|
110
|
+
if (waiver.status !== 'active') {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Check if it has required approvals (simplified check)
|
|
115
|
+
if (!waiver.approvers || waiver.approvers.length === 0) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return true;
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.warn(`Waiver validation error: ${error.message}`);
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if current changes exceed derived budget
|
|
128
|
+
* @param {Object} derivedBudget - Budget from deriveBudget()
|
|
129
|
+
* @param {Object} currentStats - Current change statistics
|
|
130
|
+
* @returns {Object} Budget check result
|
|
131
|
+
*/
|
|
132
|
+
function checkBudgetCompliance(derivedBudget, currentStats) {
|
|
133
|
+
const violations = [];
|
|
134
|
+
|
|
135
|
+
if (currentStats.files_changed > derivedBudget.effective.max_files) {
|
|
136
|
+
violations.push({
|
|
137
|
+
gate: 'budget_limit',
|
|
138
|
+
type: 'max_files',
|
|
139
|
+
current: currentStats.files_changed,
|
|
140
|
+
limit: derivedBudget.effective.max_files,
|
|
141
|
+
baseline: derivedBudget.baseline.max_files,
|
|
142
|
+
message: `File count (${currentStats.files_changed}) exceeds budget (${derivedBudget.effective.max_files})`
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (currentStats.lines_changed > derivedBudget.effective.max_loc) {
|
|
147
|
+
violations.push({
|
|
148
|
+
gate: 'budget_limit',
|
|
149
|
+
type: 'max_loc',
|
|
150
|
+
current: currentStats.lines_changed,
|
|
151
|
+
limit: derivedBudget.effective.max_loc,
|
|
152
|
+
baseline: derivedBudget.baseline.max_loc,
|
|
153
|
+
message: `Lines of code (${currentStats.lines_changed}) exceed budget (${derivedBudget.effective.max_loc})`
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return {
|
|
158
|
+
compliant: violations.length === 0,
|
|
159
|
+
violations,
|
|
160
|
+
budget: derivedBudget
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Generate burn-up report for scope visibility
|
|
166
|
+
* @param {Object} derivedBudget - Budget from deriveBudget()
|
|
167
|
+
* @param {Object} currentStats - Current change statistics
|
|
168
|
+
* @returns {string} Human-readable burn-up report
|
|
169
|
+
*/
|
|
170
|
+
function generateBurnupReport(derivedBudget, currentStats) {
|
|
171
|
+
const report = [
|
|
172
|
+
'📊 CAWS Budget Burn-up Report',
|
|
173
|
+
'===============================',
|
|
174
|
+
'',
|
|
175
|
+
`Risk Tier: ${currentStats.risk_tier}`,
|
|
176
|
+
`Baseline: ${derivedBudget.baseline.max_files} files, ${derivedBudget.baseline.max_loc} LOC`,
|
|
177
|
+
`Current: ${currentStats.files_changed} files, ${currentStats.lines_changed} LOC`,
|
|
178
|
+
];
|
|
179
|
+
|
|
180
|
+
if (derivedBudget.waivers_applied.length > 0) {
|
|
181
|
+
report.push(`Waivers Applied: ${derivedBudget.waivers_applied.join(', ')}`);
|
|
182
|
+
report.push(`Effective Budget: ${derivedBudget.effective.max_files} files, ${derivedBudget.effective.max_loc} LOC`);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const filePercent = Math.round((currentStats.files_changed / derivedBudget.effective.max_files) * 100);
|
|
186
|
+
const locPercent = Math.round((currentStats.lines_changed / derivedBudget.effective.max_loc) * 100);
|
|
187
|
+
|
|
188
|
+
report.push(`File Usage: ${filePercent}% (${currentStats.files_changed}/${derivedBudget.effective.max_files})`);
|
|
189
|
+
report.push(`LOC Usage: ${locPercent}% (${currentStats.lines_changed}/${derivedBudget.effective.max_loc})`);
|
|
190
|
+
|
|
191
|
+
if (filePercent > 90 || locPercent > 90) {
|
|
192
|
+
report.push('', '⚠️ WARNING: Approaching budget limits');
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return report.join('\n');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
module.exports = {
|
|
199
|
+
deriveBudget,
|
|
200
|
+
loadWaiver,
|
|
201
|
+
isWaiverValid,
|
|
202
|
+
checkBudgetCompliance,
|
|
203
|
+
generateBurnupReport
|
|
204
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
export = CICDOptimizer;
|
|
2
|
+
declare class CICDOptimizer {
|
|
3
|
+
constructor(options?: {});
|
|
4
|
+
projectRoot: any;
|
|
5
|
+
cacheDir: string;
|
|
6
|
+
optimizationConfig: string;
|
|
7
|
+
/**
|
|
8
|
+
* Analyze project and generate CI/CD optimization recommendations
|
|
9
|
+
*/
|
|
10
|
+
analyzeProject(specPath?: string): Promise<{
|
|
11
|
+
project_tier: string;
|
|
12
|
+
recommended_optimizations: any[];
|
|
13
|
+
cache_strategy: {};
|
|
14
|
+
parallel_groups: any[];
|
|
15
|
+
conditional_execution: {};
|
|
16
|
+
estimated_savings: {};
|
|
17
|
+
}>;
|
|
18
|
+
/**
|
|
19
|
+
* Generate tier-based conditional execution rules
|
|
20
|
+
*/
|
|
21
|
+
generateConditionalExecutionRules(tier: any): {
|
|
22
|
+
coverage_required: boolean;
|
|
23
|
+
mutation_required: boolean;
|
|
24
|
+
contract_testing: boolean;
|
|
25
|
+
accessibility_check: boolean;
|
|
26
|
+
performance_budget: boolean;
|
|
27
|
+
security_scan: boolean;
|
|
28
|
+
lint_strict: boolean;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Analyze what optimizations are beneficial for this tier
|
|
32
|
+
*/
|
|
33
|
+
analyzeOptimizationOpportunities(tier: any): Promise<{
|
|
34
|
+
type: string;
|
|
35
|
+
description: string;
|
|
36
|
+
impact: string;
|
|
37
|
+
effort: string;
|
|
38
|
+
}[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Generate intelligent caching strategy
|
|
41
|
+
*/
|
|
42
|
+
generateCacheStrategy(): Promise<{
|
|
43
|
+
node_modules: {
|
|
44
|
+
key: string;
|
|
45
|
+
paths: string[];
|
|
46
|
+
restore_keys: string[];
|
|
47
|
+
};
|
|
48
|
+
build_artifacts: {
|
|
49
|
+
key: string;
|
|
50
|
+
paths: string[];
|
|
51
|
+
restore_keys: any[];
|
|
52
|
+
};
|
|
53
|
+
test_cache: {
|
|
54
|
+
key: string;
|
|
55
|
+
paths: string[];
|
|
56
|
+
restore_keys: string[];
|
|
57
|
+
};
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Create parallel execution groups for quality gates
|
|
61
|
+
*/
|
|
62
|
+
createParallelGroups(): Promise<{
|
|
63
|
+
name: string;
|
|
64
|
+
description: string;
|
|
65
|
+
jobs: string[];
|
|
66
|
+
max_parallel: number;
|
|
67
|
+
timeout: number;
|
|
68
|
+
}[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Analyze changed files to determine what tests to run
|
|
71
|
+
*/
|
|
72
|
+
analyzeChangedFiles(changedFiles?: any[]): Promise<{
|
|
73
|
+
unit: any[];
|
|
74
|
+
integration: any[];
|
|
75
|
+
contract: any[];
|
|
76
|
+
e2e: any[];
|
|
77
|
+
}>;
|
|
78
|
+
/**
|
|
79
|
+
* Estimate time savings from optimizations
|
|
80
|
+
*/
|
|
81
|
+
estimateTimeSavings(analysis: any): {
|
|
82
|
+
original_minutes: any;
|
|
83
|
+
optimized_minutes: number;
|
|
84
|
+
savings_percent: number;
|
|
85
|
+
monthly_savings_hours: number;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Generate optimized CI/CD configuration
|
|
89
|
+
*/
|
|
90
|
+
generateOptimizedConfig(platform?: string): Promise<string | {
|
|
91
|
+
name: string;
|
|
92
|
+
on: {
|
|
93
|
+
push: {
|
|
94
|
+
branches: string[];
|
|
95
|
+
};
|
|
96
|
+
pull_request: {
|
|
97
|
+
branches: string[];
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
jobs: {};
|
|
101
|
+
} | {
|
|
102
|
+
stages: string[];
|
|
103
|
+
cache: {
|
|
104
|
+
key: string;
|
|
105
|
+
paths: string[];
|
|
106
|
+
};
|
|
107
|
+
}>;
|
|
108
|
+
/**
|
|
109
|
+
* Generate optimized GitHub Actions workflow
|
|
110
|
+
*/
|
|
111
|
+
generateGitHubActionsConfig(analysis: any): {
|
|
112
|
+
name: string;
|
|
113
|
+
on: {
|
|
114
|
+
push: {
|
|
115
|
+
branches: string[];
|
|
116
|
+
};
|
|
117
|
+
pull_request: {
|
|
118
|
+
branches: string[];
|
|
119
|
+
};
|
|
120
|
+
};
|
|
121
|
+
jobs: {};
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Generate GitLab CI configuration
|
|
125
|
+
*/
|
|
126
|
+
generateGitLabCIConfig(analysis: any): {
|
|
127
|
+
stages: string[];
|
|
128
|
+
cache: {
|
|
129
|
+
key: string;
|
|
130
|
+
paths: string[];
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Generate Jenkins pipeline configuration
|
|
135
|
+
*/
|
|
136
|
+
generateJenkinsConfig(analysis: any): string;
|
|
137
|
+
/**
|
|
138
|
+
* Create hash for cache invalidation
|
|
139
|
+
*/
|
|
140
|
+
createCacheHash(files: any): string;
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=cicd-optimizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cicd-optimizer.d.ts","sourceRoot":"","sources":["../src/cicd-optimizer.js"],"names":[],"mappings":";AAaA;IACE,0BASC;IARC,iBAAuD;IACvD,iBAA6D;IAC7D,2BAAkF;IAQpF;;OAEG;IACH;;;;;;;OAyCC;IAED;;OAEG;IACH;;;;;;;;MAyBC;IAED;;OAEG;IACH;;;;;SA6CC;IAED;;OAEG;IACH;;;;;;;;;;;;;;;;OA8CC;IAED;;OAEG;IACH;;;;;;SA0BC;IAED;;OAEG;IACH;;;;;OA2BC;IAED;;OAEG;IACH;;;;;MA+BC;IAED;;OAEG;IACH;;;;;;;;;;;;;;;;;OAYC;IAED;;OAEG;IACH;;;;;;;;;;;MA4EC;IAED;;OAEG;IACH;;;;;;MAiCC;IAED;;OAEG;IACH,6CA+CC;IAED;;OAEG;IACH,oCAQC;CACF"}
|