| 1 | # On-demand historical session migration |
| 2 | |
| 3 | ## Scope |
| 4 | |
| 5 | Desktop startup no longer converts every legacy transcript or canonical v4 |
| 6 | directory. Startup only repairs small, non-historical lifecycle reservations. |
| 7 | The historical catalog reads directory entries, published head indexes, and |
| 8 | durable registry metadata. Legacy and canonical v4 rows participate in the normal sidebar and |
| 9 | history search; opening one starts preparation in the conversation navigation |
| 10 | flow and switches to the canonical target only after preparation commits. |
| 11 | |
| 12 | Restored, unprepared tabs retain their title and a non-error **Import and open** |
| 13 | action. Merely restarting does not prepare content or start a controller. The |
| 14 | action uses the same navigation owner as sidebar/history selection. Empty |
| 15 | canonical probe directories are not historical sessions; damaged session |
| 16 | artifacts remain discoverable for an explicit retry. |
| 17 | |
| 18 | The management surface is **Settings → Storage → Historical sessions**. Trash |
| 19 | contains archived/deleted canonical sessions only. |
| 20 | |
| 21 | ## Ownership and lifecycle |
| 22 | |
| 23 | - A source import takes a per-source cross-process lock and, for canonical |
| 24 | stores, a shared directory ownership lock for the complete copy and commit. |
| 25 | - A source already owned by another CLI or runtime returns a blocked source |
| 26 | status immediately. It never waits behind the desktop runtime rebuild lock. |
| 27 | - Duplicate requests for one source join the same revisioned preparation task. |
| 28 | Interactive navigation and a bulk batch hold separate demands, so cancelling |
| 29 | a batch cannot cancel a session that the user is currently opening. |
| 30 | - Batch import is sequential, cancellable, and resumable. Its selected source |
| 31 | snapshot is stored in `historical-import-queue.v1.json` with an atomic, |
| 32 | cross-process-locked update. After restart it is paused until the user |
| 33 | explicitly continues. Cancellation leaves |
| 34 | `prepared` and `content_ready` reservations for the next explicit attempt. |
| 35 | - Existing `content_ready` operations are replayed against their durable target; |
| 36 | they are not converted into a second session. Recovery validates the target |
| 37 | and lifecycle fences without requiring the old source or its ownership lock. |
| 38 | - Archive and purge state remains authoritative. Deleted or archived sessions |
| 39 | are not resurrected by a later catalog scan. |
| 40 | - `PrepareSession`, `GetSessionPreparation`, and |
| 41 | `CancelSessionPreparation` expose `queued`, `preparing`, `ready`, `blocked`, |
| 42 | `failed`, and `cancelled` scheduling states without adding lifecycle phases. |
| 43 | - Source content checks compare durable bytes rather than timestamps or title |
| 44 | metadata. A confirmed version can be explicitly imported with |
| 45 | `PrepareHistoricalSourceVersion`; its `:review:<fingerprint>` mapping is a |
| 46 | separate branch while the original mapping remains stable. |
| 47 | |
| 48 | Discovery publishes a metadata snapshot in the background; ordinary lists only |
| 49 | read that snapshot. Renames and pins are applied before search and sorting, and |
| 50 | transferred on adoption. A pending sidebar source follows the same navigation |
| 51 | preparation owner as history. Cancellation responses are fenced by navigation |
| 52 | intent, operation identity, and revision; branch preparation cannot take focus |
| 53 | back after the user navigates elsewhere. |
| 54 | |
| 55 | Shutdown drains the batch worker before releasing queue ownership, preserving |
| 56 | the current and remaining selections for manual continuation. One process owns |
| 57 | a batch worker lease. Sidecar mutations read the latest disk value under the |
| 58 | write lock, modify only their owned fields, and atomically replace it; stale |
| 59 | queue revisions are rejected rather than overwriting another process's work. |
| 60 | |
| 61 | ## Compatibility |
| 62 | |
| 63 | Source files remain unchanged. Existing source mappings, recovery entries, |
| 64 | unknown fields, presentations, and retained artifacts are preserved. The |
| 65 | path-only legacy route remains an alias for the selected DAG head; valid head |
| 66 | indexes expose alternate heads as separate on-demand sources. A missing or |
| 67 | stale index degrades to one source row and never causes event-log replay in a |
| 68 | listing RPC. |
| 69 | |
| 70 | The queue sidecar is scheduling intent only. The workspace lifecycle registry |
| 71 | remains authoritative for target Session IDs and commit state. Older builds |
| 72 | ignore the sidecar and optional RPC fields; committed sessions and retained |
| 73 | sources remain readable after rollback. Preparation metadata is never added to |
| 74 | model prompts or transcript messages. |
| 75 | |
| 76 | | Data | Compatibility behavior | |
| 77 | | --- | --- | |
| 78 | | Lifecycle registry | No new operation types or phases; existing target IDs and mappings remain authoritative. | |
| 79 | | Version 1 queue sidecar | Optional `queueRevision` defaults to zero; existing files load paused. Unknown root and presentation fields survive writes. | |
| 80 | | Rollback to pre-sidecar builds | Scheduling is unavailable; source files and committed canonical sessions remain readable. | |
| 81 | | Concurrent older sidecar writers | Older code does not honor the new worker lease/revision contract; do not run mixed-version batch writers. Upgrade all Desktop instances first. | |
| 82 | |
| 83 | ## Verification |
| 84 | |
| 85 | The implementation has deterministic coverage for startup non-migration, |
| 86 | cross-process cold-export contention, duplicate and cancelled imports, |
| 87 | prepared/content-ready resume, revisioned duplicate preparation, paused queue |
| 88 | restart, archive/purge fencing, and browser interactions for listing, retry, |
| 89 | open-after-commit, and batch controls. Regression tests additionally cover normal |
| 90 | global/project discovery while a source is occupied, title/pin search and adoption, |
| 91 | shutdown during commit followed by restart, independent sidecar writers, unknown |
| 92 | field preservation, source-independent recovery, and late navigation responses. |
| 93 |