fix(GRA-1233): add PostToolUse auto_correct hook to claude_code adapter install#245
fix(GRA-1233): add PostToolUse auto_correct hook to claude_code adapter install#245Gradata wants to merge 2 commits into
Conversation
Zero RULE_PATCHED events in production; oscillation guard untriggered. Identifies two persistent failure rules and seven burst-only candidates, with freeze/demote recommendations and delta vs GRA-1382 baseline. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er install gradata install --agent claude-code only installed PreToolUse (inject_brain_rules), missing the PostToolUse (auto_correct) hook that captures Edit|Write events for correction learning. Users got injection but no correction capture — core value prop broken at install. Changes: - _base.py: add auto_correct_command() helper mirroring hook_command() - claude_code.py:install() — add PostToolUse hook with Edit|Write matcher - claude_code.py:uninstall() — clean both PreToolUse and PostToolUse (iterates over both event keys instead of hardcoding PreToolUse only) Closes GRA-1233
There was a problem hiding this comment.
Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.
📝 Walkthrough
WalkthroughThis PR adds research findings on patch system convergence and oscillation (GRA-1477), identifying persistent multi-session failure candidates and hook reversion patterns, along with new infrastructure to manage auto-correct hook entries during agent initialization and cleanup in both install and uninstall operations. ChangesPatch oscillation analysis and auto-correct hook wiring
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 OpenGrep (1.22.0)OpenGrep fatal error (exit code 2): �[32m✔�[39m �[1mOpengrep OSS�[0m �[1m Loading rules from local config...�[0m Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@Gradata/src/gradata/hooks/adapters/claude_code.py`:
- Around line 79-94: The smoke test and adapter are out of sync:
tests/HOST_MATRIX for claude-code only expects "PreToolUse" so the new
PostToolUse wiring in Gradata/src/gradata/hooks/adapters/claude_code.py will not
be asserted, and the adapter uses a single matcher "Edit|Write" while
auto_correct.generate_hook_config() emits separate "Edit" and "Write" matchers
(risking accidental matches like "MultiEdit"). Fix by (1) updating the test
HOST_MATRIX entry for "claude-code" to include "PostToolUse" in expected_events
so the smoke matrix will catch regressions, and (2) change the PostToolUse hook
installation in claude_code.py to either add two distinct matcher entries
("Edit" and "Write") or use an exact-match regex like "^(Edit|Write)$" (adjust
the code that appends the dict using auto_correct_command and sig) to match
auto_correct.generate_hook_config() semantics exactly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: f3b78391-dbe5-4204-9bfd-02bcb3744987
📒 Files selected for processing (3)
Gradata/docs/research/patch-oscillation-2026-06-02.mdGradata/src/gradata/hooks/adapters/_base.pyGradata/src/gradata/hooks/adapters/claude_code.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
Gradata/src/**/*.py
📄 CodeRabbit inference engine (Gradata/AGENTS.md)
Gradata/src/**/*.py: Prefersentence-transformersfor local embeddings,google-genaifor Gemini embeddings,cryptographyfor AES-GCM encrypted system.db,bm25sfor BM25 rule ranking, andmem0aifor external memory adapters — guard all optional dependency imports withtry / except ImportErrorat the call site, never at module level
Maintain strict layering: Layer 0 (Primitives: _types.py, _db.py, _events.py, _paths.py, _file_lock.py; Patterns: contrib/patterns/) must never import from Layer 1 (Enhancements: enhancements/, rules/) or Layer 2 (Public API: brain.py, cli.py, daemon.py, mcp_server.py)
Never use bareexcept: pass— use typed exceptions or at minimumlogger.warning(...)withexc_info=Trueto avoid silent failure in a memory product
Never import from out-of-scope sibling directories../Sprites/or../Hausgem/withingradata/*code — that is a layering bug
Never leak private-sibling paths into public docs/code — no references to../Sprites/,../Hausgem/, email addresses, OneDrive paths, or Sprites-specific examples from insidegradata/*
Use atomic-write helper when writing JSON files to prevent corruption from mid-write crashes
Files:
Gradata/src/gradata/hooks/adapters/_base.pyGradata/src/gradata/hooks/adapters/claude_code.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: Gradata
Repo: Gradata/gradata PR: 0
File: :0-0
Timestamp: 2026-04-17T17:18:07.439Z
Learning: In PR `#102` (gradata/gradata), Round 2 addressed: cli.py env-first brain resolution (GRADATA_BRAIN > --brain-dir > cwd), _tenant.py corrupt .tenant_id overwrite, _env_int default clamping to minimum, and _events.py tenant-scoped fallback SELECT for dedup. All ruff and 99 tests green after these fixes.
📚 Learning: 2026-05-01T15:50:32.772Z
Learnt from: CR
Repo: Gradata/gradata PR: 0
File: Gradata/AGENTS.md:0-0
Timestamp: 2026-05-01T15:50:32.772Z
Learning: Use `from gradata import Brain` as the public entry point — `brain.correct()` is THE entry point for the headline product promise
Applied to files:
Gradata/src/gradata/hooks/adapters/_base.py
🪛 LanguageTool
Gradata/docs/research/patch-oscillation-2026-06-02.md
[uncategorized] ~142-~142: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ...cific content fragments (code snippets, markdown table rows, PR references) | Content-ch...
(MARKDOWN_NNP)
[uncategorized] ~167-~167: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ... description contains code fragments or markdown table syntax 2. Add session-burst filte...
(MARKDOWN_NNP)
🪛 markdownlint-cli2 (0.22.1)
Gradata/docs/research/patch-oscillation-2026-06-02.md
[warning] 166-166: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 171-171: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below
(MD022, blanks-around-headings)
[warning] 172-172: Ordered list item prefix
Expected: 1; Actual: 4; Style: 1/2/3
(MD029, ol-prefix)
[warning] 173-173: Ordered list item prefix
Expected: 2; Actual: 5; Style: 1/2/3
(MD029, ol-prefix)
[warning] 174-174: Ordered list item prefix
Expected: 3; Actual: 6; Style: 1/2/3
(MD029, ol-prefix)
🔇 Additional comments (4)
Gradata/docs/research/patch-oscillation-2026-06-02.md (1)
1-197: LGTM!Gradata/src/gradata/hooks/adapters/_base.py (1)
139-143: LGTM!Gradata/src/gradata/hooks/adapters/claude_code.py (2)
56-104: LGTM!
107-153: LGTM!
| # PostToolUse: auto_correct (Edit|Write capture) | ||
| post_tool = hooks.setdefault("PostToolUse", []) | ||
| post_present = any(sig in str(item) for item in post_tool) | ||
| if not post_present: | ||
| post_tool.append( | ||
| { | ||
| "matcher": "Edit|Write", | ||
| "hooks": [ | ||
| { | ||
| "type": "command", | ||
| "command": auto_correct_command(brain_dir), | ||
| "id": sig, | ||
| } | ||
| ], | ||
| } | ||
| ) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 1) Inspect HOST_MATRIX expected_events for claude-code in the smoke test
fd -t f 'test_install_smoke_matrix.py' --exec rg -n -C3 'HOST_MATRIX|expected_events|claude-code|PostToolUse|PreToolUse' {}
# 2) Compare matcher shapes between adapter install and generate_hook_config
rg -nP -C3 "matcher" --type=py -g '!**/tests/**' gradata/src/gradata/hooks 2>/dev/null || \
rg -nP -C3 "matcher" --type=pyRepository: Gradata/gradata
Length of output: 21624
Fix smoke-matrix coverage for Claude Code PostToolUse + clarify matcher semantics
tests/test_install_smoke_matrix.pysetsHOST_MATRIXforclaude-codetoexpected_events={"PreToolUse"}; since the test only checksexpected_events <= set(hooks), it will not assert the newPostToolUsewiring—so a regression inGradata/src/gradata/hooks/adapters/claude_code.pywon’t fail the smoke test.claude_code.pyinstalls a singlePostToolUseentry with matcher"Edit|Write", whileauto_correct.generate_hook_config()emits two separate matchers"Edit"and"Write". Confirm that Claude Code’s matcher evaluation treats"Edit|Write"as intended and does not accidentally trigger onMultiEdit(or add a test to lock this down).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@Gradata/src/gradata/hooks/adapters/claude_code.py` around lines 79 - 94, The
smoke test and adapter are out of sync: tests/HOST_MATRIX for claude-code only
expects "PreToolUse" so the new PostToolUse wiring in
Gradata/src/gradata/hooks/adapters/claude_code.py will not be asserted, and the
adapter uses a single matcher "Edit|Write" while
auto_correct.generate_hook_config() emits separate "Edit" and "Write" matchers
(risking accidental matches like "MultiEdit"). Fix by (1) updating the test
HOST_MATRIX entry for "claude-code" to include "PostToolUse" in expected_events
so the smoke matrix will catch regressions, and (2) change the PostToolUse hook
installation in claude_code.py to either add two distinct matcher entries
("Edit" and "Write") or use an exact-match regex like "^(Edit|Write)$" (adjust
the code that appends the dict using auto_correct_command and sig) to match
auto_correct.generate_hook_config() semantics exactly.
gradata install --agent claude-code only installed PreToolUse (inject_brain_rules), missing PostToolUse (auto_correct) -- users got injection but no correction capture.
Fix:
Closes GRA-1233