@paths.design/caws-cli 9.1.1 → 9.3.0

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 (48) hide show
  1. package/dist/budget-derivation.js +15 -3
  2. package/dist/commands/specs.js +28 -15
  3. package/dist/commands/status.js +1 -1
  4. package/dist/commands/verify-acs.js +471 -0
  5. package/dist/commands/worktree.js +107 -15
  6. package/dist/index.js +21 -1
  7. package/dist/parallel/parallel-manager.js +5 -12
  8. package/dist/scaffold/cursor-hooks.js +0 -1
  9. package/dist/scaffold/git-hooks.js +18 -1
  10. package/dist/templates/.caws/tools/README.md +4 -7
  11. package/dist/templates/.caws/tools/scope-guard.js +115 -171
  12. package/dist/templates/.claude/hooks/audit.sh +25 -0
  13. package/dist/templates/.claude/hooks/block-dangerous.sh +39 -0
  14. package/dist/templates/.claude/hooks/lite-sprawl-check.sh +30 -2
  15. package/dist/templates/.claude/hooks/naming-check.sh +5 -2
  16. package/dist/templates/.claude/hooks/scope-guard.sh +66 -4
  17. package/dist/templates/.claude/hooks/session-log.sh +38 -5
  18. package/dist/templates/.claude/hooks/worktree-write-guard.sh +13 -1
  19. package/dist/templates/.claude/rules/worktree-isolation.md +36 -4
  20. package/dist/templates/.cursor/README.md +0 -9
  21. package/dist/templates/.cursor/hooks/audit.sh +1 -1
  22. package/dist/templates/.cursor/hooks/block-dangerous.sh +1 -0
  23. package/dist/templates/.cursor/hooks/scan-secrets.sh +8 -3
  24. package/dist/templates/.cursor/hooks.json +0 -8
  25. package/dist/templates/.vscode/launch.json +0 -12
  26. package/dist/utils/detection.js +37 -0
  27. package/dist/utils/project-analysis.js +0 -1
  28. package/dist/utils/spec-resolver.js +23 -10
  29. package/dist/validation/spec-validation.js +8 -0
  30. package/dist/worktree/worktree-manager.js +242 -6
  31. package/package.json +1 -1
  32. package/templates/.caws/tools/README.md +4 -7
  33. package/templates/.caws/tools/scope-guard.js +115 -171
  34. package/templates/.claude/hooks/audit.sh +25 -0
  35. package/templates/.claude/hooks/block-dangerous.sh +39 -0
  36. package/templates/.claude/hooks/lite-sprawl-check.sh +30 -2
  37. package/templates/.claude/hooks/naming-check.sh +5 -2
  38. package/templates/.claude/hooks/scope-guard.sh +66 -4
  39. package/templates/.claude/hooks/session-log.sh +38 -5
  40. package/templates/.claude/hooks/worktree-write-guard.sh +13 -1
  41. package/templates/.claude/rules/worktree-isolation.md +36 -4
  42. package/templates/.cursor/README.md +0 -9
  43. package/templates/.cursor/hooks/audit.sh +1 -1
  44. package/templates/.cursor/hooks/block-dangerous.sh +1 -0
  45. package/templates/.cursor/hooks/scan-secrets.sh +8 -3
  46. package/templates/.cursor/hooks.json +0 -8
  47. package/templates/.vscode/launch.json +0 -12
  48. package/templates/.cursor/hooks/caws-tool-validation.sh +0 -121
@@ -65,13 +65,22 @@ if [[ "$WT_COUNT" -le 0 ]] 2>/dev/null; then
65
65
  exit 0
66
66
  fi
67
67
 
68
- # Allow edits to .claude/ configuration (hooks, settings, rules)
68
+ # Allow edits to configuration and documentation (benign, no merge conflict risk)
69
69
  if [[ -n "$FILE_PATH" ]]; then
70
70
  case "$FILE_PATH" in
71
71
  */.claude/*|*/.caws/*) exit 0 ;;
72
+ */docs/*) exit 0 ;;
72
73
  esac
73
74
  fi
74
75
 
76
+ # Allow edits during an active merge (conflict resolution).
77
+ # The worktree-isolation rules explicitly permit merge commits on the base branch.
78
+ # Conflict resolution requires Write/Edit on the conflicted files.
79
+ MERGE_HEAD_PATH=$(cd "$AGENT_DIR" && git rev-parse --git-dir 2>/dev/null || echo ".git")
80
+ if [[ -f "$MERGE_HEAD_PATH/MERGE_HEAD" ]]; then
81
+ exit 0
82
+ fi
83
+
75
84
  # Block: we're on the base branch with active worktrees
76
85
  echo "BLOCKED: Cannot write/edit files on '$CURRENT_BRANCH' while $WT_COUNT worktree(s) are active: $WT_NAMES" >&2
77
86
  echo "" >&2
@@ -81,4 +90,7 @@ echo " To create a new worktree: caws worktree create <name>" >&2
81
90
  echo "" >&2
82
91
  echo "Do NOT make changes on main and create a worktree retroactively." >&2
83
92
  echo "The worktree must exist BEFORE you start making changes." >&2
93
+ echo "" >&2
94
+ echo "If you are merging a worktree branch, use: caws worktree merge <name>" >&2
95
+ echo "Or start the merge first (git merge --no-ff <branch>), then resolve conflicts." >&2
84
96
  exit 2
@@ -9,29 +9,62 @@ When multiple agents are working on this project, each agent MUST work in its ow
9
9
 
10
10
  ## Before starting work
11
11
 
12
- 1. Check if worktrees exist: look for `.caws/worktrees.json` or `.caws/parallel.json`
12
+ 1. Check if worktrees exist: `caws worktree list` shows all active worktrees with last commit time and owner
13
13
  2. If worktrees are active and you are on the base branch, switch to your assigned worktree
14
14
  3. If no worktree exists for you, create one with `caws worktree create <name>` or `caws parallel setup <plan-file>`
15
+ 4. **Never touch a worktree you did not create.** Do not destroy, prune, stash, or "clean up" another agent's worktree — even if it looks stale. Another agent may be actively working in it. If you think a worktree is abandoned, leave it alone and let the user decide.
15
16
 
16
17
  ## Forbidden operations when worktrees are active
17
18
 
18
19
  - `git commit --amend` -- rewrites history that other agents depend on
20
+ - `git rebase` -- rewrites branch history; the hook blocks this automatically while worktrees are active. If you need code from main, create a new worktree from current main instead
21
+ - `git cherry-pick` -- replays commits across branches; blocked while worktrees are active to prevent cross-boundary contamination
19
22
  - `git stash` / `git stash pop` -- stash is shared across all worktrees; using it can destroy another agent's uncommitted work
20
23
  - `git reset --hard` -- discards work that other agents may depend on
21
24
  - `git push --force` -- rewrites remote history
22
25
  - Direct commits to the base branch -- only `merge(worktree):` and `wip(checkpoint):` formats are allowed
23
26
  - Copying files between your worktree and the main repo directory -- defeats isolation
27
+ - Destroying another agent's worktree -- even with `--force`. If you did not create it, do not destroy it. Period.
24
28
 
25
29
  ## Merging worktree branches back to base
26
30
 
27
31
  Merge commits ARE allowed on the base branch while other worktrees are active. This lets you incrementally merge completed work without waiting for all agents to finish.
28
32
 
33
+ ### Recommended: use `caws worktree merge`
34
+
35
+ The `merge` command handles the full sequence (conflict check, destroy, merge, cleanup):
36
+
37
+ ```bash
38
+ # Preview conflicts before merging
39
+ caws worktree merge <name> --dry-run
40
+
41
+ # Merge (destroys worktree, merges branch, deletes branch)
42
+ caws worktree merge <name>
43
+
44
+ # Merge with custom commit message
45
+ caws worktree merge <name> --message "merge(worktree): description of changes"
46
+ ```
47
+
48
+ ### Manual merge (if you need more control)
49
+
29
50
  1. Destroy the worktree first: `caws worktree destroy <name>`
30
51
  2. Switch to the base branch: `git checkout main`
31
52
  3. Merge with: `git merge --no-ff <worktree-branch>`
32
53
  4. The commit-msg hook enforces the `merge(worktree): <description>` format for non-FF merges
33
54
  5. For manual merge commits: `git commit -m "merge(worktree): integrate scenarios work"`
34
55
 
56
+ ### Conflict resolution during merge
57
+
58
+ The write guard allows edits on the base branch while a merge is in progress (MERGE_HEAD exists). This lets you resolve merge conflicts without needing to abort and retry. After resolving, commit with the `merge(worktree):` format.
59
+
60
+ ## What the write guard allows on the base branch
61
+
62
+ Even when worktrees are active, the following edits are allowed on the base branch:
63
+
64
+ - `.claude/` and `.caws/` configuration files
65
+ - `docs/` directory (documentation changes are benign)
66
+ - Any file while a merge is in progress (conflict resolution)
67
+
35
68
  ## Virtual environment in worktrees
36
69
 
37
70
  Do NOT create a new virtual environment in your worktree. Use the main repo's venv:
@@ -46,6 +79,5 @@ If your project uses `.caws/scope.json`, the `designatedVenvPath` field specifie
46
79
 
47
80
  1. Commit all changes to your worktree branch
48
81
  2. Run tests in your worktree to verify
49
- 3. Destroy your worktree with `caws worktree destroy <name>`
50
- 4. Merge your branch to base: `git merge --no-ff <branch>` (uses `merge(worktree):` format)
51
- 5. Delete the branch if no longer needed: `git branch -d <branch>`
82
+ 3. Merge: `caws worktree merge <name>` (handles destroy + merge + branch cleanup)
83
+ 4. Or manually: destroy worktree, then `git merge --no-ff <branch>`, then delete branch
@@ -9,7 +9,6 @@ Cursor hooks enable seamless integration between CAWS and the Cursor IDE, provid
9
9
  - **Real-time quality validation** as you code
10
10
  - **Automatic spec validation** when editing working specs
11
11
  - **Scope enforcement** preventing out-of-scope file access
12
- - **Tool validation** for safe MCP execution
13
12
  - **Quality monitoring** after file edits
14
13
 
15
14
  ## Hook Configuration
@@ -19,7 +18,6 @@ The `hooks.json` file defines when each hook runs:
19
18
  ```json
20
19
  {
21
20
  "beforeShellExecution": ["block-dangerous.sh", "audit.sh"],
22
- "beforeMCPExecution": ["audit.sh", "caws-tool-validation.sh"],
23
21
  "beforeReadFile": ["scan-secrets.sh", "caws-scope-guard.sh"],
24
22
  "afterFileEdit": ["format.sh", "naming-check.sh", "validate-spec.sh", "caws-quality-check.sh", "audit.sh"],
25
23
  "beforeSubmitPrompt": ["caws-scope-guard.sh", "audit.sh"],
@@ -43,12 +41,6 @@ The `hooks.json` file defines when each hook runs:
43
41
  - **Blocks**: Yes (for out-of-scope file access)
44
42
  - **Requires**: `.caws/working-spec.yaml`
45
43
 
46
- #### `caws-tool-validation.sh`
47
- - **Trigger**: `beforeMCPExecution`
48
- - **Purpose**: Validates CAWS MCP tool calls for security
49
- - **Blocks**: Yes (for dangerous operations or invalid waivers)
50
- - **Validates**: Waiver creation, tool permissions, command safety
51
-
52
44
  ### General Security Hooks
53
45
 
54
46
  #### `block-dangerous.sh`
@@ -242,7 +234,6 @@ Cursor Hooks ←→ CAWS CLI ←→ VS Code Extension
242
234
 
243
235
  - **Git Hooks**: `.git/hooks/` for commit/push validation
244
236
  - **VS Code Extension**: Rich UI for CAWS operations
245
- - **MCP Server**: Agent tool integration
246
237
  - **CAWS CLI**: Core functionality
247
238
 
248
239
  ### Data Flow
@@ -2,7 +2,7 @@
2
2
  # Cursor Hook: Audit Trail
3
3
  #
4
4
  # Purpose: Log all Cursor AI events for provenance tracking
5
- # Event: All (beforeShellExecution, beforeMCPExecution, beforeReadFile,
5
+ # Event: All (beforeShellExecution, beforeReadFile,
6
6
  # afterFileEdit, beforeSubmitPrompt, stop)
7
7
  #
8
8
  # @author @darianrosebrook
@@ -29,6 +29,7 @@ HARD_BLOCKS=(
29
29
  "git commit --amend --no-edit" # Can rewrite commit history destructively
30
30
  "git reset --hard" # Can lose uncommitted work and stashed changes
31
31
  "git push --force" # Can overwrite remote repository history
32
+ "git rebase" # Rewrites branch history; blocked while worktrees are active
32
33
  "dd if="
33
34
  "mkfs"
34
35
  "format c:"
@@ -28,14 +28,19 @@ if [[ "$FILE_PATH" =~ \.(pem|key|p12|pfx|cert|crt)$ ]]; then
28
28
  fi
29
29
 
30
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
31
+ # bearer requires 20+ chars to avoid false positives on short tokens in docs
32
+ # AKIA prefix is specific to AWS access keys
33
+ if echo "$CONTENT" | grep -qiE "(api[_-]?key\s*[:=]\s*['\"]?[A-Za-z0-9_\-]{16,}|secret[_-]?key\s*[:=]\s*['\"]?[A-Za-z0-9_\-]{16,}|password\s*[:=]\s*['\"]?[^\s'\"]{8,}|private[_-]?key\s*[:=]|access[_-]?token\s*[:=]\s*['\"]?[A-Za-z0-9_\-]{16,}|[Bb]earer\s+[A-Za-z0-9_\-\.]{20,}|AKIA[0-9A-Z]{16})"; then
32
34
  # Don't block, but warn
33
35
  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
36
  exit 0
35
37
  fi
36
38
 
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
+ # Check for common PII patterns (SSN, credit card)
40
+ # SSN: exactly 3-2-4 digit pattern (not inside longer numbers)
41
+ # Credit card: require at least a Luhn-plausible 13-19 digit sequence with separators
42
+ if echo "$CONTENT" | grep -qE "(^|[^0-9])[0-9]{3}-[0-9]{2}-[0-9]{4}($|[^0-9])" || \
43
+ echo "$CONTENT" | grep -qE "(^|[^0-9])[0-9]{4}[- ][0-9]{4}[- ][0-9]{4}[- ][0-9]{4}($|[^0-9])"; then
39
44
  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
45
  exit 0
41
46
  fi
@@ -9,14 +9,6 @@
9
9
  "command": "./.cursor/hooks/audit.sh"
10
10
  }
11
11
  ],
12
- "beforeMCPExecution": [
13
- {
14
- "command": "./.cursor/hooks/audit.sh"
15
- },
16
- {
17
- "command": "./.cursor/hooks/caws-tool-validation.sh"
18
- }
19
- ],
20
12
  "beforeReadFile": [
21
13
  {
22
14
  "command": "./.cursor/hooks/scan-secrets.sh"
@@ -1,18 +1,6 @@
1
1
  {
2
2
  "version": "0.2.0",
3
3
  "configurations": [
4
- {
5
- "name": "Debug MCP Server",
6
- "type": "node",
7
- "request": "launch",
8
- "program": "${workspaceFolder}/packages/caws-mcp-server/index.js",
9
- "args": [],
10
- "env": {
11
- "NODE_ENV": "development",
12
- "CAWS_DEBUG": "true"
13
- },
14
- "console": "integratedTerminal"
15
- },
16
4
  {
17
5
  "name": "Debug CAWS CLI",
18
6
  "type": "node",
@@ -1,121 +0,0 @@
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