| 1 | # Windows close and transcript diagnostics validation |
| 2 | |
| 3 | [简体中文](WINDOWS_CLOSE_TRANSCRIPT_VALIDATION.zh-CN.md) |
| 4 | |
| 5 | This note records the validation boundary for the Windows close-race fix and |
| 6 | the transcript follow diagnostics added on `main-v2`. It does not claim that an |
| 7 | unknown transcript synchronization root cause has been fixed. |
| 8 | |
| 9 | ## Implemented behavior |
| 10 | |
| 11 | - The title-bar minimize, maximize, maximize-state, and close actions go |
| 12 | directly through the preload IPC to Electron. Compatibility calls using the |
| 13 | old generated Go command names are handled by the same native window owner. |
| 14 | - `QuitSequencer` owns window close, app quit, system quit, and update relaunch. |
| 15 | Repeated requests share draft preparation and one service shutdown. An app |
| 16 | quit arriving during a background-close policy check upgrades that operation |
| 17 | to a real quit. Preparation retains ownership through renderer resume and |
| 18 | draft-error dialogs; queued quit requests run after that ownership is released. |
| 19 | - The service publishes `stopping` as soon as shutdown begins. Its public |
| 20 | readiness is false, new business calls fail as shutting down, and lifecycle |
| 21 | shutdown/status traffic continues on the existing service session. |
| 22 | - Transcript followers stop without sending subscription-cleanup RPCs once the |
| 23 | service is stopping. The shared follower owner covers local and remote tabs, |
| 24 | including late hydration. A delayed response from the old generation cannot |
| 25 | update the displayed transcript or send cleanup after service stopping. |
| 26 | - Transcript failures are logged with bounded stage, reason, error type, transport, |
| 27 | revision, commit, attempt count, failure count, duration, service phase, and |
| 28 | service generation fields. Repeated identical failures emit at most one |
| 29 | visible summary per 30 seconds; a reason change is immediate. Recovery is |
| 30 | recorded after a successful delta follow, not merely a replacement snapshot, |
| 31 | so repeated broken deltas retain their failure count and duration. Repeated |
| 32 | recovery snapshots do not add breadcrumbs. Missing or failing shell diagnostic |
| 33 | capabilities cannot interrupt transcript recovery. |
| 34 | The renderer-to-shell endpoint rejects free text, unknown fields, payloads |
| 35 | over 2 KiB, untrusted senders, and more than ten accepted events per second. |
| 36 | |
| 37 | The rotating `shell.log` is the durable source for these diagnostics. Startup |
| 38 | lines include the shell version, channel, commit, PID, and run generation; |
| 39 | service-ready lines include the service build, PID, and generation; exit lines |
| 40 | include the shutdown request ID, reason, draft-save time, service time, total |
| 41 | time, and result. |
| 42 | |
| 43 | Files under `%APPDATA%\reasonix\diagnostics\lifecycle\` are temporary lifecycle |
| 44 | evidence. A successful exit removes the current run's file, and diagnostics can |
| 45 | also be disabled by policy or a development build. An empty directory after a |
| 46 | normal exit is therefore expected. Collect `%APPDATA%\reasonix\logs\shell.log` |
| 47 | and `service.log` for post-exit investigation. |
| 48 | |
| 49 | ## Follow-up review verification |
| 50 | |
| 51 | Review baseline: `a40c1eca5f9c6849ee82c5e027798085d9692519`. Repair commit: `fee5c199b9838e2f1c606f962327f5fb5404a67f`. |
| 52 | The following local macOS checks passed: |
| 53 | |
| 54 | | Directory | Commands / evidence | |
| 55 | | --- | --- | |
| 56 | | `desktop/electron` | `pnpm typecheck`, `pnpm test` (235 tests), `pnpm build`; the final log-order adjustment also passed all 22 lifecycle tests | |
| 57 | | `desktop/frontend` | `pnpm typecheck`, `pnpm test:typecheck`, `pnpm build` including unchanged bundle budgets | |
| 58 | | `desktop/frontend` | `pnpm test:transcript`, `pnpm test:app-lifecycle`, `pnpm test:remote` | |
| 59 | | `desktop/frontend` | `pnpm exec tsx src/__tests__/transcript-follow-client.test.ts` (22 tests), `pnpm exec tsx src/__tests__/transcript-session-follower.test.ts` (37 tests) | |
| 60 | | `desktop/frontend` | `node --import ./scripts/svg-stub-register.mjs --import tsx src/__tests__/remote-session-history-prime.test.tsx` (14 checks) | |
| 61 | | `desktop/frontend` | `pnpm test:app-browser` (Chromium lifecycle, navigation, runtime, and attention checks) | |
| 62 | | Repository | `git diff --check` | |
| 63 | |
| 64 | New regressions control draft-error dialogs, renderer resume, delayed baselines, |
| 65 | lazy loading, rejection and retry timing using deferred promises and fake clocks. |
| 66 | They cover both local and remote followers, bounded diagnostics during persistent |
| 67 | delta failure, optional/failing diagnostic hosts, and generation-specific cleanup. |
| 68 | No Go sources changed. Native Windows package qualification remains unexecuted. |
| 69 | |
| 70 | ## Windows package qualification |
| 71 | |
| 72 | Use one final installer or portable build with an isolated `REASONIX_HOME` and |
| 73 | the bundled service. Do not use the development handshake bypass. |
| 74 | |
| 75 | 1. Confirm strict shell/service handshake and a renderer `Version` call. |
| 76 | 2. Exercise repeated title-bar close, Alt+F4, tray quit, background hide, and |
| 77 | reopen, including overlaps while draft preparation is held by the test |
| 78 | fixture. |
| 79 | 3. Repeat with unsent draft text, an active session, and several tabs; restart |
| 80 | and verify all durable state. |
| 81 | 4. Hold service shutdown with the deterministic fixture and repeat close/quit. |
| 82 | Verify one request ID and one shutdown transaction. |
| 83 | 5. Confirm that the shell and service both exit and no crash overlay, |
| 84 | unhandled rejection, or residual process remains. |
| 85 | 6. Inject local and remote transcript failures and verify the stable stage and |
| 86 | reason in `shell.log` and copied crash text, correlated by build commit, |
| 87 | service generation, and absolute occurrence time. |
| 88 | 7. Confirm a clean exit may leave the lifecycle directory empty while rotating |
| 89 | logs remain available. |
| 90 | |
| 91 | Until this matrix passes on native Windows, report the status as |
| 92 | “implementation and local tests complete”; do not report the Windows incident |
| 93 | as validated. |
| 94 | |
| 95 | ## Separate migration investigation |
| 96 | |
| 97 | Historical ownership migration remains outside this change. The minimum |
| 98 | redacted model is: three sessions are registered to workspace **A**, while one |
| 99 | pending import operation targets workspace **B**. Investigation must compare |
| 100 | the workspace registry membership/lifecycle records with the migration ledger's |
| 101 | source mapping, target, operation revision, and completion receipt. Do not move, |
| 102 | copy, or delete sessions or pending operations until the intended target is |
| 103 | proven. |
| 104 |