You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Problem — Reloading the editor (webview reload / Developer: Reload Window) clears the Preview tab: the .tex + .pdf you had open must be reopened by hand. The active file lives in the non-persisted ephemeral store (sessionPreviewFile), and the full open-tab set lives only in SessionPreviewTab's component-local workspace signal — both are wiped on reload, while sibling per-session UI state (open session tabs, reviewOpen, scroll) survives because it lives in the persisted serverGlobal store. Approach — Persist the preview open-paths list (+ active file) in the per-session SessionView structure, reusing the Persist.serverGlobal("layout") machinery that already survives reload. Repoint previewFile from ephemeral → the persisted store as previewActive; add a persisted previewPaths list; wire SessionPreviewTab to restore its workspace from that list on mount and mirror open/close back up. This is the #1398 wiring, landed in the persisted store so it covers reload as well as remount. Approaches Considered — (A) persisted SessionView store — chosen; smallest change, session-scoped for free, reuses the proven pattern. (B) VS Code webview getState/setState — a parallel persistence mechanism the app doesn't use for layout state; rejected. (C) opencode session.metadata (server DB) — stronger durability (survives full quit + fleet reconnection) but needs a server write per open/close; deferred as a follow-up on top of A. Scope — in: persisting the flat list of open preview paths + the active path per session, so reload/remount restores every open preview tab; restoring only when the user hasn't already opened something this mount. out: persisting the split-pane tree layout / zoom (that's the full state codec, #981); full-quit / cross-machine durability (a C follow-up). Assumptions — opencode.global.dat survives webview reload (proven: sessionTabs and sidebar width already persist through it). The Preview side-panel tab's open/active state already persists in sessionTabs, so the tab reopens on reload and its restored contents come from previewPaths.
Acceptance Criteria
Open a .tex and its .pdf in the Preview tab, Developer: Reload Window — both preview tabs come back without reopening them, active tab preserved.
Opening and closing preview files updates the persisted list (a closed file does not reappear after reload).
A different Amicode session starts with its own preview paths, not the previous session's (no cross-session bleed).
A persisted path whose file no longer exists renders the empty state on reload, not an error.
Existing within-pane / tab-switch survival does not regress; the retained-pool lifecycle is untouched.
Verification recipe
Deploy:scripts/rebuild_amicode_locally.sh --mode local, then Developer: Reload Window once to pick up the binary.
Basic: open .tex + .pdf in Preview → plain Reload Window → both restore. (Pre-fix: gone.)
Session-scoped: open file A in session 1's Preview, switch to session 2, reload → session 2 shows its own; back to session 1 → A still there.
Stale path: open a file, delete it on disk, reload → empty state, no error.
Unit:bun test .../session-preview-tree.test.ts — the open-paths round-trip invariant (list restores in order, active = last, re-open idempotent, close shrinks the list).
Key Decisions
Preview paths persist in the same serverGlobalSessionView store as reviewOpen/sessionTabs — not the webview state API, not a new store. Additive optional fields (previewActive, previewPaths); no schema-version bump (old data hydrates with them absent).
SessionPreviewTab restores from the persisted list before the previewFile effect re-focuses the active file (openPreviewPath is idempotent), and the up-sync is gated on restore so an empty pre-hydration set never clobbers the persisted list.
Keyed strictly per session — no cross-session preview bleed.
Threading the open-paths props must not recreate/remount the retained-pool views.
Prior Art
The reviewFile / reviewOpen persisted setters and the Persist.serverGlobal target in layout.tsx; createPreviewWorkspace(paths) which already accepts an initial path list.
Source
Part of #1252. Sibling to #1398 (in-memory tab-switch survival — this implements its wiring but in the persisted store), #1365 (active-state plumbing), #981 (full split-pane state codec).
Important
Problem — Reloading the editor (webview reload /
Developer: Reload Window) clears the Preview tab: the.tex+.pdfyou had open must be reopened by hand. The active file lives in the non-persistedephemeralstore (sessionPreviewFile), and the full open-tab set lives only inSessionPreviewTab's component-localworkspacesignal — both are wiped on reload, while sibling per-session UI state (open session tabs,reviewOpen, scroll) survives because it lives in the persistedserverGlobalstore.Approach — Persist the preview open-paths list (+ active file) in the per-session
SessionViewstructure, reusing thePersist.serverGlobal("layout")machinery that already survives reload. RepointpreviewFilefromephemeral→ the persisted store aspreviewActive; add a persistedpreviewPathslist; wireSessionPreviewTabto restore its workspace from that list on mount and mirror open/close back up. This is the #1398 wiring, landed in the persisted store so it covers reload as well as remount.Approaches Considered — (A) persisted
SessionViewstore — chosen; smallest change, session-scoped for free, reuses the proven pattern. (B) VS Code webviewgetState/setState— a parallel persistence mechanism the app doesn't use for layout state; rejected. (C) opencodesession.metadata(server DB) — stronger durability (survives full quit + fleet reconnection) but needs a server write per open/close; deferred as a follow-up on top of A.Scope — in: persisting the flat list of open preview paths + the active path per session, so reload/remount restores every open preview tab; restoring only when the user hasn't already opened something this mount. out: persisting the split-pane tree layout / zoom (that's the full state codec, #981); full-quit / cross-machine durability (a C follow-up).
Assumptions —
opencode.global.datsurvives webview reload (proven:sessionTabsand sidebar width already persist through it). The Preview side-panel tab's open/active state already persists insessionTabs, so the tab reopens on reload and its restored contents come frompreviewPaths.Acceptance Criteria
.texand its.pdfin the Preview tab,Developer: Reload Window— both preview tabs come back without reopening them, active tab preserved.Verification recipe
scripts/rebuild_amicode_locally.sh --mode local, thenDeveloper: Reload Windowonce to pick up the binary..tex+.pdfin Preview → plain Reload Window → both restore. (Pre-fix: gone.)bun test .../session-preview-tree.test.ts— the open-paths round-trip invariant (list restores in order, active = last, re-open idempotent, close shrinks the list).Key Decisions
serverGlobalSessionViewstore asreviewOpen/sessionTabs— not the webview state API, not a new store. Additive optional fields (previewActive,previewPaths); no schema-version bump (old data hydrates with them absent).SessionPreviewTabrestores from the persisted list before thepreviewFileeffect re-focuses the active file (openPreviewPathis idempotent), and the up-sync is gated on restore so an empty pre-hydration set never clobbers the persisted list.Constraints & Invariants
Prior Art
The
reviewFile/reviewOpenpersisted setters and thePersist.serverGlobaltarget inlayout.tsx;createPreviewWorkspace(paths)which already accepts an initial path list.Source
Part of #1252. Sibling to #1398 (in-memory tab-switch survival — this implements its wiring but in the persisted store), #1365 (active-state plumbing), #981 (full split-pane state codec).