Skip to content

fix: install post-tool hooks for Codex and OpenCode#258

Merged
Gradata merged 1 commit into
mainfrom
gra-55-post-tool-session-hooks
Jun 5, 2026
Merged

fix: install post-tool hooks for Codex and OpenCode#258
Gradata merged 1 commit into
mainfrom
gra-55-post-tool-session-hooks

Conversation

@Gradata

@Gradata Gradata commented Jun 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • add Codex post_tool and session_end hook installation alongside pre_tool
  • add OpenCode postTool and sessionEnd hook installation alongside preTool
  • add adapter tests covering pre/post/session hook installation for Codex, Hermes, and OpenCode

Verification

  • python3 -m pytest tests/test_hook_adapters.py → 21 passed
  • isolated HOME CLI smoke: python3 -m gradata.cli install --agent codex|hermes|opencode --brain <tmp> → wrote post/session hook configs and assertions passed
  • python3 -m pytest tests/test_hook_adapters.py tests/test_adapter_extraction_contracts.py tests/test_uninstall_command.py → 92 passed
  • /home/olive/.local/bin/uvx ruff check src/gradata/hooks/adapters/codex.py src/gradata/hooks/adapters/opencode.py tests/test_hook_adapters.py → All checks passed
  • git diff --check → clean

Paperclip: GRA-55

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c5f8e8ba-425a-40ba-af30-a3c1a86871a4

📥 Commits

Reviewing files that changed from the base of the PR and between 8097785 and e375608.

📒 Files selected for processing (3)
  • Gradata/src/gradata/hooks/adapters/codex.py
  • Gradata/src/gradata/hooks/adapters/opencode.py
  • Gradata/tests/test_hook_adapters.py
📜 Recent review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
  • GitHub Check: pytest (py3.11)
  • GitHub Check: pytest (py3.12)
  • GitHub Check: pytest windows-latest / py3.11
  • GitHub Check: pytest ubuntu-latest / py3.11
  • GitHub Check: pytest ubuntu-latest / py3.12
  • GitHub Check: pytest windows-latest / py3.12
  • GitHub Check: pytest macos-latest / py3.12
  • GitHub Check: pytest macos-latest / py3.11
🧰 Additional context used
📓 Path-based instructions (2)
Gradata/tests/**/*.py

📄 CodeRabbit inference engine (Gradata/AGENTS.md)

Gradata/tests/**/*.py: Set BRAIN_DIR environment variable via tmp_path in conftest.py for test isolation — ensure _paths.py module cache refreshes when calling Brain.init() directly inside tests
Add unit tests in tests/test_*.py for every CI push without LLM calls (deterministic); mark integration tests with @pytest.mark.integration and skip them by default (they hit real LLM APIs)

Files:

  • Gradata/tests/test_hook_adapters.py
Gradata/src/**/*.py

📄 CodeRabbit inference engine (Gradata/AGENTS.md)

Gradata/src/**/*.py: Prefer sentence-transformers for local embeddings, google-genai for Gemini embeddings, cryptography for AES-GCM encrypted system.db, bm25s for BM25 rule ranking, and mem0ai for external memory adapters — guard all optional dependency imports with try / except ImportError at 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 bare except: pass — use typed exceptions or at minimum logger.warning(...) with exc_info=True to avoid silent failure in a memory product
Never import from out-of-scope sibling directories ../Sprites/ or ../Hausgem/ within gradata/* 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 inside gradata/*
Use atomic-write helper when writing JSON files to prevent corruption from mid-write crashes

Files:

  • Gradata/src/gradata/hooks/adapters/opencode.py
  • Gradata/src/gradata/hooks/adapters/codex.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: Applies to Gradata/tests/**/*.py : Set `BRAIN_DIR` environment variable via `tmp_path` in conftest.py for test isolation — ensure `_paths.py` module cache refreshes when calling `Brain.init()` directly inside tests

Applied to files:

  • Gradata/tests/test_hook_adapters.py
🔇 Additional comments (11)
Gradata/src/gradata/hooks/adapters/codex.py (4)

1-24: LGTM!


77-98: LGTM!


101-147: LGTM!


150-210: LGTM!

Gradata/src/gradata/hooks/adapters/opencode.py (4)

1-24: LGTM!


52-69: LGTM!


72-100: LGTM!


103-137: LGTM!

Gradata/tests/test_hook_adapters.py (3)

59-71: LGTM!


74-88: LGTM!


91-103: LGTM!


📝 Walkthrough
  • Codex adapter: Now installs complete hook set including post_tool/auto_correct and session_end/session_close in addition to existing pre_tool/inject_brain_rules
  • OpenCode adapter: Extended to install postTool/auto_correct and sessionEnd/session_close hooks alongside existing preTool/inject_brain_rules
  • Hook installation: Both adapters now use deterministic hook IDs based on signature, event, and module name
  • Configuration helpers: Added TOML/JSON parsing utilities to detect existing hooks and remove only gradata-managed entries
  • Uninstall generalization: Both adapters now remove any gradata-managed hook table that matches the signature
  • Test coverage: Added three new test cases validating pre/post/session hook installation for Codex, Hermes, and OpenCode
  • No API changes: All public function signatures (detect, extract_correction, install, uninstall) remain unchanged
  • No breaking changes: Existing functionality preserved while extending hook management capabilities

Walkthrough

Hook adapters for Codex and OpenCode now manage multiple hook events per agent instead of single hooks. Both adapters define a HOOKS registry, implement idempotent multi-event install logic with signature-based deduplication, and generalized uninstall. Tests validate the installations across all adapters.

Changes

Multi-hook adapter expansion

Layer / File(s) Summary
Codex multi-hook support
Gradata/src/gradata/hooks/adapters/codex.py
Codex adapter imports are updated to remove contains_signature dependency. A HOOKS mapping defines three managed hook events/modules (pre_tool, post_tool, session_end). The install() function now reads existing TOML, checks for exact hook set match via new TOML parsing helpers, removes gradata-managed tables before rewriting, generates multi-block TOML with deterministic id values, and returns idempotent already_present or added status. The uninstall() function generalizes table detection to match any [[hooks.*]] header by signature and updates success messages to reflect removal of hook blocks rather than a single pre_tool block.
OpenCode multi-hook support
Gradata/src/gradata/hooks/adapters/opencode.py
OpenCode adapter now defines a HOOKS tuple enumerating three managed hook events/modules (preTool, postTool, sessionEnd). The install() function was refactored to check for exact existing hook entries per event/module, remove any matching module hooks, append new entries, persist the JSON, and return already_present vs added status. New JSON helpers detect whether an entry corresponds to a specific module/event, verify exact hook presence, and remove matching module entries. The uninstall() function now scans all configured hook events, removes signature-matching entries, deletes the hooks block when empty, and returns hook not present or removed status.
Multi-hook adapter test validation
Gradata/tests/test_hook_adapters.py
Three new test cases validate adapter installations for Codex, Hermes, and OpenCode agents. Each test installs the adapter into a temp directory, asserts the result is "added", parses the config (TOML for Codex, JSON for OpenCode), and verifies expected hook group names exist with command strings referencing gradata.hooks.inject_brain_rules, gradata.hooks.auto_correct, and gradata.hooks.session_close modules.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels

feature

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: install post-tool hooks for Codex and OpenCode' directly describes the main changes in the changeset: installing post-tool hooks for these two adapters.
Description check ✅ Passed The description is clearly related to the changeset, detailing the installation of post_tool and session_end hooks for Codex and OpenCode, plus test coverage, with comprehensive verification results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch gra-55-post-tool-session-hooks

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):
┌──────────────┐
│ Opengrep CLI │
└──────────────┘

�[32m✔�[39m �[1mOpengrep OSS�[0m
�[32m✔�[39m Basic security coverage for first-party code vulnerabilities.

�[1m Loading rules from local config...�[0m
[00.18][ERROR]: Error: exception Glob.Lexer.Syntax_error("malformed glob pattern: missing ']'")
Raised at Glob__Lexer.syntax_error in file "libs/glob/Lexer.mll", line 8, characters 2-26
Called from Glob__Lexer.__ocaml_lex_token_rec in file "libs/glob/Lexer.mll", line 29, characters 26-53
Cal


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

@coderabbitai coderabbitai Bot added the feature label Jun 5, 2026
@Gradata Gradata merged commit d958235 into main Jun 5, 2026
9 checks passed
@Gradata Gradata deleted the gra-55-post-tool-session-hooks branch June 5, 2026 02:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant