fix(plan-mode): render plan_ready output as Markdown - #293
Open
Matt-qwq wants to merge 2 commits into
Open
Conversation
plan_ready registered no renderResult, so the TUI fell back to its plain-text renderer and the recorded plan appeared as raw Markdown source. Render it with the Markdown component, the same treatment subagent results already get. Validated with bun run check (format, lint, tsc) and bun run test (959 node:test cases and 30 vitest cases pass) on Linux.
Nine cases pin that the renderer is registered and that a realistic plan survives it: headings, ordered and nested lists, block quotes, tables, inline code and bold, links, three fenced code shapes, a thematic break, a 40K plan, and unicode. Assertions strip ANSI first, because the Markdown component colors itself from the global theme rather than the theme passed to renderResult. Verified red against the pre-fix code (all nine fail with "plan_ready must supply renderResult"), so these catch the regression rather than just documenting it.
tt-a1i
requested changes
Aug 30, 2026
tt-a1i
left a comment
Collaborator
There was a problem hiding this comment.
P1 Must-Fix:extensions/plan-mode/index.ts:455-462 的自定义 renderResult 忽略了 options.expanded,折叠态和展开态都会返回完整 Markdown。Pi 会把 expanded 状态传给自定义 renderer,但不会替它截断 renderer 返回的行;因此接近现有 48 KiB 上限的计划会在默认折叠态整段铺进 transcript,Ctrl+O 也不会产生任何折叠效果。新增测试 tests/extensions/plan-mode/result-rendering.test.ts:242-252 还把 collapsed/expanded 完全相同固定成了预期,这与 PR 中“Pi 已提供 expand/collapse,所以不需要第二层截断”的理由相矛盾。请在 expanded === false 时提供有界摘要/预览,在展开态再渲染完整 Markdown,并补一条长计划测试,证明默认输出行数有界且展开能恢复完整内容。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
plan_readyrenders the finalized plan as raw Markdown source in the TUI.extensions/plan-mode/index.tsregistersplan_readywith only anexecutehandler and norenderResult, so the TUI falls back to its default plain-text renderer: headings, lists, and code fences appear as literal#,-, and```characters instead of rendered text.
Affects every Plan Mode user — the plan is the one artifact Plan Mode exists to produce, and it is meant to be read, not inspected as source.
No existing issue tracks this. I searched
plan_ready,renderResult, and Markdown-rendering across open and closed issues inopenpi-dev/openpi; the closest hits (#28, #27, #18, #105, #101, #96, #93, #67, #40) are all about othersubsystems.
Value
Every other extension tool that returns human-readable prose already supplies a renderer — there are 19
renderResultimplementations acrossgoal,tasks,git-read,file-search,workflows,subagents,ask-user,background-terminals, andfile-mutation-display.plan_readyis the outlier. Rendering it makes Plan Mode's output consistent with the rest of OpenPI and lets the user read the plan without decoding Markdown syntax.Approach
Add
renderResultto theplan_readyregistration, renderingresult.details.planwith theMarkdowncomponent from@earendil-works/pi-tuiusinggetMarkdownTheme()— the same treatmentrenderWaitResult()gives subagent results(
extensions/subagents/src/ui/wait-result.ts:59).Two deliberate choices:
MAX_READY_PLAN_UTF8_BYTES(48 KB).executealready storessanitizeTerminalText(params.plan), sodetails.planis clean on the way in.Validation
Ran on WSL2 (Fedora 44), Node v22.23.1, bun 1.3.14:
bun run testgrows from 959 to 968 cases — the 9 intests/extensions/plan-mode/result-rendering.test.ts. Those were verified red against the pre-fix code: withrenderResultremoved, all nine fail withplan_ready must supply renderResult, so they catch the regression rather than document it.Manual TUI check. Loaded the checkout with
pi install, ran/plan, and calledplan_readywith a plan exercising headings, ordered and nested lists, a block quote, a table, inline code, bold, italics, links, three fenced code shapes,and a thematic break. In the TUI: heading markers are consumed, the table renders with box-drawing characters, the quote gets a
│gutter, links render aslabel (URL), the thematic break becomes a─rule, and fenced code bodies areindented two spaces.
Two behaviors are pi-tui's design, not regressions:
```characters —Markdownrenders them viatheme.codeBlockBorder()(pi-tui/dist/components/markdown.js:384) and colors them rather than drawing a background block.###prefix; only levels 1–2 hide it (markdown.js:350). Level 3+ still receives heading color and bold.Impact
plan_readyoutput now goes through the TUI Markdown renderer instead of the plain-text fallback. Heading markers are consumed, list bullets and code fences are colored, inline code / bold / italic / linkmarkers are consumed, tables are drawn with box characters, and fenced code bodies are indented. Nothing else changes.
promptSnippet,promptGuidelines, parameters, or the text returned incontent— only how the result is drawn.renderResultis pure presentation;terminate: truesemantics and the plan-state commit are untouched.plan_readyremains parent-only (already inCHILD_EXCLUDED_TOOL_NAMES,extensions/shared/child-session.ts:452), so the child-session drift guard is unaffected — its test passes.