Repository navigation
feat(documents): add visual LaTeX authoring and reusable templates - #353
yaacovcorcos merged 39 commits into
Conversation
Review update and direction — 2026-09-29
Thank you for the quick and thorough response to the first review. The source-fidelity work in 1. Recheck at
|
| Earlier finding | Now |
|---|---|
Paragraphs containing ~ could not be edited |
Edits are accepted, and ~ is preserved |
--/--- rewritten to Unicode dashes; \textit rewritten to \emph |
Both preserved as written |
| Multi-line paragraphs collapsed onto one line | Line breaks preserved |
| Adding a table row dropped cell formatting | \textit{A} survives |
| Table labels escaped as text | \label{tab:x_z} preserved |
| Insertions into an included file silently omitted root declarations | Refused instead of breaking the build |
The default table needed booktabs |
The default is now plain |
indexGeneration was a required contract field |
Now optional |
| MathLive loaded for Source-only users | The Visual view loads on demand |
| About 2,900 lines of unused PDF-overlay code, a duplicate revision store, and a personal-notes doc | Removed |
| The Source view used a separate editor | It uses the shared file editor again |
Still open
- The page-layout editor writes more than it changes. Changing only the font size on
\documentclass[11pt]{article}still addsletterpaper,\usepackage[margin=1.8in,letterpaper]{geometry},\setlength{\parindent}{1.5em}, and\setlength{\parskip}{0pt plus 1pt}, which pins the class-default margins and spacing. Only the setting that changed should be written. % scient-hidden-author:is still written into the preamble when an author is hidden. Scient state should not be stored as comments in the user's source.- The MathLive bundle patch remains. The choice of math input is now an explicit decision in the shared plan (see below), so please don't invest further in the patch until that is settled.
- Builds on save. The branch still changes the default from rebuilding on save to rebuilding only on request. That is a product decision, and it is tracked separately.
- Launcher files. See section 2.
2. Correction: the development-launcher changes
The first review listed the desktop development-launcher and backend PID-handoff changes under this PR's scope. They came from earlier commits on the #326 branch that this branch was built on; you did not write them. Those fixes are now handled on main by #377. Please remove these files from this branch; your Windows bundled-renderer default (scripts/dev-runner.ts and its note in local-dev-app-windows.md) can stay:
apps/desktop/scripts/{dev-app-process,dev-electron,electron-launcher}.mjsand their tests;apps/desktop/src/app/{DesktopConfig,DesktopEnvironment}.tsandapps/desktop/src/backend/{DesktopBackendConfiguration,DesktopBackendManager}.ts, with their tests;apps/server/src/desktopDevelopmentBackendPidHandoff.ts, its test, and its import inapps/server/src/bin.ts;- the launcher changes in
scripts/local-dev-app.mjs, its test, anddocs/operations/local-dev-app.md.
3. Direction: one document-editing system
The LaTeX editor is becoming part of a shared document-editing system with the Markdown editor. The plan is in the design record in #373 (docs/internals/scient-document-editing.md). It is still a proposal, and comments there are welcome. It builds on the accepted rich Markdown editor contract, which remains the rulebook for source preservation, sessions, verification, and performance budgets.
In short:
- One system, two formats. One document-editing system is developed through improvements to the Markdown editor and tested early against LaTeX, with no waiting until the end to see whether LaTeX fits.
- Two modes of one Scient editor. The header, toolbar, footer, menus, and common interactions are the same. The document canvas differs only where that helps the writer. Simulated pagination becomes an optional capability, and page positions come from the built PDF when its mapping is current.
- Several ideas from this PR are adopted for both editors: the footer, the Documents panel, the Insert menu, document checks (from Review), zoom, the symbol catalog, table presets, the shared table picker, and the keyboard scopes and writing-command list.
- Shared foundations, extracted through Markdown:
- one document session for every file editor, replacing separate draft and save paths;
- a format-adapter contract that verifies the smallest affected region, not the whole document on every keystroke;
- a floating object-editor layer;
- shared editor chrome.
- ProseMirror directly is the recommended base for document editors. It will be validated by a thin LaTeX path on the shared core before it is settled.
What this means for this PR now:
- It stays one PR. Splitting it is not the focus; quality is.
- Ownership. Yaacov sets the direction for the LaTeX work. You continue on it through concrete assignments, each with a bounded area, the shared interface to build against, and acceptance criteria. The first one will follow shortly.
- Where effort pays off. The LaTeX logic (the translator, construct coverage, layout profile, templates, symbol catalog) carries forward regardless of framework.
- Please avoid:
- new Tiptap-specific building blocks (React node views through Tiptap, or reliance on StarterKit behaviors), since these would have to move later;
- new draft or save mechanisms;
- changes to shared modules (the keyboard system, math input,
scient/writing/, the Markdown editor) without agreeing them first.
How this was checked: the branch's document-model functions were run on small inputs at abe28c1b3e, and the changed files were read. No visual review was done. CI has not run on this draft.
Hands-on review of the Visual editor@nattikahana, I spent a session using the Visual editor at First, what works well:
The numbers below are for discussion; please reply with them. Where to start: the small fixes marked (small fix). Items marked (after the architecture notes) touch how blocks are projected and saved. We're writing a short architecture note that will affect them, so please hold those until it's posted. Editing1. Equations with Any equation containing
2. Theorem, proof and remark bodies show a stripped preview and can't be edited (after the architecture notes)
3. Locked blocks point to an "Edit LaTeX" button that doesn't exist (small fix) Clicking the block does nothing either (
4. An outside change can delete the title on the next key press (small fix, please prioritise)
5. Editing an editable theorem or abstract rebuilds the whole block (after the architecture notes) Found by calling the translator directly, not yet through the app. A body edit re-serializes the block from its attributes (
Related, in the translator:
Rendering6. The Visual view should either render a block faithfully or show its source, never an approximation (after the architecture notes) Today there are three ways a block is shown: rendered, source (the grey block), and a
Page appearance7. Gaps before inline maths and Each formula and chip starts with about 22px of extra space. That's the paragraph's 8. Space after headings is about twice the space between other blocks (small fix)
9. Remove the underline under the title while editing it (small fix)
Top bar and header10. The paragraph-style button changes width, so the whole bar jumps (small fix) The button is as wide as its label: "Proof" and "Enumerate-Resume" have very different widths (
11. The paragraph-style menu mixes three kinds of things It holds about 35 entries:
Several names come from LyX and are unclear to most users. For example, "Address" and "Right Address" are
12. Status labels repeat each other and wrap (small fix) "Rebuild required" (
13. One Export menu instead of separate "Export ▸ Word" and "Export PDF" buttons Use the same Export menu the Markdown editor has in its More menu ( 14. The "Review before export" dialog can go Its first two checks cover this file only; the build already reports repeated labels and unresolved references across the whole document. The third check only finds Scient's starter text. It opens as a blocking dialog even when there's nothing to report. 15. Zoom field (small fix)
16. Pressing Update PDF makes the whole view jump (small fix) The panes have fixed sizes, so the likely cause is the header wrapping onto a different number of lines while building: a spinner, the label change, the Cancel button, and the stale chip going away. Recording the top of PDF building17. When the PDF builds: decided (updated 2026-10-01; the full statement is rule 6 of the architecture note) By default, typing doesn't request a build. The PDF updates when asked, or when the user has clearly stopped.
Who does what: we write the scheduler and the setting, and you connect the LaTeX surface to it once we have agreed the interface. Until then, builds stay explicitly requested, so there is nothing to build for this item now. Please don't add a separate scheduler in the branch. What is yours now is item 18, and Update PDF saying why when it can't run instead of staying disabled. 18. The PDF banner says "The latest build failed" when the PDF is only out of date (small fix)
Footer19. "N source-only blocks" opens the source of the block at the cursor, not a source-only block (small fix) It also switches to Split ( Dialogs20. Writing shortcuts: the title and inputs run to the card's edges (small fix)
Found in the code, worth checking
(after the architecture notes: saving and recovery will move onto one shared document session per file.) Ours, no need to build in this PRThese are shared with the Markdown editor, and we'll do them as shared work (#373):
Underlying causes, for contextMost items come from four patterns. The architecture note will address them:
Thanks for all the work on this. Happy to discuss any item here. |
Answer the design record's hard questions for the LaTeX Visual editor and say how the structural items from the #353 review should be built: what is shown, how edits are written back, how outside changes are adopted, undo, refused edits, saving and building, and interpretation context. Record three decisions in the design record: the owner's side owns the complete LaTeX persistence migration; one existing cross-file edit kind stays as a stated exception; and the build policy (nothing rebuilds while writing or reading, with an idle rebuild and a setting). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Architecture note, and an update to item 17@nattikahana, thank you for the two fixes ( 1. The architecture note the review promised is here: docs/internals/scient-latex-visual-architecture-note.md (part of #373). It covers how the structural items should be built. In short:
The table near the end of the note maps each review item to who does it and when. 2. Item 17 (when the PDF builds) is updated in the review above. Nothing rebuilds while typing. The PDF builds when it is opened and out of date, on Cmd+S while it is visible, on request, and once after about 45 seconds without edits or interaction with the PDF. Every build runs in the background and swaps in only when ready. Questions and disagreements are welcome, here or on #373. |
The request the #353 review and the architecture note refer to: a capability table for the LaTeX translator and the translator-level tests that back it. Editor- and saving-level tests, and the timing measurements, stay on the owner's side. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor request, and a request to realign with
|
|
@nattikahana, a short supplement to the hands-on review. We went through the translator again at One thing first: we pushed a small commit to your branch. How these were checkedEach case below was reproduced by projecting a small source, applying one edit through Cases that change the source in ways the user didn't ask for1. Formatting wraps every character. Bold on the word \textbf{H}\textbf{e}\textbf{l}\textbf{l}\textbf{o} worldItalic does the same ( 2. The same path breaks characters outside the basic plane. Bold on 3. A paragraph appended after an % main.tex % chapter.tex
Root intro. Chapter paragraph.
\input{chapter}
\end{document}appending a paragraph after "Chapter paragraph." produces, in \input{chapter}
Appended paragraph.The chapter file is unchanged, although it was the preferred destination. With 4. Changing a figure's caption rewrites the figure. 5. Editing a listing moves its options into the code. Changing \begin{lstlisting}
[language=Python]
print(2)
\end{lstlisting}6. Core maths commands add a package. Adding All six pass the round-trip comparison, because the rewritten source projects back to what the editor asked for. That is why the architecture note now asks for three checks (rule 2), and for an inserted block to name the file it belongs to (rule 7). Tests
One item that is oursThe change to shared maths input (a new blank equation inserts nothing where it inserted Statement bodiesItem 2 of the review (theorem, proof and abstract bodies shown with the commands stripped, and locked) turned out to be the most visible gap when reading a real paper. We would like a first step earlier than planned: show a locked body with its maths rendered, read-only. Making bodies editable stays where it was. Order we suggest
Saving, recovery and the PDF build scheduler stay with us, as before. The recovery repair mentioned in the note is in review on our side and we will propose it to you before it lands on the branch. Thank you for the two fixes after the review; the labelled-equation approach is the pattern the note asks the other blocks to follow. Reproduction file (10 tests; 9 fail at
|
|
@nattikahana, one more note, on a single topic: why so much of a real paper can't be edited in Visual, and what we think the fix is. Reading a paper in the editor, most of what gets in the way is the same thing seen from different sides: a theorem or an abstract locks as soon as it contains a formula, a paragraph with We wrote up the cause and a direction here: Editing inside blocks. In short:
It doesn't change the order in the earlier comments: realigning with This is a larger piece of work than anything else we have asked, so please read it as a direction to discuss, not a task list. We would like your view on the approach and on the split of work before you start; in particular, we agree the patch contract with you before step 0. What is locked today, measured at
|
| Content | Result |
|---|---|
Paragraph with bold, italic, inline maths, ~, dashes, a custom macro in maths |
Editable |
Heading, lists (nested, with maths), equations (labelled equation and align, cases, matrices), plain quote |
Editable |
Paragraph with \cite, \ref, \eqref or a footnote |
Editable around a fixed piece |
| Abstract, theorem, proof, description list: plain text | Fields editable |
| Abstract with italic or maths | Locked |
| Theorem or proof with inline maths, display maths, a reference or bold | Locked |
| Description list with maths | Locked |
Table: plain or bold cells, rules, p{…}, float with caption, tabularx, longtable |
Cells editable |
Table with maths in a cell, or \multicolumn |
Locked |
| Figure with one image, caption and label | Fields editable |
| Figure whose caption has maths | Locked |
Paragraph with an accent command, a % comment, \href, or an unknown command |
Source only |
A list with one such item, or with \item[a)] |
Source only |
Figure with two images or TikZ; center; minipage; \bibliography{…}; unknown environments |
Source only |
|
@nattikahana, thank you for yesterday's three commits. We went through What we measured as fixed
Three things to align1. Automatic PDF builds. Thank you for wiring opening the PDF, Cmd+S and save-before-build; those can stay as the interim. A manual build can still leave out unapplied input or an unsaved included chapter; we will handle those checks in our save barrier. One part doesn't: the build 2.5 seconds after typing stops. The decided default is that typing doesn't build (rule 6 of the architecture note); that timer is the opt-in "as I type" choice, which needs the setting. Could you remove the timed build for now and keep the rest? The scheduler with the setting, the idle rule and the save barrier across included files is ours and will replace Small things we noticed while reading it:
2. Recovery. The revision check on Restore helps, and these remain:
Our repair for these is ready on top of 3. Shared files. Exposing Edits that still rewrite source they didn't touchEach reproduced at
Step 0 of Editing inside blocks covers the first row: retained child ranges for lists and We keep your statement-body work. The order we would suggest: agree the patch contract, then step 0, then bounded unsupported pieces inside statements (one Smaller items
The two Markdown maths tests still fail; that fix is ours and is ready with the recovery repair. Realigning with |
|
The edit contract we said we would propose is written down: The edit contract. In short: the planner hands the file's session a list of exact patches and the version it planned on; the session applies all of them or none and says why. The code and tests are on #415 ( It is a proposal. Tell us what doesn't fit the planner and we change it before step 0. Two things are not in it yet and are listed at the end of the section: several files in one edit, and context revisions. |
|
Thanks for the new commits, and for merging main in. We went through What we saw working
Still open from the last review Our reproduction file gives the same results at this head:
The exact-source tests for these are not in yet. Two further source-preservation cases, both reproduced
Both come under the same rule as before: source an edit is not about stays byte-identical, and where that can't be done the edit is refused. Shared PDF reader Moving navigation and search into Tests
From our side
|
|
We pushed two commits to this branch, on top of
A small fix in the shared maths input. With it the two shared maths tests pass. Checks at this head
Three things we noticed on the way, all small
If you change the recovery code or the footer slot it sits in, a short note here is enough; we'll keep that part working with your changes. |
|
@nattikahana — Yaacov would like to go over where the editing commands should live in both editors (Markdown and LaTeX Visual) before more features are added to the top bar. The full list, command by command, with where each is today and a proposed home, is here: The proposal is one shared bar, |
…head a9403b2) into the bars pilot Conflicts resolved: - LatexVisualEditor.tsx: imports unioned; the candidate's recovery bar and the collaborator's symbol picker both stay in the footer; the collaborator's writing-row menus are taken as they are, and the pilot's decisions are re-applied on top (style and list buttons show the current choice, icons per heading level, Markdown's names, no Indent/Outdent entries). - scient-latex.css: both sides appended. - FilePreviewPanel.tsx: the candidate's session-aware file status kept. - ScientFileFreshnessControls.tsx: the collaborator's popover width variant. - docs/user/latex.md: the collaborator's guide with the candidate's recovery wording. - pnpm-lock.yaml: regenerated. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Brings claude/document-bars-pilot-main-20261003 (the reviewed bars pilot) onto claude/pr353-main-sync-20261003 (PR ScientFactory#353 aligned with main, with his newest work: references panel, macros, theorems, pagination). Resolution: the editor follows the pilot's writing row exactly (Undo/Redo · Text · Insert · Math · Lists · Document; formatting inside Text; Link in Insert, Cmd+K kept), hosted header, shared footer and find & replace; his features stay, with References under Document and his insert entries in Insert. Menu labels keep the no-trailing-dots rule. Document settings stays one card and gains his packages-and-macros summary at the bottom. Recovered work sits directly in the shared footer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@nattikahana This branch now holds everything in one place, as you asked. I pushed on top of your latest commit ( Before you continue: pull first ( What was added on top of your work
Your newest features are all kept: algorithms, TikZ, colour boxes, long tables, literal code, page layouts with running headers and footers, the editing target, compiled bibliographies, engine selection. Three things for you to look at
All of this was reviewed by Codex in several rounds before pushing. Web 10,321 tests, desktop and packages pass; server passes except items 1 and 3. 🤖 Generated with Claude Code |
…erging main Merging main added main's copy of the header button's move and recovery callbacks next to #353's; the unguarded copy let a new LaTeX document move from the header. Keep the Markdown-only one and a single recovery step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Selecting a formula, including one just inserted from the Math menu, prepares
its editor. Until it is ready, a document-wide listener swallowed printable
keys, so the first characters typed straight after inserting a formula were
lost ("x+1" became "+1"). Preparation got slower with the paging batch on a
cold start, which made this visible: the section-to-math test lost its first
key in about one run in three of its file, and never before the batch.
When the formula was selected without a click (inserted from a menu or reached
with the keyboard), characters typed while waiting are now kept in order and
typed into the field key by key once it is ready; MathLive's batch typedText
would process a backslash twice. A plain Backspace removes the last kept
character and never deletes anything in the formula. Composing keys are not
kept, and cancelled or timed-out admission discards what was kept. After a
click, keys are still not kept, as before: the click's caret and selection are
relayed to the field and kept text would race them.
Tests hold readiness and check that kept keys produce exactly what typing the
same keys into the ready editor produces (a command, brackets, scripts, spaces
and a corrected letter), that Backspaces delete nothing in the formula, that a
composing key and keys after a click leave the formula unchanged (Codex review
rounds 4 to 7). Known limit: Scient's environment completion (\beg to \begin{})
is not applied to kept keys.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
While an edit raced the page planner, a footnote's line could be placed on a page the plan had not drawn a sheet for, and positioning its note read a missing sheet and threw. The pass was abandoned with an uncaught error (about one run in ten of the Hebrew editing test, intermittently). A note whose page has no sheet now keeps its previous position until the next pass. The exact cause of the missing sheet was not reproduced with instrumentation in place; the Hebrew tests then passed in 20 of 20 runs without an error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under a loaded full-suite run, reopening a document was checked three frames after opening while its pages were still being placed (51 px; CI saw 48 px), and typed prose beside a display took longer than the 1 s default poll to publish. Reopening now checks where reading resumes once the pages are laid out; under CPU load in isolation it lands within 2 px both before and after. The prose poll waits up to 5 s. Test-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… count off Linux The reopening test scrolled to its reading position before the document's font had loaded and before pages were laid out, so it remembered a position in an unfinished layout; on CI the reopened document then landed 48 px away. It now scrolls once the font and pages are in place, as a reader does. Template 26 sets its Hebrew text in Arial, which macOS and Windows ship and Linux runners do not: there a substitute with other metrics lays it out to 5 pages instead of the PDF's 4, and measuring whether Arial is installed is unreliable (the Latin-only substitute reports it present). The PDF page count is checked off Linux; the sheets must match the plan everywhere. Test-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The document-closing test counted Chrome's benign "ResizeObserver loop completed" notice, which Linux emits more often, as an error; it now ignores only that notice. Test-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Linux CI the test changed the inserted matrix while its editor was still being admitted: the field was the hidden staged copy (admission pending, not focused), and edits to it were dropped, so the source never showed the spaced rows. Logged on Linux in draft PR ScientFactory#591. A user cannot reach the staged copy; keys typed meanwhile are kept by the admission. The test now waits until the field has focus before editing it. Test-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A formula's rendering lands in its shadow root inside a preview task, and the batch made those tasks user-visible priority. Nothing corrected the reading anchor until the next ResizeObserver delivery, so a cold open could paint one frame with the reading line moved by formulas finishing above it (14-102 px), and skipped blocks with stale size hints switched height in between. Queue the existing one-per-task microtask correction from completed preview and load events too, not only from resize delivery. Pending preview events are ignored; completions in one task share a correction. "formulas finishing above the reading area do not move it" failed alone since the batch and passes again. Benchmarks show no cost (300 pages and the thesis, interleaved runs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A correction measured against the anchor taken before a deliberate scroll (a restored reading position, the caret followed) undid that scroll whenever layout or a formula published before the next frame took the new reading line. On Linux the reopen restore landed 47 px off this way; the correction from the previous commit can run in that window too. The anchor records the scroll offset it was taken at. When a correction finds the area scrolled since, the reading line is a new one: drift of the old line is corrected only when reading moved down (that content lies above the new line too); a move up corrects nothing, since it cannot be told apart from a range clamped by content shrinking above; and the new line is taken at once. Content changing between the lines, or above both on a move up, in that same frame is absorbed; it previously undid the whole scroll. The new test covers a scroll then growth above, in the same task and from the scroll event, and a clamp at the end; it fails without the change (scroll undone) and with a rebase-only variant (clamp moves the text 208 px). It waits for layout to settle and measures text rather than the paper, shrinks the frame itself as the stage observer does, and checks the clamp only when text is in view at the end: Linux CI's fonts can end the document on a blank stretch of the last page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
e261c9d to
6d239c6
Compare
|
@nattikahana this branch ( Please don't pull or push this branch as it is in your local clone. A plain git fetch origin # the remote for your fork
git switch codex/source-derived-writing-canvas
git branch backup/pr353-before-rewrite # keeps your local state, just in case
git reset --hard origin/codex/source-derived-writing-canvasIf you have commits that were never pushed, cherry-pick them onto the new branch afterwards ( 🤖 Generated with Claude Code |
Bring ScientFactory#353 up to current main, including the T3 alignments ScientFactory#593 and ScientFactory#607 (React Compiler migration, browser test project), ScientFactory#596, ScientFactory#601, ScientFactory#603-ScientFactory#606, ScientFactory#608-ScientFactory#610 and ScientFactory#567. Composition: - Workspace writes: ScientFactory#353's mutation service keeps main's known-workspace boundary and Git-folder write denial. Every write path (write, create, binary write, delete, rename, retained replace/remove, inspect) is authorized first, and the mutation lock re-checks protected paths on each non-history resolution. Test layers provide KnownWorkspaces. - Web: conflicted files follow main's React Compiler patterns (no manual memo, refs synced in layout effects, render-phase resets, effect events, try/finally in module helpers) with ScientFactory#353's behaviour on top, including ScientLatexSurface, the PDF reader, the file preview panel, save coordinator, workspace refresh, Pandoc tool and source PDF preview. - Tests moved to main's browser project are ported (createRoot, async act); ScientFactory#353's deletions of the Markdown rename button and its seam test are kept. - pnpm-lock.yaml regenerated with pnpm install. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop manual memoization and render-time ref access in the editing target, table selection, source recovery, document compiler, reference state and pinch-zoom hooks; port their tests' render captures. The PDF reader's Save Copy keeps calling props.actions.saveCopy, which its seam test checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… React Compiler Main lints every web file against the React Compiler rules: no manual useMemo/useCallback, no ref access during render, no synchronous state updates in effects. Bring the remaining LaTeX authoring files in line: - Drop manual memoization from 22 controls and dialogs; keep a stable identity with useStableCallback only where an effect or child needs it. - LatexVisualEditor: update handler refs after commit, track the rendered title and checkpoint as state, measure fit width from the DOM, and derive source notices from live editor state. - LatexReferencesPanel: keep `apply` and `updateFile` stable so publishing the bibliography catalog cannot re-render the panel in a loop. Also align two tests with main after the catch-up: the asset URL test no longer expects `waiting: false` (main only sets it while refreshing), and the workspace refresh test keeps the real atom library in its mock because the refresh hook now reaches the app atom registry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The zoomed paper is scaled with a transform, so its resize observer never sees a zoom change. The frame used to resize because its sync callback was rebuilt for every zoom; as a stable callback it no longer is, which left zooming out with blank scroll space below the document. Sync on zoom explicitly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
useStableCallback infers its argument tuple, so a parameter typed only by its default value became unknown and failed the web typecheck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without useMemo the editor's command context changed identity on every render. The layout effect that refreshes math reading context depended on it, so it re-ran while a math field was being admitted and cancelled the staged editor before <math-field> mounted: clicking an equation no longer opened it. Refresh only when the preamble (mathSetupSource) changes, which is everything the context and its macros derive from. Also give the workspace mutation test the retention settings ScientFactory#353 made required; main added the test without them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The refresh hook now reaches Markdown persistence, which imports confirmProjectFileQueryData and setProjectFileQueryData. The test's narrow mock lacked them, so the file failed to load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Han column cut: CI now installs Playwright's system dependencies only when needed, so the CJK fallback font can differ. Forty short paragraphs could then all end exactly at column boundaries. One continuous Han paragraph forces a cut between Han characters on any font; the test still requires that cut and no drawn hyphen. - Native word selection: wait until loading ends, fonts are ready, math previews have published and paged layout has settled before double-clicking, and click the word's own fragment rather than its union box, which a wrapped word can centre over unrelated text. All selection, mapping, scroll and handoff assertions are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ublish Since #353 the applier writes only through native file publication and refuses elsewhere, so on Linux CI both review-to-applier tests failed with WorkspaceFileMutationUnavailableError. They now skip unless nativePublicationHost(), as the applier's own suites do. The file-layer agreement test treats an unavailable publication as "not refused": the Git folder refusal comes before any write. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>













Landing state (19 October 2026)
This branch was rewritten on 19 October 2026, at the owner's request (the collaborator was informed beforehand), so it can land as it is. Its earlier history contained merges of non-main branches, which the upstream provenance check rejects. It is now 31 linear commits on
main(e19ef4a0b2). The original 364 commits are kept unchanged under the tagarchive/pr353-history(e261c9d600). This replaces the interim landing PR #589, which is closed.The work itself, in three layers (each typechecks on its own):
feat(desktop): the native file-publication helper, its build and packaging, and its desktop bootstrap.feat(documents): visual LaTeX authoring and reusable templates, with the server, shared packages and web editor together.docs: user and internal documentation and the seam manifests. The four generatedthesis-responsiveness-*.htmlreports (27k lines) were left out; they stay in the archive tag.Then 28 fixes, each one concern with the test that proves it, for what the paging batch broke or left untested:
\paragraph) stay on their paragraph's line.\maketitlespans both columns.The final code is identical to the state verified on #589: 13 Codex review rounds, all LaTeX layout tests, all 13 required CI checks green, and benchmarks on the owner's thesis and 300 synthetic pages (no slowdown from the latest fixes).
Known limits, to address after landing:
\includeonlyinside\iffalse, and a second\inputon one line when saving a personal template.LatexVisualEditor.tsx(about 10,600 lines) should be split into modules.Before marking ready: a Windows save test (collaborator) and a hands-on pass in the dev app (owner).
LaTeX documents need a writing surface that stays connected to editable source, coordinated saving, and the compiled PDF. This PR adds a source-derived, paged Visual editor alongside Source, PDF, and Split, plus document creation and reusable templates.
Visual supports included chapters, scientific structures, references and bibliography, tables, figures, contextual editing, and source-preserving fallback for unsupported LaTeX. Local edits update immediately; compiled PDF remains authoritative for TeX-dependent typesetting. Personal templates retain included source and bibliography files. Compatible renames preserve active editors, source undo, recovery, and revision checks.
The writing toolbar and contextual footer preserve the innermost editing selection across menus. Nested math supports stable slot guides, centered empty-argument carets, bracket insertion, portable color export, current spoken labels, and the shared Cut/Copy/Paste/Select All context menu. Hebrew and mixed-language rendering use source-derived language, fonts, direction, and direction-aware tables, statements, and footnote separators.
Split selection and navigation
Double-clicking Visual or PDF reveals source only in Split and preserves ordinary word/cell selection. Each pane retains its own cursor and selection; the source selection remains until Source interaction, which also cancels delayed navigation. Returning to Visual or PDF preserves a manual source selection. Navigation uses native source selections instead of a persistent whole-line overlay, and the PDF gesture hint popup is removed.
Visual maps authored ranges inside table cells, captions, title fields, footnotes, description items, literal code, figures, framed content, and matrix/cases/aligned-equation cells. Native selection endpoints take precedence over stale pointer coordinates. Verified PDF word selections refine SyncTeX's mapped source line; ambiguous results retain line-level precision. PDF navigation retains Yaacov's compiled-source revision and freshness checks, including target session admission and cancellation of stale queued reveals.
Visual selections reuse the shared Ask in chat action. Read-only snapshots expose selected content, geometry, source ownership, and revision through the existing selection system. Citation reopening verifies the captured mapping. Shared source/chat support from #519 is merged into main and included here; there is no pending merge-order dependency on that PR.
Editing, saving, and reading
Markdown and LaTeX share revision-aware saving, retained recovery evidence, and file-version controls. Native Visual edits use lossless source edit plans. Guarded atomic publication, fresh compiler outputs, and captured-revision PDF export checks are retained.
Documents settings provides Auto-compile, On save (default), and Manual compilation modes. Automatic mode waits for settled saves and a pause in editing; explicit save/rebuild flushes pending edits. Optional compiler installation preserves the working default. AI builds preserve an already-open document's view and reading position without reactivating background tabs.
Visual prepares complete pages before revealing them, retains reusable geometry/formula results within the shared estimated 24 MiB budget, and protects active editing. Completed passive reading DOM is retained within a separate 64 MiB admission estimate, without an independent block-count ceiling. Equation activation keeps passive ink and numbering visible until the connected MathLive input has painted stable ink, then transfers focus while respecting newer user intent. Page remounts use a paint fence and preparation spinner, with five-second fallback/Retry. Worker preparation, bounded active math inputs, deferred mounting, interruptible pagination, incremental geometry, source columns, and medical-template content layouts are included. Visual and PDF share horizontal fit/scroll behavior.
Synchronization and verification
Published head
5f6342e468includes alignment commitb87625d49d, which merges ScientFactory main84a7e2663binto the PR's prior head1fb52333c0. All existing editor and contributor ancestry is preserved; no rebase or force push. The eight incoming commits merge cleanly. The three overlapping files (UPSTREAM.mdand the packaging script/test) preserve both native publication payload support and main's Windows-only WSL package exclusions.ResizeObserverrule inlatexVisualPaginationExtension.ts, also present atdcac0f447.Remaining qualification gaps include broader lint/full-suite failures, 21 previously reproduced Visual source-transaction unit failures, native acceptance for scrolling and every compilation mode. Complex macro/package layouts retain exact-source fallback; cross-file selections require separate quotes. Rapid undo in active math and the imported parser limit beyond ten matrix columns remain known limits. Personal templates do not collect every figure, logo, or local package dependency.
Existing synthetic matrix editing evidence, not fresh qualification of this head:
matrix-source-roundtrip-demo.webm
Documentation impact: Updated —
docs/user/latex.md,docs/user/export-conversations.md,docs/internals/scient-latex-visual.md,docs/internals/scient-latex.md,docs/internals/scient-latex-visual-authoring-proposal.md,docs/internals/scient-pdf-reader.md,docs/design/editing-commands-placement.md,docs/operations/local-dev-app.md,docs/reports/editor-computer-use-stress-20261012.md,docs/reports/latex-reading-retention-20261013.md, andUPSTREAM.md.Implementation and synchronization: GPT-6.1-Sol through Scient's Codex harness; original contributor history retained. The PR remains draft with auto-merge disabled.
Declaration-scanner repair
Published correction:
7ec809b3f843b65479b5f71e0e4a649890ddd552, on top of8474d9d8b2. The exact four-file delta is selectively integrated fromf70edd24d6; its stable patch ID is unchanged. No other shared DocStart work was staged or included.Comment/newline trivia before declaration stars or unbraced names now uses the same bounded trivia reader as argument scanning.
DeclareDocumentCommandis recognized, so unused replacement text containingbegin{comment}no longer hides the actual document body. The previously reported declaration-scanner blocker is resolved.Current integrated correction: 21 focused unit cases pass, covering the full lexical suite and mounted body edit/undo/exact redo; 3 Chromium keyboard cases pass, covering typing, keyboard undo and exact redo for all three declaration forms. Whole web typechecking, four-file formatting, focused lint (two existing warnings), brand check and whitespace checks pass. The broader mounted-editor run was stopped in favor of the bounded regression checks; it is not claimed passing.
Standalone owner evidence covers 182 unit and 24 Chromium cases on its isolated snapshot. The complete suite, build and desktop smoke were not rerun for this correction; broader qualification limits above remain in effect. The review app was not restarted and the PR remains draft with auto-merge disabled.
Visual preparation efficiency and cold-scroll repair
Three focused commits are delivered on top of the scanner repair:
e35dbd5edbpauses idle cache admission at capacity, resumes on released space, uses constant-time background-first LRU, and retains terminal model/context fallbacks for oversized formula keys and explicit Retry.2c04471a6eretains one source anchor through cold preparation, fences same-top navigation/selection/source changes, reuses compatible compact top-level paragraph geometry, and reuses empty detached local measurement hosts.1fb52333c0coalesces completion reconciliation, targets pending page invalidation, distinguishes mounted readiness from reusable cache availability, and keeps headers, footers and page numbers outside content-area masks.Only the frozen 16-path incremental slice is included; current PR changes and the shared
observeResizeintegration adapter are preserved. No shared DocStart staging, app lifecycle, native build or user-document action was performed.Integrated delivery qualification: 48 Chromium cases pass (47 page/viewport/opening/pressure/snapshot/local-measurement cases plus the original large-scroll stress case); 25 focused unit cases pass (13 cache/font/retention/preview cases plus 12 pagination cases). Whole web typechecking, owned 16-file formatting, whitespace checks and production web build pass. Scoped lint remains red on two unchanged baseline raw
ResizeObservercalls inlatexViewport.tsandlatexVisualPaginationExtension.ts, with two warnings; no new raw observer is introduced by this slice.The previously reproduced 443px cold-scroll displacement is resolved in the integrated automated check, with its original one-pixel assertion unchanged. It is removed from the current known-failure list. This evidence does not establish every-hardware/native scrolling acceptance, native byte-changing persistence or compiler execution. The historical broader Visual unit gap and other qualification limits above remain disclosed; the complete suite and desktop smoke were not rerun.
Latest main integration qualification
Main alignment commit:
b87625d49d535d9afd3a3319d5e1f1258d7b23db, with parents1fb52333c0and84a7e2663b. Main was rechecked after push and remains at that revision. The merge imports Antigravity lifecycle/auth ownership and WSL runtime packaging/permission corrections; no LaTeX renderer source changed.The review app and shared DocStart working tree were left unchanged. This merge was checked in the isolated delivery checkout. Full repository tests, whole lint, new desktop smoke, actual Windows/WSL packaging and live provider/native document acceptance were not rerun; earlier broader editor qualification gaps remain disclosed. Draft status and disabled auto-merge are retained.
Mounted reading retention and equation handoff
Delivered on top of the aligned main snapshot:
2e856f1f9aretains completed passive DOM under a 64 MiB estimated admission budget, including idle completions and compatible cached blocks. Source, text, attributes and formula shadow markup contribute to the estimate; visited views take priority. The separate reusable cache remains 24 MiB.1116b4821fkeeps original reading ink and numbering visible until stable painted MathLive readiness, then transfers focus without disconnecting the custom element. Pending input protection, identity/context/source/selection/readonly cancellation, newer focus intent, deadline and local Retry are covered.5f6342e468records the policy and bounded qualification, including the report-only format correction.Only the frozen 18-path incremental slice and its report-format patch are included. Current PR source, resize adapter and MathField accessibility/context-menu/selection changes are preserved. No shared DocStart index/HEAD/source edits, diagnostic files, native builds, app lifecycle or user-document writes are included.
Integrated qualification on this snapshot: 59 Chromium cases pass and 5 fail out of 64; the five failure titles match the supplied font-correct pre-slice control exactly, with unchanged assertions and no additional failure titles. Passing checks include inline/display typing and undo, held readiness, pending input protection, cancellation, Retry, newer focus intent, accessible labels, retention/return behavior and the unchanged original one-pixel scroll assertion. 15 focused units pass. Whole web typecheck, scoped 18-file formatting, whitespace checks and production web build pass. Scoped lint still reports the unchanged raw
ResizeObserverinlatexViewport.tsplus four existing warnings; whole lint is not claimed green.The five existing browser failures concern display-whitespace prose input, plain/mixed-font local layout, prose input beside title/statements, and structural editing under a fallback overlay. They remain qualification gaps, alongside the earlier broader Visual unit gap. Full repository tests, native saving/compiler acceptance and live acceptance of this exact pushed head were not rerun.
The owner's independent 104-page reading surface and measured retention evidence are recorded in the bounded retention report; those observations qualify that separate source snapshot, not native acceptance of this pushed branch. Memory figures are admission estimates, not physical RAM or total heap. The review app remains available; draft status and disabled auto-merge are unchanged.
Clipboard source preservation
Copying a LaTeX selection containing references, citations, links or footnotes now preserves supported commands in the text clipboard instead of dropping atom nodes. The extracted helper shares the source adapter's command admission, retains plain/math/table behavior, and keeps normal cut/paste/undo ownership.
Validation at
d9464132e6: 150 focused units and 15 Chromium cases pass, including browser Copy/Cut/Undo shortcuts, readonly and nested selections, Hebrew roundtrip/reopen, 2,000 command atoms, and 30 no-math copy/paste/undo cycles. Whole formatting/lint and combined build pass; 46 type tasks are covered after two isolated setup/resource retries; isolated desktop launch smoke passes. Full recursive tests remain red outside this scope, and two representative existing editor failures match the unmodified base; the broad affected-editor rerun was interrupted after stalling. The smoke verifies launch only, not native clipboard/IME acceptance. DocStart and its live source/profile were untouched.Documentation impact: Updated
docs/internals/scient-latex-visual.md. Implementation/review: Codex harness, gpt-6.1-sol.Renderer and pagination follow-up
Updated in
e261c9d600d504833bd05cf822243cc21ba669a4: renderer coverage and PDF-calibrated typography, mixed-column/long tables, image crop/rotation, landscape pages, paging reuse, selection and typing-recovery improvements. The legacy dashed PAGE BREAK marker is removed in every layout state; authored page commands remain source-backed flow controls.The integration preserves the existing main merge and integration fixes. Shared recovery storage retains the reconnect-aware transaction helper and adds the Visual input stores. Seven unrelated dirty local files were excluded.
Prior isolated browser comparison: thesis 13/13 pages; heavy template 54/54 pages, all 69 photo instances loaded, no source fallback blocks. Exact float placement and page-spanning frame borders remain approximate; TeX drawings require explicit preview. These are prior comparison results, not a fresh acceptance run against this integrated head.
For this delivery, formatting, focused recovery-code lint and diff-whitespace checks passed (lint retains existing schema-hoisting warnings). Test suites and full integrated desktop checks were not run, following the owner's test-run instruction. Review template 29's cropped/rotated gallery, landscape sheet, repeated longtable bands and final-row edit; then check cross-environment selection, typing/undo and save/reopen.
The earlier fork review PR contains the detailed implementation, discarded approaches and remaining qualification checklist. Its old delivery/base instructions are superseded: the code is now included directly in #353.