Skip to content

Transcript: a sent prompt of megabytes never freezes the chat (literal, collapsed to its head) - #29840

Merged
teamleaderleo merged 7 commits into
feat-cmux-nextfrom
lane/huge-prompt-render
Nov 1, 2026
Merged

teamleaderleo merged 7 commits into
feat-cmux-nextfrom
lane/huge-prompt-render

Conversation

@teamleaderleo

Copy link
Copy Markdown
Collaborator

Leo, 2026-10-31: "surface_id=tab_c487e18b4f0083b34190540cd40eaa7a this is completely hardlocked bc of message size"

The transport side of this ask has already landed: #29670 (acpmux message limit 15 MiB → 31 MiB), #28754 (a chat whose records add up past one message still opens), #28778 (an oversized prompt or chat is never retried unchanged), #29500 (a prompt's attachments never add up past one message). This PR covers the render side: a chat that holds a prompt of megabytes no longer freezes the pane once it opens.

Before

A sent prompt draws through PromptText. A long prompt is collapsed with CSS only, so the whole text is still rendered: it goes through Markdown when it looks like Markdown, gets a URL scan, and softBreaks adds a <wbr> after every / - _ . : = & ? # @ , in each long token. For a multi-MB paste or a base64 blob that means hundreds of thousands of DOM nodes, laid out on the main thread for text the clamp hides. The row estimate (model.ts) also lexed or prepared the whole text.

After

  • A prompt longer than HUGE_PROMPT_CHARS (200k characters) draws as one literal text node: no Markdown, no link scan, no break points.
  • While collapsed, it renders only its first HUGE_PROMPT_HEAD_CHARS (4,000 characters, which is well over ten lines at any width). Show more renders the whole text, still as one text node. Copy, Edit, Retry and Find still use the whole prompt (Find opens it on a match, as before).
  • The row estimate for a huge prompt is its collapsed height (ten lines plus Show more), the same height any long prompt gets, without lexing or measuring the text.
  • Prompts under 200k characters are unchanged.

Tests

conversation/hugePrompt.test.tsx: checks that a huge Markdown-shaped part renders literally with no <wbr>, a 5 MiB blob renders only its head while collapsed, the head never splits a surrogate pair, and a 20 MiB prompt's row estimate matches a long prompt's collapsed height in under 500 ms.

Risk

Low. The change is limited to the sent-prompt bubble and its row estimate, and it only applies to prompts over 200k characters. A huge prompt that is Markdown now shows as plain text, which is intended.

Agent session: agent session

🤖 Generated with Claude Code

…to its head, never freezing the chat

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-df4c966270872064ca90
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 415434f: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr29840 -f ref=lane/huge-prompt-render -f platform=macos -f backend_mode=local

Stale: these images are of 415434f; the head is now 5b14814 and a new capture is running.

Gallery before/after for 415434f: 16 states rendered, 6 images differ, 2710 more touched states not rendered. Images are in the run's artifact, not on this public PR; the independent review of this head reads them on its own, so the PR needs no hand-made screenshots of these states.

gh run download 41266613161 -R manaflow-ai/cmux -n gallery-advisory-29840-415434f838ae0e7ce2e72c07e8ae3ef8582f5b99 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.prompt-markdown/plain Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.prompt-markdown/plain Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.prompt-markdown/markdown Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.prompt-markdown/markdown Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.user-bubble/claude Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.user-bubble/claude Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.user-bubble/prompt-hover Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.user-bubble/prompt-hover Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.user-bubble/running-edit-branches Apple System Colors Light changed 0.0062% own PromptText.tsx
agent-pane.user-bubble/running-edit-branches Apple System Colors changed 0.0058% own PromptText.tsx
agent-pane.user-bubble/finished-original-branch Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.user-bubble/finished-original-branch Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.user-bubble/answer-hover Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.user-bubble/answer-hover Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.user-bubble/prompt-time-tooltip Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.user-bubble/prompt-time-tooltip Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.user-bubble/answer-time-tooltip Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.user-bubble/answer-time-tooltip Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.user-bubble/other Apple System Colors Light unchanged 0% own PromptText.tsx
agent-pane.user-bubble/other Apple System Colors unchanged 0% own PromptText.tsx
agent-pane.access-offer/turn-no-credits Apple System Colors Light unchanged 0% imports model.ts (1 hops)
agent-pane.access-offer/turn-no-credits Apple System Colors unchanged 0% imports model.ts (1 hops)
agent-pane.access-offer/turn-low-credits Apple System Colors Light unchanged 0% imports model.ts (1 hops)
agent-pane.access-offer/turn-low-credits Apple System Colors unchanged 0% imports model.ts (1 hops)
agent-pane.access-offer/turn-no-offer Apple System Colors Light unchanged 0% imports model.ts (1 hops)
agent-pane.access-offer/turn-no-offer Apple System Colors unchanged 0% imports model.ts (1 hops)
agent-pane.acpmux-batch-send/batches Apple System Colors Light changed 0.0007% imports model.ts (1 hops)
agent-pane.acpmux-batch-send/batches Apple System Colors changed 0% imports model.ts (1 hops)
agent-pane.acpmux-batch-send/batch-raw Apple System Colors Light changed 0.0007% imports model.ts (1 hops)
agent-pane.acpmux-batch-send/batch-raw Apple System Colors changed 0% imports model.ts (1 hops)
agent-pane.acpmux-batch-send/batch-sending Apple System Colors Light unchanged 0% imports model.ts (1 hops)
agent-pane.acpmux-batch-send/batch-sending Apple System Colors unchanged 0% imports model.ts (1 hops)

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

red: cmux-next checks (god files, concurrency, crash safety, l10n); base red: the same failure on the base 5bdd4c9; does not block

Shipped in:

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
teamleaderleo and others added 2 commits November 1, 2026 00:36
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-df4c966270872064ca90
…part beside a big paste keeps its Markdown; the pasted estimate measures a huge part's head

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-df4c966270872064ca90
…nt placement; looser timing bound

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-df4c966270872064ca90
@blacksmith-sh

blacksmith-sh Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Found 2 test failures on Blacksmith runners:

Failures

Test View Logs
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)/
test_every_listed_hook_is_one_glaeda_released_with_the_check (main.SigningHooksInSt
epWithGlaedaTests.test_every_listed_hook_is_one_glaeda_released_with_the_check)
View Logs
test_no_runner_picker_returns_a_hosted_mac (main.NoHostedMacInNightlies.test_no_run
ner_picker_returns_a_hosted_mac)/
test_no_runner_picker_returns_a_hosted_mac (main.NoHostedMacInNightlies.test_no_run
ner_picker_returns_a_hosted_mac)
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent Codex gpt-6.1-sol, high, via the review router; full diff from merge base 07efced to this head): BLOCK at 46b8c1b.

[P2] [blocking] webviews/src/agent-session/acpmux/conversation/PromptText.tsx:90 - Truncation creates an infinite layout-effect update loop when the displayed head fits within ten lines but the full prompt does not. For example, "data:text/plain;base64," + "A".repeat(210000) + "\nline".repeat(20) has a head that show() reduces to one image label. Measurement sets long=false, restoring the full text; measurement then sets long=true, truncating it again. This repeats until React throws “Maximum update depth exceeded,” breaking a previously renderable chat. Fix by preventing measurements of truncated content from clearing long, and add a DOM regression test.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (subagent claude-opus-5-5 medium): SHIP at 353db48

Two rounds before this one; follow-ups found there are fixed at this head (inline-placed attachments draw their head; plain per part; pasted estimate measures the head; a huge typed part beside pastes starts collapsed). bun test over conversation/ 636 pass, 0 fail; tsc only error is the pre-existing test/latency/probe.ts one.

Follow-ups:

  • Find auto-opens a huge prompt (renders its whole text) and lower-cases the whole text each render while Find targets the row.
  • The 4,000-char head may cut a data: URI so some raw base64 shows.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent Codex gpt-6.1-sol, high, via the review router; full diff from merge base 07efced to this head): BLOCK at 46b8c1b.

[P1] [blocking] webviews/src/agent-session/acpmux/conversation/PromptText.tsx:90 - Truncation can trigger an infinite layout-effect update loop. For example, a huge prompt beginning with a 5,000-character base64 data URI followed by 40,000 text lines renders its preview as just [Image] through show(). Measurement sets long=false, rendering the full message; measurement then sets long=true, restoring the short preview. This repeats until React throws “Maximum update depth exceeded,” breaking the chat. Keep truncated huge prompts classified as long rather than measuring their preview to decide whether to truncate.

…mps it (review of #29840)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-df4c966270872064ca90

@cubic-dev-ai cubic-dev-ai Bot 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.

6 issues found across 5 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="webviews/src/agent-session/acpmux/conversation/hugePrompt.test.tsx">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/hugePrompt.test.tsx:31">
P3: The test title says 'one literal text node', but the assertions only check for absent tags and the outer span. Either assert a single text node or rename the test to match what it checks.</violation>

<violation number="2" location="webviews/src/agent-session/acpmux/conversation/hugePrompt.test.tsx:67">
P3: The wall-clock `elapsed < 2_000` assertion can flake on a loaded CI runner, and it includes building the 20 MiB fixture. Assert on the equality of heights, which already proves the path, and drop or start the timer after the fixture is built.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/conversation/PromptText.tsx">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/PromptText.tsx:236">
P2: `PromptTyped` selects literal mode using only this part’s length. A prompt with more than 200,000 typed characters split across smaller parts still parses each part as Markdown or scans it for links and break points when expanded; compute the threshold from aggregate typed text and pass the result to each part.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/model.ts">

<violation number="1" location="webviews/src/agent-session/acpmux/model.ts:1610">
P2: A huge prompt made of one pasted block bypasses this fast path and is estimated as only the 40px paste chip, but `PromptText` still renders its 24px Show more row. Include that forced button in the estimate for huge pasted prompts to avoid underestimating their height.</violation>

<violation number="2" location="webviews/src/agent-session/acpmux/model.ts:1656">
P2: For pasted prompts, this checks each typed part against 200,000 characters instead of the prompt-wide 4,000-character head budget. A 190,000-character part beside a large paste is fully measured even though only its first 4,000 characters render; measure using the remaining head budget.</violation>
</file>

<file name="webviews/src/agent-session/acpmux/conversation/promptCollapse.ts">

<violation number="1" location="webviews/src/agent-session/acpmux/conversation/promptCollapse.ts:50">
P1: `headParts` retains paste parts regardless of size, so a collapsed huge paste still reaches `PasteChip`, which splits the full text to derive its name and line count. Bound those calculations for huge paste chips so collapsing the prompt does not allocate arrays proportional to the paste’s line count.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

if (left <= 0) break;
const text = typed(part);
if (text === undefined) {
out.push(part);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: headParts retains paste parts regardless of size, so a collapsed huge paste still reaches PasteChip, which splits the full text to derive its name and line count. Bound those calculations for huge paste chips so collapsing the prompt does not allocate arrays proportional to the paste’s line count.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/promptCollapse.ts, line 50:

<comment>`headParts` retains paste parts regardless of size, so a collapsed huge paste still reaches `PasteChip`, which splits the full text to derive its name and line count. Bound those calculations for huge paste chips so collapsing the prompt does not allocate arrays proportional to the paste’s line count.</comment>

<file context>
@@ -21,6 +21,49 @@ export function collapsedPromptHeight(height: number, lineHeight: number): numbe
+    if (left <= 0) break;
+    const text = typed(part);
+    if (text === undefined) {
+      out.push(part);
+      continue;
+    }
</file context>

plain?: boolean;
}) {
const shown = show(text);
if (plain || isHugePrompt(text)) return <span className="cv-user__typed">{shown}</span>;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: PromptTyped selects literal mode using only this part’s length. A prompt with more than 200,000 typed characters split across smaller parts still parses each part as Markdown or scans it for links and break points when expanded; compute the threshold from aggregate typed text and pass the result to each part.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/PromptText.tsx, line 236:

<comment>`PromptTyped` selects literal mode using only this part’s length. A prompt with more than 200,000 typed characters split across smaller parts still parses each part as Markdown or scans it for links and break points when expanded; compute the threshold from aggregate typed text and pass the result to each part.</comment>

<file context>
@@ -201,8 +222,18 @@ export function PromptText({
+  plain?: boolean;
+}) {
   const shown = show(text);
+  if (plain || isHugePrompt(text)) return <span className="cv-user__typed">{shown}</span>;
   return isPromptMarkdown(text) ? (
     <Markdown className="cv-user__markdown" thumbnails={false}>
</file context>

const pasted = row.kind === "user" && Boolean(row.pasted?.length);
// A huge prompt opens collapsed to its first lines whatever it holds (conversation/PromptText.tsx):
// its height is those lines and Show more, never a lex or measure of megabytes of text.
if (row.kind === "user" && !pasted && row.from !== "chief" && isHugePrompt(row.text) && !chiefEnvelope(row.text)) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: A huge prompt made of one pasted block bypasses this fast path and is estimated as only the 40px paste chip, but PromptText still renders its 24px Show more row. Include that forced button in the estimate for huge pasted prompts to avoid underestimating their height.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/model.ts, line 1610:

<comment>A huge prompt made of one pasted block bypasses this fast path and is estimated as only the 40px paste chip, but `PromptText` still renders its 24px Show more row. Include that forced button in the estimate for huge pasted prompts to avoid underestimating their height.</comment>

<file context>
@@ -1597,6 +1605,15 @@ function measuredRowHeight(
   const pasted = row.kind === "user" && Boolean(row.pasted?.length);
+  // A huge prompt opens collapsed to its first lines whatever it holds (conversation/PromptText.tsx):
+  // its height is those lines and Show more, never a lex or measure of megabytes of text.
+  if (row.kind === "user" && !pasted && row.from !== "chief" && isHugePrompt(row.text) && !chiefEnvelope(row.text)) {
+    const height =
+      messageBelow(beforeFooter) +
</file context>

// A huge typed part draws collapsed to its head (conversation/PromptText.tsx), so its
// head is all there is to measure.
textHeight(
isHugePrompt(part.text) ? promptHead(part.text, HUGE_PROMPT_HEAD_CHARS) : part.text,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: For pasted prompts, this checks each typed part against 200,000 characters instead of the prompt-wide 4,000-character head budget. A 190,000-character part beside a large paste is fully measured even though only its first 4,000 characters render; measure using the remaining head budget.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/model.ts, line 1656:

<comment>For pasted prompts, this checks each typed part against 200,000 characters instead of the prompt-wide 4,000-character head budget. A 190,000-character part beside a large paste is fully measured even though only its first 4,000 characters render; measure using the remaining head budget.</comment>

<file context>
@@ -1631,7 +1648,17 @@ function measuredRowHeight(
+                // A huge typed part draws collapsed to its head (conversation/PromptText.tsx), so its
+                // head is all there is to measure.
+                textHeight(
+                  isHugePrompt(part.text) ? promptHead(part.text, HUGE_PROMPT_HEAD_CHARS) : part.text,
+                  contentWidth,
+                  entry.prepared,
</file context>

// Markdown-shaped, so a small one would go through the Markdown renderer.
const markdown = (chars: number) => `# Log\n- item **bold** \`code\`\n${"x".repeat(chars)}`;

test("a huge typed part draws as one literal text node, with no break points or Markdown", () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The test title says 'one literal text node', but the assertions only check for absent tags and the outer span. Either assert a single text node or rename the test to match what it checks.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/hugePrompt.test.tsx, line 31:

<comment>The test title says 'one literal text node', but the assertions only check for absent tags and the outer span. Either assert a single text node or rename the test to match what it checks.</comment>

<file context>
@@ -0,0 +1,162 @@
+// Markdown-shaped, so a small one would go through the Markdown renderer.
+const markdown = (chars: number) => `# Log\n- item **bold** \`code\`\n${"x".repeat(chars)}`;
+
+test("a huge typed part draws as one literal text node, with no break points or Markdown", () => {
+  const text = markdown(HUGE_PROMPT_CHARS);
+  const html = renderToStaticMarkup(<PromptTyped text={text} show={same} />);
</file context>

test("a huge prompt's row is estimated as its collapsed lines, quickly", () => {
const { lineHeight } = currentChatMetrics();
const row = (id: string, text: string) => ({ id, version: 1, at: 0, kind: "user", text });
const started = performance.now();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The wall-clock elapsed < 2_000 assertion can flake on a loaded CI runner, and it includes building the 20 MiB fixture. Assert on the equality of heights, which already proves the path, and drop or start the timer after the fixture is built.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/conversation/hugePrompt.test.tsx, line 67:

<comment>The wall-clock `elapsed < 2_000` assertion can flake on a loaded CI runner, and it includes building the 20 MiB fixture. Assert on the equality of heights, which already proves the path, and drop or start the timer after the fixture is built.</comment>

<file context>
@@ -0,0 +1,162 @@
+test("a huge prompt's row is estimated as its collapsed lines, quickly", () => {
+  const { lineHeight } = currentChatMetrics();
+  const row = (id: string, text: string) => ({ id, version: 1, at: 0, kind: "user", text });
+  const started = performance.now();
+  const [huge] = [...layoutConversation([row("h", markdown(20 * 1024 * 1024))] as never, 720).heights];
+  const elapsed = performance.now() - started;
</file context>

… with no dead Show more (review of #29840)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-df4c966270872064ca90
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6.1-sol xhigh, router-review): BLOCK at 82d3f2e

BLOCK at 82d3f2e

Visual verdict: no images; Leo tries the build

  1. [P1] [blocking] Large pasted prompts get a nonfunctional “Show more” and an incorrect row estimate. PromptText.tsx:65,205 treats the full text as huge, but headParts leaves pasted ranges as closed chips; clicking “Show more” only opens the parent fold and never opens the PasteChip. Meanwhile model.ts:1607,1642-1675 excludes pasted rows from the huge fast path and estimates only the chip height, omitting the 24px Show more control. Rows below such a prompt shift when mounted, and the control does not reveal the prompt as promised.

@cubic-dev-ai cubic-dev-ai Bot 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.

1 existing issue remains and 1 new issue found across 5 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="webviews/src/agent-session/acpmux/model.ts">

<violation number="1" location="webviews/src/agent-session/acpmux/model.ts:1617">
P2: A large inline text-file part fails this guard because `hasHugeTypedPart` ignores `kind: "file"`, so the estimator processes its full `row.text` even though the body renders as a chip. Estimate visible inline parts without lexing chip bodies.</violation>
</file>

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.

View guided diff | Turn on auto-fix | Re-trigger cubic

!pasted &&
row.from !== "chief" &&
isHugePrompt(row.text) &&
(!row.inlineParts || hasHugeTypedPart(row.inlineParts)) &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: A large inline text-file part fails this guard because hasHugeTypedPart ignores kind: "file", so the estimator processes its full row.text even though the body renders as a chip. Estimate visible inline parts without lexing chip bodies.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At webviews/src/agent-session/acpmux/model.ts, line 1617:

<comment>A large inline text-file part fails this guard because `hasHugeTypedPart` ignores `kind: "file"`, so the estimator processes its full `row.text` even though the body renders as a chip. Estimate visible inline parts without lexing chip bodies.</comment>

<file context>
@@ -1607,7 +1608,15 @@ function measuredRowHeight(
+    !pasted &&
+    row.from !== "chief" &&
+    isHugePrompt(row.text) &&
+    (!row.inlineParts || hasHugeTypedPart(row.inlineParts)) &&
+    !chiefEnvelope(row.text)
+  ) {
</file context>

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex, router-review): SHIP at 415434f

Reviewer: codex gpt-6.1-sol xhigh, fast tier.

Follow-ups: 2. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward.

SHIP at 415434f

Visual verdict: no images; Leo tries the build

  1. [P1][follow-up] Inline pasted parts can still freeze layout. When inlineParts contains a huge kind:"pasted" block but row.pasted is absent, PromptText counts the paste in looksLongPrompt and shows a dead “Show more” (PromptText.tsx:62), while the estimator skips the huge fast path and lexes the full megabytes (model.ts:1612-1618, 1648-1650). This occurs on echo/reload records that preserve inline parts without paste ranges.

  2. [P2][follow-up] Huge detection is per typed block, not aggregate. Multiple typed blocks split by an attachment can exceed 200,000 characters without any individual block crossing the threshold, so Markdown/link scanning and full row measurement still run (promptCollapse.ts:34-37, PromptText.tsx:62).

Follow-ups:

  • [P1][follow-up] Handle huge inline pasted parts without row.pasted ranges.
  • [P2][follow-up] Detect aggregate typed length across prompt parts.

cmux-bot[bot]
cmux-bot Bot previously approved these changes Nov 1, 2026

@cmux-bot cmux-bot Bot 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.

cmux-bot approves 415434f: an independent review passed this exact head (router-review receipt by teamleaderleo). A push needs a new review; a later BLOCK at this head dismisses this approval.

@cmux-bot
cmux-bot Bot temporarily deployed to ci-routing-agent November 1, 2026 05:58 Inactive
@cmux-bot
cmux-bot Bot temporarily deployed to ci-routing-agent November 1, 2026 05:59 Inactive
@cmux-bot
cmux-bot Bot dismissed their stale review November 1, 2026 06:15

A newer verdict blocks 5b14814 (no independent SHIP at the head).

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Head moved 415434f -> 5b14814 by cmux-bot's base merge only (parents 415434f and feat-cmux-next 5bdd4c9). The PR's own diff is identical: git patch-id --stable of merge-base..head is cd799bc6595970133a908b394a75a818738d6d23 at both heads. The router-review SHIP at 415434f carries to 5b14814. bun test conversation/ + rowEstimates at the new head: 663 pass, 0 fail.

@teamleaderleo
teamleaderleo merged commit 8d279f6 into feat-cmux-next Nov 1, 2026
169 of 175 checks passed
@teamleaderleo
teamleaderleo deleted the lane/huge-prompt-render branch November 1, 2026 09:59
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Reds at 5b14814, compared against base before landing:

  • Webview verdict web / react-apps-base-check (1-8): all green.
  • app platform: generated/cmux-app.d.ts is stale (gen-cmux-global.ts --check). The base this head merged, 5bdd4c9, gives the same result. Base fixed it later in 9e3b7ac, and this diff touches nothing under cmux-tui.
  • cmux-next checks "Checks job structure": test_cmux_next_checks_workflow.py fails on base with the same check:session-info-names assertion (from carry #29651: Session Info is called Session Info in its code, not Inspector #29921).
  • defaults guard rerun: the GitHub App installation hit its API rate limit (HTTP 403), an infra failure.
  • release-notary and Guard status: non-blocking base guards.

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 5b14814f Deployed Nov 1, 2026 by cmux-bot[bot] via wait for same-key tree publisher #94059
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant