Skip to content

feat(cli): split-pane plan panel in TUI#2227

Merged
esengine merged 2 commits into
esengine:mainfrom
z1223473749:feat/cli-plan-split-pane
May 29, 2026
Merged

feat(cli): split-pane plan panel in TUI#2227
esengine merged 2 commits into
esengine:mainfrom
z1223473749:feat/cli-plan-split-pane

Conversation

@z1223473749

Copy link
Copy Markdown

What

New unified `PlanPanel` right-side component replacing the modal-overlay pattern. Covers five plan states: pending / refining / executing / checkpoint / revising.

Layout changes:

  • App.tsx: side-by-side flex layout — left conversation column at 35% width, right PlanPanel at flexGrow=1 when plan is active
  • LiveActivityArea: new `suppressPlanLiveRow` prop avoids duplicate plan card
  • Refine flow: inline plan body display + text input instead of separate modal

Why

The current modal-overlay pattern replaces the composer area with plan modals, hiding the conversation. A persistent right panel keeps the conversation visible while showing plan detail, and the inline refine flow lets users reference the plan body while typing feedback instead of switching to a blank text input.

How to verify

  1. Start plan mode, let model submit a plan — panel opens on right
  2. Click refine — plan body stays visible, input appears below
  3. Click approve — panel persists showing step progress
  4. Complete all steps — panel auto-closes
  5. Confirm conversation still scrollable, composer accessible at bottom-left

What

Why

How to verify

Checklist

  • npm run verify passes locally (lint + typecheck + tests + comment-policy gate)
  • No Co-Authored-By: Claude trailer in commits
  • Comments follow CONTRIBUTING.md (no module-essay headers, no incident history)
  • No edits to CHANGELOG.md — release notes are maintainer-written at release time

## What
New unified \`PlanPanel\` right-side component replacing the modal-overlay pattern.
Covers five plan states: pending / refining / executing / checkpoint / revising.

Layout changes:
- App.tsx: side-by-side flex layout — left conversation column at 35% width,
  right PlanPanel at flexGrow=1 when plan is active
- LiveActivityArea: new \`suppressPlanLiveRow\` prop avoids duplicate plan card
- Refine flow: inline plan body display + text input instead of separate modal

## Why
The current modal-overlay pattern replaces the composer area with plan modals,
hiding the conversation. A persistent right panel keeps the conversation visible
while showing plan detail, and the inline refine flow lets users reference the
plan body while typing feedback instead of switching to a blank text input.

## How to verify
1. Start plan mode, let model submit a plan — panel opens on right
2. Click refine — plan body stays visible, input appears below
3. Click approve — panel persists showing step progress
4. Complete all steps — panel auto-closes
5. Confirm conversation still scrollable, composer accessible at bottom-left

@esengine esengine left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Reviewed the code — well-gated, and a good split out of #2072 (this is the TUI piece, now its own declared PR). The PlanPanel is conditionally rendered: planPanelOpen = !!(pendingPlan || (planSteps.length > 0 && !planMode)), the main area is flexGrow={open ? 0 : 1} / width={open ? "35%" : undefined}, and suppressPlanLiveRow={planPanelOpen} avoids the inline/​panel duplication. So a no-plan session's layout is completely unchanged — the 65/35 split only kicks in when a plan is active. That bounds the regression risk nicely.

The one thing I can't check from here is how the split-pane actually renders. Since it's a TUI layout change (+704), could you attach a screenshot of the active-plan state — the 35% PlanPanel alongside the main area — ideally at a narrow-ish width to confirm the main content reflows cleanly and doesn't clip? Covering a couple of the five states (executing + checkpoint) would be ideal. Code's sound; once I see it render I'll merge.

@z1223473749

Copy link
Copy Markdown
Author

Reviewed the code — well-gated, and a good split out of #2072 (this is the TUI piece, now its own declared PR). The PlanPanel is conditionally rendered: planPanelOpen = !!(pendingPlan || (planSteps.length > 0 && !planMode)), the main area is flexGrow={open ? 0 : 1} / width={open ? "35%" : undefined}, and suppressPlanLiveRow={planPanelOpen} avoids the inline/​panel duplication. So a no-plan session's layout is completely unchanged — the 65/35 split only kicks in when a plan is active. That bounds the regression risk nicely.

The one thing I can't check from here is how the split-pane actually renders. Since it's a TUI layout change (+704), could you attach a screenshot of the active-plan state — the 35% PlanPanel alongside the main area — ideally at a narrow-ish width to confirm the main content reflows cleanly and doesn't clip? Covering a couple of the five states (executing + checkpoint) would be ideal. Code's sound; once I see it render I'll merge.
image46c61264-b31d-461b-9ebd-6bf09c72c7c2

Reviewed the code — well-gated, 和 a good split out of #2072 (this is the TUI piece, now its own declared PR). The PlanPanel is conditionally rendered: planPanelOpen = !!(pendingPlan || (planSteps.length > 0 && !planMode)), the main area is flexGrow={open ? 0 : 1} / width={open ? "35%" : undefined},和 suppressPlanLiveRow={planPanelOpen} avoids the inline/​panel duplication. So a no-plan session's layout is completely unchanged — the 65/35 split only kicks in when a plan is active. That bounds the regression risk nicely.

The one thing I can't check from here is how the split-pane actually renders. Since it's a TUI layout change (+704), could you attach a screenshot of the active-plan state — the 35% PlanPanel alongside the main area — ideally at a narrow-ish width to confirm the main content reflows cleanly and doesn't clip? Covering a couple of the five states (executing + checkpoint) would be ideal. Code's sound; once I see it render I'll merge.
这个是在还没计划时截图,右侧工作区 有个计划点击即可

image image image image 关键细化我大体的优化了,之前点击无反应,优化后继续调整计划,在原计划中继续完善计划, image image 当用户主动打开或者点击状态标签(展开)时 image

@esengine esengine left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for the screenshots — that's the visual confirmation I asked for, covering the active-plan split-pane across multiple states plus a narrow-width capture (the reflow case I was worried about). Combined with the gating I verified in code (planPanelOpen conditional, flexGrow/width only applied when a plan is active, suppressPlanLiveRow to avoid duplication — so no-plan sessions are untouched) and green CI, I'm satisfied the layout holds. Good split out of #2072. Merging.

@esengine

Copy link
Copy Markdown
Owner

Approving the content — screenshots + code both check out. It just needs a rebase: it now conflicts with main on App.tsx (recent merges, incl. #2182's themed-background change, touched it). git fetch origin main && git merge origin/main, resolve App.tsx, and I'll merge — no further review needed.

@z1223473749 z1223473749 force-pushed the feat/cli-plan-split-pane branch from 999be4f to 5ea9a88 Compare May 29, 2026 06:56
@esengine

Copy link
Copy Markdown
Owner

Thanks for this — the split-pane plan UX is a nice direction. Heads up though: the branch is stale and that's not just the typecheck failure.

CI fails because the telegram/weixin channels merged in #2240 added a telegramChannel prop to <App> from chat.tsx, and AppProps on this branch no longer declares it. But scanning the diff, several other recently merged features are being silently reverted:

  • telegram + weixin channel wiring (useTelegramChannel, useWeixinChannel, submit/error refs, parseSubmit chain) — feat(weixin): add trusted iLink channel #2240
  • prepareAutoGitRollbackForEditBlocks in the edit-tool gate
  • hashSystemPrompt cache-miss warning — REASONIX.md change causes cache miss on session resume #2212
  • loadMaxOutputTokens / loadMaxIterPerTurn config wiring
  • shouldEnterPlanModeForExplicitIntent / shouldSuggestPlanForEngineeringIntent lifecycle hooks
  • buildEditToolBlocksForReview (async, with readTracker) reverted to the older sync buildEditToolBlocks
  • resolveContextTokens(model) helper inlined back to a raw map lookup

Could you rebase onto current main and keep all of the above? Happy to re-review once CI is green.

@esengine esengine merged commit e57ca88 into esengine:main May 29, 2026
4 checks passed
nianyi778 pushed a commit to nianyi778/DeepSeek-Reasonix that referenced this pull request May 29, 2026
## What
New unified \`PlanPanel\` right-side component replacing the modal-overlay pattern.
Covers five plan states: pending / refining / executing / checkpoint / revising.

Layout changes:
- App.tsx: side-by-side flex layout — left conversation column at 35% width,
  right PlanPanel at flexGrow=1 when plan is active
- LiveActivityArea: new \`suppressPlanLiveRow\` prop avoids duplicate plan card
- Refine flow: inline plan body display + text input instead of separate modal

## Why
The current modal-overlay pattern replaces the composer area with plan modals,
hiding the conversation. A persistent right panel keeps the conversation visible
while showing plan detail, and the inline refine flow lets users reference the
plan body while typing feedback instead of switching to a blank text input.

## How to verify
1. Start plan mode, let model submit a plan — panel opens on right
2. Click refine — plan body stays visible, input appears below
3. Click approve — panel persists showing step progress
4. Complete all steps — panel auto-closes
5. Confirm conversation still scrollable, composer accessible at bottom-left
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants