Skip to content

feat(codex): add native Goal lifecycle controls - #7935

Open
stekman08 wants to merge 2 commits into
pingdotgg:mainfrom
stekman08:feat/codex-goal-control
Open

feat(codex): add native Goal lifecycle controls#7935
stekman08 wants to merge 2 commits into
pingdotgg:mainfrom
stekman08:feat/codex-goal-control

Conversation

@stekman08

@stekman08 stekman08 commented Aug 22, 2026

Copy link
Copy Markdown

@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:

T3 command Native Codex operation
/goal create <objective> thread/goal/set with the objective and active status
/goal status thread/goal/get
/goal steer <objective> thread/goal/set with the updated objective
/goal pause thread/goal/set with paused status
/goal resume thread/goal/set with active status
/goal reset or /goal clear thread/goal/clear

/goal <objective> remains a create shorthand. Native thread/goal/updated and thread/goal/cleared notifications 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

  • Codex App Server remains authoritative for all Goal state and lifecycle semantics.
  • Goal requests use the existing Codex session runtime, provider adapter, provider service, and WebSocket RPC path.
  • Native Goal notifications are translated into provider runtime events and streamed to subscribed clients.
  • Operations and subscriptions are scoped to the active environment and thread. There is no global Goal singleton.
  • T3 does not persist a duplicate Goal record, add a database migration, or introduce a second Goal state machine. Client state is only an ephemeral projection of the native snapshot and notifications.
  • Unsupported providers do not expose Goal capability or commands.

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

image

After

image

Verification

  • Focused contract, adapter, provider service, WebSocket, client projection, command parsing, notification ordering, error handling, provider gating, and thread-scoping tests pass.
  • Typecheck passes for contracts, client-runtime, server, web, and mobile.
  • Lint and formatting pass for all changed TypeScript files.
  • The web production build passes.
  • Native Goal creation, status display, asynchronous banner updates, and continued instructions while a Goal remains active were manually exercised through T3.

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 /goal in 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 through CodexAdapter / ProviderService, then new WS RPCs (codex.goal.get|set|clear and codex.goal.subscribe). Subscriptions emit a snapshot then live updated/cleared events, 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 /goal sends (no attachments/context), call the RPCs, and show status plus usage. Codex advertises a /goal slash 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 /goal commands

  • Adds contract schemas and WS RPC methods for getting, setting, clearing, and subscribing to CodexGoal updates in codexGoal.ts and rpc.ts
  • Implements goal lifecycle methods (get, set, clear) in ProviderService and CodexAdapter, translating provider notifications into thread.goal.updated and thread.goal.cleared runtime events in CodexAdapter.ts
  • Adds WebSocket RPC handlers in ws.ts that wrap errors in CodexGoalOperationError and stream snapshot updates followed by live events
  • Surfaces /goal commands (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.tsx
  • Risk: The codexGoal property is optional on ProviderAdapterShape; calling goal operations on unsupported providers returns a ProviderValidationError

Macroscope summarized 2185bbc.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 187c3c84-8ef0-482f-aa5d-598dcae28a43

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XL 500-999 changed lines (additions + deletions). labels Aug 22, 2026

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread packages/contracts/src/codexGoal.ts Outdated
Comment thread apps/server/src/ws.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread apps/web/src/components/ChatView.tsx Outdated
Comment thread apps/web/src/components/ChatView.tsx Outdated
Comment thread apps/mobile/src/features/threads/ThreadDetailScreen.tsx
Comment thread apps/server/src/ws.ts Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread packages/contracts/src/codexGoal.ts Outdated
Comment thread apps/server/src/ws.ts Outdated
Comment thread apps/web/src/components/ChatView.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread apps/web/src/components/ChatView.tsx Outdated
Comment thread apps/mobile/src/features/threads/ThreadDetailScreen.tsx Outdated
Comment thread apps/mobile/src/features/threads/ThreadDetailScreen.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread apps/web/src/components/ChatView.tsx Outdated
Comment thread apps/web/src/components/ChatView.tsx Outdated

@macroscopeapp macroscopeapp Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread apps/web/src/components/ChatView.tsx Outdated
@stekman08
stekman08 force-pushed the feat/codex-goal-control branch from 8b9f2e1 to 3ebf2f2 Compare August 22, 2026 23:29
Comment thread packages/client-runtime/src/state/threadCommands.ts Outdated
@stekman08
stekman08 marked this pull request as ready for review August 22, 2026 23:35
Comment thread apps/web/src/components/ChatView.tsx
@macroscopeapp

macroscopeapp Bot commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: 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.

@stekman08
stekman08 force-pushed the feat/codex-goal-control branch from 3ebf2f2 to 8966e79 Compare August 22, 2026 23:45
Comment thread apps/server/src/provider/Layers/ProviderService.ts
@stekman08
stekman08 force-pushed the feat/codex-goal-control branch 2 times, most recently from c28b52b to eac40cf Compare August 23, 2026 00:07
Comment thread apps/server/src/ws.ts
Comment thread apps/web/src/components/ChatView.tsx Outdated
@stekman08
stekman08 force-pushed the feat/codex-goal-control branch from eac40cf to 3e66480 Compare August 23, 2026 06:39
Comment thread apps/server/src/provider/Layers/CodexSessionRuntime.ts
Comment thread packages/client-runtime/src/state/threadCommands.ts Outdated
Comment thread apps/web/src/components/ChatView.tsx Outdated
@stekman08
stekman08 force-pushed the feat/codex-goal-control branch from 3e66480 to a66a1bd Compare August 23, 2026 07:27
Comment thread apps/server/src/provider/Layers/ProviderService.ts Outdated
@github-actions github-actions Bot removed the size:XL 500-999 changed lines (additions + deletions). label Aug 23, 2026
@github-actions github-actions Bot added the size:XXL 1,000+ changed lines (additions + deletions). label Aug 23, 2026
@stekman08
stekman08 force-pushed the feat/codex-goal-control branch from d70b918 to 2185bbc Compare August 23, 2026 14:10

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ 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;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2185bbc. Configure here.

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

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Support /goal in codex provider

1 participant