Skip to content

[Workstream D] PR 3 of 8: Codex parity — register PreToolUse and PreCompact/PostCompact after the hook failure is attributed #95

Description

@zaxbysauce

Order: third in Phase 3, and hard-gated on A-3. Registering more Codex hooks while an existing Codex hook fails proves nothing. Part of #100.

Why now (verified 2026-09-02 from Codex source and the local CLI)

Upstream supports what we do not register:

  • The canonical event enum (codex-rs/app-server-protocol/schema/typescript/v2/HookEventName.ts) is: preToolUse, permissionRequest, postToolUse, preCompact, postCompact, sessionStart, sessionEnd, userPromptSubmit, subagentStart, subagentStop, stop, interrupt. There is no PostToolUseFailure, so our second PostToolUse entry is the correct shape and should stay.
  • PreToolUse additionalContext was added by openai/codex#20692 (merged 2026-05-05); issue #19385, which our docs once cited as the blocker, was closed 2026-08-04. codex-rs/hooks/src/events/pre_tool_use.rs sets an additional_context_limit.
  • PreToolUse input carries tool_name, tool_input, tool_use_id, cwd, session_id, turn_id; SubagentStart carries agent_id/agent_type and no task text.
  • Our side already implements both verbs: hooks/zmem-launch.js:63-74 lists pretool-recall and precompact and :103-115 maps them to PreToolUse/PreCompact. Only hooks/hooks.codex.json omits them, and tests/test_pretool_inject.py:392-411 pins that omission to this issue.

Claim freshness: the facts above are dated 2026-09-02 against codex-cli 0.152.1. Re-verify before wiring, per the convention set by #103/#104.

Scope

  1. Blocking prerequisite: #A-3 must have attributed the failing Codex SessionStart hook and the canary must show a zmem line in the log. Do not proceed on a host where the existing hooks do not demonstrably run.
  2. Live-dump the tool names Codex actually emits for shell and patch operations (do not assume Bash), and write the matcher from the dump. Record the dump in a comment here.
  3. Register PreToolUse with the verified matcher and an explicit additional-context limit below the host's spill threshold.
  4. Register PreCompact and PostCompact, wired to the same handlers D-2 ([Workstream D] PR 2 of 8: Query-aware re-injection after compaction (and settle whether the PreCompact fence survives) #118) defines for Claude.
  5. Extend tests/test_codex_adapter.js with real envelope tests, and flip the pin at tests/test_pretool_inject.py:392-411 — the failure message on that assertion should name this issue so the next reader knows the flip is intentional.

Acceptance criteria

Depends on / blocks

Addendum — Muse Spark 1.3 report, validated 2026-09-03

Three additions, all verified against Codex source on 2026-09-03:

  • Units trap (verified). Codex's hook-output limit is 2,500 tokens by default (codex-rs/hooks/src/output_spill.rs:12, DEFAULT_HOOK_OUTPUT_TOKEN_LIMIT = 2_500); above it the text is spilled to a file and the model receives a head/tail preview (:59-90). zmem's envelope budget is charactershooks/zmem-launch.js:356 sets ZMEM_CTX_BUDGET to 9,000 on Codex, ≈ 2,250 tokens by the plugin's own 4-chars-per-token estimator — so a full fence sits within ~10% of the spill point, and C-5 ([Workstream C] PR 5 of 6: Make the 1500-token injection budget a measured hard ceiling #116) measured a single real prompt rendering 3,231 tokens before any cap. Add a Codex-specific token clamp with margin (or set the per-handler additionalContextLimit) and a unit test that a maximal fence never spills.
  • Trust gate. Codex requires hash-based trust review of hooks before they run (~/.codex/config.toml carries per-hook trusted hashes on this box). Every new hook entry changes its hash and must be re-trusted; deployment docs must say so, or the new hooks silently do not run.
  • Contract. Surfacing-only on every host: never emit permissionDecision, never deny, --no-bump, fail-open exit 0. The hazard-prevention "deny with reason" idea stays out (see D-7 [Workstream D] PR 7 of 8: Hermes parity — query-aware remote prefetch, shared gate and budget, derived namespace #122 for the same reasoning on Hermes).

Acceptance additions: the live tool_name dump must cover the shell tool and the patch/apply tool shape, and decide MCP/local-function tools in or out; a launcher end-to-end test with a Codex-shaped payload proves fence injection; the token-clamp test above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestseverity:highHigh-severity finding from codebase review

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions