| 1 | # Manual session creation recovery |
| 2 | |
| 3 | [中文](MANUAL_SESSION_CREATION_RECOVERY.zh-CN.md) |
| 4 | |
| 5 | ## Ownership and recovery |
| 6 | |
| 7 | Desktop registers new requests, startup recovery and explicit retries with one |
| 8 | process-local creation manager. A request retains its operation, session and |
| 9 | topic identities across interruptions. The existing OS creation lock is the |
| 10 | cross-process authority; a lock file's existence or age never grants ownership. |
| 11 | |
| 12 | If another process owns the lock, the manager keeps the request pending and |
| 13 | retries with jittered intervals of 0.5, 1, 2, 4 and at most 5 seconds. Startup |
| 14 | recovery is armed after tab restoration and rescans every 30 seconds. Display |
| 15 | polling does not initiate or own recovery. After acquiring the lock the worker |
| 16 | reads the current revision and phase again. Failed operations require explicit |
| 17 | retry, bound to the observed revision; a stale retry cannot restart a newer |
| 18 | failure. |
| 19 | |
| 20 | After runtime construction, a transient result-save error retries persistence |
| 21 | with the same result and lock. It does not repeat runtime construction. Invalid |
| 22 | identities, incompatible states and unsupported database versions remain visible |
| 23 | as blocked operations. Archived or deleted sessions are not revived. |
| 24 | |
| 25 | Recovery never changes the selected session. A newer navigation intent wins over |
| 26 | an earlier creation's completion. A topic activation claims its terminal event |
| 27 | before publishing readiness, so switching again while background pruning is |
| 28 | pending cannot emit a second cancellation for an already-ready request. |
| 29 | |
| 30 | ## Progress and diagnostics |
| 31 | |
| 32 | The existing Begin/Get/List/Retry RPCs retain their arguments and add an optional |
| 33 | `progress` response. Its status is `queued`, `running`, `waiting_lock`, |
| 34 | `retrying_storage`, `blocked` or `stopping`. Stage, start time, elapsed milliseconds, |
| 35 | next retry time, slow flag and a sanitized error code are observational only. |
| 36 | Clients must tolerate missing or unknown progress values. |
| 37 | |
| 38 | The recovery notice offers **Export creation diagnostics**, implemented by |
| 39 | `ExportManualCreationDiagnostics()`. The JSON contains build identity, current |
| 40 | local task snapshots and the latest 256 stage/attempt events. It can be exported |
| 41 | without reading the session database and contains no chat, attachment, provider |
| 42 | configuration or raw service-log content. Other processes' stages/PIDs are not |
| 43 | inferred. The service log also records stage transitions and rate-limited slow |
| 44 | stage warnings. A 30-second slow threshold is diagnostic, not a takeover timeout. |
| 45 | |
| 46 | If initialization remains stuck, export this report from the affected running |
| 47 | application before restarting. Record the triggering action and approximate |
| 48 | time. The report narrows the blocked stage; it does not establish the cause of |
| 49 | every historical `starting` record. |
| 50 | |
| 51 | ## Shutdown and compatibility |
| 52 | |
| 53 | Shutdown freezes admission, stops scanning/retries, cancels builds and joins |
| 54 | their actual executions before closing shared resources. Superseding a build's |
| 55 | notification cannot complete that join. If joining exceeds ten seconds, shutdown |
| 56 | reports a retryable failure and retains resources/ownership; it does not close |
| 57 | the database or report clean exit. Interrupted creation remains recoverable on |
| 58 | the next start. There is no new user cancellation action. |
| 59 | |
| 60 | SQLite schema, lock paths, identity derivation and persisted phases |
| 61 | (`reserved`, `starting`, `ready`, `failed`) are unchanged. Phase/error updates |
| 62 | preserve unknown JSON fields. Local progress is not written to creation records. |
| 63 | Older readers ignore the optional RPC field; newer readers accept older records. |
| 64 | |
| 65 | ## Verification |
| 66 | |
| 67 | Run focused tests from the independent Desktop Go module: |
| 68 | |
| 69 | ```sh |
| 70 | go test -race . -run 'TestManualCreation|TestComposerRestart|TestShutdownServiceFailure|TestArchiveLastVisibleSession' -count=1 |
| 71 | node ../scripts/desktop-windows-go-tests.mjs --all |
| 72 | ``` |
| 73 | |
| 74 | The tests use disposable state and real subprocess locks. They cover owner exit, |
| 75 | two competing managers, revision changes while waiting, result-only retries, |
| 76 | superseded build completion, shutdown ownership, prepared-storage reuse, unknown |
| 77 | fields and archive-then-create. Run these on Windows x64 and macOS; cross-compiling |
| 78 | does not qualify native locking or shutdown behavior. |
| 79 | |
| 80 | Frontend checks include `manual-creation-recovery.test.tsx`, |
| 81 | `formal-submission-recovery.test.tsx`, composer lifecycle and navigation tests. |
| 82 | `node bench/manual-creation-recovery.mjs` exercises the notice in Chromium with |
| 83 | the actual component and a mock host. Set `CHROME_EXECUTABLE` if using an installed |
| 84 | Chrome instead of Playwright's browser. The browser test does not qualify native |
| 85 | file-dialog behavior. |
| 86 |