Skip to content

[codex] Add desktop plan and goal mode UI - #55651

Closed
wjj1872744570-source wants to merge 3 commits into
NousResearch:mainfrom
wjj1872744570-source:codex/plan-goal-desktop-ui
Closed

[codex] Add desktop plan and goal mode UI#55651
wjj1872744570-source wants to merge 3 commits into
NousResearch:mainfrom
wjj1872744570-source:codex/plan-goal-desktop-ui

Conversation

@wjj1872744570-source

Copy link
Copy Markdown
Contributor

Summary

  • Add desktop Plan mode that first asks the model to draft todos, then waits for explicit user approval before execution.
  • Add desktop Goal mode controls backed by the existing /goal gateway command.
  • Surface status.update events with kind: "goal" in the composer status stack.

Details

This reuses the existing todo/status stack infrastructure and gateway slash command path instead of introducing a new backend API. Plan mode stores a pending plan locally, shows the todo plan in the existing composer status stack, and sends a follow-up implementation prompt only when the user confirms. Goal mode parses slash command output and goal status events into a session-scoped status row with pause/resume/clear actions.

Validation

  • npm run typecheck
  • npm run test:ui -- src/store/goals.test.ts src/store/plans.test.ts
  • npx eslint src/app/chat/composer/controls.tsx src/app/chat/composer/hooks/use-composer-submit.ts src/app/chat/composer/index.tsx src/app/chat/composer/status-stack/index.tsx src/app/chat/composer/status-stack/status-row.tsx src/app/chat/composer/types.ts src/app/session/hooks/use-message-stream/gateway-event.ts src/app/session/hooks/use-prompt-actions/slash.ts src/app/session/hooks/use-prompt-actions/submit.ts src/app/session/hooks/use-prompt-actions/utils.ts src/i18n/en.ts src/i18n/types.ts src/i18n/zh.ts src/store/composer-status.ts src/store/goals.ts src/store/goals.test.ts src/store/plans.ts src/store/plans.test.ts

@wjj1872744570-source
wjj1872744570-source marked this pull request as ready for review June 30, 2026 12:41
@alt-glitch alt-glitch added type/feature New feature or request comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have labels Jun 30, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary - COMMENT - High Surface Area. 18 files changed with 907 additions. This PR adds desktop plan and goal mode UI for Codex. High file count (18 files) exceeds the 15-file surface-area threshold. This is a significant UI feature addition. Would benefit from a focused review of the UI components and state management. Consider splitting into smaller PRs if possible, or noting the specific files that are critical vs. mechanical. Reviewed by Hermes Agent

@wjj1872744570-source

Copy link
Copy Markdown
Contributor Author

Thank you for your careful review.
I notice this PR exceeds the 15-file threshold. Since Plan mode and Goal mode are strongly associated in logic, all 18 files work together to finish this whole feature.

If you still think splitting is better for review, I am willing to reorganize the code and submit smaller incremental PRs step by step later.

@wjj1872744570-source

Copy link
Copy Markdown
Contributor Author

Gentle reminder, could you approve the waiting workflow to trigger the required checks? Thank you.

@wjj1872744570-source

Copy link
Copy Markdown
Contributor Author

Thanks for the review note.

To make the surface area easier to inspect, here is the structure of this PR:

  • Core Goal state/status work: goal store, status.update kind="goal" handling, and status-stack rendering.
  • Core Plan mode work: pending-plan store, plan-first submit flow, and approve/cancel execution controls.
  • Mechanical support: i18n keys, type extensions, and focused store tests.

The 18 touched files are connected because the desktop composer controls, session status stack, and existing todo/goal gateway paths need to work together for the feature to be usable end-to-end.

If maintainers prefer, I can split this into smaller incremental PRs:

  1. Goal status plumbing and status-stack display
  2. Goal composer controls
  3. Plan mode pending-plan flow and confirmation UI

Could you please approve the waiting workflow so the required checks can run first?

@wjj1872744570-source
wjj1872744570-source force-pushed the codex/plan-goal-desktop-ui branch from 19df415 to f8e757a Compare June 30, 2026 21:25
@wjj1872744570-source

Copy link
Copy Markdown
Contributor Author

Resolved the latest merge conflict in apps/desktop/src/app/chat/composer/index.tsx.

The conflict was only around the React import line after main changed the composer imports. I removed the unnecessary useCallback wrappers from the Plan/Goal composer handlers so the import now matches main while keeping the same submit/cancel/goal behavior.

Validation run locally:

  • npm run typecheck
  • npm run test:ui -- src/store/goals.test.ts src/store/plans.test.ts
  • targeted npx eslint over the changed desktop Plan/Goal files

GitHub now reports the PR as mergeable; it appears to be waiting for the required workflow/check approval to proceed.

@wjj1872744570-source

Copy link
Copy Markdown
Contributor Author

Since this PR has stayed blocked on workflow approval for a while, I started splitting it into smaller, independently reviewable PRs.

First split PR: #63527 — desktop Goal status plumbing/display only.

That PR reduces the surface area to 9 files and intentionally excludes the composer Goal button and Plan mode flow. It is locally validated with typecheck, the focused goal store test, and targeted ESLint.

I am keeping this larger PR open for context while maintainers decide which route is easier to review.

@teknium1 teknium1 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.

Thanks for splitting the Desktop goal/plan work around the existing gateway and status-stack seams.

Problems

  • apps/desktop/src/app/chat/composer/index.tsx:750 calls clearSessionTodos(statusSessionId) on plan cancellation. apps/desktop/src/store/todos.ts:64-74 removes the entire todo entry for that session, so cancelling a plan also erases unrelated todo state.
  • The new copy changes only apps/desktop/src/i18n/en.ts and apps/desktop/src/i18n/zh.ts; Desktop also ships ja and zh-hant through apps/desktop/src/i18n/catalog.ts:1-11.
  • The added tests are store-only (apps/desktop/src/store/goals.test.ts, apps/desktop/src/store/plans.test.ts), leaving the new composer submit/approve/cancel path untested.

Suggested changes

  • Make cancellation remove only plan-owned state; it must not clear the session's ordinary todos.
  • Add Japanese and Traditional Chinese copy.
  • Add composer-level coverage for plan submission, approval, rejection recovery, and cancellation preserving existing todos.

Automated hermes-sweeper review.

clearPendingPlan(planSessionKey)

if (statusSessionId) {
clearSessionTodos(statusSessionId)

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.

clearSessionTodos() deletes the entire runtime-session todo list (src/store/todos.ts:64-74), including work unrelated to this pending plan. Please remove only plan-owned state here, or preserve and restore existing todos.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 15, 2026
teknium1 added a commit that referenced this pull request Jul 26, 2026
…locale copy

Follow-ups on the salvaged goal-status display (#63527):

- Seed the goal store from the /goal dispatch notice ("⊙ Goal set …") and
  from /goal status|pause|resume|clear exec output in slash.ts. The backend
  only emits status.update kind:"goal" after the first turn's post-turn
  judge, so without this the indicator stayed empty while the kickoff turn
  ran (sweeper review finding on #63527).
- Add the missing ja / zh-hant statusStack goal copy — desktop ships four
  locales, not two (sweeper review finding on #55651).
- Add a component-level vitest for the composer goal indicator rendering
  from store states: none / active / paused / detail line / other-session.

Co-authored-by: HaisamAbbas <95044189+HaisamAbbas@users.noreply.github.com>

Assisted-by: Claude Fable 5 via Hermes Agent
teknium1 added a commit that referenced this pull request Jul 27, 2026
…locale copy

Follow-ups on the salvaged goal-status display (#63527):

- Seed the goal store from the /goal dispatch notice ("⊙ Goal set …") and
  from /goal status|pause|resume|clear exec output in slash.ts. The backend
  only emits status.update kind:"goal" after the first turn's post-turn
  judge, so without this the indicator stayed empty while the kickoff turn
  ran (sweeper review finding on #63527).
- Add the missing ja / zh-hant statusStack goal copy — desktop ships four
  locales, not two (sweeper review finding on #55651).
- Add a component-level vitest for the composer goal indicator rendering
  from store states: none / active / paused / detail line / other-session.

Co-authored-by: HaisamAbbas <95044189+HaisamAbbas@users.noreply.github.com>

Assisted-by: Claude Fable 5 via Hermes Agent
@teknium1

Copy link
Copy Markdown
Contributor

The goal/plan-mode desktop UI work was unified into #72244 (now merged) with credit — #63527 served as the cherry-picked base since it was the minimal display implementation. Thanks for pushing this area forward!

@teknium1 teknium1 closed this Jul 27, 2026
randlee pushed a commit to randlee/hermes-agent that referenced this pull request Aug 11, 2026
…locale copy

Follow-ups on the salvaged goal-status display (NousResearch#63527):

- Seed the goal store from the /goal dispatch notice ("⊙ Goal set …") and
  from /goal status|pause|resume|clear exec output in slash.ts. The backend
  only emits status.update kind:"goal" after the first turn's post-turn
  judge, so without this the indicator stayed empty while the kickoff turn
  ran (sweeper review finding on NousResearch#63527).
- Add the missing ja / zh-hant statusStack goal copy — desktop ships four
  locales, not two (sweeper review finding on NousResearch#55651).
- Add a component-level vitest for the composer goal indicator rendering
  from store states: none / active / paused / detail line / other-session.

Co-authored-by: HaisamAbbas <95044189+HaisamAbbas@users.noreply.github.com>

Assisted-by: Claude Fable 5 via Hermes Agent
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/desktop Electron desktop app (apps/desktop/*) P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants