@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.
- package/dist/budget-derivation.js +5 -4
- package/dist/commands/diagnose.js +24 -19
- package/dist/commands/init.js +51 -4
- package/dist/commands/specs.js +40 -1
- package/dist/commands/status.js +2 -2
- package/dist/commands/tool.js +2 -3
- package/dist/config/index.js +17 -8
- package/dist/generators/working-spec.js +19 -6
- package/dist/scaffold/git-hooks.js +127 -29
- package/dist/scaffold/index.js +53 -7
- package/dist/templates/.caws/tools/README.md +20 -0
- package/dist/templates/.cursor/README.md +311 -0
- package/dist/templates/.cursor/hooks/audit.sh +55 -0
- package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
- package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
- package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
- package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
- package/dist/templates/.cursor/hooks/format.sh +38 -0
- package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
- package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
- package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
- package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
- package/dist/templates/.cursor/hooks.json +59 -0
- package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
- package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
- package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
- package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
- package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
- package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
- package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
- package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
- package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
- package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
- package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
- package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
- package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
- package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
- package/dist/templates/.cursor/rules/README.md +148 -0
- package/dist/templates/.github/copilot/instructions.md +311 -0
- package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
- package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
- package/dist/templates/.vscode/launch.json +56 -0
- package/dist/templates/.vscode/settings.json +93 -0
- package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
- package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
- package/dist/templates/OIDC_SETUP.md +300 -0
- package/dist/templates/agents.md +1047 -0
- package/dist/templates/codemod/README.md +1 -0
- package/dist/templates/codemod/test.js +93 -0
- package/dist/templates/docs/README.md +150 -0
- package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
- package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
- package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
- package/dist/tool-loader.js +6 -1
- package/dist/tool-validator.js +8 -2
- package/dist/utils/detection.js +4 -3
- package/dist/utils/git-lock.js +118 -0
- package/dist/utils/gitignore-updater.js +148 -0
- package/dist/utils/quality-gates.js +47 -7
- package/dist/utils/spec-resolver.js +23 -3
- package/dist/utils/yaml-validation.js +155 -0
- package/dist/validation/spec-validation.js +81 -2
- package/package.json +2 -2
- package/templates/.caws/schemas/waivers.schema.json +30 -0
- package/templates/.caws/schemas/working-spec.schema.json +133 -0
- package/templates/.caws/templates/working-spec.template.yml +74 -0
- package/templates/.caws/tools/README.md +20 -0
- package/templates/.caws/tools/scope-guard.js +208 -0
- package/templates/.caws/tools-allow.json +331 -0
- package/templates/.caws/waivers.yml +19 -0
- package/templates/.cursor/hooks/scope-guard.sh +2 -2
- package/templates/.cursor/hooks/validate-spec.sh +42 -7
- package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
- package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
- package/templates/apps/tools/caws/README.md +0 -463
- package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
- package/templates/apps/tools/caws/attest.js +0 -357
- package/templates/apps/tools/caws/ci-optimizer.js +0 -642
- package/templates/apps/tools/caws/config.ts +0 -245
- package/templates/apps/tools/caws/cross-functional.js +0 -876
- package/templates/apps/tools/caws/dashboard.js +0 -1112
- package/templates/apps/tools/caws/flake-detector.ts +0 -362
- package/templates/apps/tools/caws/gates.js +0 -198
- package/templates/apps/tools/caws/gates.ts +0 -271
- package/templates/apps/tools/caws/language-adapters.ts +0 -381
- package/templates/apps/tools/caws/language-support.d.ts +0 -367
- package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
- package/templates/apps/tools/caws/language-support.js +0 -585
- package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
- package/templates/apps/tools/caws/legacy-assessor.js +0 -764
- package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
- package/templates/apps/tools/caws/perf-budgets.ts +0 -349
- package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
- package/templates/apps/tools/caws/property-testing.js +0 -707
- package/templates/apps/tools/caws/provenance.d.ts +0 -14
- package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
- package/templates/apps/tools/caws/provenance.js +0 -132
- package/templates/apps/tools/caws/provenance.js.backup +0 -73
- package/templates/apps/tools/caws/provenance.ts +0 -211
- package/templates/apps/tools/caws/security-provenance.ts +0 -483
- package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
- package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
- package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
- package/templates/apps/tools/caws/shared/types.ts +0 -444
- package/templates/apps/tools/caws/shared/validator.ts +0 -305
- package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
- package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
- package/templates/apps/tools/caws/test-quality.js +0 -578
- package/templates/apps/tools/caws/validate.js +0 -76
- package/templates/apps/tools/caws/validate.ts +0 -228
- package/templates/apps/tools/caws/waivers.js +0 -344
- /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
- /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# CAWS Scope Guard Hook
|
|
3
|
+
# Prevents agents from accessing files outside CAWS-defined scope
|
|
4
|
+
# @author @darianrosebrook
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# Read input from Cursor
|
|
9
|
+
INPUT=$(cat)
|
|
10
|
+
ACTION=$(echo "$INPUT" | jq -r '.action // ""')
|
|
11
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // ""')
|
|
12
|
+
|
|
13
|
+
# Check if CAWS is available and we have a working spec
|
|
14
|
+
if command -v caws &> /dev/null && [[ -f ".caws/working-spec.yaml" ]]; then
|
|
15
|
+
|
|
16
|
+
# AGENT GUARDRAILS - Prevent policy bypass attempts
|
|
17
|
+
if [[ "$ACTION" == "edit_file" ]] || [[ "$ACTION" == "create_file" ]]; then
|
|
18
|
+
if [[ "$FILE_PATH" == ".caws/policy.yaml" ]]; then
|
|
19
|
+
echo '{
|
|
20
|
+
"userMessage": "🚫 Policy file editing blocked by agent guardrails",
|
|
21
|
+
"agentMessage": "Agents cannot edit .caws/policy.yaml - requires human dual control",
|
|
22
|
+
"block": true,
|
|
23
|
+
"suggestions": [
|
|
24
|
+
"Policy changes must be approved by humans with Gatekeeper role",
|
|
25
|
+
"Create a separate PR for policy changes",
|
|
26
|
+
"For budget exceptions: caws waivers create --title=\"Budget exception\" --reason=architectural_refactor --gates=budget_limit",
|
|
27
|
+
"Contact @gatekeepers for policy modifications"
|
|
28
|
+
]
|
|
29
|
+
}'
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if [[ "$FILE_PATH" == "CODEOWNERS" ]]; then
|
|
34
|
+
echo '{
|
|
35
|
+
"userMessage": "🚫 CODEOWNERS editing blocked by agent guardrails",
|
|
36
|
+
"agentMessage": "Agents cannot modify CODEOWNERS - governance changes require approval",
|
|
37
|
+
"block": true,
|
|
38
|
+
"suggestions": [
|
|
39
|
+
"CODEOWNERS changes require governance review",
|
|
40
|
+
"Contact repository maintainers for ownership changes",
|
|
41
|
+
"For approval workflows: caws waivers create --reason=governance_change"
|
|
42
|
+
]
|
|
43
|
+
}'
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
if [[ "$FILE_PATH" == ".caws/working-spec.yaml" ]]; then
|
|
48
|
+
# Check if trying to add change_budget
|
|
49
|
+
FILE_CONTENT=$(echo "$INPUT" | jq -r '.content // ""')
|
|
50
|
+
if echo "$FILE_CONTENT" | grep -q "change_budget"; then
|
|
51
|
+
echo '{
|
|
52
|
+
"userMessage": "🚫 Budget editing blocked by agent guardrails",
|
|
53
|
+
"agentMessage": "Agents cannot introduce change_budget fields - budgets are derived automatically",
|
|
54
|
+
"block": true,
|
|
55
|
+
"suggestions": [
|
|
56
|
+
"Check current budget status: caws burnup",
|
|
57
|
+
"For budget exceptions: caws waivers create --title=\"Scope expansion\" --reason=architectural_refactor --gates=budget_limit --expires-at=\"2025-12-31T23:59:59Z\"",
|
|
58
|
+
"Add waiver_ids to working spec instead: [\"WV-XXXX\"]",
|
|
59
|
+
"Validate waiver: caws validate .caws/working-spec.yaml"
|
|
60
|
+
]
|
|
61
|
+
}'
|
|
62
|
+
exit 1
|
|
63
|
+
fi
|
|
64
|
+
fi
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# For file access actions, check scope
|
|
68
|
+
if [[ "$ACTION" == "read_file" ]] || [[ "$ACTION" == "edit_file" ]] || [[ -n "$FILE_PATH" ]]; then
|
|
69
|
+
|
|
70
|
+
# Get scope information from CAWS spec
|
|
71
|
+
SCOPE_CHECK=$(caws validate .caws/working-spec.yaml --scope-check "$FILE_PATH" 2>/dev/null || echo "unknown")
|
|
72
|
+
|
|
73
|
+
if [[ "$SCOPE_CHECK" == "out_of_scope" ]]; then
|
|
74
|
+
echo '{
|
|
75
|
+
"userMessage": "🚫 File access blocked by CAWS scope guard",
|
|
76
|
+
"agentMessage": "Cannot access '"$FILE_PATH"' - outside CAWS defined scope",
|
|
77
|
+
"block": true,
|
|
78
|
+
"suggestions": [
|
|
79
|
+
"Check current scope: caws validate .caws/working-spec.yaml",
|
|
80
|
+
"Update scope in working spec: edit .caws/working-spec.yaml scope.in array",
|
|
81
|
+
"For scope exceptions: caws waivers create --title=\"Scope expansion\" --reason=architectural_refactor --gates=scope_boundary --description=\"Need access to '"$FILE_PATH"' for implementation\"",
|
|
82
|
+
"Validate changes: caws validate .caws/working-spec.yaml"
|
|
83
|
+
]
|
|
84
|
+
}'
|
|
85
|
+
exit 1
|
|
86
|
+
elif [[ "$SCOPE_CHECK" == "scope_warning" ]]; then
|
|
87
|
+
echo '{
|
|
88
|
+
"userMessage": "⚠️ File access outside primary scope",
|
|
89
|
+
"agentMessage": "File '"$FILE_PATH"' is outside primary scope but allowed",
|
|
90
|
+
"suggestions": [
|
|
91
|
+
"Check if needed in primary scope: edit .caws/working-spec.yaml scope.in",
|
|
92
|
+
"Consider scope implications: caws agent evaluate",
|
|
93
|
+
"Document scope decision in working spec invariants",
|
|
94
|
+
"Validate scope changes: caws validate .caws/working-spec.yaml"
|
|
95
|
+
]
|
|
96
|
+
}'
|
|
97
|
+
fi
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
# For prompt submissions, check working spec compliance
|
|
101
|
+
if [[ "$ACTION" == "submit_prompt" ]]; then
|
|
102
|
+
PROMPT_CONTENT=$(echo "$INPUT" | jq -r '.prompt // ""')
|
|
103
|
+
|
|
104
|
+
# Check if prompt mentions files outside scope
|
|
105
|
+
if [[ -n "$PROMPT_CONTENT" ]]; then
|
|
106
|
+
MENTIONED_FILES=$(echo "$PROMPT_CONTENT" | grep -oE '\b[a-zA-Z0-9_/.-]+\.(js|ts|jsx|tsx|py|go|rs|java|yaml|json|md)\b' | sort | uniq || true)
|
|
107
|
+
|
|
108
|
+
OUT_OF_SCOPE=""
|
|
109
|
+
for file in $MENTIONED_FILES; do
|
|
110
|
+
if [[ -f "$file" ]] && ! caws validate .caws/working-spec.yaml --scope-check "$file" 2>/dev/null | grep -q "in_scope"; then
|
|
111
|
+
OUT_OF_SCOPE="$OUT_OF_SCOPE $file"
|
|
112
|
+
fi
|
|
113
|
+
done
|
|
114
|
+
|
|
115
|
+
if [[ -n "$OUT_OF_SCOPE" ]]; then
|
|
116
|
+
echo '{
|
|
117
|
+
"userMessage": "⚠️ Prompt references files outside CAWS scope",
|
|
118
|
+
"agentMessage": "Prompt mentions out-of-scope files: '"$OUT_OF_SCOPE"'",
|
|
119
|
+
"suggestions": [
|
|
120
|
+
"Check current scope definition: caws validate .caws/working-spec.yaml",
|
|
121
|
+
"Update working spec scope: edit .caws/working-spec.yaml scope.in array",
|
|
122
|
+
"For scope exceptions: caws waivers create --title=\"Scope expansion\" --reason=architectural_refactor --gates=scope_boundary",
|
|
123
|
+
"Refocus prompt on in-scope files or request scope update approval",
|
|
124
|
+
"Validate scope changes: caws validate .caws/working-spec.yaml"
|
|
125
|
+
]
|
|
126
|
+
}'
|
|
127
|
+
fi
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
fi
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# CAWS Tool Validation Hook
|
|
3
|
+
# Validates MCP tool calls against CAWS security policies
|
|
4
|
+
# @author @darianrosebrook
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# Read input from Cursor
|
|
9
|
+
INPUT=$(cat)
|
|
10
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // ""')
|
|
11
|
+
TOOL_ARGS=$(echo "$INPUT" | jq -r '.arguments // "{}"')
|
|
12
|
+
|
|
13
|
+
# Only validate CAWS-related tools
|
|
14
|
+
if [[ "$TOOL_NAME" =~ ^caws_ ]]; then
|
|
15
|
+
|
|
16
|
+
echo "🔍 Validating CAWS tool call: $TOOL_NAME" >&2
|
|
17
|
+
|
|
18
|
+
# Check if CAWS CLI is available
|
|
19
|
+
if ! command -v caws &> /dev/null; then
|
|
20
|
+
echo '{
|
|
21
|
+
"userMessage": "❌ CAWS CLI not available",
|
|
22
|
+
"agentMessage": "Cannot execute CAWS tools - CLI not installed",
|
|
23
|
+
"block": true,
|
|
24
|
+
"suggestions": [
|
|
25
|
+
"Install CAWS CLI: npm install -g @caws/cli",
|
|
26
|
+
"Check PATH includes CAWS CLI"
|
|
27
|
+
]
|
|
28
|
+
}'
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Check if we're in a CAWS project
|
|
33
|
+
if [[ ! -f ".caws/working-spec.yaml" ]]; then
|
|
34
|
+
echo '{
|
|
35
|
+
"userMessage": "⚠️ Not in a CAWS project",
|
|
36
|
+
"agentMessage": "CAWS tools require .caws/working-spec.yaml",
|
|
37
|
+
"suggestions": [
|
|
38
|
+
"Initialize CAWS project: caws init",
|
|
39
|
+
"Create working spec: caws scaffold"
|
|
40
|
+
]
|
|
41
|
+
}'
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Validate tool-specific arguments
|
|
45
|
+
case "$TOOL_NAME" in
|
|
46
|
+
"caws_waiver_create")
|
|
47
|
+
# Check waiver creation permissions
|
|
48
|
+
IMPACT_LEVEL=$(echo "$TOOL_ARGS" | jq -r '.impactLevel // "low"')
|
|
49
|
+
|
|
50
|
+
if [[ "$IMPACT_LEVEL" == "critical" ]]; then
|
|
51
|
+
echo '{
|
|
52
|
+
"userMessage": "🚨 Critical waiver requires approval",
|
|
53
|
+
"agentMessage": "Critical impact waivers need human approval",
|
|
54
|
+
"block": false,
|
|
55
|
+
"warnings": [
|
|
56
|
+
"Critical waivers require code owner review",
|
|
57
|
+
"Waiver will be flagged for manual approval"
|
|
58
|
+
]
|
|
59
|
+
}'
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Check expiration time
|
|
63
|
+
EXPIRES_AT=$(echo "$TOOL_ARGS" | jq -r '.expiresAt // ""')
|
|
64
|
+
if [[ -n "$EXPIRES_AT" ]]; then
|
|
65
|
+
EXPIRE_TIME=$(date -j -f "%Y-%m-%dT%H:%M:%S%Z" "$EXPIRES_AT" +%s 2>/dev/null || echo "")
|
|
66
|
+
CURRENT_TIME=$(date +%s)
|
|
67
|
+
DAYS_DIFF=$(( (EXPIRE_TIME - CURRENT_TIME) / 86400 ))
|
|
68
|
+
|
|
69
|
+
if [[ $DAYS_DIFF -gt 90 ]]; then
|
|
70
|
+
echo '{
|
|
71
|
+
"userMessage": "⚠️ Waiver expiration too far in future",
|
|
72
|
+
"agentMessage": "Waivers cannot exceed 90 days expiration",
|
|
73
|
+
"suggestions": [
|
|
74
|
+
"Reduce expiration time to within 90 days",
|
|
75
|
+
"Consider shorter waiver periods for better security"
|
|
76
|
+
]
|
|
77
|
+
}'
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
;;
|
|
81
|
+
|
|
82
|
+
"caws_evaluate"|"caws_iterate")
|
|
83
|
+
# These are generally safe to run
|
|
84
|
+
echo '{"userMessage": "✅ CAWS quality tool validated", "agentMessage": "Tool execution approved"}'
|
|
85
|
+
;;
|
|
86
|
+
|
|
87
|
+
*)
|
|
88
|
+
# Unknown CAWS tool - allow but warn
|
|
89
|
+
echo '{
|
|
90
|
+
"userMessage": "⚠️ Unknown CAWS tool",
|
|
91
|
+
"agentMessage": "Tool '"'"$TOOL_NAME"'"' not recognized - proceeding with caution",
|
|
92
|
+
"suggestions": [
|
|
93
|
+
"Verify tool name and arguments",
|
|
94
|
+
"Check CAWS CLI documentation"
|
|
95
|
+
]
|
|
96
|
+
}'
|
|
97
|
+
;;
|
|
98
|
+
esac
|
|
99
|
+
|
|
100
|
+
elif [[ "$TOOL_NAME" =~ (exec|shell|run|terminal) ]]; then
|
|
101
|
+
# Generic shell execution - check for dangerous commands
|
|
102
|
+
COMMAND=$(echo "$TOOL_ARGS" | jq -r '.command // .cmd // ""')
|
|
103
|
+
|
|
104
|
+
DANGEROUS_COMMANDS=("rm -rf" "rm -rf /" "format" "mkfs" "dd" "fdisk" ">" "sudo" "chmod 777")
|
|
105
|
+
|
|
106
|
+
for dangerous in "${DANGEROUS_COMMANDS[@]}"; do
|
|
107
|
+
if [[ "$COMMAND" =~ $dangerous ]]; then
|
|
108
|
+
echo '{
|
|
109
|
+
"userMessage": "🚫 Dangerous command blocked",
|
|
110
|
+
"agentMessage": "Command contains dangerous operations: '"'"$dangerous"'"'",
|
|
111
|
+
"block": true,
|
|
112
|
+
"suggestions": [
|
|
113
|
+
"Avoid destructive operations",
|
|
114
|
+
"Use safer alternatives",
|
|
115
|
+
"Get explicit approval for dangerous commands"
|
|
116
|
+
]
|
|
117
|
+
}'
|
|
118
|
+
exit 1
|
|
119
|
+
fi
|
|
120
|
+
done
|
|
121
|
+
fi
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Cursor Hook: Auto-formatting
|
|
3
|
+
#
|
|
4
|
+
# Purpose: Run formatters after file edits
|
|
5
|
+
# Event: afterFileEdit
|
|
6
|
+
#
|
|
7
|
+
# @author @darianrosebrook
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
# Read input from Cursor
|
|
12
|
+
INPUT=$(cat)
|
|
13
|
+
|
|
14
|
+
# Extract file path
|
|
15
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // ""')
|
|
16
|
+
|
|
17
|
+
# Only format source code files
|
|
18
|
+
if [[ "$FILE_PATH" =~ \.(js|ts|jsx|tsx|json|md|yml|yaml)$ ]]; then
|
|
19
|
+
# Try prettier if available
|
|
20
|
+
if command -v prettier &> /dev/null; then
|
|
21
|
+
prettier --write "$FILE_PATH" 2>/dev/null || true
|
|
22
|
+
elif [ -f "node_modules/.bin/prettier" ]; then
|
|
23
|
+
node_modules/.bin/prettier --write "$FILE_PATH" 2>/dev/null || true
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Try eslint for JS/TS files
|
|
27
|
+
if [[ "$FILE_PATH" =~ \.(js|ts|jsx|tsx)$ ]]; then
|
|
28
|
+
if command -v eslint &> /dev/null; then
|
|
29
|
+
eslint --fix "$FILE_PATH" 2>/dev/null || true
|
|
30
|
+
elif [ -f "node_modules/.bin/eslint" ]; then
|
|
31
|
+
node_modules/.bin/eslint --fix "$FILE_PATH" 2>/dev/null || true
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# Always allow - formatting is non-blocking
|
|
37
|
+
exit 0
|
|
38
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Cursor Hook: Naming Conventions
|
|
3
|
+
#
|
|
4
|
+
# Purpose: Enforce CAWS naming conventions (no enhanced-, -copy, etc.)
|
|
5
|
+
# Event: afterFileEdit
|
|
6
|
+
#
|
|
7
|
+
# @author @darianrosebrook
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
# Read input from Cursor
|
|
12
|
+
INPUT=$(cat)
|
|
13
|
+
|
|
14
|
+
# Extract file path
|
|
15
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // ""')
|
|
16
|
+
|
|
17
|
+
# Get just the filename
|
|
18
|
+
FILENAME=$(basename "$FILE_PATH")
|
|
19
|
+
|
|
20
|
+
# Check for banned naming patterns
|
|
21
|
+
BANNED_PATTERNS=(
|
|
22
|
+
"enhanced-"
|
|
23
|
+
"-enhanced"
|
|
24
|
+
"unified-"
|
|
25
|
+
"-unified"
|
|
26
|
+
"better-"
|
|
27
|
+
"-better"
|
|
28
|
+
"new-"
|
|
29
|
+
"-new"
|
|
30
|
+
"next-"
|
|
31
|
+
"-next"
|
|
32
|
+
"final-"
|
|
33
|
+
"-final"
|
|
34
|
+
"-copy"
|
|
35
|
+
"copy-"
|
|
36
|
+
"-revamp"
|
|
37
|
+
"revamp-"
|
|
38
|
+
"-improved"
|
|
39
|
+
"improved-"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
for pattern in "${BANNED_PATTERNS[@]}"; do
|
|
43
|
+
if [[ "$FILENAME" == *"$pattern"* ]]; then
|
|
44
|
+
# Extract the pattern for the message
|
|
45
|
+
echo '{"userMessage":"⚠️ Naming violation: File contains banned pattern '"'$pattern'"'. Use purpose-driven names instead.","agentMessage":"This file uses a generic naming pattern ('"$pattern"'). Please rename with a specific, purpose-driven name that describes what the file does."}' 2>/dev/null
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
done
|
|
49
|
+
|
|
50
|
+
# Check for duplicate module patterns (e.g., both processor.ts and enhanced-processor.ts)
|
|
51
|
+
if [[ "$FILENAME" =~ ^(enhanced|unified|better|new|next|final|improved)- ]]; then
|
|
52
|
+
BASE_NAME=$(echo "$FILENAME" | sed -E 's/^(enhanced|unified|better|new|next|final|improved)-//')
|
|
53
|
+
DIR_PATH=$(dirname "$FILE_PATH")
|
|
54
|
+
|
|
55
|
+
# Check if base file exists
|
|
56
|
+
if [ -f "$DIR_PATH/$BASE_NAME" ]; then
|
|
57
|
+
echo '{"userMessage":"⚠️ Duplicate module detected: Both '"$FILENAME"' and '"$BASE_NAME"' exist. Merge into canonical name.","agentMessage":"Found duplicate modules. Please merge '"$FILENAME"' into '"$BASE_NAME"' and remove the duplicate."}' 2>/dev/null
|
|
58
|
+
exit 0
|
|
59
|
+
fi
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Allow by default
|
|
63
|
+
exit 0
|
|
64
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Cursor Hook: Secret & PII Scanner
|
|
3
|
+
#
|
|
4
|
+
# Purpose: Prevent reading files with secrets or sensitive information
|
|
5
|
+
# Event: beforeReadFile
|
|
6
|
+
#
|
|
7
|
+
# @author @darianrosebrook
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
# Read input from Cursor
|
|
12
|
+
INPUT=$(cat)
|
|
13
|
+
|
|
14
|
+
# Extract file path and content
|
|
15
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // ""')
|
|
16
|
+
CONTENT=$(echo "$INPUT" | jq -r '.content // ""')
|
|
17
|
+
|
|
18
|
+
# Block reading of environment files
|
|
19
|
+
if [[ "$FILE_PATH" =~ \.(env|env\.local|env\.development|env\.production|env\.test)$ ]]; then
|
|
20
|
+
echo '{"permission":"deny","userMessage":"⚠️ Blocked: Environment files contain secrets. Use placeholder values instead."}' 2>/dev/null
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Block reading of key files
|
|
25
|
+
if [[ "$FILE_PATH" =~ \.(pem|key|p12|pfx|cert|crt)$ ]]; then
|
|
26
|
+
echo '{"permission":"deny","userMessage":"⚠️ Blocked: Certificate/key files should not be read by AI."}' 2>/dev/null
|
|
27
|
+
exit 0
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# Scan content for common secret patterns
|
|
31
|
+
if echo "$CONTENT" | grep -qiE "(api[_-]?key|secret[_-]?key|password|private[_-]?key|access[_-]?token|bearer\s+[A-Za-z0-9_\-\.]+|AKIA[0-9A-Z]{16})"; then
|
|
32
|
+
# Don't block, but warn
|
|
33
|
+
echo '{"permission":"allow","userMessage":"⚠️ Warning: Potential secrets detected in file. Ensure they are not committed.","agentMessage":"This file may contain secrets. Use placeholder values or environment variables."}' 2>/dev/null
|
|
34
|
+
exit 0
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Check for common PII patterns (SSN, credit card, etc.)
|
|
38
|
+
if echo "$CONTENT" | grep -qE "([0-9]{3}-[0-9]{2}-[0-9]{4}|[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4})"; then
|
|
39
|
+
echo '{"permission":"allow","userMessage":"⚠️ Warning: Potential PII detected. Ensure compliance with data protection policies.","agentMessage":"This file may contain PII (SSN, credit card). Use anonymized test data."}' 2>/dev/null
|
|
40
|
+
exit 0
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Allow by default
|
|
44
|
+
echo '{"permission":"allow"}' 2>/dev/null
|
|
45
|
+
exit 0
|
|
46
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Cursor Hook: Scope Guard
|
|
3
|
+
#
|
|
4
|
+
# Purpose: Check if files being worked on are within working-spec scope
|
|
5
|
+
# Event: beforeSubmitPrompt
|
|
6
|
+
#
|
|
7
|
+
# @author @darianrosebrook
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
# Read input from Cursor
|
|
12
|
+
INPUT=$(cat)
|
|
13
|
+
|
|
14
|
+
# Extract attachments
|
|
15
|
+
ATTACHMENTS=$(echo "$INPUT" | jq -r '.attachments // []')
|
|
16
|
+
|
|
17
|
+
# Only check if we have file attachments and a working spec
|
|
18
|
+
if [ ! -f ".caws/working-spec.yaml" ] && [ ! -f ".caws/working-spec.yml" ]; then
|
|
19
|
+
# No spec file, allow by default
|
|
20
|
+
echo '{"continue":true}' 2>/dev/null
|
|
21
|
+
exit 0
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Check if scope-guard tool exists
|
|
25
|
+
if [ -f ".caws/tools/scope-guard.js" ]; then
|
|
26
|
+
# Extract file paths from attachments
|
|
27
|
+
FILE_PATHS=$(echo "$ATTACHMENTS" | jq -r '.[] | select(.type=="file") | .file_path' 2>/dev/null || echo "")
|
|
28
|
+
|
|
29
|
+
if [ -n "$FILE_PATHS" ]; then
|
|
30
|
+
# Check each file against scope
|
|
31
|
+
OUT_OF_SCOPE=()
|
|
32
|
+
while IFS= read -r file; do
|
|
33
|
+
if [ -n "$file" ]; then
|
|
34
|
+
if ! node .caws/tools/scope-guard.js check "$file" 2>/dev/null; then
|
|
35
|
+
OUT_OF_SCOPE+=("$file")
|
|
36
|
+
fi
|
|
37
|
+
fi
|
|
38
|
+
done <<< "$FILE_PATHS"
|
|
39
|
+
|
|
40
|
+
# If any files are out of scope, warn but don't block
|
|
41
|
+
if [ ${#OUT_OF_SCOPE[@]} -gt 0 ]; then
|
|
42
|
+
FILES_LIST=$(printf '%s\n' "${OUT_OF_SCOPE[@]}")
|
|
43
|
+
echo '{"continue":true,"userMessage":"⚠️ Warning: Some attached files may be outside working-spec scope:\n'"$FILES_LIST"'","agentMessage":"Some files are outside the defined scope in working-spec.yaml. Consider updating the scope or removing these files."}' 2>/dev/null
|
|
44
|
+
exit 0
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Allow by default
|
|
50
|
+
echo '{"continue":true}' 2>/dev/null
|
|
51
|
+
exit 0
|
|
52
|
+
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Cursor Hook: CAWS Spec Validation
|
|
3
|
+
#
|
|
4
|
+
# Purpose: Validate working-spec.yaml when it's edited
|
|
5
|
+
# Event: afterFileEdit
|
|
6
|
+
#
|
|
7
|
+
# @author @darianrosebrook
|
|
8
|
+
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
|
|
11
|
+
# Read input from Cursor
|
|
12
|
+
INPUT=$(cat)
|
|
13
|
+
|
|
14
|
+
# Extract file path from input
|
|
15
|
+
FILE_PATH=$(echo "$INPUT" | jq -r '.file_path // ""')
|
|
16
|
+
|
|
17
|
+
# Validate if any CAWS YAML file was edited (.caws/**/*.yaml or .caws/**/*.yml)
|
|
18
|
+
if [[ "$FILE_PATH" == *".caws/"* ]] && ([[ "$FILE_PATH" == *.yaml ]] || [[ "$FILE_PATH" == *.yml ]]); then
|
|
19
|
+
echo "🔍 Validating CAWS spec file..." >&2
|
|
20
|
+
|
|
21
|
+
# First, validate YAML syntax
|
|
22
|
+
if command -v node >/dev/null 2>&1; then
|
|
23
|
+
# Check YAML syntax using Node.js
|
|
24
|
+
YAML_SYNTAX_VALID=$(node -e "
|
|
25
|
+
const yaml = require('js-yaml');
|
|
26
|
+
const fs = require('fs');
|
|
27
|
+
try {
|
|
28
|
+
const content = fs.readFileSync('$FILE_PATH', 'utf8');
|
|
29
|
+
yaml.load(content);
|
|
30
|
+
process.exit(0);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('YAML syntax error:', error.message);
|
|
33
|
+
if (error.mark) {
|
|
34
|
+
console.error('Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
|
|
35
|
+
}
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
" 2>&1)
|
|
39
|
+
|
|
40
|
+
if [ $? -ne 0 ]; then
|
|
41
|
+
echo '{
|
|
42
|
+
"userMessage": "⚠️ YAML syntax error detected",
|
|
43
|
+
"agentMessage": "The spec file has invalid YAML syntax. Fix syntax errors before continuing.",
|
|
44
|
+
"suggestions": [
|
|
45
|
+
"Check indentation (YAML uses 2 spaces)",
|
|
46
|
+
"Ensure all array items use consistent format",
|
|
47
|
+
"Remove duplicate keys",
|
|
48
|
+
"Consider using '\''caws specs create <id>'\'' instead of manual creation"
|
|
49
|
+
]
|
|
50
|
+
}' 2>/dev/null
|
|
51
|
+
exit 0
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Check if CAWS CLI is available for semantic validation
|
|
56
|
+
if command -v caws &> /dev/null; then
|
|
57
|
+
# Run CAWS validation with suggestions
|
|
58
|
+
if VALIDATION=$(caws validate "$FILE_PATH" --quiet 2>&1); then
|
|
59
|
+
echo '{"userMessage":"✅ CAWS spec validation passed","agentMessage":"Specification is valid and complete."}' 2>/dev/null
|
|
60
|
+
else
|
|
61
|
+
# Get suggestions for fixing the spec
|
|
62
|
+
SUGGESTIONS=$(caws validate "$FILE_PATH" --suggestions 2>/dev/null | head -5 | tr '\n' '; ' | sed 's/; $//' || echo "Run caws validate --suggestions for details")
|
|
63
|
+
|
|
64
|
+
echo '{
|
|
65
|
+
"userMessage": "⚠️ CAWS spec validation failed. Run: caws validate --suggestions",
|
|
66
|
+
"agentMessage": "The spec file has validation errors. Please review and fix before continuing.",
|
|
67
|
+
"suggestions": [
|
|
68
|
+
"Run caws validate --suggestions for detailed error messages",
|
|
69
|
+
"Check required fields: id, title, risk_tier, mode",
|
|
70
|
+
"Ensure acceptance criteria are properly defined",
|
|
71
|
+
"Verify scope boundaries are appropriate",
|
|
72
|
+
"Consider using '\''caws specs create <id>'\'' for proper structure"
|
|
73
|
+
]
|
|
74
|
+
}' 2>/dev/null
|
|
75
|
+
fi
|
|
76
|
+
else
|
|
77
|
+
echo '{"userMessage":"⚠️ CAWS CLI not available for validation","agentMessage":"Install CAWS CLI for automatic spec validation: npm install -g @caws/cli"}' 2>/dev/null
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
|
|
81
|
+
# Allow the edit
|
|
82
|
+
exit 0
|
|
83
|
+
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"hooks": {
|
|
4
|
+
"beforeShellExecution": [
|
|
5
|
+
{
|
|
6
|
+
"command": "./.cursor/hooks/block-dangerous.sh"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"command": "./.cursor/hooks/audit.sh"
|
|
10
|
+
}
|
|
11
|
+
],
|
|
12
|
+
"beforeMCPExecution": [
|
|
13
|
+
{
|
|
14
|
+
"command": "./.cursor/hooks/audit.sh"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"command": "./.cursor/hooks/caws-tool-validation.sh"
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"beforeReadFile": [
|
|
21
|
+
{
|
|
22
|
+
"command": "./.cursor/hooks/scan-secrets.sh"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"command": "./.cursor/hooks/caws-scope-guard.sh"
|
|
26
|
+
}
|
|
27
|
+
],
|
|
28
|
+
"afterFileEdit": [
|
|
29
|
+
{
|
|
30
|
+
"command": "./.cursor/hooks/format.sh"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"command": "./.cursor/hooks/naming-check.sh"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"command": "./.cursor/hooks/validate-spec.sh"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"command": "./.cursor/hooks/caws-quality-check.sh"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"command": "./.cursor/hooks/audit.sh"
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"beforeSubmitPrompt": [
|
|
46
|
+
{
|
|
47
|
+
"command": "./.cursor/hooks/caws-scope-guard.sh"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"command": "./.cursor/hooks/audit.sh"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"stop": [
|
|
54
|
+
{
|
|
55
|
+
"command": "./.cursor/hooks/audit.sh"
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
}
|