Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions docs/research/CODEMODE_TUI_PRESENTATION_2026-10-04.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,15 @@ Focused tests passed 13/13 in 1.72 seconds, including actual locked SDK 0.99.1 r
The local repository check passed. One complete local test run passed 2,283 Node tests (9 skipped; 128.75 seconds) and 1,158 UI tests (32.13 seconds). The candidate was under a narrow cancellation-display correction during that run; final focused tests and exact-head CI must separately cover the frozen correction. No timeout increase, disabled assertion, executor replacement or installed-host edit was used.

Real terminal pixels, keyboard expansion in the user's actual Session and package reload remain unverified. Installation was not changed.

## 2026-10-05: background continuity after truncation

- Status: validated at the ANSI renderer and isolated native SDK boundaries; live terminal pixels after reload remain unverified.
- Source boundary: main `214fac3786f80107e22d5bd2b53b472461ef16b2` plus the repair linked from [#683](https://github.com/openpi-dev/openpi/issues/683).
- Created / verified: 2026-10-05. This supplements the earlier observations without replacing their evidence.

A new user screenshot showed the card background ending immediately after a truncated Bash preview. Pi's public `truncateToWidth` inserts SGR `ESC[0m`, resetting background as well as foreground. Wrapping the complete padded row once with `theme.bg` does not restore the background after that embedded reset. The regression reproduced an unpainted ellipsis and trailing space before the fix.

The OpenPI frame now applies its owning background independently to each segment separated by the native full-style reset. The original reset is retained between segments, preserving foreground/style termination. Displayed text, width, truncation budgets, execution and result evidence are unchanged. This repair applies to main and child presentations through their shared Code Mode renderer.

The regression checks ANSI background state for every visible character, including padding, at 40/120/240 columns in collapsed and expanded views with a long Chinese-containing Bash preview. It deliberately retains escape sequences; a stripped-text comparison could not detect this defect. Focused renderer/native tests pass 21/21 on locked Pi 0.99.1 and installed Pi 1.0.2, without model calls. Full repository checks and independent review are reported on the repair PR. The installed dirty source checkout was preserved; no assertion here proves that a running Session reloaded the repair.
12 changes: 9 additions & 3 deletions extensions/codemode-display/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,15 @@ function framed(
if (edges.top) rows.unshift("");
if (edges.bottom()) rows.push("");
const bg = tone();
return rows.map((row) =>
theme.bg(bg, row + " ".repeat(Math.max(0, width - visibleWidth(row)))),
);
return rows.map((row) => {
const padded = row + " ".repeat(Math.max(0, width - visibleWidth(row)));
// Pi's truncation/wrapping resets all SGR styles. Reapply the owning
// card background after each reset, including ellipsis and padding.
return padded
.split("\x1b[0m")
.map((segment) => theme.bg(bg, segment))
.join("\x1b[0m");
});
},
invalidate() {},
};
Expand Down
48 changes: 48 additions & 0 deletions tests/extensions/codemode-display/render.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -552,3 +552,51 @@ test("a shared row puts the status in the call header and hides output", () => {
assert.doesNotMatch(body.join("\n"), /completed/u);
assert.doesNotMatch(body.join("\n"), /first|second|│/u);
});

test("truncated previews keep the card background through ellipsis and right padding", () => {
const colorTheme = {
fg: (_color: string, text: string) => `\x1b[38;5;145m${text}\x1b[39m`,
bg: (_color: string, text: string) => `\x1b[48;5;237m${text}\x1b[49m`,
bold: (text: string) => `\x1b[1m${text}\x1b[22m`,
} as Theme;
const value = result("done", [
{
id: "1",
name: "bash",
status: "running",
args: JSON.stringify({
command: `bunx biome format --write ${"extensions/中文.ts ".repeat(20)}`,
}),
},
]);
for (const width of [40, 120, 240]) {
for (const expanded of [false, true]) {
const rows = codemodeRenderers.renderResult!(
value,
{ expanded, isPartial: true },
colorTheme,
context(expanded),
).render(width);
if (!expanded)
assert.ok(
rows.some((row) => row.includes("\x1b[0m")),
"exercise native truncation/wrapping resets",
);
for (const row of rows) {
assert.equal(visibleWidth(row), width);
let background = false;
for (const token of row.matchAll(/\x1b\[([\d;]*)m|([^\x1b])/gu)) {
if (token[1] !== undefined) {
if (token[1] === "0" || token[1] === "49") background = false;
if (token[1] === "48;5;237") background = true;
} else {
assert.ok(
background,
`unpainted cell at width=${width}, expanded=${expanded}: ${JSON.stringify(row)}`,
);
}
}
}
}
}
});
Loading