Add guidance for coding agents to keep worktree comments updated at meaningful
checkpoints, making work-in-progress status visible in the Orca UI without
explicit user requests.
Without this, a failed restart is a silent no-op. Now all three
call sites (settings pane, auto-restart, and "Restart Now" toast
action) surface the failure to the user and reset autoRestartAfterDownload
to avoid a stuck state.
Move editor autosave/save-queue logic out of EditorPanel into a
standalone controller that survives tab switches without keeping
the full editor UI mounted. Add updater lifecycle events so
beforeunload guards step aside during quitAndInstall, preventing
stale dirty-file prompts from blocking app restarts.
* feat: save dirty editor files before auto-update quitAndInstall
Dispatch a custom event from the preload quitAndInstall to flush unsaved
editor buffers before Electron's quitAndInstall bypasses the normal close
sequence. The EditorPanel claims the event, saves all dirty files via the
existing queueSave path, and resolves/rejects so the updater knows whether
it is safe to proceed.
* fix: address review findings
- Wrap save-before-update in try/catch so a save failure never silently
prevents the update from installing
- Move detail.claim() inside try/catch to prevent promise hang on
unexpected errors
- Add duplicate dirty tab detection to reject when the same file is
dirty in multiple tabs (prevents silent write races)
- Cap module-scoped caches (combinedDiffViewStateCache, combinedDiffScrollTopCache)
at 20 entries with LRU eviction to prevent unbounded memory growth
- Promote generationRef to useState for use in React key prop so key changes
are properly tracked by React's rendering cycle
- Show user-friendly guidance instead of raw git stderr when worktree
deletion fails due to changed files, directing users to Force Delete.
- Extract toast message logic to reusable getDeleteWorktreeToastCopy
function with comprehensive test coverage.
Local images referenced in markdown (both preview and rich editor) failed
to display in dev mode because file:// URLs are blocked by cross-origin
restrictions when the renderer is served from localhost.
- Load local images via IPC readFile → blob URL conversion
- Add useLocalImageSrc hook for react-markdown preview
- Add loadLocalImageSrc for ProseMirror nodeView in rich editor
- Snapshot cursor position before native file picker to fix insertion point
- Add blob URL cache with LRU eviction (max 100) and revokeObjectURL cleanup
- Add resolveImageAbsolutePath helper with tests
* fix: defer updater quitAndInstall to allow React/UI state to settle
PR #299 introduced a regression where the one-click auto-update flow
would synchronously invoke `quitAndInstall` immediately upon receiving
the `downloaded` state transition. This triggered a synthetic `beforeunload`
event (to capture terminal buffers) and an IPC call to quit in the exact
same event loop tick that React and the Toast library were processing
state updates. This disrupted the renderer's synchronous shutdown and flush
logic, causing the app to fail to quit and install properly.
This adds a `setTimeout` to defer `quitAndInstall`, pushing it to the
bottom of the event queue. This allows the UI state to settle and ensures
the `beforeunload` flush sequence executes cleanly.
Test cases have also been updated to use fake timers.
* fix: centralize updater restart deferral in main process
Replace the activeWorktreeSelectionNonce / frozen-sort-override approach
with the simpler sortEpoch-only strategy. Selection side-effects
(clearing isUnread, PR cache refresh) no longer participate in sort
ordering, so clicking a card never reshuffles the sidebar.
- Remove activeWorktreeSelectionNonce from store
- Remove RecentSortOverride refs and secondary sort memo
- Swap prCache → repos in sortedIds deps (prCache changes are consumed
inside the memo via direct store access when sortEpoch increments)
The `gh api --cache 60s` flag caused stale check-run data even when
the user explicitly clicked refresh. Thread a `noCache` flag through
IPC so manual refreshes skip the gh CLI cache while polling still
benefits from it.
* clean-up-repo-local-setup-script
- Add authorization cache for worktree roots to improve filesystem read performance
- Use ensureAuthorizedRootsCache instead of rebuilding on every list operation
- Fix useMemo side effect in WorktreeList by returning sorted IDs directly
- Add error display in QuickOpen and FileExplorer for unauthorized paths
- Improve section order in SourceControl (unstaged, staged, untracked)
- Add keyboard shortcut guard in WorktreeList for arrow keys
- Address review findings from code quality checks
* fix: update test mocks for filesystem-auth cache integration
- filesystem.test.ts: invalidate auth roots cache in beforeEach to
prevent stale cache state from leaking between tests
- worktrees.test.ts / worktrees-windows.test.ts: add store.getRepos
mock return value so rebuildAuthorizedRootsCache can iterate repos
- worktrees-windows.test.ts: add third listWorktrees mock for the
cache rebuild call consumed during worktrees:create
* fix: resolve oxlint errors for max-lines and missing useEffect dependency
- Extract repeated worktree mock data into shared variable to reduce
worktrees.test.ts below the 300-line limit
- Add missing 'toggleSidebar' to useEffect dependency array in App.tsx
- Capture startup reference synchronously at function entry
- Clear deps.startup to prevent re-execution by split panes
- Use captured local copy in onConnect callback
- Add documentation for intentional mutation side effect
* fix: restore update toast flow and cover updater transitions
* fix: resolve oxlint errors in test file and FileExplorer
- Replace smart quote (U+2019) with ASCII apostrophe in update toast test
- Use .at(-1) instead of array[length - 1] per prefer-at rule
- Extract background context menu into FileExplorerBgMenu to fix max-lines
* fix: restore dismissed update version check in toast controller
The old UpdateReminder component checked dismissedUpdateVersion before
showing the update prompt. This logic was missing from the new
createUpdateToastController, causing the toast to reappear even after
the user dismissed it. Now the controller skips the available toast when
the version matches the dismissed one and persists the dismissal when
the user closes the toast without clicking Update.