Skip to content

feat(status,update): report upstream hooks missing from settings.json (PHARN-04) - #198

Merged
PrzemekGalarowicz merged 1 commit into
mainfrom
claude/bold-archimedes-5czyyn
Sep 24, 2026
Merged

PrzemekGalarowicz merged 1 commit into
mainfrom
claude/bold-archimedes-5czyyn

Conversation

@PrzemekGalarowicz

Copy link
Copy Markdown
Contributor

What this changes

Upstream pharn-oss changed its hook wiring twice:

  • 6.1.0: both guards are anchored on CLAUDE_PROJECT_DIR. The old relative commands stopped running after a cd into a subdirectory, silently.
  • 6.12.0: a new exec-form Stop hook.

update installs the new hook scripts but never looks at .claude/settings.json, which is user-owned and never overwritten. Reproduced going from 6.0.0 to 6.17.1: settings.json was byte-identical afterwards, with the old relative commands and no Stop hook. status --strict still exited 0 with "No drift", so existing installs kept outdated hook wiring with no warning.

New module src/lib/hook-wiring.ts (diffHookWiring) compares the hooks block of the project's settings.json with the upstream one:

  • It lists the upstream hooks the project does not have, matching on event, matcher, command and args as exact text.
  • It checks both files the same safe way: 256 KB size cap, symlinks refused, parsed as data only.
  • When printing commands, control characters are replaced.
  • Hooks the user added themselves never count as a difference.

How the commands use it:

  • status: a new HOOKS section; --strict exits 1 while any upstream hook is not wired.
  • update: prints the same HOOKS note, and still never writes settings.json.
  • Docs: docs/commands/status.md, docs/commands/update.md and CLAUDE.md updated.

Built with /pharn-dev-ship; stage artifacts are in .dev/features/hook-wiring-drift/. Results:

  • validate: exit 0
  • regress: no-regressions
  • verify: PASS

Type of change

  • feat — new stack option, wizard step, or command capability
  • fix — bug fix
  • docs — docs-only change
  • chore / refactor — tooling or internal restructure, no behavior change

Area(s) touched

lib/hook-wiring (new) | commands/status, update | docs

Checklist

  • Read the existing file(s) before editing; followed the ESM .js-extension import convention.
  • Added tests/hook-wiring.test.ts (13 cases) and new cases in status and update tests. The command-level cases fail on the old source.
  • Updated the relevant docs/ pages.
  • Preserved the security invariants.

Quality gates

  • npm run check passes locally (1321/1321; non-root user, node 22).
  • npm run build succeeds (left to CI).
  • npm run test:coverage passes (left to CI).

Notes for the reviewer

  • Behavior change: status --strict now goes red for any install whose settings.json predates upstream's hook changes, until the user merges the hooks by hand. This is intended, but CI pipelines that run --strict will notice.
  • Matching is exact text, so a hook the user rewrote in an equivalent but differently-written form is still listed. The note says so.
  • update only shows the note on runs that fetch upstream; when it is already up to date it does not fetch, so status is the command that always checks.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TvcuVhk8hTeDskp5pAJhnc


Generated by Claude Code

… (PHARN-04)

Upstream re-wired its hooks twice (6.1.0 anchored both guards on
CLAUDE_PROJECT_DIR because the relative form was silently off after a cd;
6.12.0 added an exec-form Stop hook). `update` installed the new hook scripts
but never looks at settings.json (user-owned, never overwritten), and
`status --strict` stayed green — so existing installs kept dead or broken
wiring with no signal at all.

New lib/hook-wiring.ts compares the `hooks` block of the project's
settings.json with the fetched upstream one (exact Event/matcher/command/args
set difference; both files size-capped, symlink-refused, parsed as data):
- `status` prints a HOOKS section and `--strict` exits 1 while an upstream
  hook is unwired (extra user hooks never count);
- `update` prints the same HOOKS note — and still never writes the file.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TvcuVhk8hTeDskp5pAJhnc
@coderabbitai

coderabbitai Bot commented Sep 24, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: a3723f30-9234-4f0a-b710-7f358c44c007


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@PrzemekGalarowicz
PrzemekGalarowicz merged commit a6c55bc into main Sep 24, 2026
13 checks passed
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.

2 participants