Replacing a page from a host accepts a spread on its own, and the Page panel's Type tells the truth.
Replacing a page with just a spread. A host replacing a page's contents can now send the
spread by itself — the spread object, or a list of spreads — as well as { "spreads": [ … ] }.
A single spread used to be turned down with "the payload carries no spreads". The same rule still
applies to every form without definitions: each colour and image it uses must already be in the
document.
The replace report names the right spread. pages_replaced now gives the container_index
the host passed in. It gave the spread's internal id instead — -1 for a spread created in code —
which could not be passed back to any other call.
The page's Type says what the page is. In the Page panel, Type now reads Single, Spread, Stacked or Cover. It was a menu offering "other", "single" and "spread", and it showed "spread_horizontal" for an ordinary spread. Choosing "spread" on a single page doubled its width into a spread, but choosing "single" on a spread left one page twice as wide. Whether a page is single or part of a spread follows from its pages, so it is no longer chosen here: add or remove pages with the Page menu instead.
c366894 — the replace fixes below.fix/replace-report-container-index (PR #157): classify() in pagereplace.ts wraps a
single wire spread (elements and pages, no spreads) or a bare array into {spreads:[…]}; the
manifest precondition is unchanged. place_page() takes the caller's container_index for the
report instead of target.id. Browser suite run_page_replace_tests(): 26/26. The same PR runs
vitest with pool: 'forks': on CI's node:18 a worker torn down mid font-fetch aborted the run.feat/page-type-label: the page panel's Type popup is now a read-only field
(#page-type, still under the parameterbar.page.type pb-group). Canvas derives Spread.type from
the page records in sync_container_from_records() — single, spread_horizontal,
spread_vertical — and toJSON() does not write it, so the popup's own vocabulary
(other/single/spread) matched nothing. ⚠️ Picking an item did NOT go through the empty
set_page_type() callback but through menucontroler.ts → set_PageType() (menucommands.ts),
which doubled native_size.width on single → spread and compared against 'spread', so a derived
spread_horizontal → single only relabelled it. That conversion, its menu-controller branches and
its menuactions registration are removed; nothing else produced popupmenu_page_type_* ids.