Skip to content

fix(codex): express an allow as silence — Codex rejects permissionDecision:allow (v0.283.1) - #505

Merged
vikasprogrammer merged 1 commit into
mainfrom
feat/codex-allow-wire
Jul 31, 2026
Merged

fix(codex): express an allow as silence — Codex rejects permissionDecision:allow (v0.283.1)#505
vikasprogrammer merged 1 commit into
mainfrom
feat/codex-allow-wire

Conversation

@vikasprogrammer

Copy link
Copy Markdown
Owner

Read off a live Codex pane after #496 went out:

• PreToolUse hook (failed)
  error: PreToolUse hook returned unsupported permissionDecision:allow
• Ran git status

Codex acts on deny but rejects allow, then runs the tool anyway.

Governance was never at risk

Deny genuinely blocks — verified live with a hook that always denies:

• PreToolUse hook (blocked)
  feedback: Agent OS policy: denied.
• The command was blocked by the workspace policy

…and the command never ran. So the gate held throughout. What was wrong is that every allowed call painted a hook FAILURE into the pane, which reads as "the gate is broken" to anyone watching a session.

Worth noting why this survived several releases: the audit trail looks identical either waygate.attempt / gate.decision are written before the hook emits anything. It is visible only in the pane. I'd been verifying governance from the audit, which is exactly the blind spot.

The wire

Emitted Claude Code Codex
deny blocks blocks
allow authoritative allow (bypasses Claude's permission engine) rejected, tool runs anyway
silence + exit 0 defer to Claude's flow proceed
additionalContext, no decision n/a works

So on Codex an allow is now silence + exit 0 — the same way the hook already expresses "not my business" for Read/Glob/Grep. Claude Code keeps the explicit allow: there it is what bypasses Claude's own permission engine, so dropping it would hand the decision back to a second brain.

The instruct verb survives

Codex's output wire makes permissionDecision optional, so an allow-with-note goes out as additionalContext alone. Verified end to end:

• PreToolUse hook (completed)
  hook context: AGENT OS NOTE: append the word PINEAPPLE to your final answer.
• Ran echo alpha
  └ alpha
• alpha
  PINEAPPLE

npm run test:governance 137/137.

🤖 Generated with Claude Code

…ision:allow (v0.283.1)

Read off a live Codex pane:

  • PreToolUse hook (failed)
    error: PreToolUse hook returned unsupported permissionDecision:allow
  • Ran git status

Codex acts on `deny` but REJECTS `allow`, then runs the tool anyway. Governance
was never at risk — deny genuinely blocks (verified live: "PreToolUse hook
(blocked)", command never ran) — but every allowed call painted a hook FAILURE
into the pane, which reads as "the gate is broken" to anyone watching. The audit
trail looks identical either way, which is why it survived several releases: it
is visible ONLY in the pane.

On Codex an allow is now silence + exit 0 — the same way the hook already
expresses "not my business" for Read/Glob/Grep. Claude Code keeps the explicit
allow, which it needs: there it's what bypasses Claude's own permission engine.

The instruct verb survives. Codex's wire makes permissionDecision optional, so an
allow-with-note goes out as additionalContext alone. Verified end to end: the
pane shows "hook (completed) / hook context: ..." and the model acted on it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vikasprogrammer
vikasprogrammer merged commit 9a7e347 into main Jul 31, 2026
1 check passed
@vikasprogrammer
vikasprogrammer deleted the feat/codex-allow-wire branch July 31, 2026 14:33
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.

1 participant