sequant 2.0.1 → 2.1.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 (58) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/dist/bin/cli.js +2 -1
  4. package/dist/marketplace/external_plugins/sequant/.claude-plugin/plugin.json +1 -1
  5. package/dist/marketplace/external_plugins/sequant/.mcp.json +6 -0
  6. package/dist/marketplace/external_plugins/sequant/README.md +58 -8
  7. package/dist/marketplace/external_plugins/sequant/hooks/post-tool.sh +19 -8
  8. package/dist/marketplace/external_plugins/sequant/hooks/pre-tool.sh +36 -49
  9. package/dist/marketplace/external_plugins/sequant/skills/_shared/references/subagent-types.md +158 -48
  10. package/dist/marketplace/external_plugins/sequant/skills/assess/SKILL.md +354 -352
  11. package/dist/marketplace/external_plugins/sequant/skills/exec/SKILL.md +1155 -33
  12. package/dist/marketplace/external_plugins/sequant/skills/fullsolve/SKILL.md +35 -4
  13. package/dist/marketplace/external_plugins/sequant/skills/qa/SKILL.md +2157 -104
  14. package/dist/marketplace/external_plugins/sequant/skills/qa/scripts/quality-checks.sh +1 -1
  15. package/dist/marketplace/external_plugins/sequant/skills/setup/SKILL.md +386 -0
  16. package/dist/marketplace/external_plugins/sequant/skills/solve/SKILL.md +38 -664
  17. package/dist/marketplace/external_plugins/sequant/skills/spec/SKILL.md +505 -120
  18. package/dist/marketplace/external_plugins/sequant/skills/test/SKILL.md +246 -1
  19. package/dist/marketplace/external_plugins/sequant/skills/testgen/SKILL.md +138 -1
  20. package/dist/src/commands/dashboard.js +1 -1
  21. package/dist/src/commands/doctor.js +1 -1
  22. package/dist/src/commands/init.js +10 -10
  23. package/dist/src/commands/logs.js +1 -1
  24. package/dist/src/commands/run.js +49 -39
  25. package/dist/src/commands/state.js +3 -3
  26. package/dist/src/commands/status.js +5 -5
  27. package/dist/src/commands/sync.js +8 -8
  28. package/dist/src/commands/update.js +16 -16
  29. package/dist/src/lib/cli-ui.js +20 -19
  30. package/dist/src/lib/merge-check/index.js +2 -2
  31. package/dist/src/lib/settings.d.ts +8 -0
  32. package/dist/src/lib/settings.js +1 -0
  33. package/dist/src/lib/shutdown.js +1 -1
  34. package/dist/src/lib/templates.js +2 -0
  35. package/dist/src/lib/wizard.js +6 -4
  36. package/dist/src/lib/workflow/batch-executor.js +1 -1
  37. package/dist/src/lib/workflow/log-writer.js +6 -6
  38. package/dist/src/lib/workflow/metrics-writer.js +5 -3
  39. package/dist/src/lib/workflow/phase-executor.js +5 -1
  40. package/dist/src/lib/workflow/platforms/github.js +5 -1
  41. package/dist/src/lib/workflow/state-cleanup.js +1 -1
  42. package/dist/src/lib/workflow/state-manager.js +15 -13
  43. package/dist/src/lib/workflow/state-rebuild.js +2 -2
  44. package/dist/src/lib/workflow/types.d.ts +11 -0
  45. package/dist/src/lib/workflow/worktree-manager.js +40 -41
  46. package/dist/src/lib/worktree-isolation.d.ts +130 -0
  47. package/dist/src/lib/worktree-isolation.js +310 -0
  48. package/package.json +8 -8
  49. package/templates/agents/sequant-explorer.md +23 -0
  50. package/templates/agents/sequant-implementer.md +18 -0
  51. package/templates/agents/sequant-qa-checker.md +24 -0
  52. package/templates/agents/sequant-testgen.md +25 -0
  53. package/templates/scripts/cleanup-worktree.sh +18 -0
  54. package/templates/skills/_shared/references/subagent-types.md +158 -48
  55. package/templates/skills/exec/SKILL.md +72 -6
  56. package/templates/skills/qa/SKILL.md +8 -217
  57. package/templates/skills/spec/SKILL.md +446 -120
  58. package/templates/skills/testgen/SKILL.md +138 -1
@@ -8,7 +8,7 @@
8
8
  {
9
9
  "name": "sequant",
10
10
  "description": "Structured workflow system for Claude Code - GitHub issue resolution with spec, exec, test, and QA phases. Includes 17 skills, MCP server with workflow tools, and pre/post-tool hooks.",
11
- "version": "1.20.3",
11
+ "version": "2.1.0",
12
12
  "author": {
13
13
  "name": "sequant-io",
14
14
  "email": "hello@sequant.io"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sequant",
3
3
  "description": "Structured workflow system for Claude Code - GitHub issue resolution with spec, exec, test, and QA phases",
4
- "version": "2.0.1",
4
+ "version": "2.1.0",
5
5
  "author": {
6
6
  "name": "sequant-io",
7
7
  "email": "hello@sequant.io"
package/dist/bin/cli.js CHANGED
@@ -66,7 +66,7 @@ configureUI({
66
66
  // This helps users who accidentally have a stale local install
67
67
  if (!process.argv.includes("--quiet") && isLocalNodeModulesInstall()) {
68
68
  const pmCommands = getPackageManagerCommands(detectPackageManagerSync());
69
- console.warn(chalk.yellow("⚠️ Running sequant from local node_modules\n" +
69
+ console.warn(chalk.yellow("! Running sequant from local node_modules\n" +
70
70
  " For latest version: npx sequant@latest\n" +
71
71
  ` To remove local: ${pmCommands.removePkg} sequant\n`));
72
72
  }
@@ -152,6 +152,7 @@ program
152
152
  .option("--no-pr", "Skip PR creation after successful QA (manual PR workflow)")
153
153
  .option("-f, --force", "Force re-execution of completed issues (bypass pre-flight state guard)")
154
154
  .option("--concurrency <n>", "Max concurrent issues in parallel mode (default: 3)", parseInt)
155
+ .option("--isolate-parallel", "Isolate parallel agent groups in separate worktrees (prevents file conflicts)")
155
156
  .option("--reflect", "Analyze run results and suggest improvements")
156
157
  .option("--agent <name>", 'Agent driver for phase execution (default: "claude-code")')
157
158
  .action(runCommand);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sequant",
3
3
  "description": "Structured workflow system for Claude Code - GitHub issue resolution with spec, exec, test, and QA phases",
4
- "version": "1.17.0",
4
+ "version": "2.0.1",
5
5
  "author": {
6
6
  "name": "sequant-io",
7
7
  "email": "hello@sequant.io"
@@ -0,0 +1,6 @@
1
+ {
2
+ "sequant": {
3
+ "command": "npx",
4
+ "args": ["-y", "sequant@latest", "serve"]
5
+ }
6
+ }
@@ -2,31 +2,81 @@
2
2
 
3
3
  Structured workflow system for Claude Code — GitHub issue resolution with spec, exec, test, and QA phases.
4
4
 
5
+ ## Prerequisites
6
+
7
+ - **Git** with a GitHub remote
8
+ - **GitHub CLI** (`gh`) authenticated (`gh auth status`)
9
+ - **Node.js 20+** (for MCP server via `npx`)
10
+
5
11
  ## Installation
6
12
 
13
+ ### Plugin (interactive users)
14
+
7
15
  ```
8
- /plugin install sequant@claude-plugin-directory
16
+ /plugin install sequant@sequant-io/sequant
9
17
  ```
10
18
 
11
19
  Or browse in `/plugin > Discover`.
12
20
 
13
- ## Features
21
+ After installing, run `/sequant:setup` to configure your project.
22
+
23
+ ### npm (power users / CI)
14
24
 
15
- - **16 workflow skills** for planning, implementation, testing, and code review
16
- - **Automated quality gates** with test and QA loops
17
- - **GitHub integration** for issue tracking and PR creation
18
- - **Multi-stack support** (Next.js, Python, Go, Rust, and more)
25
+ ```bash
26
+ npm install -g sequant
27
+ sequant init
28
+ ```
29
+
30
+ ## What You Get
19
31
 
20
- ## Skills
32
+ ### 17 Workflow Skills
21
33
 
22
34
  | Skill | Purpose |
23
35
  |-------|---------|
36
+ | `/assess` | Triage issue, recommend workflow |
24
37
  | `/spec` | Plan implementation and extract acceptance criteria |
25
38
  | `/exec` | Implement changes in a feature worktree |
26
39
  | `/test` | Browser-based UI testing |
27
40
  | `/qa` | Code review and AC validation |
28
41
  | `/fullsolve` | End-to-end issue resolution |
29
- | `/solve` | Generate recommended workflow for issues |
42
+ | `/loop` | Quality loop iterate until gates pass |
43
+ | `/testgen` | Generate test stubs from spec criteria |
44
+ | `/verify` | CLI/script execution verification |
45
+ | `/docs` | Generate documentation for features |
46
+ | `/reflect` | Strategic workflow reflection |
47
+ | `/improve` | Codebase analysis and improvement |
48
+ | `/clean` | Repository cleanup |
49
+ | `/security-review` | Deep security analysis |
50
+ | `/release` | Automated release workflow |
51
+ | `/merger` | Multi-issue integration and merge |
52
+ | `/setup` | Project initialization for plugin users |
53
+
54
+ ### MCP Tools (automatic with plugin)
55
+
56
+ | Tool | Purpose |
57
+ |------|---------|
58
+ | `sequant_status` | Check issue progress and workflow state |
59
+ | `sequant_run` | Execute workflow phases |
60
+ | `sequant_logs` | Review past run results |
61
+
62
+ ### MCP Resources
63
+
64
+ | Resource | Purpose |
65
+ |----------|---------|
66
+ | `sequant://state` | Dashboard view of all tracked issues |
67
+ | `sequant://config` | Current workflow settings |
68
+
69
+ ### Hooks
70
+
71
+ - **Pre-tool guardrails** — blocks dangerous commands, enforces worktree safety
72
+ - **Post-tool tracking** — timing, quality metrics, smart test runner
73
+
74
+ ## Quick Start
75
+
76
+ ```
77
+ /assess 123 # Analyze issue, get recommended workflow
78
+ /fullsolve 123 # End-to-end: spec → exec → qa → PR
79
+ ```
30
80
 
31
81
  ## Documentation
32
82
 
@@ -38,24 +38,35 @@ else
38
38
  TOOL_OUTPUT=$(echo "$INPUT_JSON" | grep -oE '"tool_response"\s*:\s*\{[^}]+\}' | head -1)
39
39
  fi
40
40
 
41
- TIMING_LOG="/tmp/claude-timing.log"
42
- QUALITY_LOG="/tmp/claude-quality.log"
43
- TESTS_LOG="/tmp/claude-tests.log"
44
- PARALLEL_MARKER_PREFIX="/tmp/claude-parallel-"
41
+ _TMPDIR="${TMPDIR:-/tmp}"
42
+
43
+ # Use CLAUDE_PLUGIN_DATA for persistent logs (survives plugin updates)
44
+ if [[ -n "${CLAUDE_PLUGIN_DATA}" ]]; then
45
+ _LOG_DIR="${CLAUDE_PLUGIN_DATA}/logs"
46
+ mkdir -p "$_LOG_DIR"
47
+ else
48
+ _LOG_DIR="${_TMPDIR}"
49
+ fi
50
+
51
+ TIMING_LOG="${_LOG_DIR}/claude-timing.log"
52
+ QUALITY_LOG="${_LOG_DIR}/claude-quality.log"
53
+ TESTS_LOG="${_LOG_DIR}/claude-tests.log"
54
+ PARALLEL_MARKER_PREFIX="${_TMPDIR}/claude-parallel-"
45
55
 
46
56
  # === AGENT ID DETECTION ===
47
57
  # For parallel agents, detect group ID from marker files
48
- # Format: /tmp/claude-parallel-<group-id>.marker
58
+ # Format: ${_TMPDIR}/claude-parallel-<group-id>.marker
49
59
  AGENT_ID=""
50
60
  IS_PARALLEL_AGENT="false"
51
- for marker in "${PARALLEL_MARKER_PREFIX}"*.marker; do
52
- if [[ -f "$marker" ]]; then
61
+ # Find marker files using find (works in both bash and zsh)
62
+ while IFS= read -r marker; do
63
+ if [[ -n "$marker" && -f "$marker" ]]; then
53
64
  # Extract group ID from marker filename
54
65
  AGENT_ID=$(basename "$marker" | sed 's/claude-parallel-//' | sed 's/\.marker//')
55
66
  IS_PARALLEL_AGENT="true"
56
67
  break
57
68
  fi
58
- done
69
+ done < <(find "${_TMPDIR}" -maxdepth 1 -name "claude-parallel-*.marker" 2>/dev/null)
59
70
 
60
71
  # === TIMING END ===
61
72
  # Include agent ID in log format if available (AC-4)
@@ -33,20 +33,32 @@ else
33
33
  fi
34
34
  fi
35
35
 
36
- TIMING_LOG="/tmp/claude-timing.log"
37
- PARALLEL_MARKER_PREFIX="/tmp/claude-parallel-"
36
+ _TMPDIR="${TMPDIR:-/tmp}"
37
+
38
+ # Use CLAUDE_PLUGIN_DATA for persistent logs (survives plugin updates)
39
+ if [[ -n "${CLAUDE_PLUGIN_DATA}" ]]; then
40
+ _LOG_DIR="${CLAUDE_PLUGIN_DATA}/logs"
41
+ mkdir -p "$_LOG_DIR"
42
+ else
43
+ _LOG_DIR="${_TMPDIR}"
44
+ fi
45
+
46
+ TIMING_LOG="${_LOG_DIR}/claude-timing.log"
47
+ HOOK_LOG="${_LOG_DIR}/claude-hook.log"
48
+ PARALLEL_MARKER_PREFIX="${_TMPDIR}/claude-parallel-"
38
49
 
39
50
  # === AGENT ID DETECTION ===
40
51
  # For parallel agents, detect group ID from marker files
41
- # Format: /tmp/claude-parallel-<group-id>.marker
52
+ # Format: ${_TMPDIR}/claude-parallel-<group-id>.marker
42
53
  AGENT_ID=""
43
- for marker in "${PARALLEL_MARKER_PREFIX}"*.marker; do
44
- if [[ -f "$marker" ]]; then
54
+ # Find marker files using find (works in both bash and zsh)
55
+ while IFS= read -r marker; do
56
+ if [[ -n "$marker" && -f "$marker" ]]; then
45
57
  # Extract group ID from marker filename
46
58
  AGENT_ID=$(basename "$marker" | sed 's/claude-parallel-//' | sed 's/\.marker//')
47
59
  break
48
60
  fi
49
- done
61
+ done < <(find "${_TMPDIR}" -maxdepth 1 -name "claude-parallel-*.marker" 2>/dev/null)
50
62
 
51
63
  # === TIMING START ===
52
64
  # Include agent ID in log format if available (AC-4)
@@ -75,38 +87,38 @@ if [[ "$TOOL_NAME" == "Bash" ]]; then
75
87
  if ! echo "$TOOL_INPUT" | grep -qE '^gh (issue|pr) '; then
76
88
  # Pattern requires command to START with file reader (not match in quoted strings)
77
89
  if echo "$TOOL_INPUT" | grep -qE '^(cat|less|head|tail|more) .*\.(env|pem|key)'; then
78
- echo "HOOK_BLOCKED: Reading secret file" | tee -a /tmp/claude-hook.log >&2
90
+ echo "HOOK_BLOCKED: Reading secret file" | tee -a "$HOOK_LOG" >&2
79
91
  exit 2
80
92
  fi
81
93
 
82
94
  if echo "$TOOL_INPUT" | grep -qE '^(cat|less) .*~/\.(ssh|aws|gnupg|config/gh)'; then
83
- echo "HOOK_BLOCKED: Reading credential directory" | tee -a /tmp/claude-hook.log >&2
95
+ echo "HOOK_BLOCKED: Reading credential directory" | tee -a "$HOOK_LOG" >&2
84
96
  exit 2
85
97
  fi
86
98
  fi
87
99
 
88
100
  # Bare environment dump
89
101
  if echo "$TOOL_INPUT" | grep -qE '^(env|printenv|export)$'; then
90
- echo "HOOK_BLOCKED: Environment dump" | tee -a /tmp/claude-hook.log >&2
102
+ echo "HOOK_BLOCKED: Environment dump" | tee -a "$HOOK_LOG" >&2
91
103
  exit 2
92
104
  fi
93
105
 
94
106
  # Destructive system commands
95
107
  if echo "$TOOL_INPUT" | grep -qE 'sudo|rm -rf /|rm -rf ~|rm -rf \$HOME'; then
96
- echo "HOOK_BLOCKED: Destructive system command" | tee -a /tmp/claude-hook.log >&2
108
+ echo "HOOK_BLOCKED: Destructive system command" | tee -a "$HOOK_LOG" >&2
97
109
  exit 2
98
110
  fi
99
111
 
100
112
  # Deployment (should never happen in issue automation)
101
113
  if echo "$TOOL_INPUT" | grep -qE 'vercel (deploy|--prod)|terraform (apply|destroy)|kubectl (apply|delete)'; then
102
- echo "HOOK_BLOCKED: Deployment command" | tee -a /tmp/claude-hook.log >&2
114
+ echo "HOOK_BLOCKED: Deployment command" | tee -a "$HOOK_LOG" >&2
103
115
  exit 2
104
116
  fi
105
117
 
106
118
  # Force push
107
119
  # Pattern requires -f to be a standalone flag (not part of branch name like -fix)
108
120
  if echo "$TOOL_INPUT" | grep -qE 'git push.*(--force| -f($| ))'; then
109
- echo "HOOK_BLOCKED: Force push" | tee -a /tmp/claude-hook.log >&2
121
+ echo "HOOK_BLOCKED: Force push" | tee -a "$HOOK_LOG" >&2
110
122
  exit 2
111
123
  fi
112
124
 
@@ -149,14 +161,14 @@ if echo "$TOOL_INPUT" | grep -qE 'git reset.*(--hard|origin)'; then
149
161
  echo " git stash # save changes"
150
162
  echo " git merge --abort # cancel merge"
151
163
  echo " Or run directly in terminal (outside Claude Code) to bypass"
152
- } | tee -a /tmp/claude-hook.log >&2
164
+ } | tee -a "$HOOK_LOG" >&2
153
165
  exit 2
154
166
  fi
155
167
  fi
156
168
 
157
169
  # CI/CD triggers (automation shouldn't trigger more automation)
158
170
  if echo "$TOOL_INPUT" | grep -qE 'gh workflow run'; then
159
- echo "HOOK_BLOCKED: Workflow trigger" | tee -a /tmp/claude-hook.log >&2
171
+ echo "HOOK_BLOCKED: Workflow trigger" | tee -a "$HOOK_LOG" >&2
160
172
  exit 2
161
173
  fi
162
174
 
@@ -222,7 +234,7 @@ if [[ "${CLAUDE_HOOKS_SECURITY:-true}" != "false" ]]; then
222
234
  {
223
235
  echo "HOOK_BLOCKED: Hardcoded secret detected in staged changes"
224
236
  echo " Use 'git commit --no-verify' to bypass if this is a false positive"
225
- } | tee -a /tmp/claude-hook.log >&2
237
+ } | tee -a "$HOOK_LOG" >&2
226
238
  exit 2
227
239
  fi
228
240
 
@@ -233,7 +245,7 @@ if [[ "${CLAUDE_HOOKS_SECURITY:-true}" != "false" ]]; then
233
245
  echo "HOOK_BLOCKED: Sensitive file in commit (${STAGED_FILES})"
234
246
  echo " Files like .env, *.pem, *.key should not be committed"
235
247
  echo " Use 'git commit --no-verify' to bypass if this is intentional"
236
- } | tee -a /tmp/claude-hook.log >&2
248
+ } | tee -a "$HOOK_LOG" >&2
237
249
  exit 2
238
250
  fi
239
251
  fi
@@ -262,7 +274,7 @@ if [[ "$TOOL_NAME" == "Bash" ]] && echo "$TOOL_INPUT" | grep -qE 'git commit'; t
262
274
  fi
263
275
 
264
276
  if [[ "$CHANGES" -eq 0 ]]; then
265
- echo "HOOK_BLOCKED: No changes to commit. Stage files with 'git add' first." | tee -a /tmp/claude-hook.log >&2
277
+ echo "HOOK_BLOCKED: No changes to commit. Stage files with 'git add' first." | tee -a "$HOOK_LOG" >&2
266
278
  exit 2
267
279
  fi
268
280
  fi
@@ -271,7 +283,7 @@ fi
271
283
  # --- Worktree Validation (AC-8) ---
272
284
  # Warn (but don't block) when committing outside a feature worktree
273
285
  # This catches accidental commits to main repo during feature work
274
- QUALITY_LOG="/tmp/claude-quality.log"
286
+ QUALITY_LOG="${_LOG_DIR}/claude-quality.log"
275
287
  if [[ "$TOOL_NAME" == "Bash" ]] && echo "$TOOL_INPUT" | grep -qE 'git commit'; then
276
288
  CWD=$(pwd)
277
289
  if ! echo "$CWD" | grep -qE 'worktrees/feature/'; then
@@ -321,7 +333,7 @@ if [[ "$TOOL_NAME" == "Bash" ]] && echo "$TOOL_INPUT" | grep -qE 'git commit'; t
321
333
  fi
322
334
  echo " Types: feat|fix|docs|style|refactor|test|chore|ci|build|perf"
323
335
  echo " Got: $MSG"
324
- } | tee -a /tmp/claude-hook.log >&2
336
+ } | tee -a "$HOOK_LOG" >&2
325
337
  exit 2
326
338
  fi
327
339
  fi
@@ -356,7 +368,7 @@ if [[ "$TOOL_NAME" == "Edit" || "$TOOL_NAME" == "Write" ]]; then
356
368
  # AC-4 (Issue #31): Check worktree directory exists before path validation
357
369
  # Prevents Write tool from creating non-existent worktree directories
358
370
  if [[ ! -d "$EXPECTED_WORKTREE" ]]; then
359
- echo "HOOK_BLOCKED: Worktree does not exist: $EXPECTED_WORKTREE" | tee -a /tmp/claude-hook.log >&2
371
+ echo "HOOK_BLOCKED: Worktree does not exist: $EXPECTED_WORKTREE" | tee -a "$HOOK_LOG" >&2
360
372
  exit 2
361
373
  fi
362
374
 
@@ -385,7 +397,7 @@ if [[ "$TOOL_NAME" == "Edit" || "$TOOL_NAME" == "Write" ]]; then
385
397
  if [[ -n "${SEQUANT_ISSUE:-}" ]]; then
386
398
  echo " Issue: #$SEQUANT_ISSUE"
387
399
  fi
388
- } | tee -a /tmp/claude-hook.log >&2
400
+ } | tee -a "$HOOK_LOG" >&2
389
401
  exit 2
390
402
  fi
391
403
  fi
@@ -408,7 +420,7 @@ if [[ "${CLAUDE_HOOKS_FILE_LOCKING:-true}" == "true" ]]; then
408
420
 
409
421
  if [[ -n "$FILE_PATH" ]]; then
410
422
  # Create a lock file based on file path hash (handles special chars)
411
- LOCK_FILE="/tmp/claude-lock-$(echo "$FILE_PATH" | md5 -q 2>/dev/null || echo "$FILE_PATH" | md5sum | cut -d' ' -f1).lock"
423
+ LOCK_FILE="${_TMPDIR}/claude-lock-$(echo "$FILE_PATH" | md5 -q 2>/dev/null || echo "$FILE_PATH" | md5sum | cut -d' ' -f1).lock"
412
424
 
413
425
  # Try to acquire lock with 30 second timeout
414
426
  # Use a subshell to hold the lock during the tool execution
@@ -416,7 +428,7 @@ if [[ "${CLAUDE_HOOKS_FILE_LOCKING:-true}" == "true" ]]; then
416
428
  # macOS: use lockf
417
429
  exec 200>"$LOCK_FILE"
418
430
  if ! lockf -t 30 200 2>/dev/null; then
419
- echo "HOOK_BLOCKED: File locked by another agent: $FILE_PATH" | tee -a /tmp/claude-hook.log >&2
431
+ echo "HOOK_BLOCKED: File locked by another agent: $FILE_PATH" | tee -a "$HOOK_LOG" >&2
420
432
  exit 2
421
433
  fi
422
434
  # Lock will be released when the file descriptor closes (process exits)
@@ -424,7 +436,7 @@ if [[ "${CLAUDE_HOOKS_FILE_LOCKING:-true}" == "true" ]]; then
424
436
  # Linux: use flock
425
437
  exec 200>"$LOCK_FILE"
426
438
  if ! flock -w 30 200 2>/dev/null; then
427
- echo "HOOK_BLOCKED: File locked by another agent: $FILE_PATH" | tee -a /tmp/claude-hook.log >&2
439
+ echo "HOOK_BLOCKED: File locked by another agent: $FILE_PATH" | tee -a "$HOOK_LOG" >&2
428
440
  exit 2
429
441
  fi
430
442
  fi
@@ -433,31 +445,6 @@ if [[ "${CLAUDE_HOOKS_FILE_LOCKING:-true}" == "true" ]]; then
433
445
  fi
434
446
  fi
435
447
 
436
- # === PRE-MERGE WORKTREE CLEANUP ===
437
- # Auto-remove worktree before `gh pr merge` to prevent --delete-branch failure
438
- # The worktree locks the branch, causing merge to partially fail
439
- if [[ "$TOOL_NAME" == "Bash" ]] && echo "$TOOL_INPUT" | grep -qE 'gh pr merge'; then
440
- # Extract PR number from command
441
- PR_NUM=$(echo "$TOOL_INPUT" | grep -oE 'gh pr merge [0-9]+' | grep -oE '[0-9]+')
442
-
443
- if [[ -n "$PR_NUM" ]]; then
444
- # Get the branch name for this PR
445
- BRANCH_NAME=$(gh pr view "$PR_NUM" --json headRefName --jq '.headRefName' 2>/dev/null || true)
446
-
447
- if [[ -n "$BRANCH_NAME" ]]; then
448
- # Check if a worktree exists for this branch
449
- # Note: worktree line is 2 lines before branch line in porcelain output
450
- WORKTREE_PATH=$(git worktree list --porcelain 2>/dev/null | grep -B2 "branch refs/heads/$BRANCH_NAME" | grep "^worktree " | sed 's/^worktree //' || true)
451
-
452
- if [[ -n "$WORKTREE_PATH" && -d "$WORKTREE_PATH" ]]; then
453
- # Remove the worktree before merge proceeds
454
- git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || true
455
- echo "PRE-MERGE: Removed worktree $WORKTREE_PATH for branch $BRANCH_NAME" >> /tmp/claude-hook.log
456
- fi
457
- fi
458
- fi
459
- fi
460
-
461
448
  # === ALLOW EVERYTHING ELSE ===
462
449
  # Slash commands need: git, npm, file edits, gh pr/issue, MCP tools
463
450
  exit 0