feat(codex): add native Goal lifecycle controls - #7935
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Reviewed the new Codex Goal service/RPC surface against the Effect service conventions. Two related findings on the new CodexGoalOperationError wrapper: it carries an unstructured message as its only data and the wrapping site derives that message from cause.message while discarding the cause. Everything else (namespace imports at the ProviderService boundary, optional codexGoal adapter capability, environment-based dependency acquisition, test-only service stubs) looks consistent with the conventions.
Posted via Macroscope — Effect Service Conventions
There was a problem hiding this comment.
UI consistency review of the web changes (apps/web/src/components/ChatView.tsx, apps/web/src/state/threads.ts).
The new Goal surface correctly reuses the shared systems — ComposerBannerStack/Alert for the banner and stackedThreadToast for command feedback — and useCodexGoal follows the existing useEnvironmentThread atom pattern. Two issues are specific to the banner the diff adds: an unbounded user-authored description in the composer drawer, and stack ordering that lets a permanent informational banner sit in front of the actionable ones.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
One remaining convention issue with CodexGoalOperationError: the wire-visible detail field is populated by copying the provider error's message, and the wrapper's message is then derived from it. Now that operation, threadId, and cause are modelled, detail can be dropped so the message comes only from stable structural attributes and the provider text stays in cause.
Posted via Macroscope — Effect Service Conventions
There was a problem hiding this comment.
One finding: the Goal banner is ordered ahead of the parked-thread banner, which pushes that banner's Wake now / Un-settle button behind the collapsed stack on Codex threads with an active Goal.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
One finding: the Goal status enum is rendered directly as user-facing copy in the composer banner and the /goal status toast. Prior findings on banner ordering and description clamping look resolved.
Posted via Macroscope — UI Consistency
There was a problem hiding this comment.
One consistency finding on the new Codex Goal composer banner. Prior notes (status label record, banner ordering behind the actionable parked/woke/branch banners, clamped description) are addressed.
Posted via Macroscope — UI Consistency
8b9f2e1 to
3ebf2f2
Compare
ApprovabilityVerdict: Skipped Macroscope did not run approvability analysis for this PR. Macroscope could not determine whether this PR modifies its approvability configuration, so the PR was not approved automatically. A PR that may change the rules that govern approval is never approved automatically. |
3ebf2f2 to
8966e79
Compare
c28b52b to
eac40cf
Compare
eac40cf to
3e66480
Compare
3e66480 to
a66a1bd
Compare
d70b918 to
2185bbc
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 2185bbc. Configure here.
| }), | ||
| ); | ||
| return; | ||
| } |
There was a problem hiding this comment.
Goal commands skip session gate
Medium Severity
/goal only checks for a server thread id, unlike /feedback which requires a live session. On a Codex thread that has never started a provider session, Goal RPCs still run, then fail in ProviderService with a binding or resume-state error instead of the intended “send a message first” guidance.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 2185bbc. Configure here.


@t3dotgg After watching one of your recent YouTube videos, I wanted to make T3 Code my main interface for coding agents. But I quickly hit one frustrating gap: Goals are one of the Codex features I rely on most, and once a Goal existed, T3 did not expose the controls needed to inspect, steer, pause, resume, or reset it.
I found #2819 and the closed #2877, then implemented the narrowest integration I could: T3 acts only as a remote-capable control surface over Codex App Server's native Goal API. Codex remains the source of truth.
What this adds
Codex threads now expose the complete native Goal lifecycle through the normal conversation composer:
/goal create <objective>thread/goal/setwith the objective and active status/goal statusthread/goal/get/goal steer <objective>thread/goal/setwith the updated objective/goal pausethread/goal/setwith paused status/goal resumethread/goal/setwith active status/goal resetor/goal clearthread/goal/clear/goal <objective>remains a create shorthand. Nativethread/goal/updatedandthread/goal/clearednotifications keep connected clients synchronized while the session is running.The current objective, native status, token usage and budget, and elapsed time are shown when Codex exposes them. The command and status surfaces only appear for Codex.
Architecture
This intentionally takes a narrower approach than #2877: it does not project Goal state into T3's persistence layer. That keeps remote clients synchronized without making T3 compete with Codex as the owner of the state.
Known limitation
When Codex is actively processing a turn while a Goal is active, T3 still shows its existing red stop control. Activating it interrupts the current provider turn only; the native Goal remains active. Changing that shared composer and turn-state behavior would affect more than Goal support, so I deliberately left it unchanged to avoid scope creep.
T3 also does not open Codex's interactive Goal editor.
/goal steer <objective>updates the native objective directly. A broader Goal dashboard or control redesign is out of scope for this PR; the UI is intentionally limited to the existing composer flow and a lightweight status banner or card.UI Changes
Before
After
Verification
Closes #2819.
Related: #2877.
Implementation and verification were performed with Codex. Additional review and cleanup used Claude Code with Opus 5. Final audit and PR preparation used Codex with GPT-5.6 Sol.
Note
Medium Risk
Touches provider session routing, WebSocket RPC, and composer send paths, including optional session recovery for Goal reads/writes. Goal state stays Codex-owned, but bugs here can mis-route sessions or drop live updates.
Overview
Adds a control surface for native Codex Goals: create, status, steer, pause, resume, and clear via
/goalin the composer. Codex remains the source of truth; T3 does not persist a duplicate Goal record.Server maps App Server
thread/goal/*requests and notifications throughCodexAdapter/ProviderService, then new WS RPCs (codex.goal.get|set|clearandcodex.goal.subscribe). Subscriptions emit a snapshot then liveupdated/clearedevents, attaching the live stream before the snapshot so in-flight updates are not lost. Child-collab Goal notifications are dropped so they cannot rewrite the parent thread. Unsupported providers fail with a validation error; get can skip recovering inactive sessions.Web and mobile intercept unadorned
/goalsends (no attachments/context), call the RPCs, and show status plus usage. Codex advertises a/goalslash command. Client projection ignores a late snapshot after a live update.Reviewed by Cursor Bugbot for commit 2185bbc. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add native Codex Goal lifecycle controls and
/goalcommandsCodexGoalupdates in codexGoal.ts and rpc.tsget,set,clear) inProviderServiceandCodexAdapter, translating provider notifications intothread.goal.updatedandthread.goal.clearedruntime events in CodexAdapter.tsCodexGoalOperationErrorand stream snapshot updates followed by live events/goalcommands (status,create,steer,pause,resume,clear) in the web and mobile chat UIs, rendering a status banner and blocking concurrent sends during operations in ChatView.tsx and ThreadDetailScreen.tsxcodexGoalproperty is optional onProviderAdapterShape; calling goal operations on unsupported providers returns aProviderValidationErrorMacroscope summarized 2185bbc.