| Files | Last commit | Last update |
|---|---|---|
feat(desktop): ship the macOS x64 desktop build (#894) * feat(desktop): ship the macOS x64 desktop build Electrobun 2.0.1 publishes no macOS x64 core, so Intel Macs had no desktop installer. Pin 2.0.5 — the first release with a macos-x64 core and the paired Hutch 0.28.2 — and teach the release recipe about the new target. - collector maps bun-darwin-x64 to the macos-x64 DMG, update manifest, and expanded-app archive under thinkrail-desktop-darwin-x64.dmg - updater enablement accepts darwin-x64 like the other shipped targets - install.sh still refuses the Intel CLI, but now points at the DMG - specs and README drop the "no Intel build" claim * feat(install): ship the Intel macOS CLI and keep Rosetta shells on arm64 * docs(desktop): refresh Electrobun 2.0.5 behaviour notes and document the Intel CLI * docs(architecture): Cottontail is no longer Electrobun's default runtime --------- Co-authored-by: 金宇 <jinyu6@antcode.com> Co-authored-by: rsolmano <rinat.suleimanov@jetbrains.com> | 12 days ago | |
feat(web): translate the interface and let users add their own languages (#788) * feat(web): translate the interface and let users add their own languages * test(i18n): pass the translator in tests main added for usage counters and hydration * fix(server): reattach the locale watchers when Linux drops them with a deleted folder * fix(resource-renderers): retranslate the editor's comment controls without remounting * fix(resource-renderers): install the current comment label when the editor mounts late * fix(server): poll the locales folder instead of watching it * fix(server): catch permission repairs and mtime-preserving rewrites in the locales poller * fix(locales): let plural forms show or omit the count and fill missing forms from _other * fix(i18n): stop terminal-group labels rendering their raw key and split the Done status from the Done action * fix(web): translate default chat, terminal, Changes, diff and plan tab names at render instead of storing them * fix(i18n): translate theme names, the default workspace, thinking levels and the remaining UI labels * fix(chat): word the round closer, failure notices and durations at render instead of storing English text * fix(chat): export the plan Markdown in the interface language * fix(desktop): translate the native startup and update error dialogs * fix(i18n): keep extension notices' text, report untitled sessions without an English title, and word the default workspace everywhere * docs(specs): record that stored names carry no translated text and the plural-form rules --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
feat(web): translate the interface and let users add their own languages (#788) * feat(web): translate the interface and let users add their own languages * test(i18n): pass the translator in tests main added for usage counters and hydration * fix(server): reattach the locale watchers when Linux drops them with a deleted folder * fix(resource-renderers): retranslate the editor's comment controls without remounting * fix(resource-renderers): install the current comment label when the editor mounts late * fix(server): poll the locales folder instead of watching it * fix(server): catch permission repairs and mtime-preserving rewrites in the locales poller * fix(locales): let plural forms show or omit the count and fill missing forms from _other * fix(i18n): stop terminal-group labels rendering their raw key and split the Done status from the Done action * fix(web): translate default chat, terminal, Changes, diff and plan tab names at render instead of storing them * fix(i18n): translate theme names, the default workspace, thinking levels and the remaining UI labels * fix(chat): word the round closer, failure notices and durations at render instead of storing English text * fix(chat): export the plan Markdown in the interface language * fix(desktop): translate the native startup and update error dialogs * fix(i18n): keep extension notices' text, report untitled sessions without an English title, and word the default workspace everywhere * docs(specs): record that stored names carry no translated text and the plural-form rules --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
feat(website): add consented journey analytics foundation (#524) * Update website analytics specs for settled mechanics * feat(website): add consented journey analytics foundation * fix(website): clear journey enrichment when consent becomes unknown * feat(website): instrument attribution events (#526) * feat(website): instrument attribution events * test(website): cover unattributed install events * feat(website): persist campaign attribution context (#528) * feat(website): persist campaign attribution context * fix(website): import attribution through its public surface * fix(website): invalidate download bridge on new acquisition * fix(website): keep attribution context through unknown consent * feat(website): add attribution claim protocol core (#529) * feat(website): add attribution claim protocol core * feat(website): deploy browser attribution claims (#530) * feat(website): deploy browser attribution claims * fix(website): require confirmation before binding attribution claims * feat(analytics): add first-install lifecycle (#531) * feat(analytics): add first-install lifecycle * fix(analytics): claim first installs once across concurrent hosts * feat(analytics): link browser acquisition to product usage (#532) * feat(analytics): link browser acquisition to product usage * fix(analytics): revoke queued campaign basics and allow claim confirmation * test(analytics): verify website-to-product attribution contract (#534) * refactor(attribution): drop landing page key from claim touches * fix(website): keep attribution D1 out of preview deployments * fix(website): derive analytics keys from public page paths * test(website): validate analytics across every generated page * fix(website): guard analytics and assets on all built pages * refactor(website): drop extra build checks and simplify the 404 page * feat(website): link claims silently and open the blog * fix(web): describe website attribution in plain language * fix(web): avoid promising deletion in the attribution note * fix(web): describe the blog opening as conditional * adjusts wording * docs: align privacy specs with the simplified settings copy * fix(website): bind claims only with current Marketing consent * docs(web): drop removed privacy copy from the panels spec | 1 month ago | |
feat(website): add consented journey analytics foundation (#524) * Update website analytics specs for settled mechanics * feat(website): add consented journey analytics foundation * fix(website): clear journey enrichment when consent becomes unknown * feat(website): instrument attribution events (#526) * feat(website): instrument attribution events * test(website): cover unattributed install events * feat(website): persist campaign attribution context (#528) * feat(website): persist campaign attribution context * fix(website): import attribution through its public surface * fix(website): invalidate download bridge on new acquisition * fix(website): keep attribution context through unknown consent * feat(website): add attribution claim protocol core (#529) * feat(website): add attribution claim protocol core * feat(website): deploy browser attribution claims (#530) * feat(website): deploy browser attribution claims * fix(website): require confirmation before binding attribution claims * feat(analytics): add first-install lifecycle (#531) * feat(analytics): add first-install lifecycle * fix(analytics): claim first installs once across concurrent hosts * feat(analytics): link browser acquisition to product usage (#532) * feat(analytics): link browser acquisition to product usage * fix(analytics): revoke queued campaign basics and allow claim confirmation * test(analytics): verify website-to-product attribution contract (#534) * refactor(attribution): drop landing page key from claim touches * fix(website): keep attribution D1 out of preview deployments * fix(website): derive analytics keys from public page paths * test(website): validate analytics across every generated page * fix(website): guard analytics and assets on all built pages * refactor(website): drop extra build checks and simplify the 404 page * feat(website): link claims silently and open the blog * fix(web): describe website attribution in plain language * fix(web): avoid promising deletion in the attribution note * fix(web): describe the blog opening as conditional * adjusts wording * docs: align privacy specs with the simplified settings copy * fix(website): bind claims only with current Marketing consent * docs(web): drop removed privacy copy from the panels spec | 1 month ago | |
feat(desktop): ship the macOS x64 desktop build (#894) * feat(desktop): ship the macOS x64 desktop build Electrobun 2.0.1 publishes no macOS x64 core, so Intel Macs had no desktop installer. Pin 2.0.5 — the first release with a macos-x64 core and the paired Hutch 0.28.2 — and teach the release recipe about the new target. - collector maps bun-darwin-x64 to the macos-x64 DMG, update manifest, and expanded-app archive under thinkrail-desktop-darwin-x64.dmg - updater enablement accepts darwin-x64 like the other shipped targets - install.sh still refuses the Intel CLI, but now points at the DMG - specs and README drop the "no Intel build" claim * feat(install): ship the Intel macOS CLI and keep Rosetta shells on arm64 * docs(desktop): refresh Electrobun 2.0.5 behaviour notes and document the Intel CLI * docs(architecture): Cottontail is no longer Electrobun's default runtime --------- Co-authored-by: 金宇 <jinyu6@antcode.com> Co-authored-by: rsolmano <rinat.suleimanov@jetbrains.com> | 12 days ago | |
feat: unconditional PII-free PostHog error tracking with readable stacks (#769) * feat(analytics): report sanitized exceptions through the basic PostHog sink * feat(host): report crashes, failed requests and logged errors to error tracking * feat: forward UI errors to host error tracking over client.reportError * feat(desktop): forward handled main-process errors to host error tracking * docs: document unconditional sanitized error reports in specs, README and AGENTS.md * test(artifacts): tolerate allow-listed error reports in the desktop analytics probe * feat(analytics): keep raw frames and chunk ids for PostHog symbolication * feat(web): send PostHog chunk ids with client error reports * feat(cli): embed the binary's source map for readable error stacks * feat(release): upload web and desktop-runtime source maps to PostHog * test(release): pin source-map credential scoping in the build action * docs: document source-map upload and readable error stacks * fix(analytics): carry the report's handled flag into the root exception mechanism * docs: pin client error reports to protocol v90 after rebasing onto main * feat(analytics): send a classifier instead of error message text * fix(host): wait at most 1 s for the crash report and tag the crash kind * fix(desktop): derive runtime chunk ids from the code, its map and the release * build(release): run posthog-cli only after a pinned SHA-256 check of its binary * fix: report stable boundary ids, route main's new desktop errors and scope release credentials * fix(analytics): cut the message out of every stack before the SDK parses frames --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
feat: unconditional PII-free PostHog error tracking with readable stacks (#769) * feat(analytics): report sanitized exceptions through the basic PostHog sink * feat(host): report crashes, failed requests and logged errors to error tracking * feat: forward UI errors to host error tracking over client.reportError * feat(desktop): forward handled main-process errors to host error tracking * docs: document unconditional sanitized error reports in specs, README and AGENTS.md * test(artifacts): tolerate allow-listed error reports in the desktop analytics probe * feat(analytics): keep raw frames and chunk ids for PostHog symbolication * feat(web): send PostHog chunk ids with client error reports * feat(cli): embed the binary's source map for readable error stacks * feat(release): upload web and desktop-runtime source maps to PostHog * test(release): pin source-map credential scoping in the build action * docs: document source-map upload and readable error stacks * fix(analytics): carry the report's handled flag into the root exception mechanism * docs: pin client error reports to protocol v90 after rebasing onto main * feat(analytics): send a classifier instead of error message text * fix(host): wait at most 1 s for the crash report and tag the crash kind * fix(desktop): derive runtime chunk ids from the code, its map and the release * build(release): run posthog-cli only after a pinned SHA-256 check of its binary * fix: report stable boundary ids, route main's new desktop errors and scope release credentials * fix(analytics): cut the message out of every stack before the SDK parses frames --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
fix(desktop): keep the window on its origin and open external links exactly once (#1030) * fix(desktop): confine the window to its origin and open external links once on every platform * test(desktop): smoke-test that external links open once and the window stays on its origin * docs(desktop): record how navigation rules and link routing keep the window on its origin * test(desktop): report the native will-navigate verdict when the window leaves its origin The Windows desktop smoke failed with "native window left its origin for navigate" but could not say whether native navigation rules were in effect. The navigation probe now records each will-navigate detail, and that error quotes the verdicts for the probe URL (allowed:true means no rule applied). * test(desktop): judge origin confinement by main-frame commits, not probe requests On Windows the native rules cancelled the scripted navigation (will-navigate allowed:false), yet the probe server still received the GET: WebView2 documents that a cancelled navigation may still send its request. The smoke now fails only when the window commits the probe URL (did-commit-navigation, emitted by all three native layers), quoting the will-navigate verdicts. Without the rules, the smoke fails with allowed:true on macOS. | 6 days ago | |
fix(desktop): keep the window on its origin and open external links exactly once (#1030) * fix(desktop): confine the window to its origin and open external links once on every platform * test(desktop): smoke-test that external links open once and the window stays on its origin * docs(desktop): record how navigation rules and link routing keep the window on its origin * test(desktop): report the native will-navigate verdict when the window leaves its origin The Windows desktop smoke failed with "native window left its origin for navigate" but could not say whether native navigation rules were in effect. The navigation probe now records each will-navigate detail, and that error quotes the verdicts for the probe URL (allowed:true means no rule applied). * test(desktop): judge origin confinement by main-frame commits, not probe requests On Windows the native rules cancelled the scripted navigation (will-navigate allowed:false), yet the probe server still received the GET: WebView2 documents that a cancelled navigation may still send its request. The smoke now fails only when the window commits the probe URL (did-commit-navigation, emitted by all three native layers), quoting the will-navigate verdicts. Without the rules, the smoke fails with allowed:true on macOS. | 6 days ago | |
fix(desktop): center the main window on startup (#1133) Co-authored-by: OLavrik <Olya_lavrik@inbox.ru> | 2 days ago | |
feat(desktop): add confirmed quit and in-app close shortcuts (#609) * feat(desktop): add confirmed quit and in-app close shortcuts Cmd+Q did nothing on macOS because Electrobun role menu items get no default accelerator. Quit now needs a 1.2s hold or a double press and fires on release, with a centered hint; menu, Dock, and update quits stay direct and share the existing quit coordinator. Shortcuts follow VS Code: Cmd+Q / Linux Ctrl+Q quit (confirmed); Cmd+W, Win/Linux Ctrl+W and Ctrl+F4 close the focused dialog or tab through the tab X-button path and never close the window. Hide, Hide Others, and Minimize get their macOS accelerators. The confirmation rules live once in contracts (quitConfirmation); macOS feeds them CoreGraphics key state because menu events repeat without a repeat flag, Linux feeds them web key events. A web shortcut command table serves native commands and Win/Linux keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(web): deliver close requests through a channel, not a prop Cmd+W bumped a closeRequestKey state in Shell, re-rendering Shell, WorkspaceWorkbench and Workbench per press. A shell-owned closeRequestChannel now fires the request; Workbench gets it via an injected subscribeCloseRequest prop, so layout stays props-driven and the mount-time stale-key rule goes away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(web): move quit hint state into an AppShortcuts leaf Shell no longer calls useAppShortcuts. The AppShortcuts leaf runs the hook and renders QuitHintOverlay, so quit hint changes re-render only that leaf. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(web): skip terminal check and key listeners when no chord can match matchShortcut now takes a lazy terminal check and calls it only after a chord matches. useAppShortcuts adds window keydown/keyup listeners only on platforms whose table binds web chords (windows, linux), so macOS desktop has none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(web): note synthetic Escape contract for close-item close-item dismisses layers with an untrusted Escape. Spell out what each dismissible layer must do to keep closing on the shortcut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: state contracts runtime as a rule, not a list Decision #3 named one function and its injection details. It now states the rule (types plus small dependency-free runtime) and points to the contracts spec for the list. README no longer says types-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(web): match close and quit chords on the typed letter On AZERTY/Dvorak the KeyW/KeyQ positions type other letters, so Ctrl+Z closed tabs and double Ctrl+A in a Linux terminal quit the app. Letter chords now match event.key, falling back to code for non-Latin layouts. The quit hold releases on the keyup of the physical key that started it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): count only press-time keys as the quit hold A key pressed after Command-Q no longer completes the hold. The hold tracks the non-modifier keys down when the menu action fired, so it stays layout-independent. Key-repeat presses never add keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(web): find history overlay by focused group id, not nearest element The tab strip shares data-group-id with its group root, so closest() from a focused tab returned the strip and missed the overlay; close-item then closed the chat. Match every element with the focused group id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(contracts): pin quit timings and cover a short hold Assert QUIT_CONFIRMATION matches the documented 1200/500/40 ms values, and check that a hold released before the threshold never quits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: describe contracts runtime use and AppShortcuts mount Shell, web, and desktop specs said contracts is types-only, but both import createQuitConfirmation. Shell always mounts AppShortcuts; the hook is inert without the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): quit directly on a keyboard or VoiceOver menu pick With Command up, a last key-down newer than the last modifier change means the Quit item was picked from the menu by keyboard, not by Command-Q. A late-handled tap still arms: its Command release is newer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(e2e): wait on terminal output instead of fixed sleeps The busy-close step waits for a computed marker printed by the child shell. The terminal Ctrl+W step checks the shell erased a word. Use pressPlatformShortcut for the new-workspace chord. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): cover key-state decoding and the shortcuts bridge Split CoreGraphics reads from a pure decodeKeyState and test the modifier keycode range, Command flag, and event-age ordering. Test createShortcutsBridge pub/sub directly. Type the e2e bridge stub as NativeShortcutsBridge so drift fails typecheck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: name contracts runtime exceptions instead of allowing any pure rule --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Rinat S <rinat.suleimanov@jetbrains.com> | 1 month ago | |
fix(desktop): release the menu command latch after a deadline (#1200) * fix(desktop): release the menu command latch on stale key state The repeat gate swallows menu commands while any key reads down, and its latch only released when a poll saw every key up: a key state that never clears — a KVM-over-IP or remote-desktop stack that lost the key-up packet leaves CGEventSourceKeyState reading a phantom key forever — permanently disabled every gated menu command (Settings, Close, and their accelerators) while role-handled shortcuts like quit kept working, until an app restart cleared the in-memory latch (#1199). Distinguish a held key from a stale one by event freshness, not time: a genuinely held non-modifier key auto-repeats and keeps producing key-down events, so the latch now also releases when the state claims a key is down but no key-down event has arrived for 750 ms — a signature only a lost key-up produces. The desktop guarantee that a held key never fires a command twice is preserved exactly: real repeats keep the events (and the latch) flowing. - keyState: exposes sinceKeyDown (seconds, null when unreadable) - repeatGate: releases on release or staleness; unreadable freshness falls back to trusting the state - index.ts: wires readKeys().sinceKeyDown - tests: repeat-keeps-latched, stale-releases, unreadable fallback, plus the pre-existing release/unreadable cases * docs(desktop): state the repeat gate's staleness release in the SPEC The native-menu section described the latch purely as 'until no non-modifier key is down'; the stale-state release (no key-down event for 750 ms while a key still reads down) is now recorded alongside the repeat guarantee it preserves (#1199 review). * Raise the repeat gate's stale-key release to 2.5 s so a long macOS delay-until-repeat cannot fire a held command twice, and move its rationale out of comments into the SPEC. * Assert the tall questionnaire's follow state against the reader's actual edge distance, since wheeling to the bottom-most Submit row can legitimately re-attach follow. --------- Co-authored-by: OLavrik <Olya_lavrik@inbox.ru> | 2 days ago | |
feat(web): translate the interface and let users add their own languages (#788) * feat(web): translate the interface and let users add their own languages * test(i18n): pass the translator in tests main added for usage counters and hydration * fix(server): reattach the locale watchers when Linux drops them with a deleted folder * fix(resource-renderers): retranslate the editor's comment controls without remounting * fix(resource-renderers): install the current comment label when the editor mounts late * fix(server): poll the locales folder instead of watching it * fix(server): catch permission repairs and mtime-preserving rewrites in the locales poller * fix(locales): let plural forms show or omit the count and fill missing forms from _other * fix(i18n): stop terminal-group labels rendering their raw key and split the Done status from the Done action * fix(web): translate default chat, terminal, Changes, diff and plan tab names at render instead of storing them * fix(i18n): translate theme names, the default workspace, thinking levels and the remaining UI labels * fix(chat): word the round closer, failure notices and durations at render instead of storing English text * fix(chat): export the plan Markdown in the interface language * fix(desktop): translate the native startup and update error dialogs * fix(i18n): keep extension notices' text, report untitled sessions without an English title, and word the default workspace everywhere * docs(specs): record that stored names carry no translated text and the plural-form rules --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
feat: unconditional PII-free PostHog error tracking with readable stacks (#769) * feat(analytics): report sanitized exceptions through the basic PostHog sink * feat(host): report crashes, failed requests and logged errors to error tracking * feat: forward UI errors to host error tracking over client.reportError * feat(desktop): forward handled main-process errors to host error tracking * docs: document unconditional sanitized error reports in specs, README and AGENTS.md * test(artifacts): tolerate allow-listed error reports in the desktop analytics probe * feat(analytics): keep raw frames and chunk ids for PostHog symbolication * feat(web): send PostHog chunk ids with client error reports * feat(cli): embed the binary's source map for readable error stacks * feat(release): upload web and desktop-runtime source maps to PostHog * test(release): pin source-map credential scoping in the build action * docs: document source-map upload and readable error stacks * fix(analytics): carry the report's handled flag into the root exception mechanism * docs: pin client error reports to protocol v90 after rebasing onto main * feat(analytics): send a classifier instead of error message text * fix(host): wait at most 1 s for the crash report and tag the crash kind * fix(desktop): derive runtime chunk ids from the code, its map and the release * build(release): run posthog-cli only after a pinned SHA-256 check of its binary * fix: report stable boundary ids, route main's new desktop errors and scope release credentials * fix(analytics): cut the message out of every stack before the SDK parses frames --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
feat(desktop): add trackpad pinch zoom (#589) * feat(desktop): add trackpad pinch zoom * fix(web): preserve diagram pinch zoom | 1 month ago | |
feat(desktop): add trackpad pinch zoom (#589) * feat(desktop): add trackpad pinch zoom * fix(web): preserve diagram pinch zoom | 1 month ago | |
feat(desktop): themed macOS title bar merged with the ThinkRail topbar (#458) * docs(specs): record the unified desktop title bar design macOS hides the native strip and lets the web topbar be the title bar; the desktop publishes window-chrome geometry as two CSS custom properties the header consumes with 0px fallbacks, so the web client still has no desktop branch. Windows is deferred (its hiddenInset strips the native buttons), Linux keeps native decorations. * feat(desktop): publish window-chrome geometry and hide the macOS title strip Platform-pure windowChrome policy (hiddenInset + traffic lights centred in the 40px topbar, 64px reserved zone), preload writes --window-chrome-inset-left/right on <html> at document start and on the new bun→webview windowChromeChanged message, and the main process collapses the inset in native fullscreen. Preload-global injection is shared with preferences via preloadGlobals. * feat(web): make the topbar a themed window title bar with host-published insets Fixed 40px topbar row, window-drag region with no-drag interactive controls, and aria-hidden edge spacers sized by the host-published inset tokens (0px in a browser). Two geometry-sensitive e2e specs adjusted: the tall-questionnaire review viewport keeps Submit off-screen with real slack, and the newest-first history test waits for the return motion to settle before wheeling. * feat(desktop): gate header dragging on the host and replay chrome geometry per document * test(e2e): cover the topbar window-chrome contract in the browser * refactor(desktop): keep the window-chrome CSS property names module-private * fix(artifacts): tolerate half-written launcher documents in the desktop smoke | 1 month ago | |
feat(desktop): add GitHub-hosted auto-updates (#456) * docs(desktop): define auto-update policy and manual qualification * docs(desktop): simplify auto-update qualification * docs(desktop): simplify update restart to one explicit action * docs(contracts): define the native update capability boundary * feat(desktop): add GitHub-hosted auto-updates * docs: require a simplicity pass before handoff * refactor(desktop): remove duplicate updater state layers | 1 month ago | |
feat(web): add newest-first chat order (#327) * todo: Promote the approved chat-order design ThinkRail-Todo: 01a042c1-dc8d-7035-a256-21dec8a36c07/t_daf0f2326236 * todo: Write failing tests for newest-first mode ThinkRail-Todo: 01a042c1-dc8d-7035-a256-21dec8a36c07/t_f5e3d7c06afb * todo: Implement the server-synced message-order setting ThinkRail-Todo: 01a042c1-dc8d-7035-a256-21dec8a36c07/t_f8352e3e142e * todo: Implement newest-first rendering and smooth top-follow ThinkRail-Todo: 01a042c1-dc8d-7035-a256-21dec8a36c07/t_4ac0030afe08 * todo: Run full gates and review the stacked diff ThinkRail-Todo: 01a042c1-dc8d-7035-a256-21dec8a36c07/t_15673164aba4 * todo: Isolate the opt-in preference and fix scroll risks ThinkRail-Todo: 01a05321-f558-705c-810e-7fd1e94bd5f1/t_4d7d16ec4ed6 * todo: Run targeted and full verification ThinkRail-Todo: 01a05321-f558-705c-810e-7fd1e94bd5f1/t_4cdbc452875e * todo: Fix final persistence and scroll-anchor findings ThinkRail-Todo: 01a05321-f558-705c-810e-7fd1e94bd5f1/t_9609676d4bd2 * todo: Re-run verification and final diff audit ThinkRail-Todo: 01a05321-f558-705c-810e-7fd1e94bd5f1/t_d0d06ff6c361 --------- Co-authored-by: rsolmano <rinat.suleimanov@jetbrains.com> | 2 months ago | |
fix(desktop): keep the window on its origin and open external links exactly once (#1030) * fix(desktop): confine the window to its origin and open external links once on every platform * test(desktop): smoke-test that external links open once and the window stays on its origin * docs(desktop): record how navigation rules and link routing keep the window on its origin * test(desktop): report the native will-navigate verdict when the window leaves its origin The Windows desktop smoke failed with "native window left its origin for navigate" but could not say whether native navigation rules were in effect. The navigation probe now records each will-navigate detail, and that error quotes the verdicts for the probe URL (allowed:true means no rule applied). * test(desktop): judge origin confinement by main-frame commits, not probe requests On Windows the native rules cancelled the scripted navigation (will-navigate allowed:false), yet the probe server still received the GET: WebView2 documents that a cancelled navigation may still send its request. The smoke now fails only when the window commits the probe URL (did-commit-navigation, emitted by all three native layers), quoting the will-navigate verdicts. Without the rules, the smoke fails with allowed:true on macOS. | 6 days ago | |
feat(desktop): themed macOS title bar merged with the ThinkRail topbar (#458) * docs(specs): record the unified desktop title bar design macOS hides the native strip and lets the web topbar be the title bar; the desktop publishes window-chrome geometry as two CSS custom properties the header consumes with 0px fallbacks, so the web client still has no desktop branch. Windows is deferred (its hiddenInset strips the native buttons), Linux keeps native decorations. * feat(desktop): publish window-chrome geometry and hide the macOS title strip Platform-pure windowChrome policy (hiddenInset + traffic lights centred in the 40px topbar, 64px reserved zone), preload writes --window-chrome-inset-left/right on <html> at document start and on the new bun→webview windowChromeChanged message, and the main process collapses the inset in native fullscreen. Preload-global injection is shared with preferences via preloadGlobals. * feat(web): make the topbar a themed window title bar with host-published insets Fixed 40px topbar row, window-drag region with no-drag interactive controls, and aria-hidden edge spacers sized by the host-published inset tokens (0px in a browser). Two geometry-sensitive e2e specs adjusted: the tall-questionnaire review viewport keeps Submit off-screen with real slack, and the newest-first history test waits for the return motion to settle before wheeling. * feat(desktop): gate header dragging on the host and replay chrome geometry per document * test(e2e): cover the topbar window-chrome contract in the browser * refactor(desktop): keep the window-chrome CSS property names module-private * fix(artifacts): tolerate half-written launcher documents in the desktop smoke | 1 month ago | |
fix(desktop): release the menu command latch after a deadline (#1200) * fix(desktop): release the menu command latch on stale key state The repeat gate swallows menu commands while any key reads down, and its latch only released when a poll saw every key up: a key state that never clears — a KVM-over-IP or remote-desktop stack that lost the key-up packet leaves CGEventSourceKeyState reading a phantom key forever — permanently disabled every gated menu command (Settings, Close, and their accelerators) while role-handled shortcuts like quit kept working, until an app restart cleared the in-memory latch (#1199). Distinguish a held key from a stale one by event freshness, not time: a genuinely held non-modifier key auto-repeats and keeps producing key-down events, so the latch now also releases when the state claims a key is down but no key-down event has arrived for 750 ms — a signature only a lost key-up produces. The desktop guarantee that a held key never fires a command twice is preserved exactly: real repeats keep the events (and the latch) flowing. - keyState: exposes sinceKeyDown (seconds, null when unreadable) - repeatGate: releases on release or staleness; unreadable freshness falls back to trusting the state - index.ts: wires readKeys().sinceKeyDown - tests: repeat-keeps-latched, stale-releases, unreadable fallback, plus the pre-existing release/unreadable cases * docs(desktop): state the repeat gate's staleness release in the SPEC The native-menu section described the latch purely as 'until no non-modifier key is down'; the stale-state release (no key-down event for 750 ms while a key still reads down) is now recorded alongside the repeat guarantee it preserves (#1199 review). * Raise the repeat gate's stale-key release to 2.5 s so a long macOS delay-until-repeat cannot fire a held command twice, and move its rationale out of comments into the SPEC. * Assert the tall questionnaire's follow state against the reader's actual edge distance, since wheeling to the bottom-most Submit row can legitimately re-attach follow. --------- Co-authored-by: OLavrik <Olya_lavrik@inbox.ru> | 2 days ago | |
feat(desktop): add confirmed quit and in-app close shortcuts (#609) * feat(desktop): add confirmed quit and in-app close shortcuts Cmd+Q did nothing on macOS because Electrobun role menu items get no default accelerator. Quit now needs a 1.2s hold or a double press and fires on release, with a centered hint; menu, Dock, and update quits stay direct and share the existing quit coordinator. Shortcuts follow VS Code: Cmd+Q / Linux Ctrl+Q quit (confirmed); Cmd+W, Win/Linux Ctrl+W and Ctrl+F4 close the focused dialog or tab through the tab X-button path and never close the window. Hide, Hide Others, and Minimize get their macOS accelerators. The confirmation rules live once in contracts (quitConfirmation); macOS feeds them CoreGraphics key state because menu events repeat without a repeat flag, Linux feeds them web key events. A web shortcut command table serves native commands and Win/Linux keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(web): deliver close requests through a channel, not a prop Cmd+W bumped a closeRequestKey state in Shell, re-rendering Shell, WorkspaceWorkbench and Workbench per press. A shell-owned closeRequestChannel now fires the request; Workbench gets it via an injected subscribeCloseRequest prop, so layout stays props-driven and the mount-time stale-key rule goes away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(web): move quit hint state into an AppShortcuts leaf Shell no longer calls useAppShortcuts. The AppShortcuts leaf runs the hook and renders QuitHintOverlay, so quit hint changes re-render only that leaf. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(web): skip terminal check and key listeners when no chord can match matchShortcut now takes a lazy terminal check and calls it only after a chord matches. useAppShortcuts adds window keydown/keyup listeners only on platforms whose table binds web chords (windows, linux), so macOS desktop has none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(web): note synthetic Escape contract for close-item close-item dismisses layers with an untrusted Escape. Spell out what each dismissible layer must do to keep closing on the shortcut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: state contracts runtime as a rule, not a list Decision #3 named one function and its injection details. It now states the rule (types plus small dependency-free runtime) and points to the contracts spec for the list. README no longer says types-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(web): match close and quit chords on the typed letter On AZERTY/Dvorak the KeyW/KeyQ positions type other letters, so Ctrl+Z closed tabs and double Ctrl+A in a Linux terminal quit the app. Letter chords now match event.key, falling back to code for non-Latin layouts. The quit hold releases on the keyup of the physical key that started it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): count only press-time keys as the quit hold A key pressed after Command-Q no longer completes the hold. The hold tracks the non-modifier keys down when the menu action fired, so it stays layout-independent. Key-repeat presses never add keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(web): find history overlay by focused group id, not nearest element The tab strip shares data-group-id with its group root, so closest() from a focused tab returned the strip and missed the overlay; close-item then closed the chat. Match every element with the focused group id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(contracts): pin quit timings and cover a short hold Assert QUIT_CONFIRMATION matches the documented 1200/500/40 ms values, and check that a hold released before the threshold never quits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: describe contracts runtime use and AppShortcuts mount Shell, web, and desktop specs said contracts is types-only, but both import createQuitConfirmation. Shell always mounts AppShortcuts; the hook is inert without the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): quit directly on a keyboard or VoiceOver menu pick With Command up, a last key-down newer than the last modifier change means the Quit item was picked from the menu by keyboard, not by Command-Q. A late-handled tap still arms: its Command release is newer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(e2e): wait on terminal output instead of fixed sleeps The busy-close step waits for a computed marker printed by the child shell. The terminal Ctrl+W step checks the shell erased a word. Use pressPlatformShortcut for the new-workspace chord. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): cover key-state decoding and the shortcuts bridge Split CoreGraphics reads from a pure decodeKeyState and test the modifier keycode range, Command flag, and event-age ordering. Test createShortcutsBridge pub/sub directly. Type the e2e bridge stub as NativeShortcutsBridge so drift fails typecheck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: name contracts runtime exceptions instead of allowing any pure rule --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Rinat S <rinat.suleimanov@jetbrains.com> | 1 month ago | |
fix(desktop): release the menu command latch after a deadline (#1200) * fix(desktop): release the menu command latch on stale key state The repeat gate swallows menu commands while any key reads down, and its latch only released when a poll saw every key up: a key state that never clears — a KVM-over-IP or remote-desktop stack that lost the key-up packet leaves CGEventSourceKeyState reading a phantom key forever — permanently disabled every gated menu command (Settings, Close, and their accelerators) while role-handled shortcuts like quit kept working, until an app restart cleared the in-memory latch (#1199). Distinguish a held key from a stale one by event freshness, not time: a genuinely held non-modifier key auto-repeats and keeps producing key-down events, so the latch now also releases when the state claims a key is down but no key-down event has arrived for 750 ms — a signature only a lost key-up produces. The desktop guarantee that a held key never fires a command twice is preserved exactly: real repeats keep the events (and the latch) flowing. - keyState: exposes sinceKeyDown (seconds, null when unreadable) - repeatGate: releases on release or staleness; unreadable freshness falls back to trusting the state - index.ts: wires readKeys().sinceKeyDown - tests: repeat-keeps-latched, stale-releases, unreadable fallback, plus the pre-existing release/unreadable cases * docs(desktop): state the repeat gate's staleness release in the SPEC The native-menu section described the latch purely as 'until no non-modifier key is down'; the stale-state release (no key-down event for 750 ms while a key still reads down) is now recorded alongside the repeat guarantee it preserves (#1199 review). * Raise the repeat gate's stale-key release to 2.5 s so a long macOS delay-until-repeat cannot fire a held command twice, and move its rationale out of comments into the SPEC. * Assert the tall questionnaire's follow state against the reader's actual edge distance, since wheeling to the bottom-most Submit row can legitimately re-attach follow. --------- Co-authored-by: OLavrik <Olya_lavrik@inbox.ru> | 2 days ago | |
fix(desktop): release the menu command latch after a deadline (#1200) * fix(desktop): release the menu command latch on stale key state The repeat gate swallows menu commands while any key reads down, and its latch only released when a poll saw every key up: a key state that never clears — a KVM-over-IP or remote-desktop stack that lost the key-up packet leaves CGEventSourceKeyState reading a phantom key forever — permanently disabled every gated menu command (Settings, Close, and their accelerators) while role-handled shortcuts like quit kept working, until an app restart cleared the in-memory latch (#1199). Distinguish a held key from a stale one by event freshness, not time: a genuinely held non-modifier key auto-repeats and keeps producing key-down events, so the latch now also releases when the state claims a key is down but no key-down event has arrived for 750 ms — a signature only a lost key-up produces. The desktop guarantee that a held key never fires a command twice is preserved exactly: real repeats keep the events (and the latch) flowing. - keyState: exposes sinceKeyDown (seconds, null when unreadable) - repeatGate: releases on release or staleness; unreadable freshness falls back to trusting the state - index.ts: wires readKeys().sinceKeyDown - tests: repeat-keeps-latched, stale-releases, unreadable fallback, plus the pre-existing release/unreadable cases * docs(desktop): state the repeat gate's staleness release in the SPEC The native-menu section described the latch purely as 'until no non-modifier key is down'; the stale-state release (no key-down event for 750 ms while a key still reads down) is now recorded alongside the repeat guarantee it preserves (#1199 review). * Raise the repeat gate's stale-key release to 2.5 s so a long macOS delay-until-repeat cannot fire a held command twice, and move its rationale out of comments into the SPEC. * Assert the tall questionnaire's follow state against the reader's actual edge distance, since wheeling to the bottom-most Submit row can legitimately re-attach follow. --------- Co-authored-by: OLavrik <Olya_lavrik@inbox.ru> | 2 days ago | |
feat(desktop): package ThinkRail as an Electrobun app (#317) * todo: Promote the approved desktop architecture ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_44fa5c64dcc4 * todo: Implement the Electrobun package and runtime ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_95ec4db0a29a * todo: Add packaging and desktop coverage ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_7ab33dbfe2ca * todo: Run all gates and review the final diff ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_1a397cf79389 * todo: Record and promote the approved menu design ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_d74f3263a760 * todo: Implement the native application menu ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_14f62292581a * todo: Add regression coverage ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_bba36e4af871 * todo: Run gates and review the complete diff ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_1f0975890932 * todo: Record and validate the approved design ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_882644532c0b * todo: Promote the decision across owning specs ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_90686630ca71 * todo: Add code-level boundary enforcement for launchers ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_fec4bc0ec29e * todo: Run gates and review the complete change ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_0b7d16b32cba * todo: Validate the latest main integration ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_04a51b278128 * test(e2e): reveal recalled turn after settlement --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 2 months ago | |
feat(desktop): package ThinkRail as an Electrobun app (#317) * todo: Promote the approved desktop architecture ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_44fa5c64dcc4 * todo: Implement the Electrobun package and runtime ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_95ec4db0a29a * todo: Add packaging and desktop coverage ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_7ab33dbfe2ca * todo: Run all gates and review the final diff ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_1a397cf79389 * todo: Record and promote the approved menu design ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_d74f3263a760 * todo: Implement the native application menu ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_14f62292581a * todo: Add regression coverage ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_bba36e4af871 * todo: Run gates and review the complete diff ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_1f0975890932 * todo: Record and validate the approved design ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_882644532c0b * todo: Promote the decision across owning specs ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_90686630ca71 * todo: Add code-level boundary enforcement for launchers ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_fec4bc0ec29e * todo: Run gates and review the complete change ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_0b7d16b32cba * todo: Validate the latest main integration ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_04a51b278128 * test(e2e): reveal recalled turn after settlement --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 2 months ago | |
fix(desktop): make Windows updates install and show the install journey across the restart (#803) * fix(desktop): start the host outside the app bundle so Windows updates can swap it * docs(desktop): record why startup leaves the app bundle before the host boots * feat(desktop): report install steps, a saved log, and the result after an update relaunch * feat(web): show the installer dialog, the update result, and failure recovery across the restart * feat(desktop): show a startup splash that names a pending update until the app window is ready * fix(desktop): close the startup splash when the main window closes early, and track one install attempt * docs: describe the native update install journey in the desktop, web and contracts specs and README * refactor: render the update install journey and startup splash text from locale keys * fix: carry update install-log entries as structured events the web translates | 16 days ago | |
build(ts): turn on unused, implicit-return and fallthrough tsc checks (#790) * build(ts): enable unused, implicit-return, and fallthrough checks in the base tsconfig Turn on noImplicitReturns, noUnusedLocals, noUnusedParameters, noFallthroughCasesInSwitch, allowUnreachableCode: false, and allowUnusedLabels: false for every project. Fix the four existing hits. Desktop keeps noImplicitReturns off because the Electrobun SDK sources it compiles fail that check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * build(ts): fix unused declarations upstream added since the checks were enabled * build(ts): keep desktop's own source clean under noImplicitReturns The desktop noImplicitReturns override hid one desktop site besides the two Electrobun SDK functions: runtimeSourceMap.test.ts's frameOf. An explicit annotation lets control flow see explode() never returns, so only the SDK sources need the override. The desktop spec now states when the override goes away (blackboardsh/electrobun#590). * docs(desktop): record the noImplicitReturns override as approved and temporary The override cannot be scoped to the Electrobun SDK files, so it also stops checking desktop's own source. Remove it once an Electrobun release ships blackboardsh/electrobun#590. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 14 days ago | |
feat: unconditional PII-free PostHog error tracking with readable stacks (#769) * feat(analytics): report sanitized exceptions through the basic PostHog sink * feat(host): report crashes, failed requests and logged errors to error tracking * feat: forward UI errors to host error tracking over client.reportError * feat(desktop): forward handled main-process errors to host error tracking * docs: document unconditional sanitized error reports in specs, README and AGENTS.md * test(artifacts): tolerate allow-listed error reports in the desktop analytics probe * feat(analytics): keep raw frames and chunk ids for PostHog symbolication * feat(web): send PostHog chunk ids with client error reports * feat(cli): embed the binary's source map for readable error stacks * feat(release): upload web and desktop-runtime source maps to PostHog * test(release): pin source-map credential scoping in the build action * docs: document source-map upload and readable error stacks * fix(analytics): carry the report's handled flag into the root exception mechanism * docs: pin client error reports to protocol v90 after rebasing onto main * feat(analytics): send a classifier instead of error message text * fix(host): wait at most 1 s for the crash report and tag the crash kind * fix(desktop): derive runtime chunk ids from the code, its map and the release * build(release): run posthog-cli only after a pinned SHA-256 check of its binary * fix: report stable boundary ids, route main's new desktop errors and scope release credentials * fix(analytics): cut the message out of every stack before the SDK parses frames --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
feat(desktop): package ThinkRail as an Electrobun app (#317) * todo: Promote the approved desktop architecture ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_44fa5c64dcc4 * todo: Implement the Electrobun package and runtime ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_95ec4db0a29a * todo: Add packaging and desktop coverage ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_7ab33dbfe2ca * todo: Run all gates and review the final diff ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_1a397cf79389 * todo: Record and promote the approved menu design ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_d74f3263a760 * todo: Implement the native application menu ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_14f62292581a * todo: Add regression coverage ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_bba36e4af871 * todo: Run gates and review the complete diff ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_1f0975890932 * todo: Record and validate the approved design ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_882644532c0b * todo: Promote the decision across owning specs ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_90686630ca71 * todo: Add code-level boundary enforcement for launchers ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_fec4bc0ec29e * todo: Run gates and review the complete change ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_0b7d16b32cba * todo: Validate the latest main integration ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_04a51b278128 * test(e2e): reveal recalled turn after settlement --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 2 months ago | |
feat(desktop): package ThinkRail as an Electrobun app (#317) * todo: Promote the approved desktop architecture ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_44fa5c64dcc4 * todo: Implement the Electrobun package and runtime ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_95ec4db0a29a * todo: Add packaging and desktop coverage ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_7ab33dbfe2ca * todo: Run all gates and review the final diff ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_1a397cf79389 * todo: Record and promote the approved menu design ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_d74f3263a760 * todo: Implement the native application menu ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_14f62292581a * todo: Add regression coverage ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_bba36e4af871 * todo: Run gates and review the complete diff ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_1f0975890932 * todo: Record and validate the approved design ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_882644532c0b * todo: Promote the decision across owning specs ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_90686630ca71 * todo: Add code-level boundary enforcement for launchers ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_fec4bc0ec29e * todo: Run gates and review the complete change ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_0b7d16b32cba * todo: Validate the latest main integration ThinkRail-Todo: 01a0247a-cd52-785c-917b-106f5a75dfc8/t_04a51b278128 * test(e2e): reveal recalled turn after settlement --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 2 months ago | |
feat: unconditional PII-free PostHog error tracking with readable stacks (#769) * feat(analytics): report sanitized exceptions through the basic PostHog sink * feat(host): report crashes, failed requests and logged errors to error tracking * feat: forward UI errors to host error tracking over client.reportError * feat(desktop): forward handled main-process errors to host error tracking * docs: document unconditional sanitized error reports in specs, README and AGENTS.md * test(artifacts): tolerate allow-listed error reports in the desktop analytics probe * feat(analytics): keep raw frames and chunk ids for PostHog symbolication * feat(web): send PostHog chunk ids with client error reports * feat(cli): embed the binary's source map for readable error stacks * feat(release): upload web and desktop-runtime source maps to PostHog * test(release): pin source-map credential scoping in the build action * docs: document source-map upload and readable error stacks * fix(analytics): carry the report's handled flag into the root exception mechanism * docs: pin client error reports to protocol v90 after rebasing onto main * feat(analytics): send a classifier instead of error message text * fix(host): wait at most 1 s for the crash report and tag the crash kind * fix(desktop): derive runtime chunk ids from the code, its map and the release * build(release): run posthog-cli only after a pinned SHA-256 check of its binary * fix: report stable boundary ids, route main's new desktop errors and scope release credentials * fix(analytics): cut the message out of every stack before the SDK parses frames --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
feat(desktop): add confirmed quit and in-app close shortcuts (#609) * feat(desktop): add confirmed quit and in-app close shortcuts Cmd+Q did nothing on macOS because Electrobun role menu items get no default accelerator. Quit now needs a 1.2s hold or a double press and fires on release, with a centered hint; menu, Dock, and update quits stay direct and share the existing quit coordinator. Shortcuts follow VS Code: Cmd+Q / Linux Ctrl+Q quit (confirmed); Cmd+W, Win/Linux Ctrl+W and Ctrl+F4 close the focused dialog or tab through the tab X-button path and never close the window. Hide, Hide Others, and Minimize get their macOS accelerators. The confirmation rules live once in contracts (quitConfirmation); macOS feeds them CoreGraphics key state because menu events repeat without a repeat flag, Linux feeds them web key events. A web shortcut command table serves native commands and Win/Linux keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(web): deliver close requests through a channel, not a prop Cmd+W bumped a closeRequestKey state in Shell, re-rendering Shell, WorkspaceWorkbench and Workbench per press. A shell-owned closeRequestChannel now fires the request; Workbench gets it via an injected subscribeCloseRequest prop, so layout stays props-driven and the mount-time stale-key rule goes away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(web): move quit hint state into an AppShortcuts leaf Shell no longer calls useAppShortcuts. The AppShortcuts leaf runs the hook and renders QuitHintOverlay, so quit hint changes re-render only that leaf. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(web): skip terminal check and key listeners when no chord can match matchShortcut now takes a lazy terminal check and calls it only after a chord matches. useAppShortcuts adds window keydown/keyup listeners only on platforms whose table binds web chords (windows, linux), so macOS desktop has none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(web): note synthetic Escape contract for close-item close-item dismisses layers with an untrusted Escape. Spell out what each dismissible layer must do to keep closing on the shortcut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: state contracts runtime as a rule, not a list Decision #3 named one function and its injection details. It now states the rule (types plus small dependency-free runtime) and points to the contracts spec for the list. README no longer says types-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(web): match close and quit chords on the typed letter On AZERTY/Dvorak the KeyW/KeyQ positions type other letters, so Ctrl+Z closed tabs and double Ctrl+A in a Linux terminal quit the app. Letter chords now match event.key, falling back to code for non-Latin layouts. The quit hold releases on the keyup of the physical key that started it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): count only press-time keys as the quit hold A key pressed after Command-Q no longer completes the hold. The hold tracks the non-modifier keys down when the menu action fired, so it stays layout-independent. Key-repeat presses never add keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(web): find history overlay by focused group id, not nearest element The tab strip shares data-group-id with its group root, so closest() from a focused tab returned the strip and missed the overlay; close-item then closed the chat. Match every element with the focused group id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(contracts): pin quit timings and cover a short hold Assert QUIT_CONFIRMATION matches the documented 1200/500/40 ms values, and check that a hold released before the threshold never quits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: describe contracts runtime use and AppShortcuts mount Shell, web, and desktop specs said contracts is types-only, but both import createQuitConfirmation. Shell always mounts AppShortcuts; the hook is inert without the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): quit directly on a keyboard or VoiceOver menu pick With Command up, a last key-down newer than the last modifier change means the Quit item was picked from the menu by keyboard, not by Command-Q. A late-handled tap still arms: its Command release is newer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(e2e): wait on terminal output instead of fixed sleeps The busy-close step waits for a computed marker printed by the child shell. The terminal Ctrl+W step checks the shell erased a word. Use pressPlatformShortcut for the new-workspace chord. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): cover key-state decoding and the shortcuts bridge Split CoreGraphics reads from a pure decodeKeyState and test the modifier keycode range, Command flag, and event-age ordering. Test createShortcutsBridge pub/sub directly. Type the e2e bridge stub as NativeShortcutsBridge so drift fails typecheck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: name contracts runtime exceptions instead of allowing any pure rule --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Rinat S <rinat.suleimanov@jetbrains.com> | 1 month ago | |
feat(desktop): add confirmed quit and in-app close shortcuts (#609) * feat(desktop): add confirmed quit and in-app close shortcuts Cmd+Q did nothing on macOS because Electrobun role menu items get no default accelerator. Quit now needs a 1.2s hold or a double press and fires on release, with a centered hint; menu, Dock, and update quits stay direct and share the existing quit coordinator. Shortcuts follow VS Code: Cmd+Q / Linux Ctrl+Q quit (confirmed); Cmd+W, Win/Linux Ctrl+W and Ctrl+F4 close the focused dialog or tab through the tab X-button path and never close the window. Hide, Hide Others, and Minimize get their macOS accelerators. The confirmation rules live once in contracts (quitConfirmation); macOS feeds them CoreGraphics key state because menu events repeat without a repeat flag, Linux feeds them web key events. A web shortcut command table serves native commands and Win/Linux keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(web): deliver close requests through a channel, not a prop Cmd+W bumped a closeRequestKey state in Shell, re-rendering Shell, WorkspaceWorkbench and Workbench per press. A shell-owned closeRequestChannel now fires the request; Workbench gets it via an injected subscribeCloseRequest prop, so layout stays props-driven and the mount-time stale-key rule goes away. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * refactor(web): move quit hint state into an AppShortcuts leaf Shell no longer calls useAppShortcuts. The AppShortcuts leaf runs the hook and renders QuitHintOverlay, so quit hint changes re-render only that leaf. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * perf(web): skip terminal check and key listeners when no chord can match matchShortcut now takes a lazy terminal check and calls it only after a chord matches. useAppShortcuts adds window keydown/keyup listeners only on platforms whose table binds web chords (windows, linux), so macOS desktop has none. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(web): note synthetic Escape contract for close-item close-item dismisses layers with an untrusted Escape. Spell out what each dismissible layer must do to keep closing on the shortcut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: state contracts runtime as a rule, not a list Decision #3 named one function and its injection details. It now states the rule (types plus small dependency-free runtime) and points to the contracts spec for the list. README no longer says types-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(web): match close and quit chords on the typed letter On AZERTY/Dvorak the KeyW/KeyQ positions type other letters, so Ctrl+Z closed tabs and double Ctrl+A in a Linux terminal quit the app. Letter chords now match event.key, falling back to code for non-Latin layouts. The quit hold releases on the keyup of the physical key that started it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): count only press-time keys as the quit hold A key pressed after Command-Q no longer completes the hold. The hold tracks the non-modifier keys down when the menu action fired, so it stays layout-independent. Key-repeat presses never add keys. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(web): find history overlay by focused group id, not nearest element The tab strip shares data-group-id with its group root, so closest() from a focused tab returned the strip and missed the overlay; close-item then closed the chat. Match every element with the focused group id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(contracts): pin quit timings and cover a short hold Assert QUIT_CONFIRMATION matches the documented 1200/500/40 ms values, and check that a hold released before the threshold never quits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: describe contracts runtime use and AppShortcuts mount Shell, web, and desktop specs said contracts is types-only, but both import createQuitConfirmation. Shell always mounts AppShortcuts; the hook is inert without the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(desktop): quit directly on a keyboard or VoiceOver menu pick With Command up, a last key-down newer than the last modifier change means the Quit item was picked from the menu by keyboard, not by Command-Q. A late-handled tap still arms: its Command release is newer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(e2e): wait on terminal output instead of fixed sleeps The busy-close step waits for a computed marker printed by the child shell. The terminal Ctrl+W step checks the shell erased a word. Use pressPlatformShortcut for the new-workspace chord. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(desktop): cover key-state decoding and the shortcuts bridge Split CoreGraphics reads from a pure decodeKeyState and test the modifier keycode range, Command flag, and event-age ordering. Test createShortcutsBridge pub/sub directly. Type the e2e bridge stub as NativeShortcutsBridge so drift fails typecheck. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: name contracts runtime exceptions instead of allowing any pure rule --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Rinat S <rinat.suleimanov@jetbrains.com> | 1 month ago | |
fix(desktop): make Windows updates install and show the install journey across the restart (#803) * fix(desktop): start the host outside the app bundle so Windows updates can swap it * docs(desktop): record why startup leaves the app bundle before the host boots * feat(desktop): report install steps, a saved log, and the result after an update relaunch * feat(web): show the installer dialog, the update result, and failure recovery across the restart * feat(desktop): show a startup splash that names a pending update until the app window is ready * fix(desktop): close the startup splash when the main window closes early, and track one install attempt * docs: describe the native update install journey in the desktop, web and contracts specs and README * refactor: render the update install journey and startup splash text from locale keys * fix: carry update install-log entries as structured events the web translates | 16 days ago | |
fix(desktop): make Windows updates install and show the install journey across the restart (#803) * fix(desktop): start the host outside the app bundle so Windows updates can swap it * docs(desktop): record why startup leaves the app bundle before the host boots * feat(desktop): report install steps, a saved log, and the result after an update relaunch * feat(web): show the installer dialog, the update result, and failure recovery across the restart * feat(desktop): show a startup splash that names a pending update until the app window is ready * fix(desktop): close the startup splash when the main window closes early, and track one install attempt * docs: describe the native update install journey in the desktop, web and contracts specs and README * refactor: render the update install journey and startup splash text from locale keys * fix: carry update install-log entries as structured events the web translates | 16 days ago | |
perf(shared): probe the login-shell env without blocking desktop boot (#791) * perf(shared): resolve the login-shell env asynchronously The login-shell probe ran through Bun.spawnSync and blocked the event loop for the whole rc-file run. It now runs through Bun.spawn behind one promise cached on a Symbol.for global key, so the desktop shell and its server bundle share one run. Desktop start() begins it before the server bundle import; bootHost begins it before initLogging and awaits it before the Central init. The stdout read stops 100ms after the shell exits, so a background job holding the pipe cannot stall boot. The probe timeout kills with SIGKILL, since interactive shells ignore the default SIGTERM. * fix(shared): trust the login-shell env only up to its end marker and kill a hung probe's group The probe prints LOGIN_ENV_END after env -0 and the read stops there; output without it is a failed probe, so a stalled or cut-off read can no longer apply a truncated PATH or drop variables. The deadline now SIGKILLs the probe's process group, so a hung rc command does not outlive its shell. loginShellProbe(timeout) lets tests drive that deadline. Tests no longer depend on wall-clock timing or leak jobs: the event-loop test waits on a gate file, the background-job and hung-shell tests kill their jobs, and startup.test.ts mocks the probe instead of running the developer's $SHELL, pinning that it starts after cwd leaves the bundle. Drops the index.ts comment that restated apps/desktop/SPEC.md. * fix(shared): keep draining the login shell after its end marker Stopping the read at the marker left the shell blocked on a full pipe when an EXIT trap or logout file wrote more than the buffer, so both probes hit the deadline and the login env was lost. Bytes after the marker are now drained and discarded until the shell exits; once it has exited with the marker read, the read is cancelled. --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 13 days ago | |
fix(desktop): honor the macOS title-bar double-click action on the topbar (#562) * docs(desktop): specify macOS title-bar double-click behavior * fix(desktop): honor the macOS title-bar double-click action on the topbar Forward drag-region double-clicks from the desktop preload and apply the AppleActionOnDoubleClick setting (Zoom/Fill toggle zoom, Minimize, Do Nothing). Cover it end to end in the native desktop smoke on macOS, and pre-create the smoke's isolated home so the hidden macOS window reaches DOM-ready. Closes #556 * docs(desktop): link the upstream Electrobun double-click issue | 1 month ago | |
feat: unconditional PII-free PostHog error tracking with readable stacks (#769) * feat(analytics): report sanitized exceptions through the basic PostHog sink * feat(host): report crashes, failed requests and logged errors to error tracking * feat: forward UI errors to host error tracking over client.reportError * feat(desktop): forward handled main-process errors to host error tracking * docs: document unconditional sanitized error reports in specs, README and AGENTS.md * test(artifacts): tolerate allow-listed error reports in the desktop analytics probe * feat(analytics): keep raw frames and chunk ids for PostHog symbolication * feat(web): send PostHog chunk ids with client error reports * feat(cli): embed the binary's source map for readable error stacks * feat(release): upload web and desktop-runtime source maps to PostHog * test(release): pin source-map credential scoping in the build action * docs: document source-map upload and readable error stacks * fix(analytics): carry the report's handled flag into the root exception mechanism * docs: pin client error reports to protocol v90 after rebasing onto main * feat(analytics): send a classifier instead of error message text * fix(host): wait at most 1 s for the crash report and tag the crash kind * fix(desktop): derive runtime chunk ids from the code, its map and the release * build(release): run posthog-cli only after a pinned SHA-256 check of its binary * fix: report stable boundary ids, route main's new desktop errors and scope release credentials * fix(analytics): cut the message out of every stack before the SDK parses frames --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 16 days ago | |
feat(desktop): frameless Windows title bar with HTML window controls (#536) * feat(contracts): add the optional native window-controls capability * feat(desktop): frameless Windows title bar with HTML window controls over RPC * docs(desktop): record the Windows frameless title bar and bind its user32 symbols in CI * test(e2e): drive the HTML window controls through a fake native bridge * refactor(desktop): keep the Win32 frame constants module-private * fix(desktop): keep the title-bar double-click handler macOS-only * fix(web): never let the initial window-state snapshot overwrite a fresher push * fix(desktop): verify the Windows frame style by reading it back * fix(desktop): route Windows webview RPC through the native host bridge * test(desktop): probe the HTML window controls in Windows native smoke * test(desktop): settle the Windows window-controls probe before asserting --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 1 month ago | |
feat(desktop): frameless Windows title bar with HTML window controls (#536) * feat(contracts): add the optional native window-controls capability * feat(desktop): frameless Windows title bar with HTML window controls over RPC * docs(desktop): record the Windows frameless title bar and bind its user32 symbols in CI * test(e2e): drive the HTML window controls through a fake native bridge * refactor(desktop): keep the Win32 frame constants module-private * fix(desktop): keep the title-bar double-click handler macOS-only * fix(web): never let the initial window-state snapshot overwrite a fresher push * fix(desktop): verify the Windows frame style by reading it back * fix(desktop): route Windows webview RPC through the native host bridge * test(desktop): probe the HTML window controls in Windows native smoke * test(desktop): settle the Windows window-controls probe before asserting --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 1 month ago | |
fix(desktop): rebrand Windows executables whose signature entry outlived its bytes (#946) * fix(desktop): rebrand Windows executables whose signature entry outlived its bytes * ci: build and smoke the desktop app on Windows * docs(specs): record Windows desktop CI and the stale signature entry Hutch leaves | 11 days ago | |
fix(desktop): rebrand Windows executables whose signature entry outlived its bytes (#946) * fix(desktop): rebrand Windows executables whose signature entry outlived its bytes * ci: build and smoke the desktop app on Windows * docs(specs): record Windows desktop CI and the stale signature entry Hutch leaves | 11 days ago | |
feat(desktop): frameless Windows title bar with HTML window controls (#536) * feat(contracts): add the optional native window-controls capability * feat(desktop): frameless Windows title bar with HTML window controls over RPC * docs(desktop): record the Windows frameless title bar and bind its user32 symbols in CI * test(e2e): drive the HTML window controls through a fake native bridge * refactor(desktop): keep the Win32 frame constants module-private * fix(desktop): keep the title-bar double-click handler macOS-only * fix(web): never let the initial window-state snapshot overwrite a fresher push * fix(desktop): verify the Windows frame style by reading it back * fix(desktop): route Windows webview RPC through the native host bridge * test(desktop): probe the HTML window controls in Windows native smoke * test(desktop): settle the Windows window-controls probe before asserting --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 1 month ago | |
feat(desktop): frameless Windows title bar with HTML window controls (#536) * feat(contracts): add the optional native window-controls capability * feat(desktop): frameless Windows title bar with HTML window controls over RPC * docs(desktop): record the Windows frameless title bar and bind its user32 symbols in CI * test(e2e): drive the HTML window controls through a fake native bridge * refactor(desktop): keep the Win32 frame constants module-private * fix(desktop): keep the title-bar double-click handler macOS-only * fix(web): never let the initial window-state snapshot overwrite a fresher push * fix(desktop): verify the Windows frame style by reading it back * fix(desktop): route Windows webview RPC through the native host bridge * test(desktop): probe the HTML window controls in Windows native smoke * test(desktop): settle the Windows window-controls probe before asserting --------- Co-authored-by: danyaberezun <danya.berezun@gmail.com> | 1 month ago | |
test: stop the Windows desktop smoke and real-shortcut test flakes (#1112) * test(artifact-tests): give the desktop smoke's cold first DOM-ready a 120 s budget On the win25-vs2026/20261030.294 Windows runner image a cold WebView2 profile reached its first DOM-ready in 8-30 s when it passed and missed the 30 s deadline in half the sampled runs (#1108). Each launch now logs its time to ready, so the remaining headroom shows in CI. * test(desktop): give the real-shortcut stamp test a 30 s PowerShell budget It starts powershell.exe four times under Bun's default 5 s timeout; a stalled PowerShell start on a slow Windows runner killed it mid-call and surfaced as a blank `Error:`. Failures now carry the exit code and signal. | 6 days ago | |
fix: show ThinkRail's icon and name on Windows executables instead of Bun's (#881) * feat(shared): derive Windows file properties from the release identity * fix(desktop): order the Windows icon's frames largest first * fix(cli): stamp ThinkRail's icon and file properties on the Windows binary * test(artifact-tests): check the Windows CLI binary's icon and file properties * fix(desktop): brand bun.exe, launcher.exe and the uninstaller as ThinkRail * fix(desktop): set the Windows window icon that Electrobun leaves unset * docs(specs): record how Windows executables get ThinkRail's identity * fix(desktop): add the DPI-scale frames to the Windows icon and pin signed-PE branding * fix(desktop): group a pinned ThinkRail and its window on the Windows taskbar (#883) * fix(desktop): give the Windows process an explicit AppUserModelID * fix(desktop): stamp ThinkRail shortcuts and pins with the process AppUserModelID * docs(specs): record the Windows taskbar identity * refactor(desktop): read Electrobun's shortcut manifest without a type cast * fix(desktop): match a shortcut's target by its canonical Windows path * fix(desktop): harden the taskbar-identity stamp after review * refactor: move the native icon set to packages/shared * fix(desktop): cache COM thunks, open shortcuts read-only until a stamp is needed, defer the taskbar stamp past readiness, and harden the Windows identity checks --------- Co-authored-by: OLavrik <Olya_lavrik@inbox.ru> | 12 days ago | |
fix: show ThinkRail's icon and name on Windows executables instead of Bun's (#881) * feat(shared): derive Windows file properties from the release identity * fix(desktop): order the Windows icon's frames largest first * fix(cli): stamp ThinkRail's icon and file properties on the Windows binary * test(artifact-tests): check the Windows CLI binary's icon and file properties * fix(desktop): brand bun.exe, launcher.exe and the uninstaller as ThinkRail * fix(desktop): set the Windows window icon that Electrobun leaves unset * docs(specs): record how Windows executables get ThinkRail's identity * fix(desktop): add the DPI-scale frames to the Windows icon and pin signed-PE branding * fix(desktop): group a pinned ThinkRail and its window on the Windows taskbar (#883) * fix(desktop): give the Windows process an explicit AppUserModelID * fix(desktop): stamp ThinkRail shortcuts and pins with the process AppUserModelID * docs(specs): record the Windows taskbar identity * refactor(desktop): read Electrobun's shortcut manifest without a type cast * fix(desktop): match a shortcut's target by its canonical Windows path * fix(desktop): harden the taskbar-identity stamp after review * refactor: move the native icon set to packages/shared * fix(desktop): cache COM thunks, open shortcuts read-only until a stamp is needed, defer the taskbar stamp past readiness, and harden the Windows identity checks --------- Co-authored-by: OLavrik <Olya_lavrik@inbox.ru> | 12 days ago | |
fix: show ThinkRail's icon and name on Windows executables instead of Bun's (#881) * feat(shared): derive Windows file properties from the release identity * fix(desktop): order the Windows icon's frames largest first * fix(cli): stamp ThinkRail's icon and file properties on the Windows binary * test(artifact-tests): check the Windows CLI binary's icon and file properties * fix(desktop): brand bun.exe, launcher.exe and the uninstaller as ThinkRail * fix(desktop): set the Windows window icon that Electrobun leaves unset * docs(specs): record how Windows executables get ThinkRail's identity * fix(desktop): add the DPI-scale frames to the Windows icon and pin signed-PE branding * fix(desktop): group a pinned ThinkRail and its window on the Windows taskbar (#883) * fix(desktop): give the Windows process an explicit AppUserModelID * fix(desktop): stamp ThinkRail shortcuts and pins with the process AppUserModelID * docs(specs): record the Windows taskbar identity * refactor(desktop): read Electrobun's shortcut manifest without a type cast * fix(desktop): match a shortcut's target by its canonical Windows path * fix(desktop): harden the taskbar-identity stamp after review * refactor: move the native icon set to packages/shared * fix(desktop): cache COM thunks, open shortcuts read-only until a stamp is needed, defer the taskbar stamp past readiness, and harden the Windows identity checks --------- Co-authored-by: OLavrik <Olya_lavrik@inbox.ru> | 12 days ago |
| Files | Last commit | Last update |
|---|---|---|
| 12 days ago | ||
| 16 days ago | ||
| 16 days ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 12 days ago | ||
| 16 days ago | ||
| 16 days ago | ||
| 6 days ago | ||
| 6 days ago | ||
| 2 days ago | ||
| 1 month ago | ||
| 2 days ago | ||
| 16 days ago | ||
| 16 days ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 2 months ago | ||
| 6 days ago | ||
| 1 month ago | ||
| 2 days ago | ||
| 1 month ago | ||
| 2 days ago | ||
| 2 days ago | ||
| 2 months ago | ||
| 2 months ago | ||
| 16 days ago | ||
| 14 days ago | ||
| 16 days ago | ||
| 2 months ago | ||
| 2 months ago | ||
| 16 days ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 16 days ago | ||
| 16 days ago | ||
| 13 days ago | ||
| 1 month ago | ||
| 16 days ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 11 days ago | ||
| 11 days ago | ||
| 1 month ago | ||
| 1 month ago | ||
| 6 days ago | ||
| 12 days ago | ||
| 12 days ago | ||
| 12 days ago |