Skip to content

fix(codex): omit idle PreToolUse hook relays#94515

Open
mazmorra-oc wants to merge 2 commits into
openclaw:mainfrom
mazmorra-oc:fix/codex-pretooluse-action-gate
Open

fix(codex): omit idle PreToolUse hook relays#94515
mazmorra-oc wants to merge 2 commits into
openclaw:mainfrom
mazmorra-oc:fix/codex-pretooluse-action-gate

Conversation

@mazmorra-oc

@mazmorra-oc mazmorra-oc commented Jun 18, 2026

Copy link
Copy Markdown

Summary

  • Stops Codex native hook config from installing PreToolUse when the OpenClaw relay has no local pre-tool work to do.
  • Keeps PermissionRequest and other requested hooks intact when they still have relay work.
  • Removes the --pre-tool-use-unavailable noop fallback from generated relay commands; empty hook arrays are now the signal that no Codex pre-tool hook should run.
  • Leaves explicit native loop detection behavior in scope: if native loop detection is enabled, PreToolUse still remains active.
  • Intentionally changes the default contract: native PreToolUse is no longer installed as a presence/noop hook; it is installed only when local pre-tool work can make a decision.
  • Success looks like fewer no-op native hook subprocesses for Codex tool calls while preserving approval and explicitly configured pre-tool behavior.

Linked context

Which issue does this close?

Closes #91009

Which issues, PRs, or discussions are related?

Related #94120

Was this requested by a maintainer or owner?

No maintainer request was available to me. This supersedes #94120 with the same patch rebased onto current main and a corrected real-behavior proof section.

Real behavior proof (required for external PRs)

  • Behavior or issue addressed: Codex sessions could receive a native PreToolUse command even when OpenClaw had no local pre-tool hook/policy work, causing avoidable no-op hook subprocesses on every tool call.
  • Real environment tested: Local OpenClaw checkout on Linux ARM64, PR head 8a7cedfeb6, running the native hook relay builders directly through the TypeScript runtime used by the repository.
  • Exact steps or command run after this patch: Ran a local Node/tsx proof script that registers a Codex relay with pre_tool_use and permission_request, with loop detection disabled, then builds the Codex native hook config and prints the resulting hook counts and command fallback presence.
  • Evidence after fix (screenshot, recording, terminal capture, console output, redacted runtime log, linked artifact, or copied live output):
PreToolUse hooks: 0
PermissionRequest hooks: 1
Contains --pre-tool-use-unavailable noop: false
Configured events: hooks.PermissionRequest, hooks.PostToolUse, hooks.PreToolUse, hooks.Stop
  • Observed result after fix: PreToolUse is represented as an empty hook array when no local pre-tool work exists, PermissionRequest remains installed, and the generated config no longer contains the unavailable noop fallback.
  • What was not tested: I did not run a live Codex session against a deployed OpenClaw gateway or measure subprocess counts under production traffic. The proof is from a live local checkout of the relay/config path plus focused regression tests.
  • Proof limitations or environment constraints: The direct bridge portions of the broader relay test file still fail in this local environment with native hook relay bridge not found; that failure also reproduced on an unpatched baseline during the earlier fix(codex): skip noop PreToolUse native hook relays #94120 work and is not caused by this diff.
  • Before evidence (optional but encouraged): In the previous version of this path, PreToolUse could still be installed with a noop fallback command when no local pre-tool work existed; the focused regression now asserts that this hook is not installed in that case.

Tests and validation

Which commands did you run?

git diff --check origin/main...HEAD
./node_modules/.bin/vitest run extensions/codex/src/app-server/native-hook-relay.test.ts --config test/vitest/vitest.extension-codex.config.ts --reporter=verbose
./node_modules/.bin/vitest run src/agents/harness/native-hook-relay.test.ts --config test/vitest/vitest.agents.config.ts --reporter=verbose -t "builds pre-tool relay commands only when before-tool policy is active|does not keep pre-tool relays active for loop detection alone|keeps pre-tool relays active when native loop detection is explicitly enabled|omits pre-tool relays when native loop detection is explicitly disabled|builds relay commands only for native events with matching local hooks|uses the Codex hook relay command shape|includes explicit unavailable noop mode only for PreToolUse"
node --import tsx --input-type=module -e "<local proof script>"

What regression coverage was added or updated?

  • Updated Codex app-server native hook relay tests so the config clears PreToolUse when the relay reports no local work.
  • Added/updated core relay tests for pre-tool local-work detection, explicit native loop detection, and command generation without the noop fallback.

What failed before this fix, if known?

  • The old behavior could install a Codex PreToolUse hook even when no local pre-tool work existed, relying on a noop fallback instead of omitting the hook.
  • A broader run of src/agents/harness/native-hook-relay.test.ts still has pre-existing direct bridge failures in this local environment (native hook relay bridge not found); the focused tests for this patch pass.

If no test was added, why not?

Tests were added/updated.

Risk checklist

Did user-visible behavior change? (Yes/No)

No.

Did config, environment, or migration behavior change? (Yes/No)

Yes. Generated Codex hook overlay config changes by omitting inactive PreToolUse hook commands.

Did security, auth, secrets, network, or tool execution behavior change? (Yes/No)

Yes. Tool execution hook behavior changes by avoiding no-op pre-tool relay commands when no local pre-tool decision path exists.

What is the highest-risk area?

Accidentally removing PreToolUse when a local policy or explicit native loop detector still needs it.

How is that risk mitigated?

The relay now decides per event via shouldRelayEvent(event), with regression coverage for before-tool policy active, loop detection disabled, loop detection explicitly enabled, and mixed event sets where PermissionRequest remains installed.

Current review state

What is the next action?

Waiting for maintainer review and CI.

What is still waiting on author, maintainer, CI, or external proof?

CI must run on the new PR. No author-side code changes are pending from my local validation.

Which bot or reviewer comments were addressed?

This PR addresses the presentation/proof problem from #94120 by using the required Real behavior proof section and including after-fix terminal output.

@openclaw-barnacle openclaw-barnacle Bot added agents Agent runtime and tooling extensions: codex size: S proof: supplied External PR includes structured after-fix real behavior proof. labels Jun 18, 2026
@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. labels Jun 19, 2026
@clawsweeper

clawsweeper Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 1, 2026, 3:06 PM ET / 19:06 UTC.

Summary
The PR changes Codex native hook relay config and tests so inactive PreToolUse events are emitted as empty hook arrays instead of no-op relay command hooks, while preserving active policy and explicit loop-detection paths.

PR surface: Source -6, Tests +23. Total +17 across 6 files.

Reproducibility: yes. for source-level reproduction: current main builds synchronous Codex PreToolUse command hooks for selected inactive/default loop-detection cases, and upstream Codex executes matched command hooks as child processes. I did not run a live multi-agent load reproduction in this read-only review.

Review metrics: 1 noteworthy metric.

  • Hook Default Change: 1 generated event path changed; 1 loopDetection predicate changed. Maintainers should notice that upgraded Codex sessions with unset loopDetection will stop installing native PreToolUse command hooks by default.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #91009
Summary: This PR is an open candidate for the canonical Codex native hook relay CPU/RSS fan-out issue, but it is a narrowed idle-relay mitigation rather than a proven full fix for every related relay failure mode.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • Get maintainer sign-off on the unset loopDetection default change.
  • Scope the linked P1 issue closure or keep a follow-up open for explicit loopDetection and concurrency fan-out.

Risk before merge

  • [P1] Generated Codex hook overlay behavior changes for upgraded sessions with unset tools.loopDetection: PreToolUse no longer installs unless before-tool policy or explicit tools.loopDetection.enabled=true exists.
  • [P1] The PR closes Codex PreToolUse native hook relay spawns CPU-bound openclaw-hooks processes and stalls gateway RPC #91009, but that issue includes explicit loopDetection and relay-concurrency fan-out cases that may remain after this scoped idle-relay mitigation.
  • [P1] Contributor proof demonstrates the local config-builder/runtime path, not a live multi-agent Codex load run showing reduced gateway stalls or relay process residency.

Maintainer options:

  1. Scope The P1 Closure (recommended)
    Remove or qualify the automatic closure unless maintainers accept that explicit loopDetection and concurrency fan-out remain separate follow-up work.
  2. Accept As Narrow Mitigation
    Merge with an explicit maintainer decision that the unset loopDetection default change is acceptable and remaining relay fan-out stays tracked elsewhere.
  3. Pause For Broader Relay Design
    Pause this PR if maintainers want a concurrency cap, lightweight relay entrypoint, or explicit loopDetection fan-out solved before any default change lands.

Next step before merge

  • [P2] Maintainer review is needed because the remaining blocker is compatibility and P1 issue scope, not a narrow mechanical repair.

Security
Cleared: The diff removes an idle generated command path and changes hook gating without adding dependencies, CI changes, network access, secret handling, or new supply-chain execution surface.

Review details

Best possible solution:

Land this only as a scoped idle-relay mitigation after maintainer sign-off on the default hook change, and keep or split tracking for the broader relay fan-out work before treating the linked P1 issue as fully fixed.

Do we have a high-confidence way to reproduce the issue?

Yes for source-level reproduction: current main builds synchronous Codex PreToolUse command hooks for selected inactive/default loop-detection cases, and upstream Codex executes matched command hooks as child processes. I did not run a live multi-agent load reproduction in this read-only review.

Is this the best way to solve the issue?

Yes as a bounded mitigation for idle no-work PreToolUse relays; unclear as the complete solution for the linked P1 issue because explicit loopDetection and concurrency fan-out remain maintainer decision points.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 5db7c3797de3.

Label changes

Label justifications:

  • P1: The PR targets an open Codex native hook relay problem reported as gateway stalls, CPU/RSS relay fan-out, OOMs, and host restarts.
  • merge-risk: 🚨 compatibility: The diff changes generated Codex hook overlay behavior and whether existing sessions with unset loopDetection install PreToolUse after upgrade.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body includes after-fix terminal output from a local runtime proof showing PreToolUse hooks at 0, PermissionRequest hooks at 1, and no noop fallback command; live load proof remains a residual merge-risk question.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body includes after-fix terminal output from a local runtime proof showing PreToolUse hooks at 0, PermissionRequest hooks at 1, and no noop fallback command; live load proof remains a residual merge-risk question.
Evidence reviewed

PR surface:

Source -6, Tests +23. Total +17 across 6 files.

View PR surface stats
Area Files Added Removed Net
Source 2 5 11 -6
Tests 4 65 42 +23
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 6 70 53 +17

What I checked:

Likely related people:

  • pashpashpash: Prior ClawSweeper/git-history context ties the native hook relay foundation and Codex native hook parity work to the affected core relay and Codex app-server surfaces. (role: feature introducer; confidence: medium; commits: 7a958d920c88, cec11954e474, 2fadc33d1d83; files: src/agents/harness/native-hook-relay.ts, extensions/codex/src/app-server/native-hook-relay.ts, src/cli/native-hook-relay-cli.ts)
  • steipete: Prior review context links this person to merged native relay foundation/idle-relay work and the no-policy native hook fallback in the same command/config paths. (role: recent adjacent contributor and merger; confidence: medium; commits: 7a958d920c88, 592aae3696da, 76eb478ac9fe; files: src/agents/harness/native-hook-relay.ts, extensions/codex/src/app-server/native-hook-relay.ts, src/cli/native-hook-relay-cli.ts)
  • joshavant: Authored and merged the adjacent native hook relay lifetime-bound fix across the same core relay, Codex extension, and CLI relay surfaces. (role: recent process-lifecycle contributor; confidence: high; commits: 68dabb735245, 14b1ebd640c6; files: src/agents/harness/native-hook-relay.ts, extensions/codex/src/app-server/native-hook-relay.ts, src/cli/native-hook-relay-cli.ts)
  • evgyur: Prior review context links this person to merged work avoiding native hook relay subprocesses without handlers, sharing the idle-relay invariant involved here. (role: adjacent idle-relay fix author; confidence: medium; commits: 592aae3696da, d01983db7836, 7745fc5adb72; files: src/agents/harness/native-hook-relay.ts, extensions/codex/src/app-server/native-hook-relay.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (1 earlier review cycle)
  • reviewed 2026-06-21T13:45:56.279Z sha cb5ea57 :: needs maintainer review before merge. :: none

@mazmorra-oc

Copy link
Copy Markdown
Author

@clawsweeper re-review

Updated adjacent app-server tests to pin the new default: inactive PreToolUse is omitted unless there is local pre-tool work or explicit loopDetection.enabled=true. PermissionRequest coverage remains separate.

Local validation after the update:

  • git diff --check
  • vitest run extensions/codex/src/app-server/run-attempt.native-hook-relay.test.ts extensions/codex/src/app-server/side-question.test.ts --config test/vitest/vitest.extension-codex.config.ts --reporter=verbose -> 57 passed
  • vitest run extensions/codex/src/app-server/native-hook-relay.test.ts --config test/vitest/vitest.extension-codex.config.ts --reporter=verbose -> 9 passed
  • focused src/agents/harness/native-hook-relay.test.ts relay cases -> 7 passed

@clawsweeper

clawsweeper Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jun 20, 2026

Copy link
Copy Markdown
Contributor

This is materially affecting our production OpenClaw deployment, and our live evidence matches the idle PreToolUse path this PR removes.

Environment:

  • OpenClaw 2026.7.1 (2d2ddc4), Linux x64, 2 vCPU
  • Codex app-server runtime
  • tools.loopDetection.enabled=false explicitly configured

Reproduction:

  1. Run 3–4 concurrent Codex-backed chat sessions.
  2. Have each session perform native tool calls (shell/file operations are sufficient).
  3. Observe synchronous commands shaped like openclaw hooks relay --provider codex ... --event pre_tool_use --pre-tool-use-unavailable noop spawning openclaw-hooks workers.
  4. Monitor workers and gateway liveness with:
    pgrep -a -f 'openclaw-hooks|openclaw(\.mjs)? hooks relay --provider codex'
    journalctl --user -u openclaw-gateway.service --since '10 min ago' | grep -E 'event_loop_delay|event_loop_utilization|memory pressure'

Observed during one incident:

  • individual no-op relay workers: roughly 336–421 MiB RSS and 42–95% CPU each
  • 73 unique relay PIDs and 93 watchdog TERM/KILL actions during the affected period
  • with four concurrent sessions: gateway event-loop utilization 0.998, p99 delay 55,129.9 ms
  • gateway probe/status degraded to 7.9 s / 17.1 s
  • chat queues backed up for more than an hour
  • no OOM occurred; the host was CPU-starved and the gateway remained technically alive but barely responsive

The important detail for this PR is that explicitly disabling loop detection did not suppress process creation—it only produced the --pre-tool-use-unavailable noop path. That makes this patch highly relevant for real multi-chat workloads, not merely a process-count optimization.

Happy to provide additional redacted logs or validate a build containing this patch if maintainers need production confirmation.

@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: fix(codex): omit idle PreToolUse hook relays This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

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

Labels

agents Agent runtime and tooling extensions: codex merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. size: S status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Codex PreToolUse native hook relay spawns CPU-bound openclaw-hooks processes and stalls gateway RPC

2 participants