Codex ACP harness parity and memory
Original request (verbatim): "Close the gap between Claude, Codex, Antigravity and Pi. More universal code, less provider specific"
Settled inputs: PRD (Task 9932) and Architecture (Task 9933) of this epic. Approach (architecture §1): lifecycle events run in Jaah-owned code in front of every session (ACP: `jaah-acp-host`, `apps/jaahd/acp/host.py`; terminal: node daemon + vendor CLI events); tool events run in-band through ONE neutral dispatcher `tools/hook_bridge_core.py::dispatch`. Adapters contribute only declarations (event names, tool-name map, placement literals, error text patterns, question prefix), never a copy of the logic.
Requirement R1 (verbatim): "Each of these mechanisms has exactly ONE provider-neutral implementation home that every provider uses; an adapter contributes only vendor literals and capability declarations, never its own copy of the logic: (a) hook/guard rendering & chaining, (b) hook-context injection into the model, (c) charter placement as system/built-in instructions, (d) session-start rule list (guard brief), (e) read-once guard reset signal, (f) prompt-submit and session-end lifecycle events, (g) StopFailure / API-error self-heal, (h) project-memory hooks, (i) token/cost (spend) reading, (j) usage-window (quota) reading, (k) the operator question / structured interview channel."
R5 (verbatim): "Availability: every closed capability is ON by default on the dev control plane (`dev.jaah.ai`) — no new switch that ships OFF; if a switch is unavoidable it defaults ON and is wired in the real deployment."
Closing-test naming contract (architecture §4): every degradation key this child closes gets a test named `test_closes_<key with - as _>` (e.g. `test_closes_no_hook_context`); C9 refuses to remove a key without it. Do NOT remove catalogue degradation keys in this child — the close-out child removes them; this child delivers the behaviour and the closing test.
## Scope (this child)
Architecture child C6 — closes Codex `omx-hooks-off-on-acp` and Codex project-memory hooks. Builds on C1 (`harness_dispatch`, S3). SECURITY SURFACE (guards): run the autonomous security review lane before merge.
- Make codex-acp run hooks without persisted trust. Codex 0.163.0 has `--dangerously-bypass-hook-trust` (`codex --help`). codex-acp embeds codex-core, so find the matching config override, or else add a fork patch passing it.
- **Security fence:** the bypass may trust only Jaah's rendered hooks file. A repository's own project hooks layer must stay untrusted or disabled. Pin this with a test that a worktree `.codex/hooks.json` does not run.
- Render the full fleet harness, memory rows included, into the ACP config instead of `_acp_hooks()` alone, and set `project_memory_hooks=True` on the Codex row.
- Map tool events natively; lifecycle per S3 — Codex keeps `host_lifecycle=()` (native `_EVENTS`, `codex.py:206-213`), so the disjointness invariant holds.
- R5: the bypass is always applied (to Jaah's hooks file only) — no switch.
Credentials & reach: C1–C7 unit and replay tests, AC1–AC4 | nothing beyond the worktree (`./dc check full`) | verified (worktree)
Out of scope (PRD, verbatim — do NOT touch):
- MUST NOT retire, rewrite or change the runtime selection of the legacy terminal runtime; Claude `oauth` stays `legacy_only` (ADR in `docs/adrs/README.md`, ACP Claude entry).
- MUST NOT remove or reword any "stay published" degradation (list above), including Pi `no-subagents` and `acp-runtime-only`.
- MUST NOT build Pi subagents or a Jaah-side subagent lane.
- MUST NOT add Jaah-side workarounds for vendor-intrinsic DeepSeek/Codex gaps (PDF conversion, model remap changes, throttling avoidance).
- MUST NOT do live-verification work for Antigravity `not-yet-observed`, nor touch `home-is-account-dir` or `microvm-signed-in-legacy-runtime`.
- MUST NOT change `tools/provider_branches.toml` patterns/allowlist scope beyond what removing branches requires (gate tightening was not selected), and set no line-count target.
- MUST NOT add a new provider or retire one; no change to login/sign-in flows, model-tier resolution, or the plan gate (`non_claude_engines`).
Stay-published keys (must stay byte-identical): DeepSeek `document-blocks-unsupported`, `images-flash-only`, `prompt-cache-controls-ignored`, `beta-features-ignored`, `web-search-extra-calls`, `claude-model-names-remapped`, `model-quality-differs`; Codex `device-code-login-workspace-gated`, `subscription-concurrency-throttling`; Pi `no-subagents`, `acp-runtime-only`. I1-escaped (stay, unchanged): Antigravity `no-spend-reading`; Pi and DeepSeek `no-quota-reading`.
Done means:
- A test that EXECUTES a hook through codex-acp (or asserts the patched launch argv/config override codex-acp actually honours) — not merely inspecting rendered config — shows oh-my-codex and fleet hooks running on Codex ACP — `test_closes_omx_hooks_off_on_acp`; `test_closes_project_memory_hooks` (Codex).
- A test proves a repo-local worktree `.codex/hooks.json` does NOT run.
- Security review lane (code-review-policy §Autonomous review profile) run and recorded in the PR body.
- Disjointness test green; `python3 tools/check_provider_branches.py` exits 0; quick gate green.
Activity
- Draft
- Ready