Context
On 2026-06-20, @tobiu asked whether Codex Stop-hook parity should affect Discussion #13621 or become a related ticket. The boundary is clear: #13621 owns the no-hold taxonomy and canonical Stop-hook reminder content; this ticket owns only the Codex Desktop harness adapter parity needed to consume that content.
Release classification: boardless post-v13 harness hardening. This is useful Agent OS stability work, but it is not a release-blocking gate.
Live duplicate sweep: checked the latest 20 open issues at 2026-06-20T12:58:17Z; no equivalent Codex Stop-hook parity ticket exists. Adjacent prior art found: #12633 (Claude-family Stop-hook enforcement), #10063 (Claude auto-memory safety-net, not build-ready), and #13480 (Codex wake submit reliability, separate final-submit boundary). A2A in-flight sweep: latest 30 inbox messages showed the #13621 re-poll, not a competing [lane-claim] / [lane-intent] on this Codex parity slice.
The Problem
The Claude family now has a concrete Stop-hook lane-state enforcement surface, but the Codex harness only has a UserPromptSubmit context hook wired today. Codex docs now document turn-scope Stop hooks, so the old fallback assumption that Codex can only receive prompt-submit context is stale enough to require a parity probe.
The risk is two-sided:
- If we do nothing, Codex remains the weak harness for the no-hold boundary: Claude can dry-run or enforce at turn-end, while GPT relies on self-policing or prompt-start reminders.
- If we blindly port the Claude hook, we may assume the wrong stdin/stdout contract. Claude uses structured
{"decision":"block","reason":"..."}. Codex must be verified before any enforcement claim.
Ungraduated Discussion Exception
This ticket intentionally cites open Discussion #13621 before its final graduation. The substantive rationale is operator-directed and scope-narrow: the ticket does not graduate #13621, does not decide the reminder wording, and does not encode the taxonomy. It creates the Codex harness adapter lane so the eventual #13621 content has parity across families.
Downstream amendment note: once #13621 graduates, this ticket's content-source row and reminder-string AC may need a small refresh to cite the final approved anchor. The transport ACs remain valid either way.
Divergence Matrix
| Option |
When this would be right |
Evidence / falsifier |
| A. New Codex parity ticket under #13618 |
The issue is harness transport parity, not reminder semantics |
Current .codex/hooks.json only wires UserPromptSubmit; official Codex docs list Stop; #13621 is converging content only |
| B. Fold into #13621 |
The open question were what the reminder should say for Codex specifically |
Rejected: that would mix content semantics with per-harness adapter mechanics and delay quorum over a non-content concern |
| C. Fold into #12633 |
The Claude Stop-hook ticket already owned all harnesses |
Rejected: #12633 explicitly scopes Claude-family Stop hook and named a Codex fallback, not a verified Codex Stop implementation |
| D. Use Goal mode / UserPromptSubmit only |
Codex Stop cannot block, inject, or expose enough turn-end state |
Kept as fallback: first prove Codex Stop; if it cannot enforce, classify/log at Stop and enrich the next prompt/wake instead |
Architectural Reality
.codex/hooks.json:3-15 currently registers only UserPromptSubmit, invoking .codex/hooks/codex-context.mjs.
.codex/hooks/codex-context.mjs:31-55 records Codex turn presence; .codex/hooks/codex-context.mjs:104-120 emits .codex/CODEX.md as turn context.
.claude/hooks/laneStateStopHook.mjs:3-38 documents the Claude Stop-hook enforcement shape; .claude/hooks/laneStateStopHook.mjs:96-120 contains the pure decision mapping; .claude/hooks/laneStateStopHook.mjs:193-230 resolves the runtime Stop payload.
test/playwright/unit/hooks/laneStateStopHook.spec.mjs:11-17 defines the current falsification layers; test/playwright/unit/hooks/laneStateStopHook.spec.mjs:149-180 proves dry-run and enforcing output for Claude.
- Codex Goal mode is not an enforcement substitute: it repeats a persistent objective and completion criteria, while Stop-hook parity is a turn-boundary detector/enforcer.
Pre-Flight (structural fast-path): potential authoring of .codex/hooks/codex-lane-state-stop.mjs matches the sibling hook-module pattern of .codex/hooks/codex-context.mjs in .codex/hooks/; sibling-file-lift applies; no novel directory choice. If implementation instead introduces a shared cross-harness lifecycle module outside the existing ai/scripts/lifecycle/ primitives, rerun structural pre-flight for that new location.
The Fix
- Add a Codex Stop-hook probe in dry-run mode to capture the real Codex
Stop stdin payload and verify event timing.
- Verify Codex output semantics empirically: whether stdout JSON, exit status, or another contract can block/inject a continuation. Do not assume Claude's
decision:block contract.
- If Codex can block/inject, add a
.codex Stop hook that reuses the existing lane-state parser/validator primitives and the canonical #13621 reminder content.
- Keep dry-run/log-only as the default. Enforcement must be operator-activated via environment/config after false-positive review.
- If Codex cannot block/inject, do not fake enforcement. Ship a classify/log path and route the reminder into the next
UserPromptSubmit / Goal-mode wake path as a best-effort fallback.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs / Evidence |
Codex Stop hook payload |
Official Codex hooks docs + live probe fixture |
Extract final assistant text or a transcript pointer suitable for lane-state parsing |
If payload lacks final text, classify unsupported and avoid enforcement claims |
Captured fixture in unit tests and PR body |
| Codex Stop decision output |
Official Codex hooks docs + live probe |
Use only a verified block/inject contract |
If no block path exists, log/classify and enrich next prompt |
Spawned-hook tests plus live dry-run evidence |
.codex/hooks.json |
Existing project-local Codex hook config |
Add Stop alongside current UserPromptSubmit, preserving the current context hook |
Leave UserPromptSubmit untouched if Stop is probe-only |
Diff + hook inspection |
| Reminder content |
Discussion #13621 after approval/graduation |
Reuse the single canonical no-hold reminder; no Codex-specific wording fork |
Temporary placeholder can cite #13621 anchor but must be refreshed before enforcement |
Discussion anchor in PR body |
| Enforcement activation |
#12633 dry-run-to-enforce safety pattern |
Default dry-run/log-only; operator-owned enforcement flip |
No enforcement if false-positive rate or hook contract is unsafe |
Unit tests + audit log evidence |
Decision Record impact
None expected. This is aligned with #13618 and the existing Agent OS hook/enforcement direction. No ADR amendment should be needed unless the Codex probe exposes a cross-harness hook contract that should become a shared design record.
Decision Record: Not needed for this ticket; #13621 remains the content discussion.
Acceptance Criteria
Out of Scope
- Changing #13621 content, quorum, or graduation criteria.
- Changing the Claude hook except for comparison tests or shared parser reuse.
- Auto-persisting memories; that belongs to #10063 after its session-id and curation-premise rescope.
- Codex wake submit reliability; #13480 remains the route for direct-message / heartbeat final-submit evidence.
- Using Goal mode as a validator or enforcement layer.
Avoided Traps
- Do not create a second canonical reminder string for Codex. Transport parity consumes the content contract; it does not fork it.
- Do not infer Codex hook decision semantics from Claude. The first deliverable is a falsifying payload/output probe.
- Do not turn OQ4 observability into an automated metric gate. #13621 converged it as team-facing observability, not enforcement.
- Do not modify ignored local
.codex/config.toml; keep project behavior in tracked .codex/hooks.json and documented activation env/config.
Related
Parent: #13618
Related: #13621, #12633, #10063, #13480
Origin Session ID: 2513f864-fce4-4a47-8d4b-afe8a5532e91
Handoff Retrieval Hints: Codex Stop-hook parity, Codex hooks Stop payload, no-hold reminder transport, laneStateStopHook parity, Goal mode fallback, UserPromptSubmit enrichment.
Context
On 2026-06-20, @tobiu asked whether Codex Stop-hook parity should affect Discussion #13621 or become a related ticket. The boundary is clear: #13621 owns the no-hold taxonomy and canonical Stop-hook reminder content; this ticket owns only the Codex Desktop harness adapter parity needed to consume that content.
Release classification: boardless post-v13 harness hardening. This is useful Agent OS stability work, but it is not a release-blocking gate.
Live duplicate sweep: checked the latest 20 open issues at 2026-06-20T12:58:17Z; no equivalent Codex Stop-hook parity ticket exists. Adjacent prior art found: #12633 (Claude-family Stop-hook enforcement), #10063 (Claude auto-memory safety-net, not build-ready), and #13480 (Codex wake submit reliability, separate final-submit boundary). A2A in-flight sweep: latest 30 inbox messages showed the #13621 re-poll, not a competing
[lane-claim]/[lane-intent]on this Codex parity slice.The Problem
The Claude family now has a concrete Stop-hook lane-state enforcement surface, but the Codex harness only has a
UserPromptSubmitcontext hook wired today. Codex docs now document turn-scopeStophooks, so the old fallback assumption that Codex can only receive prompt-submit context is stale enough to require a parity probe.The risk is two-sided:
{"decision":"block","reason":"..."}. Codex must be verified before any enforcement claim.Ungraduated Discussion Exception
This ticket intentionally cites open Discussion #13621 before its final graduation. The substantive rationale is operator-directed and scope-narrow: the ticket does not graduate #13621, does not decide the reminder wording, and does not encode the taxonomy. It creates the Codex harness adapter lane so the eventual #13621 content has parity across families.
Downstream amendment note: once #13621 graduates, this ticket's content-source row and reminder-string AC may need a small refresh to cite the final approved anchor. The transport ACs remain valid either way.
Divergence Matrix
.codex/hooks.jsononly wiresUserPromptSubmit; official Codex docs listStop; #13621 is converging content onlyStopcannot block, inject, or expose enough turn-end stateStop; if it cannot enforce, classify/log atStopand enrich the next prompt/wake insteadArchitectural Reality
.codex/hooks.json:3-15currently registers onlyUserPromptSubmit, invoking.codex/hooks/codex-context.mjs..codex/hooks/codex-context.mjs:31-55records Codex turn presence;.codex/hooks/codex-context.mjs:104-120emits.codex/CODEX.mdas turn context..claude/hooks/laneStateStopHook.mjs:3-38documents the Claude Stop-hook enforcement shape;.claude/hooks/laneStateStopHook.mjs:96-120contains the pure decision mapping;.claude/hooks/laneStateStopHook.mjs:193-230resolves the runtime Stop payload.test/playwright/unit/hooks/laneStateStopHook.spec.mjs:11-17defines the current falsification layers;test/playwright/unit/hooks/laneStateStopHook.spec.mjs:149-180proves dry-run and enforcing output for Claude.Pre-Flight (structural fast-path): potential authoring of
.codex/hooks/codex-lane-state-stop.mjsmatches the sibling hook-module pattern of.codex/hooks/codex-context.mjsin.codex/hooks/; sibling-file-lift applies; no novel directory choice. If implementation instead introduces a shared cross-harness lifecycle module outside the existingai/scripts/lifecycle/primitives, rerun structural pre-flight for that new location.The Fix
Stopstdin payload and verify event timing.decision:blockcontract..codexStop hook that reuses the existing lane-state parser/validator primitives and the canonical #13621 reminder content.UserPromptSubmit/ Goal-mode wake path as a best-effort fallback.Contract Ledger Matrix
Stophook payload.codex/hooks.jsonStopalongside currentUserPromptSubmit, preserving the current context hookUserPromptSubmituntouched if Stop is probe-onlyDecision Record impact
None expected. This is aligned with #13618 and the existing Agent OS hook/enforcement direction. No ADR amendment should be needed unless the Codex probe exposes a cross-harness hook contract that should become a shared design record.
Decision Record: Not needed for this ticket; #13621 remains the content discussion.
Acceptance Criteria
Stophook fires in a trusted project-local configuration and captures a representative payload fixture without blocking normal turns.decision:blockshape is supported, unsupported, or replaced by a Codex-specific contract..codex/hooks.jsonwires a Codex Stop hook in dry-run mode by default.Out of Scope
Avoided Traps
.codex/config.toml; keep project behavior in tracked.codex/hooks.jsonand documented activation env/config.Related
Parent: #13618
Related: #13621, #12633, #10063, #13480
Origin Session ID: 2513f864-fce4-4a47-8d4b-afe8a5532e91
Handoff Retrieval Hints:
Codex Stop-hook parity,Codex hooks Stop payload,no-hold reminder transport,laneStateStopHook parity,Goal mode fallback,UserPromptSubmit enrichment.