@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,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
// CAWS VS Code Extension Settings
|
|
3
|
+
"caws.cli.path": "caws",
|
|
4
|
+
"caws.autoValidate": true,
|
|
5
|
+
"caws.showQualityStatus": true,
|
|
6
|
+
"caws.experimentalMode": false,
|
|
7
|
+
|
|
8
|
+
// General IDE settings that work well with CAWS
|
|
9
|
+
"editor.formatOnSave": true,
|
|
10
|
+
"editor.codeActionsOnSave": {
|
|
11
|
+
"source.fixAll.eslint": "explicit",
|
|
12
|
+
"source.organizeImports": "explicit"
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
// File associations for CAWS files
|
|
16
|
+
"files.associations": {
|
|
17
|
+
".caws/working-spec.yaml": "yaml",
|
|
18
|
+
".caws/waivers/*.yaml": "yaml",
|
|
19
|
+
"apps/tools/caws/*.js": "javascript"
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Exclude CAWS-generated files from search and navigation
|
|
23
|
+
"files.exclude": {
|
|
24
|
+
".caws/cache/": true,
|
|
25
|
+
".caws/waivers/review-*.md": true
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
// Search excludes for CAWS artifacts
|
|
29
|
+
"search.exclude": {
|
|
30
|
+
".caws/cache/**": true,
|
|
31
|
+
"packages/*/dist/**": true,
|
|
32
|
+
"packages/*/node_modules/**": true
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// CAWS-aware task definitions
|
|
36
|
+
"tasks": {
|
|
37
|
+
"version": "2.0.0",
|
|
38
|
+
"tasks": [
|
|
39
|
+
{
|
|
40
|
+
"label": "CAWS: Validate",
|
|
41
|
+
"type": "shell",
|
|
42
|
+
"command": "caws",
|
|
43
|
+
"args": ["validate"],
|
|
44
|
+
"group": {
|
|
45
|
+
"kind": "build",
|
|
46
|
+
"isDefault": true
|
|
47
|
+
},
|
|
48
|
+
"presentation": {
|
|
49
|
+
"echo": true,
|
|
50
|
+
"reveal": "always",
|
|
51
|
+
"focus": false,
|
|
52
|
+
"panel": "shared"
|
|
53
|
+
},
|
|
54
|
+
"problemMatcher": []
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"label": "CAWS: Evaluate Quality",
|
|
58
|
+
"type": "shell",
|
|
59
|
+
"command": "caws",
|
|
60
|
+
"args": ["agent", "evaluate", ".caws/working-spec.yaml"],
|
|
61
|
+
"group": "test",
|
|
62
|
+
"presentation": {
|
|
63
|
+
"echo": true,
|
|
64
|
+
"reveal": "always",
|
|
65
|
+
"focus": false,
|
|
66
|
+
"panel": "shared"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"label": "CAWS: Create Waiver",
|
|
71
|
+
"type": "shell",
|
|
72
|
+
"command": "caws",
|
|
73
|
+
"args": ["waivers", "create"],
|
|
74
|
+
"group": "build"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
// Recommended extensions for CAWS development
|
|
80
|
+
"recommendations": [
|
|
81
|
+
"ms-vscode.vscode-json",
|
|
82
|
+
"redhat.vscode-yaml",
|
|
83
|
+
"ms-vscode.vscode-typescript-next",
|
|
84
|
+
"esbenp.prettier-vscode",
|
|
85
|
+
"dbaeumer.vscode-eslint"
|
|
86
|
+
],
|
|
87
|
+
|
|
88
|
+
// Workspace-specific settings
|
|
89
|
+
"yaml.schemas": {
|
|
90
|
+
"./.caws/schema/working-spec.schema.json": ".caws/working-spec.yaml",
|
|
91
|
+
"./.caws/schema/waiver.schema.json": ".caws/waivers/*.yaml"
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# /caws-guided-development
|
|
2
|
+
|
|
3
|
+
## CAWS-Guided Feature Development Workflow
|
|
4
|
+
|
|
5
|
+
**Purpose**: Guide agents through feature development with CAWS quality assurance
|
|
6
|
+
|
|
7
|
+
**Tags**: development, quality, caws, feature
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
### 1. Initialize CAWS Working Spec
|
|
12
|
+
```
|
|
13
|
+
# Create comprehensive working specification
|
|
14
|
+
caws init feature-name --interactive
|
|
15
|
+
|
|
16
|
+
# Define acceptance criteria, scope, and risk assessment
|
|
17
|
+
# Working spec: .caws/working-spec.yaml
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. Plan Implementation Strategy
|
|
21
|
+
```
|
|
22
|
+
# Get CAWS guidance for implementation approach
|
|
23
|
+
caws agent iterate --current-state "Planning phase complete, need implementation strategy"
|
|
24
|
+
|
|
25
|
+
# CAWS will suggest:
|
|
26
|
+
# - Implementation steps
|
|
27
|
+
# - Quality gates to consider
|
|
28
|
+
# - Risk mitigation strategies
|
|
29
|
+
# - Testing approach
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 3. Implement Core Functionality
|
|
33
|
+
```
|
|
34
|
+
# Start coding with CAWS quality monitoring
|
|
35
|
+
# Real-time feedback via CAWS tools
|
|
36
|
+
|
|
37
|
+
# Regular quality checks
|
|
38
|
+
caws agent evaluate --quiet
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 4. Quality Assurance Integration
|
|
42
|
+
```
|
|
43
|
+
# Run comprehensive quality gates
|
|
44
|
+
caws validate
|
|
45
|
+
|
|
46
|
+
# Address any failing gates
|
|
47
|
+
# Create waivers if justified
|
|
48
|
+
caws waivers create --reason emergency_hotfix --gates coverage_threshold
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 5. Testing & Validation
|
|
52
|
+
```
|
|
53
|
+
# Unit tests
|
|
54
|
+
npm run test:unit
|
|
55
|
+
|
|
56
|
+
# Integration tests
|
|
57
|
+
npm run test:integration
|
|
58
|
+
|
|
59
|
+
# Contract tests
|
|
60
|
+
npm run test:contract
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 6. Final Quality Review
|
|
64
|
+
```
|
|
65
|
+
# Complete CAWS evaluation
|
|
66
|
+
caws agent evaluate
|
|
67
|
+
|
|
68
|
+
# Generate provenance report
|
|
69
|
+
caws provenance generate
|
|
70
|
+
|
|
71
|
+
# Ready for integration
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
**Quality Gates**:
|
|
77
|
+
- ✅ Working spec validation
|
|
78
|
+
- ✅ Code quality standards
|
|
79
|
+
- ✅ Test coverage requirements
|
|
80
|
+
- ✅ Security scanning
|
|
81
|
+
- ✅ Performance budgets
|
|
82
|
+
|
|
83
|
+
**Success Criteria**:
|
|
84
|
+
- All CAWS quality gates pass
|
|
85
|
+
- Acceptance criteria met
|
|
86
|
+
- No critical security issues
|
|
87
|
+
- Performance requirements satisfied
|
|
88
|
+
|
|
89
|
+
**Call Other Workflows**:
|
|
90
|
+
- `/caws-testing-workflow` - Comprehensive testing
|
|
91
|
+
- `/caws-security-review` - Security validation
|
|
92
|
+
- `/caws-deployment-checklist` - Deployment preparation
|
|
@@ -427,7 +427,7 @@ jobs:
|
|
|
427
427
|
|
|
428
428
|
## 📚 Documentation
|
|
429
429
|
|
|
430
|
-
- [
|
|
430
|
+
- [Hooks & Agent Workflows Guide](../../docs/guides/hooks-and-agent-workflows.md)
|
|
431
431
|
- [Hook Strategy](../../docs/HOOK_STRATEGY.md)
|
|
432
432
|
- [Developer Guide](../../docs/caws-developer-guide.md)
|
|
433
433
|
- [API Documentation](../../docs/api/)
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview CAWS Prompt Linter
|
|
5
|
+
* Validates prompts for secrets and ensures tool allowlist compliance
|
|
6
|
+
* @author @darianrosebrook
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require("fs");
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Common secret patterns to detect
|
|
13
|
+
*/
|
|
14
|
+
const SECRET_PATTERNS = [
|
|
15
|
+
// API Keys
|
|
16
|
+
/api[_-]?key[_-]?token\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
17
|
+
/x-api-key\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
18
|
+
/authorization\s*[=:]\s*['"]?(Bearer\s+)?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
19
|
+
|
|
20
|
+
// Tokens
|
|
21
|
+
/token\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
22
|
+
/access[_-]?token\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
23
|
+
/refresh[_-]?token\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
24
|
+
/auth[_-]?token\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
25
|
+
|
|
26
|
+
// Passwords
|
|
27
|
+
/password\s*[=:]\s*['"]?([a-zA-Z0-9_-]{8,})['"]?/gi,
|
|
28
|
+
/passwd\s*[=:]\s*['"]?([a-zA-Z0-9_-]{8,})['"]?/gi,
|
|
29
|
+
/pwd\s*[=:]\s*['"]?([a-zA-Z0-9_-]{8,})['"]?/gi,
|
|
30
|
+
|
|
31
|
+
// Secrets
|
|
32
|
+
/secret\s*[=:]\s*['"]?([a-zA-Z0-9_-]{16,})['"]?/gi,
|
|
33
|
+
/private[_-]?key\s*[=:]\s*['"]?([a-zA-Z0-9_-]{20,})['"]?/gi,
|
|
34
|
+
|
|
35
|
+
// Environment variables that might contain secrets
|
|
36
|
+
/process\.env\.[A-Z_]+_KEY/gi,
|
|
37
|
+
/process\.env\.[A-Z_]+_TOKEN/gi,
|
|
38
|
+
/process\.env\.[A-Z_]+_SECRET/gi,
|
|
39
|
+
/process\.env\.[A-Z_]+_PASSWORD/gi,
|
|
40
|
+
|
|
41
|
+
// URLs with potential secrets
|
|
42
|
+
/https?:\/\/[^/]*@[^/]+/gi,
|
|
43
|
+
|
|
44
|
+
// Base64 encoded strings that might be secrets
|
|
45
|
+
/[A-Za-z0-9+/=]{40,}/g,
|
|
46
|
+
|
|
47
|
+
// AWS keys
|
|
48
|
+
/AKIA[A-Z0-9]{16}/gi,
|
|
49
|
+
|
|
50
|
+
// GitHub tokens
|
|
51
|
+
/ghp_[A-Za-z0-9]{36}/gi,
|
|
52
|
+
/github_pat_[A-Za-z0-9]{22}/gi,
|
|
53
|
+
|
|
54
|
+
// Slack tokens
|
|
55
|
+
/xoxb-[0-9]+-[0-9]+-[0-9]+-[a-zA-Z0-9]+/gi,
|
|
56
|
+
|
|
57
|
+
// Database connection strings
|
|
58
|
+
/mongodb(\+srv)?:\/\/[^:]+:[^@]+@[^/]+/gi,
|
|
59
|
+
/postgres:\/\/[^:]+:[^@]+@[^/]+/gi,
|
|
60
|
+
/mysql:\/\/[^:]+:[^@]+@[^/]+/gi,
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Scan file for potential secrets
|
|
65
|
+
* @param {string} filePath - Path to file to scan
|
|
66
|
+
* @returns {Array} Array of potential secret matches
|
|
67
|
+
*/
|
|
68
|
+
function scanForSecrets(filePath) {
|
|
69
|
+
try {
|
|
70
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
71
|
+
const matches = [];
|
|
72
|
+
|
|
73
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
74
|
+
const patternMatches = [...content.matchAll(pattern)];
|
|
75
|
+
for (const match of patternMatches) {
|
|
76
|
+
matches.push({
|
|
77
|
+
file: filePath,
|
|
78
|
+
line: content.substring(0, match.index).split("\n").length,
|
|
79
|
+
pattern: pattern.toString(),
|
|
80
|
+
match: match[0],
|
|
81
|
+
severity: "high",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return matches;
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error(`❌ Error scanning ${filePath}:`, error.message);
|
|
89
|
+
return [];
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Validate tools against allowlist
|
|
95
|
+
* @param {Array} tools - Tools used in prompts
|
|
96
|
+
* @param {Array} allowlist - Allowed tools
|
|
97
|
+
* @returns {Array} Array of violations
|
|
98
|
+
*/
|
|
99
|
+
function validateToolAllowlist(tools, allowlist) {
|
|
100
|
+
const violations = [];
|
|
101
|
+
|
|
102
|
+
for (const tool of tools) {
|
|
103
|
+
if (!allowlist.includes(tool)) {
|
|
104
|
+
violations.push({
|
|
105
|
+
tool,
|
|
106
|
+
severity: "high",
|
|
107
|
+
message: `Tool "${tool}" not in allowlist`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return violations;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Extract tools from prompt content
|
|
117
|
+
* @param {string} content - Prompt content
|
|
118
|
+
* @returns {Array} Array of tools mentioned
|
|
119
|
+
*/
|
|
120
|
+
function extractTools(content) {
|
|
121
|
+
const tools = [];
|
|
122
|
+
|
|
123
|
+
// Common tool patterns
|
|
124
|
+
const toolPatterns = [
|
|
125
|
+
/using\s+(node|npm|yarn|pnpm|git|docker|kubectl|aws|azure|gcloud)/gi,
|
|
126
|
+
/(node|npm|yarn|pnpm|git|docker|kubectl|aws|azure|gcloud)\s+command/gi,
|
|
127
|
+
/execute\s+(node|npm|yarn|pnpm|git|docker|kubectl|aws|azure|gcloud)/gi,
|
|
128
|
+
/run\s+(node|npm|yarn|pnpm|git|docker|kubectl|aws|azure|gcloud)/gi,
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
for (const pattern of toolPatterns) {
|
|
132
|
+
const matches = [...content.matchAll(pattern)];
|
|
133
|
+
for (const match of matches) {
|
|
134
|
+
const tool = match[1] || match[0];
|
|
135
|
+
if (!tools.includes(tool)) {
|
|
136
|
+
tools.push(tool);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return tools;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Lint prompts for security and compliance
|
|
146
|
+
* @param {Array} promptFiles - Array of prompt file paths
|
|
147
|
+
* @param {Array} allowlist - Allowed tools
|
|
148
|
+
* @returns {Object} Lint results
|
|
149
|
+
*/
|
|
150
|
+
function lintPrompts(promptFiles, allowlist) {
|
|
151
|
+
const results = {
|
|
152
|
+
secrets: [],
|
|
153
|
+
violations: [],
|
|
154
|
+
cleanFiles: 0,
|
|
155
|
+
totalFiles: promptFiles.length,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
for (const file of promptFiles) {
|
|
159
|
+
if (!fs.existsSync(file)) {
|
|
160
|
+
console.warn(`⚠️ Prompt file not found: ${file}`);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Scan for secrets
|
|
165
|
+
const secretMatches = scanForSecrets(file);
|
|
166
|
+
results.secrets.push(...secretMatches);
|
|
167
|
+
|
|
168
|
+
// Extract and validate tools
|
|
169
|
+
const content = fs.readFileSync(file, "utf8");
|
|
170
|
+
const tools = extractTools(content);
|
|
171
|
+
const toolViolations = validateToolAllowlist(tools, allowlist);
|
|
172
|
+
results.violations.push(...toolViolations.map((v) => ({ ...v, file })));
|
|
173
|
+
|
|
174
|
+
// Check if file is clean
|
|
175
|
+
if (secretMatches.length === 0 && toolViolations.length === 0) {
|
|
176
|
+
results.cleanFiles++;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return results;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Load tool allowlist from file
|
|
185
|
+
* @param {string} allowlistPath - Path to allowlist file
|
|
186
|
+
* @returns {Array} Array of allowed tools
|
|
187
|
+
*/
|
|
188
|
+
function loadAllowlist(allowlistPath) {
|
|
189
|
+
try {
|
|
190
|
+
if (!fs.existsSync(allowlistPath)) {
|
|
191
|
+
console.warn(`⚠️ Allowlist file not found: ${allowlistPath}`);
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const content = fs.readFileSync(allowlistPath, "utf8");
|
|
196
|
+
return JSON.parse(content);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error(`❌ Error loading allowlist:`, error.message);
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// CLI interface
|
|
204
|
+
if (require.main === module) {
|
|
205
|
+
const promptFiles = process.argv.slice(2);
|
|
206
|
+
const allowlistArg = process.argv
|
|
207
|
+
.find((arg) => arg.startsWith("--allowlist="))
|
|
208
|
+
?.split("=")[1];
|
|
209
|
+
const allowlistPath = allowlistArg || ".agent/tools-allow.json";
|
|
210
|
+
|
|
211
|
+
if (promptFiles.length === 0) {
|
|
212
|
+
console.log("CAWS Prompt Linter");
|
|
213
|
+
console.log(
|
|
214
|
+
"Usage: node prompt-lint.js <prompt-file1> [prompt-file2] ... [options]"
|
|
215
|
+
);
|
|
216
|
+
console.log("Options:");
|
|
217
|
+
console.log(
|
|
218
|
+
" --allowlist=<path> Path to tools allowlist file (default: .agent/tools-allow.json)"
|
|
219
|
+
);
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Load allowlist
|
|
224
|
+
const allowlist = loadAllowlist(allowlistPath);
|
|
225
|
+
|
|
226
|
+
console.log("🔍 Linting prompts for security and compliance...");
|
|
227
|
+
console.log(`📁 Allowlist loaded: ${allowlist.length} tools`);
|
|
228
|
+
console.log(`📄 Scanning ${promptFiles.length} files...`);
|
|
229
|
+
|
|
230
|
+
// Lint prompts
|
|
231
|
+
const results = lintPrompts(promptFiles, allowlist);
|
|
232
|
+
|
|
233
|
+
// Report results
|
|
234
|
+
if (results.secrets.length > 0) {
|
|
235
|
+
console.log("\n🚨 POTENTIAL SECRETS DETECTED:");
|
|
236
|
+
results.secrets.forEach((secret, index) => {
|
|
237
|
+
console.log(
|
|
238
|
+
` ${index + 1}. ${secret.file}:${
|
|
239
|
+
secret.line
|
|
240
|
+
} - ${secret.match.substring(0, 50)}...`
|
|
241
|
+
);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (results.violations.length > 0) {
|
|
246
|
+
console.log("\n⚠️ TOOL VIOLATIONS:");
|
|
247
|
+
results.violations.forEach((violation, index) => {
|
|
248
|
+
console.log(` ${index + 1}. ${violation.file} - ${violation.message}`);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
console.log("\n📊 SUMMARY:");
|
|
253
|
+
console.log(` - Files scanned: ${results.totalFiles}`);
|
|
254
|
+
console.log(` - Clean files: ${results.cleanFiles}`);
|
|
255
|
+
console.log(` - Secrets found: ${results.secrets.length}`);
|
|
256
|
+
console.log(` - Violations: ${results.violations.length}`);
|
|
257
|
+
|
|
258
|
+
// Exit with error if issues found
|
|
259
|
+
if (results.secrets.length > 0 || results.violations.length > 0) {
|
|
260
|
+
console.log("\n❌ Linting failed - security issues detected");
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
console.log("✅ All prompts passed security checks");
|
|
265
|
+
process.exit(0);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
module.exports = {
|
|
269
|
+
scanForSecrets,
|
|
270
|
+
validateToolAllowlist,
|
|
271
|
+
extractTools,
|
|
272
|
+
lintPrompts,
|
|
273
|
+
loadAllowlist,
|
|
274
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview CAWS Provenance Tracker - Real Implementation
|
|
5
|
+
* @author @darianrosebrook
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const crypto = require('crypto');
|
|
11
|
+
const { execSync } = require('child_process');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate comprehensive provenance data for CAWS operations
|
|
15
|
+
* @param {Object} options - Configuration options
|
|
16
|
+
* @returns {Object} Complete provenance record
|
|
17
|
+
*/
|
|
18
|
+
function generateProvenance(options = {}) {
|
|
19
|
+
const projectRoot = options.projectRoot || process.cwd();
|
|
20
|
+
|
|
21
|
+
return {
|
|
22
|
+
// Agent and model information
|
|
23
|
+
agent: options.agent || 'caws-cli',
|
|
24
|
+
model: options.model || 'cli-interactive',
|
|
25
|
+
model_hash: options.modelHash || generateModelHash(),
|
|
26
|
+
|
|
27
|
+
// Tool and security information
|
|
28
|
+
tool_allowlist: options.toolAllowlist || generateToolAllowlist(projectRoot),
|
|
29
|
+
prompts: options.prompts || [],
|
|
30
|
+
|
|
31
|
+
// Git and version control information
|
|
32
|
+
commit: getCurrentCommit(projectRoot),
|
|
33
|
+
branch: getCurrentBranch(projectRoot),
|
|
34
|
+
repository: getRepositoryInfo(projectRoot),
|
|
35
|
+
|
|
36
|
+
// File and artifact information
|
|
37
|
+
artifacts: generateArtifactList(projectRoot),
|
|
38
|
+
dependencies: generateDependencyInfo(projectRoot),
|
|
39
|
+
|
|
40
|
+
// Execution results and metadata
|
|
41
|
+
results: options.results || {},
|
|
42
|
+
approvals: options.approvals || [],
|
|
43
|
+
execution_context: generateExecutionContext(),
|
|
44
|
+
|
|
45
|
+
// Security and integrity
|
|
46
|
+
integrity: generateIntegrityInfo(),
|
|
47
|
+
|
|
48
|
+
// Timestamps and versioning
|
|
49
|
+
timestamp: new Date().toISOString(),
|
|
50
|
+
version: require(path.join(projectRoot, 'package.json')).version || '1.0.0',
|
|
51
|
+
provenance_hash: generateProvenanceHash(),
|
|
52
|
+
|
|
53
|
+
// Build and deployment information
|
|
54
|
+
build_info: generateBuildInfo(projectRoot),
|
|
55
|
+
|
|
56
|
+
// Change tracking
|
|
57
|
+
change_summary: generateChangeSummary(projectRoot),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Mock provenance saving
|
|
62
|
+
function saveProvenance(provenance, filepath) {
|
|
63
|
+
const dir = path.dirname(filepath);
|
|
64
|
+
if (!fs.existsSync(dir)) {
|
|
65
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
66
|
+
}
|
|
67
|
+
fs.writeFileSync(filepath, JSON.stringify(provenance, null, 2));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
generateProvenance,
|
|
72
|
+
saveProvenance,
|
|
73
|
+
};
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
"id",
|
|
7
7
|
"title",
|
|
8
8
|
"risk_tier",
|
|
9
|
+
"mode",
|
|
10
|
+
"blast_radius",
|
|
11
|
+
"operational_rollback_slo",
|
|
9
12
|
"scope",
|
|
10
13
|
"invariants",
|
|
11
14
|
"acceptance",
|
|
@@ -13,9 +16,24 @@
|
|
|
13
16
|
"contracts"
|
|
14
17
|
],
|
|
15
18
|
"properties": {
|
|
16
|
-
"id": { "type": "string", "pattern": "^
|
|
17
|
-
"title": { "type": "string", "minLength":
|
|
18
|
-
"risk_tier": { "type": "integer", "enum": [1, 2, 3] },
|
|
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" },
|
|
19
37
|
"scope": {
|
|
20
38
|
"type": "object",
|
|
21
39
|
"required": ["in", "out"],
|
|
@@ -1 +1,93 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Template Codemod for CAWS Framework
|
|
5
|
+
* Automated code transformations for refactoring
|
|
6
|
+
* @author CAWS Framework
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const tsMorph = require('ts-morph');
|
|
10
|
+
|
|
11
|
+
function applyCodemod(dryRun = true) {
|
|
12
|
+
console.log('🔧 Applying codemod transformations...');
|
|
13
|
+
|
|
14
|
+
const project = new tsMorph.Project();
|
|
15
|
+
|
|
16
|
+
// Load all TypeScript source files
|
|
17
|
+
const sourceFiles = project.addSourceFilesAtPaths('src/**/*.ts');
|
|
18
|
+
|
|
19
|
+
if (sourceFiles.length === 0) {
|
|
20
|
+
console.log('⚠️ No TypeScript source files found in src/ directory');
|
|
21
|
+
return { filesProcessed: 0, changesApplied: 0 };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log(`📁 Processing ${sourceFiles.length} source files`);
|
|
25
|
+
let totalChanges = 0;
|
|
26
|
+
|
|
27
|
+
for (const sourceFile of sourceFiles) {
|
|
28
|
+
const filePath = sourceFile.getFilePath();
|
|
29
|
+
console.log(`Processing: ${filePath}`);
|
|
30
|
+
|
|
31
|
+
let fileChanges = 0;
|
|
32
|
+
|
|
33
|
+
// Example transformations - customize these for your specific needs:
|
|
34
|
+
|
|
35
|
+
// 1. Add JSDoc to exported functions without documentation
|
|
36
|
+
const exportedFunctions = sourceFile
|
|
37
|
+
.getFunctions()
|
|
38
|
+
.filter((func) => func.isExported && !func.getJsDocs().length);
|
|
39
|
+
|
|
40
|
+
for (const func of exportedFunctions) {
|
|
41
|
+
func.addJsDoc({
|
|
42
|
+
description: `Handles ${func.getName()} operations`,
|
|
43
|
+
tags: [
|
|
44
|
+
{ tagName: 'param', text: 'options - Configuration options' },
|
|
45
|
+
{ tagName: 'returns', text: 'Result of the operation' },
|
|
46
|
+
],
|
|
47
|
+
});
|
|
48
|
+
fileChanges++;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// 2. Add type annotations to untyped parameters (example)
|
|
52
|
+
// const untypedParams = sourceFile.getDescendantsOfKind(tsMorph.SyntaxKind.Parameter)
|
|
53
|
+
// .filter(param => !param.getTypeNode());
|
|
54
|
+
// Add your transformation logic here...
|
|
55
|
+
|
|
56
|
+
if (fileChanges > 0) {
|
|
57
|
+
console.log(` ✅ Applied ${fileChanges} transformations`);
|
|
58
|
+
totalChanges += fileChanges;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
console.log(`📊 Codemod complete: ${totalChanges} total transformations`);
|
|
63
|
+
|
|
64
|
+
if (!dryRun) {
|
|
65
|
+
console.log('💾 Saving changes...');
|
|
66
|
+
project.saveSync();
|
|
67
|
+
console.log('✅ All changes saved successfully');
|
|
68
|
+
} else {
|
|
69
|
+
console.log('🔍 Dry run - no files were modified');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
filesProcessed: sourceFiles.length,
|
|
74
|
+
changesApplied: totalChanges,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// CLI interface
|
|
79
|
+
if (require.main === module) {
|
|
80
|
+
const args = process.argv.slice(2);
|
|
81
|
+
const dryRun = !args.includes('--apply');
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const result = applyCodemod(dryRun);
|
|
85
|
+
console.log('✅ Codemod execution completed');
|
|
86
|
+
process.exit(0);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error('❌ Codemod execution failed:', error.message);
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
module.exports = { applyCodemod };
|