Repository navigation
fix(codex): keep member hook groups at their keys and trust with the newest build (#1244, #1250) - #1263
Conversation
Every teamai writer of a Codex hooks file must leave a member's group at its key unless a teamai removal shifts it, and then carry its approval. A partial edit keeps the approvals in events it does not touch, a group that lands on a key without carrying an approval does not show one, and a caller that states no trust policy starts no Codex. Fourteen cases fail on main. The two trust-off guards and the internal-variant guard pass there because main never starts Codex from a hooks write, and the agent hook removal in a relocated Codex home passes because main already asked that file's home.
Codex keys an approval by group position. teamai now rewrites its own groups in their slots and appends new ones, so a member group moves only when a teamai group before it is removed. Every such move goes through editCodexHookFile, which carries the approval to the new key and clears the stale approvals left behind. Each production caller states the active config's Codex trust policy, and an agent hook's write asks the Codex home its file sits in; a caller that states none writes no trust and starts no Codex.
) PATH codex-cli 0.142.5 plus a desktop 0.163.0 must trust and diagnose with the newest, report a skew only when the builds hash a teamai hook differently, warn on every pull while it lasts without starting Codex, compare again on the next pull after an older build failed to list, start no older build when there is nothing to compare, and invalidate the trust cache when a desktop build appears or changes. The fake Codex answers --version, can hash like 0.142.5, can fail a method in one install only, and records which install answered.
Every app-server call, doctor's read, and the trust-cache fingerprint now resolve one build from codex on PATH and the desktop app's bundled ones (src/codex-desktop.ts), picking the newest by --version. While that build answers, each build of another version lists the same hooks; when one hashes a teamai hook differently, pull and doctor name both builds, and a pull warns once. Nothing else starts when the newest build lists none of teamai's hooks. The skew is stored with the trust cache, so every pull warns while it lasts. A pass in which another build could not list is cached only when the same builds failed in the pass before, so the next pull compares once more. The fingerprint stays stat-only, so a cached pull runs no binary.
Code Erosion ReportInformational — never blocks the merge.
Scanned 402 files / 92012 SLOC · high-CC functions 722/7877 * On TypeScript, Rule hits (TS verbosity layer)Standalone
63 distinct lines flagged across |
|
No actionable findings in the specified PR diff.
|
…1244-1250 # Conflicts: # src/init.ts
main now runs codex-team-hooks.test.ts on the Windows runner, and that file pins the POSIX dispatcher command. The team-hook dispatcher still put a Git Bash path into command on Windows, while the Codex built-ins keep bare bash on every platform and carry the Windows form in commandWindows. The dispatcher now does the same, so a committed hooks.json does not change on a Windows pull, and the Windows test list accepts a file that pins command beside commandWindows.
|
No actionable findings in the specified PR diff.
|
# Conflicts: # src/types.ts
|
No actionable findings in the specified PR diff.
|
# Conflicts: # src/hooks.ts # src/pull.ts
|
No actionable findings in the specified PR diff.
|
jeff-r2026
left a comment
There was a problem hiding this comment.
Approving 24008b0; please rebase onto current main and I'll merge. Merged locally with main: tsc, lint, build, full unit suite (only the 2 submodule-checkout cases that also fail on plain main), codex-trust/codex-team-hooks/hooks/hooks-cmd/doctor 239/239, Codex hook e2e 17/17.
Conflicts are mechanical: src/hooks.ts (keep your codexTrust line and #1330's ZCode legacy cleanup block; the ZCode reconcileHooks call needs no codexTrust) and src/pull.ts reinjectLegacyHooks (use main's hookToolPathsForConfig(teamConfig, localConfig) and append codexTrustPolicy(localConfig)).
[P2 non-blocking] On macOS desktopCodexBinaries() looks for /Applications/ChatGPT.app/Contents/Resources/codex, but current ChatGPT.app ships the CLI at Contents/Resources/codex-cli/bin/codex, so on mac the #1244 fix never sees the newer desktop build. Worth adding that candidate here or in a follow-up.
# Conflicts: # src/uninstall.ts
|
No actionable findings in the specified PR diff.
|
|
Thanks. Brought up to date with main at 2c1995d by a merge commit, not a rebase, so your approval stays on the same history. The resolutions are the ones you described, plus |
Why
Codex keys a hook's approval by its group position (
<file>:<event>:<group>:<handler>) and hashes handlers withadditionalContextLimitdifferently across versions (0.142.5ignores the field,0.163.0includes it). Rebuilding a Codexhooks.jsonmoved foreign hook groups off their trusted keys, and trusting with a stalecodexonPATHoverwrote the desktop app's trust every session.What changed
editCodexHookFileinsrc/hooks.tsso teamai updates its own groups in place, appends new ones, and carries over existing approvals viakeepCodexHookTrustinsrc/codex-trust.tswhen a removal shifts a foreign group.PATHand the desktop app bundles (src/codex-desktop.ts) insrc/codex-trust.tsfor trust writes,doctor, and the stat-only trust cache fingerprint.Codex builds disagree:once per pull and indoctorwhen an older build hashes a teamai hook differently.commandon barebashon Windows too, like the Codex built-ins, with the Windows form incommandWindows. Since main runscodex-team-hooks.test.tson the Windows runner, the dispatcher rendered a Git Bash path there and failed it. The Windows test list now accepts a file that pinscommandbesidecommandWindows.Scope
Covers all Codex
hooks.jsonwriters (reconcileHooks,removeHooks,reconcileCodexDispatchers,applyAgentHook,removeAgentHook,uninstall) and Codex build resolution on macOS and Windows. LeavesadditionalContextLimit: 0unchanged.Tradeoffs
When an older build fails to list hooks,
trustCodexForScoperetries the comparison on the next pull and then caches if the same build fails again, avoiding repeated app-server spawns on every pull when a binary predateshooks/list.Blast Radius
Touches Codex hook file reconciliation and
codex app-servertrust calls. Non-Codex tools and configurations withcodexTrustEnabled: falsedo not spawn Codex.Verification
8586c041(current main merged in):npx tsc --noEmit,npm run lint, andnpx vitest run(492 test files, 12,201 tests passed, 21 skipped). Earlier, on14821532:npm run buildand the real-CLI runs below.codex-team-hooks.test.tsand asserts both forms.inject,pull,removewith a trusted member group ahead of and between teamai groups): all 3 cases exit 0 with the member group'strustedstatus preserved.codex-cli 0.142.5onPATH+0.163.0desktop bundle):0.163.0listsSessionStartastrusted, andpullanddoctorsurface theCodex builds disagree:diagnostic.Fixes #1244
Fixes #1250