Skip to content

fix(hooks): resolve #73 #74 #75 follow-ups (test harness, path handling, set -euo) - #76

Merged
5uck1ess merged 2 commits into
mainfrom
fix/hook-followups-73-74-75
Apr 11, 2026
Merged

fix(hooks): resolve #73 #74 #75 follow-ups (test harness, path handling, set -euo)#76
5uck1ess merged 2 commits into
mainfrom
fix/hook-followups-73-74-75

Conversation

@5uck1ess

Copy link
Copy Markdown
Owner

Summary

Bundles the three hook follow-up issues from the #72 review, since the fixes and tests cluster in the same files. Closes #73, #74, #75.

#73run_hook dead exit-code check

hooks_test.sh had OUTPUT=$(…) || true followed by EXIT=$?, so $? always saw true's rc=0 and every run_hook caller's exit-code assertion was dead code. The suite runs under set -uo pipefail (no -e), so the || true was unnecessary cargo — dropping it restores the real hook exit code. Every existing run_hook call already expects exit 0 and still passes, so no assertions needed tightening.

#74post-validate.sh path handling + test coverage

Normalize both REPO_ROOT and the constructed ABS_PATH through a portable realpath pipeline before the glob match:

  • REPO_ROOT → canonicalized via cd && pwd -P (fixes symlinked-repo false positives).
  • ABS_PATH → python3 → python → cd dirname && pwd -P → pure-sed ./.. collapse. The sed tier is the safety net when python is absent and the parent dir doesn't exist yet (pre-mkdir writes, fixtures).
  • TMPDIR allowlist extended with /private/var/folders/* because python's realpath resolves /var → /private/var on macOS.

Four new tests pin all four scenarios called out in the issue:

#75 — three cleanup items

  1. security-patterns.shset -euo pipefail with || true guards on every jq assignment and the dedup echo >> SEEN_FILE, matching the pattern established in rtk-rewrite.sh. (post-validate.sh already had it.)
  2. Per-pattern dedup test — second assertion fires a different pattern (eval() on the same file used by the existing pickle dedup test. Guards against a key-collapse regression that would flatten dedup to "warn-once-ever".
  3. rtk-rewrite rc 3 + rewrite == input test — new shim mode ask-noop-rewrite exercises the intersection of the ask-suppression branch and the identity-rewrite guard.
  4. Comment trims — replace "pins the $$→$PPID fix" / "Pins the realpath -m GNU-ism fix…" archaeology with invariant phrasing. The dedup-test $() topology comment stays (it prevents a real future bug).

Windows / Git Bash compatibility

Second commit adds:

  • Drive-letter absolute-path detection (C:\foo / C:/foo) in addition to /foo.
  • python3 → python → cd/pwd → sed fallback chain so the fix works even on minimal Git Bash without python.
  • Symlink test skips cleanly (prints a SKIP: line) when ln -s can't create a real symlink (Windows Git Bash without developer mode, some FUSE mounts).

Verified the sed fallback manually by shadowing python3 and python with /bin/false: in-repo paths pass silently, ../outside paths warn, absolute outside paths warn. On macOS.

Test plan

  • bash hooks/hooks_test.sh70 passed, 0 failed on macOS
  • Manual sed-fallback verification with python shadowed to /bin/false
  • CI run on Linux (pending)
  • Manual smoke on Windows Git Bash (deferred — the symlink test is guarded to skip cleanly if ln -s is restricted)

Three related fixes from the #72 review audit, bundled because the
tests cluster in the same file.

#73 — hooks_test.sh run_hook silently swallowed exit codes. `OUTPUT=$(…)
|| true` followed by `EXIT=$?` always saw true's rc=0, so every
run_hook caller's exit-code assertion was dead. The suite runs under
`set -uo pipefail` (no -e), so the `|| true` was unnecessary; drop it
and `$?` now carries the hook's real exit.

#74 — post-validate.sh path handling edge cases. Normalize both
REPO_ROOT and ABS_PATH through a portable realpath path (python3 with
a dirname/pwd fallback) so that: (a) `..` escapes from the repo root
no longer match the "$REPO_ROOT"/* glob, (b) symlinked repo roots
compare consistently, (c) cwd=subdir + ../in-repo paths still resolve
inside the repo. Extend the TMPDIR allowlist to include
/private/var/folders/* since realpath resolves /var → /private/var on
macOS. New tests pin all four scenarios (subdir cwd, .. escape,
TMPDIR, symlinked root).

#75 — three cleanup items:
  1. security-patterns.sh: add `set -euo pipefail` with the same
     jq-tolerance guards as rtk-rewrite.sh (post-validate.sh already
     had it).
  2. Per-pattern dedup test: assert that a second, different pattern
     on the same file still warns, guarding against a key collapse
     that would flatten the dedup to warn-once-ever.
  3. rtk-rewrite rc 3 + rewrite == input test: new shim mode exercises
     the intersection of the ask-suppression branch and the identity
     guard.
  4. Comment trim: replace "pins the $$→$PPID fix" / "Pins the
     realpath -m GNU-ism fix…" archaeology with invariant phrasing.

Results: 70 passed, 0 failed (was 66 passed, 0 failed).
Three additions so the #74 path-handling fix works on Windows Git Bash
and minimal shells that lack python:

1. Absolute-path detection accepts drive-letter forms (C:\foo, C:/foo)
   in addition to POSIX /foo paths, in case Claude Code emits
   native-Windows tool_input paths.

2. Path normalization tries python3 → python → cd/pwd → sed-based
   ./../ collapse. The sed fallback is pure bash + POSIX sed -E so it
   survives when python is absent AND the parent directory doesn't
   exist yet (common for Write that creates a new file's parent).
   Verified manually by shadowing python3/python with /bin/false.

3. The new symlinked-repo-root test skips cleanly (with a SKIP line)
   on platforms where `ln -s` can't create a real symlink, e.g.
   Windows Git Bash without developer mode or restricted FUSE mounts.

Test suite still: 70 passed, 0 failed on macOS.
@5uck1ess
5uck1ess merged commit ca54b36 into main Apr 11, 2026
6 checks passed
@5uck1ess
5uck1ess deleted the fix/hook-followups-73-74-75 branch April 11, 2026 06:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hooks_test.sh: run_hook dead exit-code check silently weakens every test

1 participant