fix(codex): preserve plugin app approvals in side conversations#98812
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed July 1, 2026, 8:38 PM ET / 00:38 UTC. Summary PR surface: Source +9, Tests +104. Total +113 across 2 files. Reproducibility: yes. source-level reproduction is high confidence: current main replays app policy on thread start/resume but omits it from the side-thread fork config, while Codex reloads fork config from request overrides. I did not run a live Review metrics: 1 noteworthy metric.
Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land or close this maintainer-labeled PR after maintainer review; the best code shape is the focused side-fork replay, not a broader global reviewer or config rebuild change. Do we have a high-confidence way to reproduce the issue? Yes, source-level reproduction is high confidence: current main replays app policy on thread start/resume but omits it from the side-thread fork config, while Codex reloads fork config from request overrides. I did not run a live Is this the best way to solve the issue? Yes, this appears to be the best focused fix: it replays the same persisted app-policy patch already used by thread lifecycle at the omitted side-fork owner. Broader alternatives like changing the top-level reviewer or rebuilding plugin inventory inside AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 273729bd95ef. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +9, Tests +104. Total +113 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
Land-ready proof for exact head
Known proof gap: no external live |
|
Merged via squash.
|
* origin/main: test(gateway): isolate live release agent state test(plugins): repair prerelease validation fixtures fix(discord): guard JSON.parse against malformed API response bodies (#97889) fix(codex): preserve app approvals in side forks (#98812) fix(agents): don't inject A2A turns into isolated-cron sessions_send (#92257) (#92283) fix(browser): guard setDeep against empty keys array (#98138) docs(telegram): move maintainer decisions into scoped AGENTS.md fix(ios): generate light app store screenshots only fix(gateway): distinguish reachable gateway from failed status probe (#98183)
Co-authored-by: Peter Steinberger <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
Co-authored-by: Peter Steinberger <[email protected]>
Related: #98501
Related: #97327
Related: #98499
What Problem This Solves
Codex side conversations created with
/btwfork from a fresh request config. That fork path did not replay the persisted plugin app policy context, so an app configured withallow_destructive_actions: "ask"could lose its app-scopedapprovals_reviewer: "user"boundary in the side conversation. Reusing the thread-level reviewer would not be equivalent: it could either miss the ask app or broaden approval routing for sibling apps.Why This Change Was Made
The side-question owner now merges
buildCodexPluginAppsConfigPatchFromPolicyContext(binding.pluginAppPolicyContext)into the fork config, alongside the existing native-hook, runtime, network-proxy, sandbox, and base-reviewer fields. This uses the same canonical persisted-policy replay already used by thread start/resume, keeps the"ask"hard-cut naming from #98501, and does not introduce a compatibility path.Focused regression coverage proves that an ask-mode app keeps app-scoped user review after the fork while sibling
true,false, and"auto"apps retain their own policy and the top-level reviewer remains unchanged.Contributor provenance: Kevin Lin (@kevinslin) authored the app-scoped approval design in #97327 and the
"ask"hard cut in #98501. This follow-up preserves that boundary at the previously omitted side-fork owner.AI-assisted: yes. Codex implemented the repair and completed a clean gpt-5.6-sol xhigh autoreview against the exact synced commit.
User Impact
When a user opens a Codex side conversation from a thread containing an ask-mode plugin app, that app's destructive actions still route to the user for approval. Mixed-policy sibling apps remain unchanged, and unrelated thread-level approvals are not broadened.
Evidence
3e50f41dd6ea3446b5c98a2f19ec70982ac908e6; its substantive main run 28555775438 completed with 111 successes, one intentional skip, and zero failures.f11fec224f1ce283a13402f610b96931831d99e3; parent is the exact base above; tree isc105a1a74cfe02e86be1766595fcdb9bd58944eb.f5343a7972cd568dfb3891e60958b2a22fb62702) as the approved candidate and remains limited toextensions/codex/src/app-server/side-question.tsandextensions/codex/src/app-server/side-question.test.ts(+114/-1).side-question.test.tsandplugin-thread-config.test.ts.tbx_01kwg2ym3gm44kb6rp1c5end72(jade-shrimp) passed the changed gate in run 28556494609: extension production/test typechecks, lint, repository guards, DB/sidecar guards, and import-cycle checks. The same Testbox passed the fullcorepack pnpm build, including SDK declarations/exports and UI build.gpt-5.6-solandxhighreasoning against the exact pinned base: no accepted/actionable findings, 0.99 confidence.rust-v0.142.4source:codex-rs/app-server/src/request_processors/thread_processor.rs:3280and:3371confirm fork config reload;codex-rs/app-server-protocol/src/protocol/v2/thread.rs:484and:531define the fork request/config override;codex-rs/config/src/types.rs:451and:456define app-scopedapprovals_reviewer;codex-rs/core/src/connectors.rs:548confirms app ->_default-> global precedence;codex-rs/core/src/session/mcp.rs:508routescodex_appselicitation through it;codex-rs/core/src/connectors_tests.rs:314covers precedence.git diff --checkpassed.Commands:
Known proof gap: no external live
/btwplugin-app mutation was performed. The direct Codex contract check, focused fork regression, changed gate, full build, and clean model review cover the repaired boundary without creating a live destructive action.