Skip to content

chore(claude): add RAG reviewer + reset skill, fix broken on-edit hooks#28

Merged
hyhmrright merged 3 commits into
mainfrom
chore/claude-automation-hooks
Jun 18, 2026
Merged

chore(claude): add RAG reviewer + reset skill, fix broken on-edit hooks#28
hyhmrright merged 3 commits into
mainfrom
chore/claude-automation-hooks

Conversation

@hyhmrright

Copy link
Copy Markdown
Owner

What

Four .claude/ automations, scoped to fill real gaps in the existing setup (the hook wiring lives in the gitignored settings.local.json; these are the tracked, shareable pieces):

1. hooks/post-edit-check.py — fixes two broken on-edit checks

The old inline PostToolUse hooks had two latent bugs:

  • The biome hook read a top-level file_path (always empty in this payload — same nesting bug already fixed for the migrations/.env guards), so it silently formatted zero files on every edit.
  • The typecheck hook ran the root tsconfig, which excludes packages/client — so client type errors got no on-edit feedback and only surfaced at CI/build.

New hook reads tool_input.file_path, formats just the edited file, and routes client files to the client tsconfig, closing the type-check gap.

2. hooks/guard-bun-test.py — blocks bun test

Running Bun's built-in bun test skips the bunfig.toml preload (test env + per-test table truncation) and points tests at the shared dev stack — this once produced ~102 phantom failures. The guard blocks the bun test subcommand and nudges to bun run test; bun run test / bun run test:setup pass through.

3. agents/rag-pipeline-reviewer.md — RAG contract reviewer

A specialized reviewer for packages/gateway/src/lib/ changes: embedding provider priority (EMBEDDING_PROVIDER_PRIORITY), Qdrant UUID point ids (toUUID), container-name networking, encrypted-key handling, query-builder usage.

4. skills/reset-user-password/ — break-glass prod password reset

Codifies the verified manual procedure (Argon2id via the Bun temp-.cjs workaround + UPDATE on the confer role). User-invoked only.

Verification

All hooks tested by piping crafted payloads:

  • ✅ client type error caught (was previously never checked on edit)
  • ✅ clean edits stay silent, exit 0
  • ✅ every bun test variant blocked (bun test, bun test <path>, FOO=1 bun test, bun --watch test)
  • bun run test, bun run test:setup, piped variants, and quoted-text in commit messages all pass through

No packages/ code changed → no redeploy needed.

🤖 Generated with Claude Code

hyhmrright and others added 2 commits June 18, 2026 20:22
Implements four `.claude/` automations (hook wiring lives in the gitignored
settings.local.json; these are the tracked, shareable pieces):

- hooks/post-edit-check.py: replaces the two inline PostToolUse hooks. The old
  biome hook read a top-level `file_path` (always empty in this payload), so it
  silently formatted zero files; the typecheck hook ran the root tsconfig, which
  excludes the client package, so client type errors only surfaced at CI/build.
  The new hook reads tool_input.file_path, formats the edited file, and routes
  client files to the client tsconfig -- closing the on-edit type-check gap.
- hooks/guard-bun-test.py: blocks the `bun test` subcommand and nudges to
  `bun run test` (running Bun's built-in runner skips the bunfig preload + table
  truncation and pollutes the shared dev stack -- once caused ~102 phantom
  failures). `bun run test` / `bun run test:setup` pass through.
- agents/rag-pipeline-reviewer.md: contract reviewer for the RAG pipeline
  (embedding provider priority, Qdrant UUID point ids, container networking,
  encrypted-key handling, query-builder usage).
- skills/reset-user-password: codifies the break-glass production password reset
  (Argon2id via the Bun temp-cjs workaround + SQL UPDATE on the confer role).

Verified by piping crafted payloads: client type error caught, clean edits stay
silent, every `bun test` variant blocked while `bun run test` passes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ssword handling

- post-edit-check.py: derive REPO from __file__ (three dirname levels up from
  .claude/hooks/) instead of hardcoding an absolute path, so the tracked hook is
  portable across checkouts. Re-verified: client type error still caught, clean
  edits stay silent.
- reset-user-password skill: read the new password via `read -rs` into $NEWPW
  (no echo, no shell history, never in argv) and reuse it; build the login-verify
  body with `jq --arg` so it escapes correctly. The old inline `-e NEWPW='...'`
  only kept the password out of the container argv, not the host shell history.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hyhmrright

Copy link
Copy Markdown
Owner Author

Code review

Ran a 5-agent review (CLAUDE.md adherence, shallow bug scan, git history, prior-PR comments, comment-vs-implementation compliance). Two minor items found and fixed in b871ef1; the remaining flags were false positives.

  1. post-edit-check.py hardcoded an absolute repo path (REPO = "/Users/hyh/code/Confer"), making the tracked hook non-portable and inconsistent with the existing guard-bash-file-view.py (which carries no machine-specific state). Now derived from __file__:

# tracked hook stays portable across checkouts instead of hardcoding a path.
REPO = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
BIOME = "./node_modules/.bin/biome"

  1. The reset-password runbook passed the plaintext via inline -e NEWPW='...', which keeps it out of the container argv but not the host shell history. Now read with read -rs and reused (login-verify body built via jq --arg for correct escaping):

```bash
read -rs NEWPW # 输入新密码后回车(终端不回显)
docker compose -f docker-compose.prod.yml exec -e NEWPW="$NEWPW" gateway sh -c '

Excluded as false positives: MultiEdit payloads do carry a top-level file_path (single file, multiple edits), so the hook handles them; and the gitignored settings.local.json wiring is intentional machine-local config, not a tracked-onboarding gap.

🤖 Generated with Claude Code

- If this code review was useful, please react with 👍. Otherwise, react with 👎.

Independent 3-lens review of this PR found real defects the earlier review
missed — all verified empirically before fixing:

- post-edit-check.py: PostToolUse stdout on exit 0 only reaches the debug log,
  never the model (per the hooks docs), so the tsc errors the hook computed were
  silently discarded — the on-edit feedback gap it claims to close stayed open.
  Now emits them as `hookSpecificOutput.additionalContext` JSON, which the model
  sees next to the tool result. Verified: client- and root-routed type errors
  both surface as valid JSON; clean / non-TS edits stay silent.
- guard-bun-test.py: is_bun_test() matched `bun`/`test` anywhere in a segment,
  so `echo bun test` / `ls bun test` / `git commit -m "...bun test..."` were
  blocked (false positives violating the hook's own contract). Now only the
  command-position token counts (after skipping `VAR=value` prefixes). Verified
  against a 17-case block/allow matrix.
- guard-bun-test.py: corrected the docstring + BLOCKED message — the ~102
  phantom failures came from mock.module global pollution, not from `bun test`
  skipping the bunfig preload (two distinct incidents were conflated).
- reset-user-password skill: step 3 pasted the `$`-laden Argon2id hash into a
  double-quoted psql -c, where bash/sh expand `$argon2id`/`$v`/`$m` to empty —
  writing a corrupt hash (account lockout) while psql still reports UPDATE 1.
  Now binds via a single-quoted var + psql `:'h'` safe-quoting. Reproduced the
  corruption and verified the fix.
- reset-user-password skill: step 2's `-e NEWPW="$NEWPW"` and step 4's
  `jq --arg p "$NEWPW"` / `curl -d` put the plaintext password in process argv
  (ps / /proc), contradicting the step-5 "never in argv" claim. Now pass it via
  stdin pipe (printf builtin) and jq `env.NEWPW` + curl `--data @-`, so it never
  enters any argv. Verified the jq env round-trip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hyhmrright

Copy link
Copy Markdown
Owner Author

Pre-merge self-review (round 2)

Before merging I ran an independent 3-lens adversarial review of the current diff (hook correctness / shell-secret safety / factual+contract accuracy). It surfaced 5 real defects the first review missed — each reproduced empirically, then fixed in a0df73c:

  1. post-edit-check.py — type-check feedback never reached the model. PostToolUse stdout on exit 0 only goes to the debug log (hooks docs), so the computed tsc errors were silently discarded and the gap the hook claims to close stayed open. Now emitted as hookSpecificOutput.additionalContext JSON. Verified: client- and root-routed type errors both surface as valid JSON; clean / non-TS edits stay silent.
  2. guard-bun-test.py — false positives. is_bun_test() matched bun/test anywhere in a segment, so echo bun test, ls bun test, git commit -m "…bun test…" were blocked, violating the hook's own "blocks only the subcommand" contract. Now only the command-position token counts (after VAR=value prefixes). Verified against a 17-case block/allow matrix.
  3. guard-bun-test.py — wrong rationale. The "~102 phantom failures" came from mock.module global pollution, not from bun test skipping the bunfig preload — two incidents conflated. Docstring + BLOCKED message corrected.
  4. reset-user-password — DB-corruption bug (major). Step 3 pasted the $-laden Argon2id hash into a double-quoted psql -c; bash/sh expand $argon2id/$v/$m → a truncated hash is written (account lockout) while psql still returns UPDATE 1. Reproduced ('$argon2id$v=19…''=19…'). Now binds via single-quoted var + psql :'h' safe-quoting.
  5. reset-user-password — argv plaintext leak (major). Step 2's -e NEWPW="$NEWPW" and step 4's jq --arg p / curl -d put the plaintext in process argv (ps//proc), contradicting the step-5 "never in argv" claim. Now via stdin pipe (printf builtin) + jq env.NEWPW + curl --data @-. Verified the jq env round-trip.

CI is green on the fix commit. Merging — scope is .claude/ developer automation only (no product/A2A/DID/crypto code).

🤖 Generated with Claude Code

@hyhmrright hyhmrright merged commit 0baa575 into main Jun 18, 2026
1 check passed
@hyhmrright hyhmrright deleted the chore/claude-automation-hooks branch June 18, 2026 12:59
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.

1 participant