Skip to content

fix(hooks): make Codex hooks effective (PostToolUse socket, alternation-aware Grep, per-turn UserPromptSubmit)#245

Open
zzet wants to merge 1 commit into
mainfrom
fix/codex-hook-effectiveness
Open

fix(hooks): make Codex hooks effective (PostToolUse socket, alternation-aware Grep, per-turn UserPromptSubmit)#245
zzet wants to merge 1 commit into
mainfrom
fix/codex-hook-effectiveness

Conversation

@zzet

@zzet zzet commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Closes #241.

Codex's hooks fired correctly but delivered almost no graph value. The investigation confirmed all three reported gaps and one was worse than diagnosed — the PostToolUse HTTP endpoint doesn't just fail on an occupied port, it no longer exists. This PR closes all three, cross-referenced against the official Codex hooks spec.

1. PostToolUse enrichment reached a removed HTTP API (root cause)

lookupEnclosingSymbol / lookupFileCallerCount queried http://localhost:<port>/api/graph/symbol-at and /api/graph/file-callers. Those routes were retired when the web surface migrated onto the daemon — the daemon's HTTP surface (only with --http-addr) serves /v1/* + /mcp, never /api/graph/*. So every lookup silently returned nothing regardless of port or configuration, and since Codex runs in soft enrich mode where PostToolUse carries the value, Codex got ~zero enrichment.

The PreToolUse twin was already migrated to the AF_UNIX daemon socket (commit that "route[d] file-indexed probe through daemon socket"); PostToolUse was left behind. This routes both through one shared daemonFileSummaryRaw helper (get_file_summary over the socket), computes the enclosing symbol from node line-spans client-side, and reports importer count from the file's dependents. Deletes queryGortex and the net/http dependency.

The pre-existing posttooluse_test.go was green because it stubbed an httptest /api/graph/* bridge that production never provided — the tests are re-seamed to the socket (fileSummaryFn) so they now exercise the real path.

2. PreToolUse skipped Codex's multi-keyword Grep patterns

Codex wraps grep in Bash and batches keywords behind | (e.g. place_edges|location_edge|normalize), so the whole pattern is never a bare identifier and classifyGrepPattern skipped it — 91% of probes were skipped_non_symbol. Now alternation patterns are split and each identifier-shaped alternative is probed (hits aggregated + deduped); pure-text patterns (phrases, hyphenated words) are steered toward search_text, the correct graph equivalent for literal search. The single-pattern fast path is unchanged.

3. Codex had no per-turn reinforcement

A SessionStart orientation fades as context grows and Codex forgets MCP tools — the core adoption concern in the issue thread. This wires a Codex UserPromptSubmit hook (the event Codex supports without a matcher, per the spec) that re-surfaces prompt-relevant graph symbols on every turn, reusing the existing buildUserPromptSubmitContext path already shared with Claude Code and Kimi.

Tests

  • New unit tests: enclosingNode (line-span resolution), parseFileSummary, splitAlternation, alternation probing (hit / mixed / pure-text / unreachable), Codex UserPromptSubmit install + dispatch.
  • go build ./..., go test -race ./internal/hooks/... ./internal/agents/codex/..., and go test ./cmd/gortex/... all pass.

Notes / follow-ups (not in this PR)

  • Binary freshness (issue side-note): packaging timing, not a code issue.
  • --port flag is now vestigial (kept for backward compatibility with existing hook configs).
  • Per the spec, Codex PreToolUse also fires for apply_patch and MCP tools — an edit-redirect for apply_patch is a plausible future addition but stays out of scope (edit-blocking is env-gated/experimental).
  • The existing SessionStart hook uses command_windows; the spec's TOML example shows commandWindows. Flagged for separate Windows-only verification — untouched here.
  • If Codex's UserPromptSubmit payload omits a prompt field, the new hook degrades to a silent no-op.

…lternation-aware Grep, per-turn UserPromptSubmit

The Codex hook integration fired correctly but delivered almost no graph
value. Three independent gaps, now closed.

1. PostToolUse enrichment reached a removed HTTP API. lookupEnclosingSymbol
   and lookupFileCallerCount queried http://localhost:<port>/api/graph/*,
   an endpoint that was retired when the web surface moved onto the daemon —
   so every enclosing-symbol / caller lookup silently returned nothing
   regardless of configuration. The PreToolUse twin was already migrated to
   the AF_UNIX daemon socket; PostToolUse was left behind. Route both through
   one shared daemonFileSummaryRaw helper (get_file_summary over the socket),
   compute the enclosing symbol from node line spans client-side, and report
   importer count from the file's dependents. Deletes queryGortex and the
   net/http dependency.

2. PreToolUse skipped Codex's multi-keyword Grep patterns. Codex wraps grep
   in Bash and batches keywords behind '|' (place_edges|location_edge|...),
   so the whole pattern is never a bare identifier and classifyGrepPattern
   skipped it — 91% of probes were skipped_non_symbol. Split alternation
   patterns and probe each identifier-shaped alternative, aggregating hits;
   steer pure-text patterns (phrases, hyphenated words) toward search_text.

3. Codex had no per-turn reinforcement. A SessionStart orientation fades as
   context grows and Codex forgets MCP tools. Wire a Codex UserPromptSubmit
   hook (the event Codex supports without a matcher) that re-surfaces
   prompt-relevant graph symbols on every turn, reusing the existing
   buildUserPromptSubmitContext path already shared with Claude Code and Kimi.

Adds a socket seam (fileSummaryFn) plus unit tests for enclosingNode,
parseFileSummary, alternation splitting, and the Codex UserPromptSubmit
install + dispatch. The vestigial --port flag is retained for backward
compatibility but is no longer consumed.

Fixes #241
@zzet zzet force-pushed the fix/codex-hook-effectiveness branch from 2182359 to 9f5fbac Compare July 4, 2026 15:42
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.

bug: Codex hooks (PreToolUse/PostToolUse) are largely ineffective — 91% skipped, PostToolUse HTTP never reaches daemon

1 participant