One recovery worker and store serve every open document. Each document
keeps its slot (record id, revision, timer) and is ticked in place, parked
or active. Closing a document deletes its copy, Don't Save when quitting
does too, and a clean exit covers every open document. File > Recover
lists only copies no open document keeps; Restore opens a copy beside the
open documents or in place of an untouched blank one.
The desktop window follows the session's active document. What the window
keeps per document (AutoSave's file, comment drafts) is parked while
another document shows and comes back with it; everything about the page
that was shown (dialogs, menus, drags, composition, status, caches keyed
by revision) starts afresh. The page's scroll area is per document, so
switching back finds the page where it was left; zoom is in the session.
- View › Window › Switch Windows lists the open documents (active marked,
unsaved dotted) and shows the one chosen (view.switchWindows).
- New, Open, the mailings and personal templates open beside the open
documents and no longer ask about unsaved changes.
- File › Close shows the next open document; after the last one the
window shows no page, as before.
- Quitting asks Save / Don't Save / Cancel about each document with
unsaved work, showing it; Cancel keeps the app open.
- UI requests tagged for a document that isn't shown never act on the
shown one: theme changes apply, Close closes that document when it has
nothing unsaved, the rest are dropped.
- Read Aloud highlights and follows only the document being read.
- A late Save As answer shows and saves the document it was for.
- Untitled documents are numbered in the interface language.
- MCP: execute, batch, type_text, select_text, get_text, inspect_document,
render_page and save_document take an optional doc (an open document's
id); the headless server runs them through Session::with_document and
the bridge passes doc to the app. New list_documents tool; new_document
replies with the new document's id. Tool descriptions and the server
instructions say that file.new and file.open open another document.
- Control channel: engine.execute, document.inspect and ui.render take
doc and work on that document while the window keeps the active one;
file.close on an addressed document refuses unsaved changes unless
forced; ui.* commands need the document on screen. ui.inspect reports
document and documents. Unknown or malformed ids are errors.
- CLI run starts with one open document; help and docs describe how
file.new, file.open and view.switchWindows work in a run.
- docs/mcp.md and docs/control-protocol.md describe document ids and doc.
One session holds several open documents. The active document stays in
the Session's own fields, so commands and the UI keep working on it; the
others are parked as DocState values and swapped in field by field
(std::mem::swap, no clones or relayout). Session and DocState are
destructured exhaustively, so a new field must be classified as per
document or shared before it builds.
- Session::documents, activate, add_document, close_document,
is_untouched_blank, with_document, find_open, is_open; DocInfo.
- Document ids come from a process-wide counter.
- file.new opens beside the open documents; file.open replaces an
untouched blank document, opens beside the others otherwise, and
activates a file that is already open ("alreadyOpen": true).
- file.closeDocument {id?, force?} closes a document without a window
(refuses unsaved changes unless forced); file.close is unchanged.
- view.switchWindows {id?} lists the open documents or activates one.
- Envelopes, Labels, Finish & Merge and New from Template open their
result as a new document; the main document stays open, with no undo
step for the command.
- Each document keeps its own recovery worker and copy; Read Aloud
readings name their document; with_document tags UI requests with the
document they came from.
crates/ui-egui/src/backstage.rs: #3125's t.nav fill kept, without the recovery black. Docs: status entries prepended to main's lines; the recovery paragraph placed after the status line.
i18n: registry holds 27 languages (sl after nl, da, ro); audit.rs and the Polish test list sl beside pl and ro; tests: both sides kept. Docs: language counts and lists name ro, sl, nl and da; status entries prepended to main's lines.
ROADMAP.md: the PR's status entry prepended to main's first status line. docs/parity-checklist.md: main's side, regenerated after the merges. ko.tsv: union.
crates/ui-egui/src/backstage.rs: t03's bidi_display on the Recent names over t09's borrowed name/path. people.toml: union. Tests: both tracks' tests kept whole. Docs: status lines combined, rows unioned or word-merged.
docs/gaps.md row 4: one row (t06 had kept a second, older copy of it); t05's #1840 and t06's #2964 clauses both in, main's #2963 clause kept. docs/recovery.md: t06's retry sentence with t01's base64 size text. Test files: both tracks' tests kept whole.
crates/pdf/src/lib.rs: t01's vector_text kept before t05's watermark (box area signature). Test files and canvas.rs tests: both tracks' tests kept whole. Docs: status lines combined, rows unioned or word-merged.
crates/docx/tests/fixtures.rs: union, keeps main's shape-gradient test and the PR's band-size tests.
ROADMAP.md, docs/file-format-parity.md: main's status lines with this change added to the newest; log rows from both sides in date order.
crates/ui-egui/src/i18n/{de,et,ja,pt-br,sr,sr-latn,uk,zh-hans,zh-hant}.tsv: union by key, no duplicates.
docs/localization-parity.md: main's status line with this change added; both progress-log rows.
docs/file-format-parity.md: main's status line with this change added; both progress-log rows, this one first.
docs/localization-parity.md: main's status line with this change added.
crates/formats/src/odt.rs: StyleInfo keeps both cell_valign (#2416) and column_width.
ROADMAP.md, docs/file-format-parity.md, docs/gaps.md: main's status lines kept; the PR's log rows added.
ROADMAP.md: status line once (this change first, then main's); progress-log entries and history rows union
docs/file-format-parity.md: status line once; history rows union in date order
docs/gaps.md: status line once (this change first, then main's)
ROADMAP.md: main's status lines, with this change added to the newest.
docs/file-format-parity.md: main's status line with this change added; PDF export row keeps main's outline note and adds the lam-alef note.
crates/metafile/src/lib.rs: re-export both TextLayout (#1915) and crop_window.
ROADMAP.md, docs/layout-parity.md: main's status lines kept; the PR's log rows added.
ROADMAP.md: status line once (this change first, then main's); progress-log rows union in date order
docs/file-format-parity.md: status line once; VML row merged word by word (main's #1500 fill text plus the PR's signature-line text)