Skip to content

Dockview saved-layout contract

Chris's decision on 8 September 2026: converge on one Dockview format before production. Old staging/test panel arrangements may be discarded. Do not maintain parallel v1/v2 layout slots for rollback. This decision concerns layout preferences only; study answers, comments and review data must never be cleared or migrated by this work. Keep the existing separate-window mechanism initially.

Stored format and scope

The existing per-reviewer workspace settings collection remains the owner. Each reviewer has separate screening, annotation and combined capability slots. The sole writable envelope is version: 2, dockJson (serialized Dockview layout JSON), sourceMode, optional sourceBounds, sizingMode (content or viewport) and customHeights (boolean). Missing sizing fields mean automatic content height. Explicitly saved custom heights reuse the dimensions in dockJson; they apply only in content mode. Obsolete arrangement/order fields are ignored on database reads and are not part of the new contract. Live renderer parameters and Angular templates never enter the payload. Optional string titles are intentionally retained as standard Dockview display metadata; the client regenerates them from the allowed panel IDs on capture and restore, so old labels never override current native headings. Node sizes are non-negative layout hints (zero is allowed in engine snapshots); positive grid dimensions and measured runtime panel minimums determine the usable restored geometry.

GET omits obsolete or invalid preferences, so the client displays defaults. Nothing is deleted in bulk or rewritten during a read. Automatic layout saving atomically replaces only the selected capability slot. Reset uses DELETE api/account/review-layouts to clear the account layout map, including at narrow widths, without clearing behavioral review preferences. Its Undo restores the captured valid capability layouts; a reset failure keeps the current arrangement. Other capabilities, reviewer profiles, answers and comments are untouched. Old clients cannot write their obsolete layout format; saving requires the Dockview client. The non-Dockview workspace therefore offers session-only arrangement and source controls without a Save action; it cannot overwrite a saved Dockview layout.

The API validates a 64 KiB JSON ceiling, bounded tree depth/dimensions, allowed renderer keys, one occurrence of each capability panel, group/active-view consistency and source-only floating groups. Native popout and edge groups are not accepted in this format. Floating positions are serialized in top-left coordinates of the application floating layer below navigation, independently of the docked grid. Earlier grid-relative positions remain valid and are clamped into the available application area on restore. The authenticated active investigator remains the only identity used for read/write.

Runtime behavior

The workspace loads its capability slot when reviewer/capability resolve and cancels requests when that scope changes. Invalid, missing or incompatible preferences use fresh defaults. Load failure offers Retry or Use defaults; save is disabled until a layout loaded or defaults were explicitly chosen. Save failure retains the current arrangement for retry.

Restoration reconstructs renderer parameters from live templates and uses reuseExistingPanels: true; layout restoration and defaults must preserve dirty answer/comment components. Restored arrangements use the existing user-defined-arrangement state so late panels cannot overwrite the chosen arrangement. Floating source bounds are clamped against the current container and navigation toolbar.

A saved separate-window preference does not automatically open a popup. The source stays available in the main page and an Open study source window button invokes the existing coordinator from a user gesture. The Separate windows menu additionally opens live Dockview panels and tab groups, as described below.

Delivery

The API must accept this contract before a client writes it. This PR changes the contract and runtime together but does not deploy, activate flags, delete documents or migrate review data. Staging/preview acceptance remains distinct from local validation. Disabling Dockview or using an old client may show default layout preferences, which is explicitly accepted for these unreleased layouts.

Application space and panel headers

The default workspace grows with the selected panels' content and uses page scrolling. A separate Fit to screen action gives the workspace a finite viewport height with panel scrollports. Vertical divider resizing in content mode retains custom heights and permits scrolling inside shortened panels; Use defaults restores automatic content sizing. These preferences are saved with the layout. Window resizing and navigation height changes update geometry. Floating Study source uses Dockview's overlay across the application viewport below navigation, independent of the docked grid, and remains a Dockview group.

The existing panel headers retain their identifying title and Material icon. Dockview's engine-owned tab container moves inside the active native header; the empty external header is hidden. A single panel keeps its original title, while a grouped panel exposes the Screening/Annotation icon-and-label switcher inside that same header. Group switching works outside rearrangement mode. Rearrangement reveals move grips and menus. Moving the tab DOM preserves the engine's drag/keyboard listeners and does not recreate Angular form views.

Native headers remain sticky. Annotation actions and category navigation form a compact sticky region below the native header. Screening retains its decision footer after the criteria. In automatic content mode these regions follow page scrolling within their panel; in fit/custom-height mode they follow panel scrolling. Minimum heights measure the rendered sticky header/footer regions, including wrapping, plus a usable content allowance.

Dividers are transparent at rest and visible on hover, focus, or rearrangement; their native pointer and touch hit areas remain intact.

These corrections remain behind stageReviewDockview; no additional flag is needed.

Live panel and group windows

Behind the existing stageReviewDockview flag, Separate windows opens Screening, Annotation or Study source individually, or the selected panel's complete tab group. Dockview moves the existing Angular views into a same-origin static window shell. It does not bootstrap a second application, create another session, or copy answers. The opener remains the sole save authority; ordinary draft, comment, permission and navigation guards still apply.

The child windows inherit application styles. Panel-scoped document/overlay dependencies follow the view's owner document so menus use the child window. Closing a child or choosing Return panels to main window restores its live views; deleting a tab cannot dispose a review panel. Reviewer, study, session or capability changes revoke open/pending windows, and reset/restore returns them before changing layout. A blocked popup leaves the draft mounted. Opening a native source group closes the legacy source coordinator to prevent two competing source windows.

Native windows are session-only placements: Automatic layout saving pauses until all panels return, including pending popup creation. Pending edits and sizing changes remain queued and save after the final panel returns; changing reviewer context or restoring a layout discards the old queue. The version-2 storage contract still rejects native popout groups, and browser windows are never automatically reopened on reload. This slice changes no database schema. Persisted multi-window geometry is a later enhancement.

Compact workspace controls

The Layout icon renders in the existing stage header via a workspace-owned template. It opens sizing, rearrangement, persistence and reset actions without reserving a toolbar row. Layout feedback uses Material snackbars. Native title nodes sit inside the engine-owned tab row after the left drag grip; they return to the native header when grouped or disposed. Header rows size to their controls and wrap grouped tabs, while fit-mode content retains its independent scrollport. These presentation corrections use the existing Dockview flag.

The review shell forwards the annotation form’s required-answer count to the Annotation tab indicator. It also passes the workspace’s effective sizing mode to the top action bar: Fit contents keeps actions and categories sticky together, while Fit to screen uses the panel’s scrolling body.

The Layout menu’s More review preferences entry opens the shared preferences dialog with effective sizing (including temporary maximise), and maps its choices through setSizingMode so bounds, custom-height clearing and persistence stay consistent.

Repository persistence tests use valid version-2 Dockview layouts. The preferences/reset isolation regression verifies the complete replacement layout, including source bounds, sizing mode and custom heights, remains intact when preferences are reset; legacy arrangement fields are not part of this contract.