Repository navigation
fix(terminal): use a byte budget for Ghostty scrollback - #8766
zero-two-rafaeltab wants to merge 952 commits into
Conversation
|
Warning Review limit reachedOnly developers with an assigned seat can use this organization's usage-based review budget, and seats here are assigned manually. Ask an admin to assign a seat, or change the review continuation mode in Billing. Next included review available in 41 seconds. View limit details
Comment |
|
PR made by my agent under my supervision. I am doing a manual check of this PR and the linked PR on web, desktop and android before publishing. |
de1c7a4 to
2c4734c
Compare
|
Manually verified that this is working on: |
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — This is a 3,333-file aggregate change that includes production terminal behavior, release infrastructure, native/desktop packaging, and many unrelated product changes. It also changes the Ghostty scrollback default, Macroscope configuration, and static-analysis suppressions, so the scope and review-policy impact require human review. Notes:
You can add or adjust custom eligibility rules. Learn more. |
|
Note: GPT-6 on behalf of shivam (@shivamhwp). The new ABI test writes |
|
Heads-up, just in case it wasn't clear commit f186281 fixed shivamhwp's comment. |
|
Note Written by Hi! We are cleaning up open PRs, and this one appears to have been created with an older model ( |
|
Note Written by Reopening, this was closed by mistake. Sorry for the noise! |
|
Taking over this one. I'll rebuild it to the repo's current conventions, trim the tests to the minimum, and push to this branch. |
|
I independently checked the focused web scrollback fix on BASE With the production I then captured the production core and canvas renderer in a real browser with the same 12,000 numbered lines, dimensions, and scroll-to-top operation. BASE retained 800 rows, starting at Before — BASE After — HEAD The complete three-file source review found no demonstrated blocker in the unit correction. The measured small-run peak RSS was 70,980 KiB on BASE and 71,964 KiB on HEAD; that does not establish a strict process-memory bound or the effect of many simultaneous terminals. Still unverified: native Android, an installed desktop client, real PTY/server replay, and constrained-device or many-terminal memory behavior. The larger per-terminal default still has the existing maintainer-approval gate. This is scoped web reproduction evidence, not full multi-surface or merge-readiness approval. It follows the verification guidance. Capture method, chronology, and limitations. Screenshot assets were downloaded and byte-verified after upload. |
…sts over REST (pingdotgg#22495) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ingdotgg#22521) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ction (pingdotgg#22526) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…tes (pingdotgg#22524) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
pingdotgg#22533) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
pingdotgg#22523) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: maria-rcks <254055478+maria-rcks@users.noreply.github.com>
…ngdotgg#23149) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ngdotgg#23150) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…3226) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…2094) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gg#23052) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…gdotgg#23205) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…card (pingdotgg#23282) Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…ingdotgg#22777) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…uests (pingdotgg#23034) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…sed (pingdotgg#23170) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ngdotgg#23096) Co-authored-by: Vishal <vishalprashantdoshi@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: PR Batch Tester <agent@local.test> Co-authored-by: Vishal Doshi <vdoshi96@users.noreply.github.com>
…ingdotgg#23361) Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…ingdotgg#23106) Co-authored-by: PR Batch Tester <agent@local.test> Co-authored-by: Nikita Maximilian Grimm <github@nikitagrimm.de> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in pingdotgg#8766's Ghostty scrollback byte budget fix by zero-two-rafaeltab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The 3,333-file aggregate is the old-head → new-head push range, which incorporates 941 main commits. The current-main PR comparison has merge-base 3b95e7831b and changes four files, +50/−4, at 3bbf1c3918. GitHub's advertised synthetic merge has the same four-file delta against its first parent. Macroscope configuration, release infrastructure and static-analysis suppressions are absent from that PR delta. The existing contributor history is preserved. Two fresh reviews found no code defects; the focused tests and real-app evidence are in Verification. Android and Electron runtime checks remain unverified. Functional CI is also unverified: GitCafe reports ten successful metadata/bot contexts but no CI runs for this head. |


Problem
Ghostty interprets the pinned ABI’s
max_scrollbackas bytes, although T3 named the 10,000 value as rows. Running the reporter’s 12,000-line command in an attached web terminal on current main retained only about 700 history rows at the reproduced width, silently discarding older output.Change
Use an explicit 10,000,000-byte budget for web/desktop and Android, matching the pinned Ghostty application default. Retention remains width- and content-dependent; this does not promise exactly 10,000 rows or change the ABI. A production-core/WASM regression checks retained history, and a committed numbered-output fixture reproduces the report in a real terminal.
Credit to @zero-two-rafaeltab for identifying the mismatch and contributing the fix.
Scope and approval
Fixes https://git.cafe/pingdotgg/t3code/issues/8701
GitCafe: https://git.cafe/pingdotgg/t3code/issues/8701
Triaged bug via the automated issue flow. This continues the existing contributor PR and maintainer takeover; it adds no setting, contract or persisted state. iOS configuration and the separate client/server transcript limits are unchanged.
Verification
expected 602 to be greater than 1000.no-new-arraywarning.bash -n, emits an ESC reset, all 12,000 numbered markers, and the final column count (12,001 newlines; approximately 240 KB).knip:checkdid not finish under VM contention; three attempts were stopped, so it is not reported as passed.3bbf1c3918. The four approval-held workflows were approved before this result.Evidence
Complete evidence report and upload verification.
Issue #8701, PR #8766. Original proof matrix.
BASE 3b95e7831b (
3b95e7831b11b17627dff16843bc087bfca397ec); final HEAD 3bbf1c3918 (3bbf1c3918c120dfbbe457807f3a9a4f1a760d22). This report retains all four original matched pairs and eight original recordings, then adds stamped C1 test runs, wide-dark interaction recordings and a controlled reload pair. Native and remote verification remain incomplete; W1 is a tested interaction subset, not a full native-input pass.Environment, timestamps and procedure
Recovery began 2026-10-22 at approximately 08:19 UTC. Own T3 collaborative server-browser tab on Linux x86_64; Chrome 154.0.0.0; DPR 2; visualViewport.scale=1. Reused the lead-owned isolated dev server (
vp run dev --no-seed), web 5876/server 13916, worktree/home/ubuntu/wt/issue-8701/.t3. No server launched/stopped, no source edits, commits, pushes, PR-body writes, or direct database writes. The app's normal terminal lifecycle persisted isolated app state. Pairing credentials/private logs were excluded from uploads.Font preferences: advanced typography unset (off), code size 13, code family empty. Thus the terminal uses 13 CSS px with the default SF Mono/SFMono-Regular/Menlo/Consolas/Liberation Mono and glyph fallback stack. A browser canvas measurement using that stack gave M advance 7.80126953125 CSS px and ascent 9; the exact platform face selected by Chromium was not independently identified. Same browser and unchanged preferences across all eight retained captures. Terminal column counts are independently visible in PTY reporter output: 183 wide, 48 narrow. Fifteen visible text rows; row advance 18 CSS px inferred from renderer metrics and exported rows. No font scaling or zoom change.
CSS viewports: wide 1440×900 with canvas (0,621) 1440×279; narrow 390×844 with canvas (0,565) 390×279. Whole-surface still exports are 1280×800 wide and 780×1688 narrow (preview export scaling); videos are 2880×1800 wide and 780×1688 narrow. No cropping, registration, resizing or masks were applied to the compared stills.
Each retained run: set saved light/dark theme with follow-system off; fully navigate/reload the app; wait for terminal input; close main sidebar and notifications through their DOM controls; start recording; paste
bash /tmp/issue-8701/scrollback-repro.shwith ClipboardEvent/DataTransfer into the actual Terminal input; press Enter. This is the unchanged committed reporter from HEAD, copied outside the worktree before BASE checkout. It emits RIS, 12,000 numbered markers and T3-END with tput columns. After output settles, focus the actual scrollbar, press End, capture end, press Home, capture earliest, press End again, capture return, and leave 2.5 seconds for the recording endpoint. No synthetic terminal output or injected cosmetic UI. Navigation was keyboard End/Home, not a wheel/trackpad test.HEAD captures preceded BASE; checkout BASE detached, then full reload for a fresh core. Restored fix branch, fully reloaded and repeated HEAD wide-light last. Earlier exploratory wide-light recording is discarded. Retained timestamps and scrollbar values are in recovery-capture.json. All eight videos were decoded with ffmpeg; their final frames visibly contain T3-END and the shell prompt, proving return to end. Stills show Home at scrollbar position zero. This avoids the previous run's missing final frame.
Matched whole-surface comparisons
Diff0: absolute per-channel difference amplified 8×, black for identical pixels; counted when max RGB delta >0. Diff16: per-channel binary threshold >16/255, counted when max RGB delta >16. These images deliberately compare different retained line numbers at the same earliest-scroll position; they are behavioral evidence, not an assertion of visual equality.
diff-stats.json. All changed pixels are within terminal text: wide difference bounding box (101,559)–(135,792), narrow (227,1146)–(304,1669), in exported raster coordinates. Pixels above the terminal are exactly identical in every matched pair. Visible differences are earlier retained line-number digits and their antialiasing. Theme, layout, composer, terminal bounds and focused top scrollbar position match. At Home, both scrollbar thumbs hit the same minimum size; the increased range is recorded in metadata. No other pixel differences were observed in these retained stills. No clock freeze, cosmetic correction, or diff exclusion was used.
Interaction recordings and end-state evidence
Each original video shows the fresh PTY run, Home/earliest and visible return to End. The following timings replace the prior generic narration. Videos are variable-frame-rate: frames were decoded sequentially and their presentation timestamps inspected, rather than inferring time from frame number or seeking as if frame rate were constant. Entries below are first decoded frames visibly showing each state; a frame remains displayed until the next presentation timestamp. Whole-frame originals are unchanged.
The BASE wide-dark earliest phase is brief (~0.14 s); its still remains the readable proof. These original recordings exercise keyboard navigation, with no native wheel/trackpad claim.
Supplement — stamped C1 runs and bounded interaction/reload evidence
Supplement performed 2026-10-22, 08:36:54–08:55 UTC, using the same existing isolated web 5876/server 13916. Own new T3 preview tab; no server lifecycle action, source edits, commits, pushes, PR writes or direct database fixture writes. The exact committed reporter had already been copied to
/tmp/issue-8701/scrollback-repro.sh; it was pasted into the real terminal textarea through ClipboardEvent/DataTransfer and run by the existing PTY. Temporary BASE/RED checkouts were restored to clean final HEAD.C1. Reran the existing focused test from
apps/webon RED commit 5dea8693af, which contains the regression test on BASE, then final HEAD. Each transcript printsgit rev-parse HEAD, the command and exit code. Command:vp test run --project unit src/terminal/ghostty/core.test.ts -t 'retains thousands of rows of scrollback'. RED: expected 602 to be greater than 1000, exit 1; HEAD: one selected test passed, exit 0 (16 unselected tests skipped by-tin each run). No implementation edits. Stamped RED transcript; stamped final-HEAD transcript.W1 replacement pair. Same whole-surface CSS viewport 1440×900, DPR 2, scale 1; dark saved theme with follow-system off; advanced typography off, code size 13, unchanged default font stack; terminal canvas (0,621), 1440×279, 183 columns and 15 visible rows. Main sidebar, details card and notifications closed through existing controls. Native preview drag moves the actual scrollbar thumb to the center of its track. Then
preview_evaluatedispatches a canvasWheelEventwithdeltaY=-9000,deltaMode=0, followed by focused-scrollbar Home and End. This dispatch exercises the terminal wheel handler but is synthetic DOM input, not native wheel/trackpad input. On HEAD the thumb value traverses 3958 → 1979 → 1479 → 0 → 3958; on BASE 332 → 166 → 0 → 332. BASE reaches earliest on the wheel dispatch before Home. Drag to the exact top was not available through the locator-to-locator drag API; Home establishes earliest.Measured decoded video timestamps, above the pair: BASE shows streaming at ~1.09–1.19 s, End at 1.25 s, dragged midpoint marker 11822 at 3.12 s, dispatched-wheel earliest 11656 at 4.48 s, returned End at 8.69 s. HEAD shows streaming at 1.68 s, End at 1.89 s, dragged midpoint marker 10009 at 11.15 s, dispatched-wheel marker 09509 at 12.23 s, Home/earliest 08030 at 13.82 s, returned End at 16.07 s. Both decoded final frames show T3-END and the existing shell prompt. Different tool latency changes elapsed time, not viewport or reporter.
Interaction action metadata. W1 disposition: keyboard + thumb-to-midpoint drag + synthetic-wheel-handler subset complete. Native browser wheel, physical trackpad inertia, drag-to-earliest, and corresponding gestures in narrow/light fixtures remain unverified.
preview_scrollwas attempted on the canvas and after hovering it, but did not change the terminal: the tool calls DOMscrollBy, not wheel input. This is a tool coverage gap, not evidence that native wheel scrolling fails.R1 controlled reload. Each revision ran the reporter once, captured live earliest, returned End, fully navigated to the same thread URL, waited for the actual terminal input, closed the reopened main sidebar/dismissed the normal notification, and captured End then Home without issuing another PTY command. Same existing PTY and thread, no transcript reseeding after reload. The videos include normal reload splash/loading. The sidebar initially mounts the terminal at 1184 CSS px before closure restores 1440; therefore this is a real reload-plus-normal-layout-restoration fixture, not a claim of constant terminal width during mount. Both after-reload retained stills have canvas (0,621), 1440×279.
Decoded video narration: BASE live output ~1.57–1.67 s, live End 1.71 s, midpoint 11.03 s, synthetic-wheel earliest 11.56 s, live return End 24.22 s, reload begins ~24.63 s, restored End ~46.09 s, after-reload Home 11427 at 48.58 s, final End 58.90 s. HEAD live output ~2.26–2.37 s, live End 2.47 s, midpoint 11.78 s, wheel middle 12.24 s, live return End 24.80 s, reload begins ~25.08 s, restored End 46.74 s, after-reload Home 07003 at 47.24 s, final End 47.32 s. HEAD's after-reload Home is a short decoded frame (~0.08 s); its retained still is the readable assertion. The live Home action in this longer HEAD recording was too brief to encode and is not claimed as visible; the separate replacement interaction pair above supplies that proof.
After-reload scrollbar maxima: BASE 561; HEAD 4985; Home value zero in both. Whole-surface still diff: 3652 pixels at >0, 3049 at >16, out of 1,024,000; bounding box (101,559)–(134,791). Differences are terminal line-number digits and antialiasing; all pixels above the terminal are identical. No cropping, resizing, masks or registration. Reload diff statistics; reload action and artifact metadata.
R1 is verified only for this local web full reload and normal sidebar restoration. Retained output is bounded: earliest after reload 11427 → 07003, not marker 00001. The default server replay of about 5,000 history lines, live engine byte budget and client transcript cap remain separate limits. This does not prove full 12,000-line replay, native remount, remote disconnect/reconnect or transport recovery. BASE and HEAD final decoded frames both show T3-END cols=183 and the shell prompt: BASE reload final frame; HEAD reload final frame.
Sequentially decoded frame inspection sheets for the eight original videos: wide-light, wide-dark, narrow-light, narrow-dark. These are labeled analysis crops only; the original full-surface videos and stills above remain the evidence.
Other evidence and full matrix disposition
Lead's earlier 1280×800 comparison reported oldest marker 11285 before versus 6189 fixed. It is a separate geometry and must not be substituted into the four matched fixtures above: current-main-before.png, current-main-after.png. Existing focused red test reports retained history 602, failing >1000; green run reports 53 tests passed across four files: red-test.log, green-test.log. Those earlier logs were retained; the focused SHA-stamped rerun above supersedes them for C1 provenance. No knip success is claimed: lead stopped its stalled retry at 08:22 UTC to reduce memory pressure.
Live engine capacity, 512 KiB client transcript and server replay (~5,000 history lines by default) remain separate limits. The wide fixture still truncates at 08030; the fix increases the byte budget and does not guarantee 10,000 retained rows at every width. Narrow retains marker 00001 for this fixture. No promise of preserving the entire run through replay/remount.
Unverified surfaces:
cannot-verify android,cannot-verify desktop; hosted remote, physical wheel/trackpad input, and separate client-only remount were not exercised.Models: Claude Opus 5.5 and GPT-6.1-Sol through Claude Code/Codex harnesses in T3 Code.