import type { IControllerPersistedSessionGroup } from '../dist_ts/interfaces.projects.js'; import type { TControllerLayoutItemRef, TControllerSessionId } from '../dist_ts_interfaces/index.js'; /** * The layout document as it was persisted before conversations and resources became peers: * every member was a conversation id, and resources were excluded outright by the v18 and v24 * migrations. Frozen here rather than imported from the live model, because the live assertion * now describes item refs and would reject every historical document. */ export interface IV30LegacySessionGroup { id: string; name: string; sessionIds: TControllerSessionId[]; } export interface IV30LegacySessionGroupsDocument { id: string; controllerId: string; projectId: string; groups: IV30LegacySessionGroup[]; ungroupedSessionIds?: TControllerSessionId[]; revision?: number; } /** * The per-project layout document this migration produces. It stopped being the live shape when * the layout became controller-wide in v32, which consumes exactly this as its input, so it is * frozen here next to the legacy shape it lifts from. */ export interface IV30ItemRefSessionGroupsDocument { id: string; controllerId: string; projectId: string; groups: IControllerPersistedSessionGroup[]; ungroupedItemIds?: TControllerLayoutItemRef[]; revision?: number; } export interface IV30LayoutMigrationResult { document: IV30ItemRefSessionGroupsDocument; migrated: boolean; } /** * The layout assertion as it stood before item refs. The v6, v18 and v24 migrations normalize * historical documents into this shape and must keep validating against it: the live assertion * describes the post-lift shape they do not produce. */ export declare function assertLegacySessionLayoutDocument(valueArg: unknown): asserts valueArg is IV30LegacySessionGroupsDocument; /** * A document that already carries item refs must be left exactly as it is. * * Two shapes have to be told apart, and neither field alone does it: * - a group carrying `itemIds` is decisive on its own, because the legacy shape only ever had * `sessionIds`. This is the case that matters in practice: `ungroupedItemIds` and `revision` * are a paired *optional* pair, so a perfectly valid lifted document can omit both, and * demanding `ungroupedItemIds` made the v6, v18 and v24 migrations re-read such a document as * legacy on the next start and reject it. * - with no groups at all there is nothing to read a kind from, so the presence of the lifted * ordering field is the only signal; without it the document is legacy and must be lifted. */ export declare const isV30ItemRefLayoutDocument: (valueArg: unknown) => valueArg is IV30ItemRefSessionGroupsDocument; /** * The per-project shape this migration writes. The live document assertion describes the * controller-wide layout of v32, so it cannot validate this intermediate shape. */ export declare function assertV30ItemRefSessionGroupsDocument(valueArg: unknown): asserts valueArg is IV30ItemRefSessionGroupsDocument; /** * Lifts a pre-item-ref layout document. * * Group membership and the ungrouped order become refs tagged with their kind, because * conversation ids and resource ids are separate namespaces. The project's resources are * appended to the ungrouped order in creation order, which is the order the sidebar derived for * them before they were orderable, so the first render after the upgrade looks unchanged. * * Documents that predate explicit ordering carry neither `ungroupedSessionIds` nor `revision`. * They gain both here — at revision zero, which is exactly how the store already reads a missing * revision — so the appended resources have a persisted order rather than none. */ export declare const migrateV30SessionLayoutDocument: (valueArg: IV30LegacySessionGroupsDocument | IV30ItemRefSessionGroupsDocument, projectResourceIdsArg: readonly string[]) => IV30LayoutMigrationResult;