Skip to content

Codex hook trust: two installed versions compute different hashes for additionalContextLimit, so the review prompt returns every session #1244

Closed

Description

@natinli

Summary

On a machine with two Codex installs, the hook-review prompt reappears every session even after choosing "allow". teamai trusts hooks through whatever codex resolves to on PATH; the desktop app runs a different binary. The two versions compute the trust hash for additionalContextLimit differently, so each side keeps invalidating the other.

This is separate from #1215 (cmd syntax) — that defect is about fail-open, and does not explain a prompt that returns every session.

Two binaries on one machine

Role Version Path
teamai trust / teamai doctor 0.142.5 %APPDATA%\npm\codex.cmd → @openai/codex/bin/codex.js
Actual desktop runtime 0.163.0-alpha.10.2 …\AppData\Local\OpenAI\Codex\bin\896a0166b774037a\codex.exe

teamai's trust path spawns a bare codex app-server (teamai-cli/dist/cli.js), so it always gets the PATH one. Two live Codex processes both resolve to the 0.163 binary — verified.

Field support differs between them

Binary string counts:

Binary commandWindows additionalContextLimit
0.142.5 (bin/codex.exe, 234 MB) 0 0
0.163 (896a0166…/codex.exe, 325 MB) 11 16

Only two of the eight entries carry the field

~/.codex/hooks.json has 8 teamai entries. Exactly SessionStart and SubagentStart carry additionalContextLimit: 0 (teamai sets it so team context is not truncated); the other six do not.

Those are precisely the two entries that show as modified.

The loop

teamai (0.142.5) writes the trust hash
        ↓
desktop (0.163) computes a different hash → modified → prompt
        ↓
user clicks Allow → desktop writes its hash
        ↓
next teamai pull → old CLI re-trusts → overwrites with its hash
        ↓
prompt again

Stored hashes match the old CLI's output, confirming the last writer was 0.142.5:

Hook Stored trusted_hash
SessionStart sha256:2f7e4fcf22f583718a59cf279b6a617a63f5463b0815a150f26890857a8158cb
SubagentStart sha256:4f1f6a753debb06d9af75027d07c202dd3faeec983bf5f9ea4d1b0e3042bfa59

teamai doctor reports all checks passed throughout, because it asks the same 0.142.5 binary — it proves the old CLI agrees with itself, not that the desktop does.

Suggested fix

teamai's automatic trust and doctor should use the Codex build that actually runs the hooks, or at minimum detect a version mismatch and warn rather than silently writing a hash the other build rejects. The executable-selection / compatibility check is the shared entry point — diagnosis and writing should use one implementation.

Removing additionalContextLimit would break the loop but is not a fix: teamai sets it deliberately to avoid truncating team context.

Scope note

This report covers the trust loop only. The cmd-syntax defect stays in #1215, and the dispatcher's commandWindows stays in #1210.

Environment: Windows 11, teamai-cli@0.28.0-beta.4, Codex 0.142.5 (CLI) + 0.163.0-alpha.10.2 (desktop).

Activity

  1. self-assigned this
    on Oct 21, 2026
  2. SaulMoro commented on Oct 21, 2026

    @SaulMoro
    Collaborator

    Triage

    Status. Confirmed in code on main (fa6a361). Assigned to me. I will fix it together with #1250 in one PR, because both change how teamai writes Codex hook trust.

    Root cause. Every Codex trust call asks one build, the codex on PATH:

    • openAppServer in src/codex-trust.ts spawns a bare codex app-server. Trust writes (trustCodexHooks) and doctor (readCodexHookTrust) both go through it. doctor can only report that the PATH build agrees with itself.
    • codexTrustFingerprint in src/hooks.ts keys the trust cache on findOnPath('codex'). It never sees the desktop app's bundled binary.
    • The fingerprint includes config.toml. When the desktop app writes its own hash after "Allow", the cache misses, and the next pull re-trusts with the PATH build's hash. That is the loop in the report.

    Not yet verified by me. That 0.142.5 and 0.163 compute different currentHash values for an entry with additionalContextLimit. I will reproduce it on macOS by running both versions' app-server hooks/list against one disposable CODEX_HOME.

    Plan.

    1. Add one Codex executable resolver. Trust writes, doctor, and the trust fingerprint all use it. Candidates are codex on PATH plus the desktop-bundled binaries: the macOS app paths that src/session-flow/adapters/codex.ts already lists, and %LOCALAPPDATA%\OpenAI\Codex\bin\*\codex.exe on Windows.
    2. When the candidates report different versions, trust and diagnose with the newest one. Pull and doctor warn and name each path and version, and tell the member to upgrade the older build. Two builds that hash differently cannot both accept one stored hash, so the warning is the actual fix for whoever runs the older build.
    3. Keep additionalContextLimit: 0 on the start hooks.

    Why newest and not "always the desktop app". A newer build's hash is the one the older build will compute after it upgrades. The desktop app updates itself, so it is usually the newer one. Picking the newest therefore breaks the loop in the common case, and it still does the right thing when the CLI is the newer build.

  3. natinli commented on Oct 21, 2026

    @natinli
    Author

    Reproduced the hash split on Windows, and the negative control pins it to the field. This is the item you listed as not yet verified.

    Method

    Both builds ran app-server against the same disposable CODEX_HOME, same hooks.json (copied from a real install), hooks/list with cwds: ["G:\AICode\Nilo"].

    Build How
    0.142.5 node @openai/codex/bin/codex.js app-server
    0.163.0-alpha.10.2 …\OpenAI\Codex\bin\896a0166b774037a\codex.exe app-server

    Result — with additionalContextLimit present

    8 hooks enumerated by both builds. 6 identical, 2 differ — and the two that differ are exactly the two carrying the field:

    Key 0.163.0-alpha.10.2 0.142.5
    session_start:0:0 sha256:ffc0ac8aebaba84f40db203a6b001ffbde9297e6d4092c13743a31255fa6eb66 sha256:2f7e4fcf22f583718a59cf279b6a617a63f5463b0815a150f26890857a8158cb
    subagent_start:0:0 sha256:c3cba7220b2fa6b3aecb5ec52ae852e7b2e6ba68af52f1a32ad7d1e8d32fa1a7 sha256:4f1f6a753debb06d9af75027d07c202dd3faeec983bf5f9ea4d1b0e3042bfa59

    Identical (no field): post_tool_use:0:0, post_tool_use:1:0, post_tool_use:2:0, stop:0:0, subagent_stop:0:0, user_prompt_submit:0:0.

    Negative control — same file, field stripped

    Removing additionalContextLimit from the two start hooks and re-running both builds:

    with additionalContextLimit     → 2 of 8 differ
    without additionalContextLimit  → 0 of 8 differ
    

    So the field alone accounts for the divergence; nothing else in those entries differs between the builds.

    What this means for your plan

    • The stored hashes on this machine are the 0.142.5 values (2f7e4fcf…, 4f1f6a75…), so the last writer was the PATH build — consistent with your root-cause reading.
    • Your "newest wins" rule resolves this case: trusting with 0.163's value is what the desktop already accepted, and it is what 0.142.5 will compute once it upgrades.
    • Your point 3 (keep additionalContextLimit: 0) is compatible with all of the above — the field is not what needs removing; the version skew is.

    Caveat

    I did not exercise the cross-process loop itself (desktop writes → teamai pull overwrites → desktop prompts again); that part rests on the stored-hash evidence above plus your source reading. What I measured is the hash divergence and its cause.

    Environment: Windows 11 Pro 10.0.26200, teamai-cli@0.28.0-beta.4, both Codex builds as listed. Scratch CODEX_HOME was deleted afterwards; the real ~/.codex was not modified.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions