Repository navigation
Office files read like PDFs, and the PDF reader draws and reloads less - #783
Merged
Merged
Conversation
Contributor
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
Without `enableHWA`, pdf.js opens every page canvas with `willReadFrequently`, which Chromium keeps in software, so pages drew on the CPU. pdf.js's own viewer turns it on. `enableOptimizedPartialRendering` (off by default in pdf.js) dropped a page over the canvas limit to a quarter of its resolution and redrew a sharp patch on every scroll, and the halved `maxCanvasPixels` made pages cross that limit sooner: at any zoom above fit width, and on small or low resolution screens. Both now use pdf.js's defaults. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a PDF dispatched an empty find within 1.5 s, and pdf.js then extracted the text of every page on the worker that also draws the pages. On a long PDF that slowed page drawing for minutes, whether or not the person ever searched. Opening search, or typing a query, still prepares it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Asset URLs are re-signed every 30 minutes (and on a stale remount), and the reader treated each new URL as a new document: it downloaded, parsed and drew the whole PDF again in a hidden layer, then swapped it in. The server now reports the revision a workspace or environment PDF's URL serves (device, inode, size and modification time), as it already did for media files. The reader knows a PDF by that revision, by a generated PDF's revision id, or as an immutable attachment, and keeps the loaded document while a renewed URL serves the same bytes; actions such as Save a copy move to the renewed URL. A changed file, an edited copy, or a Try again still loads afresh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reader lets people fill in a PDF's form, but Save a copy downloaded the served file again, so the copy lacked every value typed into it while the success message still appeared. Page edits started from the same original bytes. Both now take the document from pdf.js with its form values (`saveDocument`) whenever a field has been filled in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each thumbnail in view rendered at once on the worker that draws the pages, with no limit, and released the page's resources when it scrolled away, even while the main view still used them. Thumbnails now take their turn in pdf.js's own rendering queue, as in pdf.js's sidebar: one at a time, once the pages in view are drawn. A page the reader has already drawn is copied rather than drawn again, and page resources the main view holds stay loaded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Until a newly opened PDF was drawn, every screen frame queried every page element and read its position to find the visible ones. pdf.js finds them with a search over its page positions; the fence now asks it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
yaacovcorcos
force-pushed
the
scient/office-viewers-20261105
branch
3 times, most recently
from
November 6, 2026 14:20
b281e5f to
f08aa73
Compare
T3's preparation step bounded Word files for a renderer on the main thread, and real documents lost parts: a table of a few hundred rows cut the document off there, a body stopped at 5,000 paragraphs, and long style or list definitions were dropped, unstyling the whole document. Of six real documents, three previewed wrong; one showed 6 of 21 pages. The limits are now measured against the @betteroffice engine, which runs in its own worker: a paragraph's text (line breaking grows with its square), one element's tags (a table is laid out in one go) and a header's length, with the other totals raised to where they no longer bind real documents. A document past the viewer's 1,000 pages shows the first 1,000 with the Preview limited notice instead of an error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Office files had no zoom, no find and no way to move by page; the PDF reader has all three. Word and PowerPoint now open in a reader with the same controls: page number and steps, zoom (buttons, keys, pinch, fit width, actual size), a sidebar of pages and find with every match marked. T3's viewer still draws the pages. Find runs in each engine's worker: the Word engine searches its document model, so no page is built to search it, and places matches by document position; a slide's text comes from its laid-out glyphs. Slides gain a text layer for that, so their text can now be selected and copied too. Thumbnails paint without releasing the pages built around the view. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PDFs, Markdown and code can be quoted into the chat; Office files could not. Selected text on a Word page or PowerPoint slide now offers Ask in chat (and Ask in side chat), as a PDF passage does. An Office quote is its own kind, beside the file, PDF and Compute ones: the workspace file, the page or slide the reader showed it on, and the text with what surrounds it there. The agent gets the file path, page and text with a note that the page is the reader's. The chip reopens the file at that page with the quote marked, and an exported conversation keeps it as a quote from the document's page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
yaacovcorcos
force-pushed
the
scient/office-viewers-20261105
branch
from
November 6, 2026 14:21
b281e5f to
ebaded4
Compare
A header or footer over its size limit marked the whole expansion truncated, which removed every other header, footer, note and comment too. It is now left out alone, as an unused part is, and the preview says it is limited only when the document uses it. The paragraph limit also counts text written as CDATA, which saxes reports apart from ordinary text. Found by review on the T3 copy of these limits (pingdotgg/t3code#32040). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The file panel keyed a document preview (Word, PowerPoint, archives, fonts, other binary files) by the thread's workspace mutation id, which moves after every command, file edit, tool call or subagent anywhere in the project. Each one remounted the preview: an open Word file was fetched, prepared and laid out again, and went back to its first page, every few seconds while an agent worked. The preview is now keyed by its file. Each possible change asks the server for the file's revision (device, inode, size and modification time), which it now reports for every exact workspace file rather than only PDFs, and only a new revision remounts the preview. A server that reports no revision remounts it on every change, as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Leaving a Word or PowerPoint file and coming back, or a file that changed and reloaded, started at its first page and the default zoom, while a PDF returns to its place. The Office reader now remembers, for the window's session, the page at the top of the view, the point on it and the zoom, and returns there once that page is laid out. Until the reader moves, the place holds as the panel settles its width or Word lays out more pages. A quote opened from the chat still opens at its own page, and paging or scrolling first keeps where the reader went. A jump to a page past those mounted so far (a remembered place, or a quote far into a long document) mounted pages only up to it, so the view could not scroll it to the top and stopped short. It now scrolls again as the following pages mount. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review follow-up (T3's review bot on pingdotgg/t3code#32670). With the refresh counters moved into the revision check, Reload file from disk and the Files pane's refresh no longer remounted an unchanged document, so a preview whose fetch or worker failed after its URL was issued could not be retried. A reload the reader asks for now has its own counter, kept in the preview's key with the Files pane's; the watcher and workspace mutations still go through the revision check. The boundary test resets its shared mock through a setup helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reloading a Word file that was open at page 5 came back at page 4: the page was mounted, but few pages below it were yet, so the view could not scroll it to the top and stopped short. Any jump that stops at the bottom while pages are still mounting now scrolls again as more mount, unless a newer jump comes or the reader moves first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
yaacovcorcos
enabled auto-merge
November 9, 2026 10:09
The pages take their size from a width a resize observer reports after layout. On a loaded CI runner the jump ran while every page was still zero high, so it stayed at the top. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Word previews lost parts of real documents, Office files had no zoom, search or page controls and reloaded after every agent command, and the PDF reader redrew and reloaded more than it needed to, which hurts most on slow Windows laptops. This PR makes Office files read like PDFs and takes over the PDF findings from the 2026-11-05 review.
Platforms: tested on macOS (Apple silicon) only, in a dev app and browser tests. Windows and Linux were not run. Nothing here is platform-specific. GPU drawing (
enableHWA) falls back to software where Chromium has no GPU. The file revision uses the inode, which Node reports on Windows too. The pinch zoom reads Control+wheel, which Windows and Linux touchpads also send. Still to do: a before/after on a slow Windows laptop (the same long PDF at fit width and at 150%), since the browser CPU throttle does not slow the engines' workers.Office
Word previews are complete (
fix(web): size the Word preview limits…). T3's preparation step was sized for a renderer on the main thread. A table of a few hundred rows cut the document off there, a body stopped at 5,000 paragraphs, and long style or list definitions were dropped. Three of six real documents previewed wrong; one showed 6 of 21 pages. The newWORD_LIMITSare measured against the@betterofficeengine, which runs in a worker:All six documents now open whole, with the first page in 0.3–0.7 s as before. A document past 1,000 pages shows its first 1,000 with "Preview limited" instead of an error.
The PDF reader's controls on Word and PowerPoint: page number and steps, zoom (buttons, keys, pinch, fit width, actual size), a sidebar of pages, and search with every match marked. Each engine searches in its own worker. Word searches its document model, so no page is built to search it. Slides gain a selectable text layer, word by word from their laid-out glyphs. Search: 95 matches in 30 ms on a 21-page report, 63 ms on a 69-slide deck, 2.2 s on a 385-page document (mostly waiting for its layout).
An open file stays put while the agent works. The file panel remounted every document preview (Word, PowerPoint, archives, fonts, binaries) after each command, edit, tool call or subagent in the thread, so an open report reloaded and went back to page 1 every few seconds. The preview is now keyed by its file; each possible change checks the file's revision (which the server now reports for every exact workspace file, not only PDFs), and only a real change reloads it. A reload you ask for (Reload file from disk, or refresh in Files) still always reloads it, so a failed preview can be retried. Offered to T3 as fix(web): keep an open document preview while other files change pingdotgg/t3code#32670 (issue #32669).
A Word file or slide deck reopens where it was left: page, point on the page and zoom, for the window's session, as PDFs already do. That also covers a file that changed and reloaded. A jump to a page past those mounted so far (a quote far into a long document) used to stop short; it now arrives.
Ask in chat on a Word page or slide. The new
OfficeCitationquote kind sits beside the file, PDF and Compute kinds. It keeps the file, the page or slide number and the text. The agent gets the path, page and text with a note that the page number is the reader's. The chip reopens the page with the quote marked, and an exported conversation keeps it as a page quote.PDF reader
enableHWA). The experimental quarter-resolution mode and the halved canvas limit are gone: at 300% the base canvas is twice as sharp (0.14 → 0.27 of screen resolution).Upstream seams
Scient code is in
apps/web/src/scient/office,packages/shared/src/officeCitations.tsand the existing Scient quote modules. T3 files change only in markedSCIENT-FORKseams:officeArchive.ts(limits),OfficePages,WordDocument,Presentation, both workers and their protocols, andword-text;AssetAccess,FilePreviewPanelandAssistantCitationChip.Presentation drops T3's previous/next slide bar, since the reader's page controls replace it. T3's limit tests in
AttachmentFilePreview.browser.test.tsxnow size their inputs fromWORD_LIMITS.UPSTREAM.mdrecords both ("Office preview limits", "Office reader"). The limits are offered to T3 as pingdotgg/t3code#32040, so this copy can go if it merges.Verification
Codex reviews: one of the six PDF commits, one of the three Office commits, a re-check of those fixes, one of the Word limits as offered to T3, a design review of the reload and reopen work, a review of it and a re-check. T3's own review bots found the header and CDATA problems in #32040. The earlier rounds found eight real problems, all fixed here: form edits saved against the wrong revision, a thumbnail copy ignoring CSS rotation, find activating a header match (twice), thumbnail paints retaining built Word pages, and in the Word paragraph count, an empty text-box paragraph that turned the count off and indentation or field codes counted as text. The last two rounds found four more, also fixed: a document that failed to open did not retry once its file appeared; a remembered page past the end of a now shorter file was never reached; an older page jump could scroll back over a newer one; and a test that depended on timing. T3's review bot on #32670 found that a manual refresh no longer retried a failed preview, and the live check found a reload returning one page short; both fixed.
New tests:
officeArchive.scient.test.ts: each limit path.officeFindPlacement.test.ts: Word match placement and slide words over glyphs.ScientOfficeReader.browser.test.tsx: find, zoom, sidebar, Ask in chat and reveal; reopening at the left place, far into a long document, in a shorter file, and a newer jump over a waiting one.ScientFileRevisionBoundary.browser.test.tsx: an unchanged file stays mounted across checks; a changed one reloads; a failed open retries.AssetAccess.test.ts: a workspace document reports its revision, and a changed one a new revision.officeCitations.test.ts: link format and what the agent gets.useScientPdfReader.browser.test.tsxandAssetAccess.test.ts.pdfRendering.scient.browser.test.tsx.pdfEditSession.browser.test.ts.Each regression test fails without its fix.
Gate:
vp fmt --check,vp lint --report-unused-disable-directives,pnpm run typecheck,pnpm run build,pnpm run test:desktop-smokeandgit diff --checkpass.pnpm run test: everything passes except two suites that fail the same way on main on this machine:provider-fxskills, which reads~/.fx, andscriptsrelease-build. A notebook and an audio browser test flaked once under load and pass alone. After the reload and reopen work and the merge of main (481 commits, no conflicts):pnpm run typecheck,vp fmt --checkandvp lintpass, and the file, Office, PDF, asset and file-surface browser tests (744) and the server asset tests (71) pass; the full suite runs in CI.Dev app:
Scient (Dev) · officeviewers, with a fresh profile, real Word, PowerPoint and PDF files and screenshots. It found two layout bugs, fixed here: a 3 px horizontal overflow, and fit width not following a resize. Not run there: Save a copy's native dialog, the 30-minute URL renewal, and sending to a provider. Each is covered by the tests above. Second session (2026-11-07), same app: a 21-page Word report open at page 8 stayed mounted at page 8, at the same scroll position, while a Codex agent in the thread ran four commands; switching to a slide deck and back returned to page 8; widening the panel from 277 to 533 px kept page 8; touching the file on disk reloaded it at page 8. That session found the long-document jump that stopped short, fixed here.Not in this PR
Documentation impact: Updated —
docs/user/file-previews.md,docs/user/composer.md,UPSTREAM.md.Model and harness: Claude Opus 5.5 in Claude Code (Scient); reviews by Codex gpt-6.1-sol.
🤖 Generated with Claude Code