Repository navigation
Conversation
…#856) Removes the four benchmark JSON exports, two screenshots, evaluation Markdown and AGENTS note introduced by #854: 31,419 text lines deleted. Runtime code and runnable tests are retained. Measurement summaries stay in #854's discussion. Validation: deletion-only diff, git diff --check, and no remaining references to the removed paths.
## Summary Cleanup following an inventory of 146 merged PRs from August 29 through October 6, 2026, with targeted inspection of oversized diffs, generated files, historical reports and current references. - Remove the palette gallery, 21 PR screenshots, ten historical reports/plans, the historical tail of the compatibility register, and the unused February SDK tarball/metadata under `temp/`. - Stop tracking five generated Tauri schemas; ignore their output directory and root `temp/`. Keep capability/permission sources, build logic and the vendored native fixes intact. - Remove exactly 16 unused Plugins translation keys in each of ten locales. Preserve the dynamically selected Global/Project labels and all active labels. - Repair links, index descriptions and the palette-test comment. Preserve current runtime qualification/ownership contracts, palette attribution and all executable regression tests. 58 files changed: **7 insertions, 11,723 deletions** (net **-11,716 lines**), including 22 binary removals. No new repository files or committed audit artifacts. ## Validation - UI typecheck: passed. - Production UI build through Tauri `dev:prep`: passed. - Palette quality: 40/40 passed. - Real-component browser Plugins regressions: 8/8 passed. - Clean Windows Tauri build with all five checked-in schemas absent: 188/188 tests passed, including actual generated ACL authority checks. - Warm build, delete generated schemas again, incremental rebuild: passed; generated JSON exists and remains ignored. - Exact baseline comparison: only the intended 16 translation entries removed per locale; retained compatibility body unchanged. - Retained tracked text: no references to deleted reports or removed translation keys. Synthetic Git-history fixture paths remain synthetic and do not read the deleted gallery. - Permission sources and runtime/build code unchanged; no added files; staged whitespace check passed. Validation was local on Windows, not a claim of completed Linux/macOS CI. Existing locale `settings.ts` files remain approximately 677-691 lines; this cleanup removes entries without unrelated restructuring.
## Summary Remove the hardcoded `base_version: 0.20.0` from the development release workflow. The reusable workflow already defaults to the package version at the exact dev SHA being built, currently `0.20.1`. One-line deletion; the date/SHA suffix, development npm channel and remote UI policy are unchanged. Future stable version bumps no longer require updating this workflow. ## Validation - Parsed both workflows with the existing YAML dependency and checked the default/fallback contract and retained source SHA/channel inputs. - Confirmed the source package version is `0.20.1`. - `git diff --check` passes. Existing prereleases are not renamed. No CI waiting or monitoring.
Resolve each @./ and @. mention directly in the shared prompt preparation helper. Previously every occurrence became a temporary root marker but only the first marker was restored, so later references could reach the model as ___ROOT___. Removing the sentinels also preserves literal marker text written by the user. Keep parent-path matching, attached-path handling and verbatim pasted content unchanged. Add regression checks for repeated references, pasted display metadata, message history, shell submission and slash-command arguments. The three new tests fail on the unchanged helper and pass with this fix; all 21 targeted tests and UI typechecking pass.
I removed the temporary root markers from prompt preparation. Each `@./` or `@.` reference now resolves directly, so repeated references no longer send `___ROOT___` to the model. I added regression tests for repeated references, literal marker text, pasted content and display metadata, shell input and command arguments. All three new tests fail before the fix; all 21 targeted tests and UI typechecking pass afterward. I also built the Tauri resources and passed the packaged-resource checks. I did not replace the installed app or restart the shared daemon. Fixes #863
…2.0.24 (#865) ## Summary - Qualify and pin the generated client/plugin at OpenCode **2.0.24**, recommended independently of the unchanged **2.0.7** technical minimum. - **On every runtime version**, automatic Form/permission recovery uses only the authenticated loaded-only broker. Missing capacity stops recovery non-authoritatively; it never falls back to ordinary lists across historical/inactive worktrees. - Retain known requests and editor drafts through unavailable/partial recovery and rehydration, and show a localized recovery-incomplete status even when no request is known. Only explicit settlement reconciliation may use ordinary lists at the attempted request's authorized location. Keep mutation fences and settlement tombstones. - **Remove the private reader's runtime and Effect version allowlist.** An untested/custom/prerelease/missing version label no longer disables recovery. Registration checks the real native RPC capability; each read validates graph, existing-only lease, queue, codec and identity contracts. These checks fail safely without mass-loading fallback. Tested versions remain evidence, not grounds for blocking other versions. ## Contract audit The authenticated isolated 2.0.24 daemon exposes 117 native OpenAPI paths vs 116 on 2.0.22. The new `/api/vcs/init` is not exposed by CodeNomad. Of 167 structural schema changes, most add declared `LocationNotFoundError` failures to location-sensitive routes; other changes add optional `ServerInfo.capabilities.persistentPty`, WorktreeError's literal `_tag` and the VCS-init error. Published declaration changes: 11/30 client files (+service-probe), 3/60 plugin, 8/36 protocol and 3/102 schema files (three retired IDE/question declarations removed). No removed declaration is imported by CodeNomad; no consumed dependency establishes a higher minimum. The upstream source audit leaves LocationServiceMap, Form, Permission and RPC contracts unchanged; the Location-services wrapper changes only its TypeScript error parameter. Effect remains rc.112. The published native implementation chunks are hash-checked against separate receipts before each isolated fixture run. Native SDK service contender/probe/PTY handoff internals change, but CodeNomad retains its selected-CLI lifecycle adapter and bounded authenticated registration fallback rather than using `Service.ensure/stop`. **No shared daemon restart, storage mutation or OpenCode PR is part of this change.** The source audit also covers compaction-agent model/budget selection, ChatGPT's temporary remote-model synchronization removal, local-provider discovery/cache sharing, text-capable default selection, bounded MCP connection/catalog retries and OAuth callback timing, Windows instruction ancestry, skill frontmatter, subagent text boundaries and PTY runtime storage/availability. These remain native-owned; no CodeNomad adapter change is justified by the consumed contracts. `dev-docs/OPENCODE_V2_COMPATIBILITY.md` records the consequences and limits: synthetic account tests are not real OAuth/provider certification, compaction isolation does not exhaust alternate summarizer configurations, and no desktop terminal-survival test across service restart is claimed. ## Native loaded-only evidence ### Follow-up: unjustified version lock removed At the user's explicit direction, remove both `PENDING_SNAPSHOT_NATIVE_VERSIONS` and the Effect-version equality check, as well as all version checks in registration and reader execution. The reader no longer accepts or consults an executing-version argument. Regression coverage registers across 2.0.7–2.0.24, newer/custom/prerelease/missing labels and a context whose `app` getter throws if accessed. Actual malformed/missing contracts, unsafe data, eviction/disposal races and timeouts remain non-authoritative. The rule against blocking untested versions is recorded in `AGENTS.md`. The source comparison across published tags 2.0.7–2.0.24 finds an unchanged LocationServiceMap and existing-only lookup, RPC contracts and queue-list interfaces. Changes in older releases affect Form cancellation feedback/state and permission rejection feedback, not queue listing. All these tags use Effect rc.112. This is source evidence, not a claim that all eighteen releases have passed native fixtures. After gate removal, **29/29 reader/broker/admission tests pass**, as do server typecheck and pruning build. Fresh published native fixtures on **2.0.23 and 2.0.24 pass**, recovering permissions/global Forms with 100 cold candidates (three actual Git worktrees), four native boots before/after and zero cold constructions. The fresh bounded **full-server run on the follow-up passes: 888 passed, 0 failed, 6 skipped (894 tests, 76 suites)**. Receipts: `no-gate-server.log`, `no-gate-native-23/receipt.json`, `no-gate-native-24/receipt.json`, `matrix-source-inventory.json`, `server-all-no-gate-final.log`. The follow-up also records the distinction between pinned build dependencies and an independently updated external service in `AGENTS.md`; no README changes. Independent read-only gatekeeper review of the **full diff** `1abeba78043fc6ec1fac4eb57eb6c82a541cf66e..e159068`: **APPROVE, 0 findings**, 59 independent targeted tests passed plus an isolated reactive check. The review is published separately on this PR; it is an agent review, not human approval or deployment acceptance. At the pre-merge CI inspection, runtime contracts (minimum/latest), OpenCode compatibility (Linux/Windows/macOS) and native pruning (Linux/macOS) passed; general tests, native pruning on Windows and Tauri tests were still in progress. Earlier cancelled/skipped runs are not passes. The user explicitly requested an admin merge after zero gatekeeper findings; no all-green CI claim is made. The committed Bun fixture now uses the same managed `.ts` plugin discovery shape as production, not configured-package directory resolution. It uses an authenticated unmodified published HTTP router in-process, with an in-memory database, private discovery paths, no listener/service discovery and no external provider. | Published runtime | Preloaded Locations | Locations after recovery | Native boot logs before/after | Cold candidates | Cold constructed | |---|---:|---:|---:|---:|---:| | 2.0.22 | 4 | 4 | 4 / 4 | 100 (three actual Git worktrees) | 0 | | 2.0.24 | 4 | 4 | 4 / 4 | 100 (three actual Git worktrees) | 0 | Both runs recover three permissions, six Forms including three global Forms. They exercise absent/present backend presence, two backends retaining registration, expiry, return and final disposal, coexistence with the existing Promise pruning RPC, authenticated 401 rejection, schema limits and non-authoritative failures. The boot-log assertion also detects briefly constructed Locations even if they later disappear from the map. Short-fixture RSS: 2.0.24 460,599,296 → 461,824,000 bytes; 2.0.22 463,929,344 → 461,701,120 bytes. These are receipts, **not a memory profile or comparable deployment soak**, and do not attribute the reported 10 GiB to this fallback. ## Validation Environment: Windows, Node **25.2.1**, Bun **1.3.14**. All native checks use owned processes, synthetic providers/configuration/data and explicit isolated CLI paths; never the shared daemon or user database. - `bun scripts/test-pending-snapshot-native.mjs <qualified-packages> <fresh-output>`: passes separately on published 2.0.22 and 2.0.24. - 2.0.24 native automation, pruning parent runner, Location/worktree/proxy/event relay, environment, fork, aside, degraded Git, prompt skills, provider usage/accounts, permission receipts and blank-session cleanup: **12 suites pass**. - Minimum 2.0.7 with the same 2.0.24 client/plugin dependencies: **nine isolated suites pass** (automation, pruning, Location/worktree/proxy/relay, environment, fork, aside, degraded Git, prompt skills and blank-session cleanup). Operation-specific usage/account/receipt checks do not establish a new global minimum. - `test-compaction-isolation-native.mjs <2.0.24-cli> --context-mib 2`: passes with native compaction and outline enabled; the second session completes before releasing the first session's provider gate. - Focused UI pending recovery, compaction, Forms and permission lifecycle: **37/37 pass**. Coverage includes 100 cold worktrees on unsupported capability, reconnection, request retention, per-kind mutation fences, settlement reconciliation, late supported/unsupported responses and compaction admission. - Final browser dock/selection/mobile regressions: **44/44 pass**. The incomplete status appears with no known request at 393 px, has no horizontal overflow, preserves a typed answer on repeated unavailable recovery and disappears only after full recovery. Real-shell provenance, recursive interruptions, Android keyboards and per-conversation drafts remain covered. - Server/UI typechecks and shared server/UI/plugin builds: pass. - Final full server unit run after dependency reinstall, `node --import tsx --test --test-concurrency=2 'packages/server/src/**/*.test.ts'`: **888 pass, 0 fail, 6 skipped** (894 tests, 76 suites). An earlier unbounded parallel run exceeded the existing 30-second pending-broker deadline; the bounded rerun passes without changing that deadline. - Broad UI unit tests: **1189 pass, 2 fail**. Both failures are reproduced from unmodified base `1abeba78` sources in an extracted tree: `classic-dark-surfaces.test.ts` expects a removed accent-hover override; `tool-content.test.ts` expects copy text where the renderer returns none. These paths use OpenCode types only, no runtime client import. This suite is **not green**; unrelated UI corrections are intentionally not included. - `git diff --check`: pass. Lockfile retains unrelated package versions/integrities; npm peer metadata recalculation remains. - Lockfile reproducibility: `npm ci --ignore-scripts --no-audit --no-fund` passes after browser fixtures release the Windows esbuild executable. An earlier attempt during those fixtures encountered `EPERM`; a simultaneously launched server rerun was invalidated by dependency removal and is not counted as product evidence. Detailed local receipts/logs are retained under `C:\Users\Admin\AppData\Local\Temp\opencode\q224`: `pending-native-final/receipt.json`, `pending-native-22/receipt.json`, `schema-audit.log`, `*-declarations.diff`, `server-all-bounded-final.log`, `ui-pending-final.log`, `ui-all-final.log`, `ui-unrelated-baseline.log`, `browser-interruption-final.log`, native-suite logs and `compaction-2mib-final.log`. ## Deployment acceptance and limits Not deployed to the active user service. After authorized deployment, compare passive-recovery Location boot/eviction counts and process RSS/private memory over a comparable observation window, separating explicit user actions. Accumulated pre-fix Locations are not automatically evicted. Only an explicitly confirmed shared-service restart may release them. The separate Usage-flicker work is not a substitute for this fix. Unknown requests cannot be exhaustively recovered on a daemon without the capability; known requests and live events remain usable. Existing bootstrap warming, bounded coverage, compaction admission and ownership constraints remain documented in `dev-docs/OPENCODE_V2_COMPATIBILITY.md`. File-size signal: `packages/ui/src/stores/instances.ts` remains approximately 2,300 lines; no threshold-only refactor is included.
#862) ## What changes I add independently distributed right-panel UI extensions and an official online catalogue in Customize right panel. Users browse/search available addons, choose one and confirm installation directly from its exact GitHub Release, without a manual ZIP download, rebuilding CodeNomad or restarting OpenCode. Manual ZIP installation remains available. I publish the curated index, contribution rules and Session info demo at https://github.com/NeuralNomadsAI/CodeNomad-Extensions. That repository can host several official addons; the index can also reference author-owned repositories. Separate means independent of the main application repository, not a mandatory repository per addon. I show the manifest and exact archive SHA-256 before trust confirmation. Installation starts disabled; users enable it for all projects in the server profile or for the exact opened folder. Replacement requires the previous digest and revokes every activation grant. Removal is explicit. Packages and grants stay outside project/OpenCode storage. I keep author code out of the main renderer. API 1 exposes only session ID, locale and appearance through a per-mount MessageChannel. It does not expose filesystem, transcript, images, credentials, native commands or the OpenCode proxy. Frames are sandboxed without same-origin access and receive a restrictive CSP; obsolete responses and ports are fenced on project/session changes, disconnects, revocation and replacement. I document the package, permissions, API compatibility, scope, release/checksum and maintainer rules in `dev-docs/PANEL_EXTENSIONS.md`, with a standalone starter in `examples/panel-extension/`. GitHub's source ZIP is not an installable package. There is no arbitrary URL installer or automatic update. I load catalogue metadata only during discovery. Inspection and installation each revalidate a fresh index, exact ZIP digest and full manifest; unsupported APIs/permissions cannot install. Downloads are bounded, deadline-limited, credential-free HTTPS requests to GitHub's exact release hosts, with constrained redirects. A withdrawn or changed selection cannot become a different trusted package. Offline catalogue failures leave installed addons and ZIP installation available. ## Scope and limits I keep #801's assets gallery for a separate follow-up. It needs a bounded, authorized image/history capability rather than access to internal stores. This PR only establishes external distribution and a minimal context API. Windows Tauri may inject native bridge objects into subframes: object presence is not a grant. My isolated WebView2 fixture proves parent command execution while direct/raw child calls do not reach it, and verifies context delivery plus DOM/network restrictions. A trusted hostile extension can still stall its renderer or attempt self-navigation; this is not process isolation or a universal offline guarantee. The installer warns users to trust the author. I have not run a native Electron/macOS/Linux qualification or changed the shared daemon. The runtime implementation is shared between desktop hosts; native GUI validation here is Tauri only. ## Validation - UI and server typechecks. - 14 focused server/registry/manifest tests. - Real right-panel browser tests for ZIP consent, activation scopes, replacement, revocation, context changes, stale reads and frame isolation. - Five catalogue/server checks and seven right-panel browser scenarios cover metadata-only browse/search, online consent, withdrawal, incompatibility, offline ZIP fallback, hashes/manifests, redirect restrictions and size budgets. - Live public GitHub index and Release download matched SHA-256 `cf80226a40dd077a6a8cc2a4b65bbb46bf33619d62007982bd7dcea34ae4545f`; installation and activation used a disposable isolated store. - `node scripts/test-panel-extension-native.mjs` on Windows, using the application's locked Tauri dependencies and an isolated browser profile: parent native call allowed; child native calls, parent DOM and network APIs blocked; session context delivered. - UI build, Windows Tauri release build (`--no-bundle`) and packaged-resource smoke passed. Full browser suite results are recorded in the follow-up validation comment. Existing oversized files touched only for integration: `packages/server/src/api-types.ts` (~735 lines), `packages/server/src/index.ts` (~713), `packages/server/src/server/http-server.ts` (~2,438).
I restore right-panel customization to one compact Extensions action and move catalogue, ZIP installation, activation and trust/removal confirmations into a separate non-modal utility window. Lists stay single-line, metadata is available on hover and keyboard focus, toolbar actions remain reachable at narrow translated widths, and disposal fences late results.\n\nI remove speculative per-folder activation from the UI, client contract and backend. Each installed addon has one general activation control per CodeNomad profile. Existing packages and general grants survive; legacy folder-only consent is never broadened, and obsolete grants are removed only during an explicit successful mutation. Trust, digest-bound replacement/removal and owned-instance executable-panel reads remain enforced.\n\nI publish independent gatekeeper iterations until zero findings on the exact final head. Both typechecks, nine server tests and thirteen real-component extension/Status tests pass, including migration and French/Hebrew/Japanese/Spanish narrow layouts. Windows Tauri/WebView2 command denial passes. I use the requested admin override with the documented CI caveat: four unrelated browser failures also occurred in the final pre-correction run. The installed desktop and shared OpenCode daemon are unchanged.
## Requested change Restore the normal question/permission icon for requests from unrelated conversations. Show the complete shared red status badge, including its localized text, separately at the trailing end of the collapsed bar. Clicking the badge expands the selected request. ## Layout Retain leading disclosure chevrons and source titles. Crowded mobile headers wrap trailing controls instead of squeezing away the conversation name. Reuse existing badge geometry, colors and translations. ## Validation - Initial dock/mobile run: 36 passes, one cold fixture navigation timeout. - All six final targeted checks pass, including the previously timed-out recovery case; fixture initial navigation now has the same 60-second budget as the real-shell fixture. Assertions preserved. - Final UI TypeScript, production UI build and diff checks pass. - Desktop/mobile compact question and permission captures inspected. - Independent gatekeeper reviewed final diff/captures: ZERO FINDINGS. Review will be published before the requested admin merge without waiting for CI. Installation is separate; no running application or native daemon was restarted.
I put Extensions below a separator in the customization popup, collapsed by default. I combine installed addons and the catalogue in one compact searchable list and remove the separate modes and floating window. I make the existing addon checkbox the only profile-wide activation control. Disabled installed addons stay listed; reset never grants consent. Explicit trust, digest-bound replacement/removal, offline ZIP installation and sandbox protections remain intact. I pass the UI typecheck, 9 server tests and 14 real-component extension/Status browser tests, including narrow translated/RTL layouts and real ZIP gestures. I inspect the interactive preview validated by the user. Windows Tauri release qualification and the final independent gatekeeper review are in progress; I do not replace the installed app or stop the shared daemon.
Project the existing bell/history unread count onto browser tab favicons and the native dock or taskbar in both Electron and Tauri. Reading, deleting or clearing notifications updates the badge without querying sessions or adding polling; the original favicon returns when no unread items remain. Aggregate per-window counts in the native hosts, accept bounded count-only calls from owned local and remote primary renderers, and keep preferences windows and preview guests outside the capability. Navigation and closure remove only that window's contribution, with document-generation and main-frame checks fencing stale updates. Windows overlays are generated by the host; other platforms use available native count APIs. Add real Chromium regressions for notification lifecycle, icon pixels and restoration, unavailable native support and late image completion, alongside focused Electron bridge/security and Tauri state/ACL tests. UI/Electron typechecks, 15 focused Electron Node tests, four Tauri tests and Windows Tauri resource prebuild/smoke checks pass; no installed app or shared daemon was restarted.
Serialize the shared renderer-to-host badge calls so asynchronous Tauri dispatch cannot publish an older unread count after a newer clear. Final cleanup stays in the same FIFO, while rejected native calls do not prevent subsequent updates. Add a Chromium regression with deliberately held native promises to check send order through a rejected call, rapid add/clear, and disposal. All six browser badge tests and the UI typecheck pass; Tauri resource prebuild and packaged smoke checks also pass with the ordered adapter.
Make the history search window and command palette movable from their existing top bars with native mouse and touch pointers. Share placement, pointer cleanup and viewport bounds in DismissibleWindow while leaving inputs, selectors and close buttons interactive and retaining non-modal dismissal and session authority. Portal the movable inline search without losing its initial transcript anchor. Align utility stacking with opening order, revalidate placement as content grows, and bound height to the visual viewport. Native overflow and a sticky existing toolbar keep the last result, pagination and drag/close controls reachable in landscape and at pinch zoom; preserve the palette's 60vh limit and horizontal edge access when zoomed. Extend the real-component browser regressions with drag, touch, RTL, viewport shrink, content growth, asymmetric drawers, overlap, zoom/pan and pagination. All 62 targeted browser scenarios, UI typecheck and production build pass. Five independent Gatekeeper passes corrected eight findings and the final review reports zero actionable findings on bb13b96. Merge with the requested administrator override. Native CI jobs pass; the full browser suite has 489 passes, three pre-existing permission-fallback-diff failures and two skips. Read-only base/head reproduction confirms those unchanged tests wait for Copy patch in an intentionally collapsed external request without expanding it. Do not change permission semantics or hide these unrelated failures.
Observe primary WebView2 renderer/browser exits and WebKitGTK web-process termination without polling, new dependencies or guest capabilities. Factory enrollment happens before native build, so first loads do not depend on registration timing. Physical-window identities fence retired page, failure and close callbacks; failure revokes count admission until a new page starts. Native subscriptions capture only a weak host rooted outside managed application state, avoiding controller/handler/AppHandle ownership cycles. Windows ignores frame, GPU, utility and unresponsive-process events. Update the existing narrow remote-capability regression to include the badge-only command. Document the macOS limitation: pinned Tauri does not forward Wry's Darwin builder termination hook, so a surviving-window crash may retain its count until reload/navigation/close. Do not replace the runtime-owned WKWebView delegate or invent process monitoring. All 195 Windows Rust tests pass serially; Linux API review is not presented as compile/runtime qualification.
## Summary Mirror the existing bell/history unread notifications on the browser tab favicon and native desktop dock/taskbar, as clarified in #868. This includes all existing notification kinds, including update notices; session idle/attention status does not introduce a separate counter. - Use a small red dot on the tab favicon and restore the original icon when the unread count reaches zero. - Forward count-only updates through the shared native adapter for both Electron and Tauri. Native hosts aggregate live primary-window contributions so clearing one window does not clear another's unread notifications. - Keep native badge authorization restricted to owned local/remote application renderers, not preferences windows or preview guests, and remove contributions on reload/navigation and window closure. Electron handles renderer crashes; Tauri uses native termination signals on Windows/Linux, with physical-window fences and weak native handler ownership. - Reuse history add/read/read-all/delete/clear updates without scanning sessions or polling. History remains per-window and in-memory, as before. Browser tabs are covered, not installed-PWA launcher icons. Native dock/taskbar availability depends on the operating system and desktop environment. **Tauri/macOS limitation:** the pinned public Tauri API does not forward Wry's Darwin web-content termination hook. A surviving-window renderer crash may retain its last count until reload/navigation/close. This does not replace or swizzle the runtime's WKWebView delegate or add process polling; normal macOS badge updates remain supported. See `packages/tauri-app/NOTIFICATION_BADGES.md` for the API evidence. ## Validation - Six real Chromium regressions cover unread lifecycle, generated badge pixels, icon restoration, the 50-item history cap, Electron/Tauri adapter dispatch, unavailable native support, disposal before image load and FIFO native updates through failures/cleanup. - UI and Electron typechecks passed. - Fifteen focused Electron Node tests and all 195 Windows Tauri Rust tests passed without launching either application. The Rust suite runs serially (`--test-threads=1`); an initial parallel run had three native-service fixture failures that pass serially. - Windows Tauri resource prebuild/smoke checks passed. No native visual/runtime qualification or Linux/macOS validation is claimed. - The Linux termination hook was reviewed against the installed API, but was not compiled or runtime-tested on this Windows host. - Broad Electron Node suite: 208 passed; two failures outside the badge tests (missing local Electron installation and a Windows process-termination assertion). The broad suite is not claimed green. Fixes #868
Do not mount a permission-receipt request for the internal no-session draft sentinel. Reject malformed session IDs at the receipt API boundary with a 400 instead of forwarding them to the native client where they raise a 500. Cover the draft-to-session transition and reconnect in the browser fixture, and exercise malformed IDs alongside valid pagination and ownership checks on the server. Targeted browser/server tests and both TypeScript typechecks pass.
Closes #876. The no-session draft sentinel is only a local draft identity; it must never enter the permission-receipt API. Skip the read while that draft is selected and reject invalid session IDs as HTTP 400 at the API boundary rather than forwarding them to OpenCode as HTTP 500. Valid session pagination and ownership checks remain unchanged. Validation: 12/12 server permission-receipt tests; 9/9 targeted browser tests; UI and server TypeScript typechecks.
Treat idle historical session directories as optional recovery hints while keeping roots, registered worktrees, active sessions and known request placements required. Exclude only paths rejected by ownership, retaining real loaded-only RPC negotiation and non-authoritative failure behavior. Replace the recurring interruption banner with the existing once-per-episode notification.\n\nIndependent gatekeeper reviewed the complete change and the updated dev merge tree with zero findings; the verdict is published as agent review comments. Targeted broker, UI and browser suites, typechecks and server build passed; other CI jobs were still running at admin merge.
## Behavior - Selected skills appear once in the existing composer attachment bar alongside files. Removing a skill preserves the draft and other attachments. - Sent and historical user messages display their attached skill names, including messages containing only a skill. Labels survive native history reloads. - Long skill names wrap within the message width instead of being clipped on narrow desktop, touch and RTL transcripts. ## Implementation The shared message content filter now admits normalized skill parts into the existing badge renderer. The redundant composer skill row and its styles are removed. ## Validation - The browser fixture exercises native message loading, normalization, the store and the full transcript rather than an isolated badge. It covers mixed attachments, deduplication, removal, sending, skill-only history and reloads. - The history-label regression fails on the original content filter. - All three narrow long-name regressions fail before the wrapping fix and pass afterward, measuring message, badge and text bounds. - Final head `b2a31f339c6879f1fd76d32c55db9375669547cf`: focused browser/skill checks: 16 passed. Session-action regressions: 53 passed. UI typecheck and build passed; narrow rendered captures inspected. Existing large files touched: `packages/ui/src/components/message-block.tsx` (~1,889 lines), `packages/ui/src/components/prompt-input.tsx` (~1,078 lines).
…#874) Add the shared, explicit API 2 session.assets.read capability required by the independently distributed MCP Assets addon. Keep API 1 context-only, preserve one general activation checkbox, and require consent tied to the exact installed package digest. Use the bundled native history integration for bounded metadata pages and exact embedded tool-result bytes, with session/Location ownership and final consent revalidation. Fence native/backend disconnects, generation changes and stale responses; refresh after failed tool results and direct pruning. Admit bounded source dimensions before host bitmap decoding and preserve thumbnail aspect ratio. Include the new native modules in the packed plugin as well as the shipped bundle. Two autonomous gatekeeper rounds ended with zero P0–P3 findings on 9da8513; the initial three P2s have regression coverage. Local validation passed 16 browser, 14 server/image, seven package/presence and three bundled-installation checks, both shared typechecks, and the outside-checkout native fixture with official OpenCode 2.0.24. CI native plugin tests passed on Windows/Linux/macOS, as did runtime-contract and compatibility jobs. Admin merge is explicitly requested by the maintainer. Global CI is not green: its three permission-fallback-diff Copy patch timeouts also occurred in the parent PR #872 (run 37632060353), and Windows reported two unchanged cross-host election-test failures. Preserve these failures as follow-up diagnostics rather than claiming full CI success or modifying unrelated paths in this PR. No protection settings are changed.
An offline, symbolicated dump identifies the captured Windows F6 failure as a WebView2 browser-process null dereference in MultiContentsView reached through FocusNextPane. Prevent only that native browser action on every created local, preferences, remote and preview webview. Use the per-key WebView2 accelerator policy to preserve DOM delivery and configured UI shortcuts. Hosts without that interface swallow only F6 as a safe fallback; other accelerators, capabilities and platforms stay unchanged. Handlers capture no application/controller state and do no locking, IPC or message pumping. Add a fresh-profile, static-loopback native fixture and ownership-fenced PowerShell runner for F6, Shift+F6, Ctrl+F6 and an untouched F8 control. Native decorated/frameless checks and 196 serial Rust host tests pass. Document the captured stack and the limitation that the minimal baseline does not reproduce the full installed-app crash; no fixed installed-app retest is claimed.
Address both gatekeeper findings: sanitize inherited WebView2 overrides before creating threads, force the fresh owned user-data folder and controlled browser arguments, and verify the environment's actual user-data directory. Every runner launch injects conflicting temporary overrides and checks that their folder stays unused. Require heartbeat advancement during the final two post-input intervals, after F8 confirms the last input arrived. Add a negative native check that deliberately stops only those heartbeats and verifies the fixture rejects it even though all key-policy/delivery checks pass and ProcessFailed is absent. Positive framed/frameless and negative checks pass on WebView2 154.0.4258.62.
Closes #875. ## Captured cause A trusted, foreground-checked F6 reproduced the black interface on installed Tauri 0.20.1-dev-20261007-c995044b / WebView2 154.0.4258.62. The native host remained responsive, but the WebView2 process tree exited. An offline Crashpad dump with matching Microsoft symbols identifies a browser-process null dereference in `MultiContentsView::GetActiveContentsContainerView`, reached through `chrome::FocusNextPane` and native pane-focus rotation. This is not a hard refresh or the earlier Tao input deadlock. The dump remains local because it can contain secrets. ## Mitigation - Disable F6 browser actions only, through `ICoreWebView2AcceleratorKeyPressedEventArgs2`, on each created local, preferences, remote and preview webview. - Preserve DOM delivery, including configured F6 shortcuts; retain all unrelated browser accelerators. Older runtimes without the per-key interface swallow only F6. No version gate or global accelerator disabling. - No callback locks, IPC, message pumping, app/controller capture or additional preview capabilities. Electron and other platforms remain unchanged. ## Validation - 196/196 Windows Rust host tests, serial mode. - Real isolated Tauri/WebView2 154.0.4258.62 tests in frameless and decorated windows: F6, Shift+F6 and Ctrl+F6 browser policy disabled while DOM delivery remains; F8 policy/delivery untouched; continuing JavaScript heartbeat; no ProcessFailed. - Positive native runs now verify the effective isolated profile and final post-input heartbeat advancement under deliberately conflicting inherited overrides; both framed/frameless runs pass. The negative stopped-heartbeat check correctly rejects otherwise successful keyboard checks. - Frameless post-input capture visually inspected. No installed application or shared OpenCode daemon replaced or restarted. - Windows release build passes (`cargo build --release --bin codenomad-tauri`); packaged-resource smoke checks pass. Existing dead-code warnings remain. The minimal baseline does not reproduce the captured installed-app crash. Native fixtures validate the prevention mechanism and keyboard preservation, not a full application A/B reproduction. No fixed installed-app, Electron, Linux or macOS runtime qualification is claimed. See `dev-docs/TAURI_WINDOWS_F6_CRASH.md`.
Remove the committed diagnostic/validation report and its AGENTS.md entry at the user's request. Keep the F6 mitigation and all runnable regression checks unchanged; investigation notes remain local rather than creating unsolicited development documents. Verified this change touches documentation only, passes diff checks and leaves no references to the removed file.
Remove superseded MVP/UI/tool-rendering specifications, duplicate implementation and index summaries, completed attachment planning, incident readouts and redundant CI/pruning/native-backport reports at the user's explicit request. Trim the worktree validation diary while retaining placement, ownership and native-instruction contracts. Preserve public extension contracts, attribution/licenses, private RPC safety, runtime capability policy and vendor patch provenance/removal criteria. Redirect native-backport instructions to the existing vendor README and remove dangling deployment links and a stale architecture dependency snapshot. Validation: Markdown-only diff, whitespace checks and repository-wide checks for removed-file references. No runtime source, tests, build dependencies, installed application or shared OpenCode service is changed.
Remove unsolicited/obsolete development documentation at the user's request, without changing the F6 fix or any runtime/test behavior. - Delete 15 documents: the F6 diagnostic report, superseded MVP/UI/tool-rendering specs and redundant summaries/index/implementation docs, completed attachment planning, incident readouts and duplicated pruning/CI/native-backport reports. - Remove worktree validation chronology while retaining placement, ownership and instruction contracts. - Keep public extension APIs, licences/attribution, current private-RPC safety and capability contracts, cache/interaction rules and existing vendor provenance/backports. Redirect remaining references to retained vendor documentation. Validation: Markdown-only changes; `git diff --check` passes; repository-wide removed-file reference search is empty. No new document/report, source change, build, graphical test, desktop restart or daemon mutation.
## Scope Implement the two repository-wide Ponytail audit lists, deduplicating overlapping recommendations. Based on current `dev@aa2776e`, on `refactor/ponytail-cleanup`; no direct dev changes. Initial delta: **3,548 net lines removed**, two direct dependencies removed (and their unused transitive lockfile entries). ## Changes and preserved behavior - Delete superseded MVP/UI/tool-rendering/summary docs; compact the index and canonical architecture references and remove per-review/temp-path bookkeeping from runtime-transition history. Preserve security/ownership rules, technical minimum rationale, compatibility provenance and reproduction commands. - Remove confirmed-unused UI surfaces, Electron JSON storage IPC, obsolete release fetch/shell runners and dead bridge/storage/command/keyboard utilities. Keep existing native environment discovery and shared-service lifecycle untouched. - Replace the empty first-party plugin loading layer with direct built-in right-panel construction. External sandboxed extensions, consent, assets authority, activation, ordering and visibility remain intact. - Retire the unused incremental-part message mutation engine and exclusively owned pending-part buffers/budgets/types. The active native reducer still publishes bounded authoritative snapshots. Preserve optimistic send identity, pending sends, permissions, usage, pruning/revert, memory accounting and scroll restoration. Rewrite old tests using snapshots rather than removing relevant behavioral assertions. - Share speech streaming/base64 helpers, retaining playback lifecycle and cancellation in each caller; deterministic transport regression covers ordering, start-once, completion and failures. - Replace three Material icons with existing Lucide icons; remove `@suid/icons-material` and unused `ts-node` without upgrading other dependencies. - Drop the redundant Favorites implementation-shape test; behavioral store/browser regressions stay. Repair two inherited tests to current palette and lazy copy contracts, preserving image/privacy assertions. ## Validation Server/UI/Electron typechecks, UI production build, targeted core-panel/Favorites/audio/image/palette checks pass. Full local suites and focused browser/native Electron regressions are in progress. The broad server run found one existing deadline-sensitive pending-broker test; its entire 20-test file passes in isolation. Independent gatekeeper review is required on this exact committed head, findings will be corrected and re-reviewed to zero before the explicitly authorized admin merge. No user credentials/shared daemon/database were used for testing. ## Size notes Touched existing large files: `packages/ui/src/stores/message-v2/instance-store.ts` ~1,450 lines, `packages/ui/src/stores/message-v2/instance-store.test.ts` ~516 lines, `packages/ui/src/stores/conversation-speech.ts` ~432 lines. No size-only refactor; source/test coverage reduction is tied to proven-unused paths. Native application is not replaced/restarted by these isolated checks.
Reproduce valid recovery being reported incomplete on a large live workspace: an eight-directory loaded-only broker read returned complete HTTP 200 coverage after 19.4 seconds, while the frontend's ten-second timer abandoned the same request path. The broker already budgets thirty seconds for Git/directory ownership and its bounded native snapshot. Share the existing broker budget through the API contract and allow that budget plus a five-second transport margin only for loaded-only snapshot reads. Ordinary pending-list and liveness reads keep their ten-second deadlines. Retain cancellation, generation/ownership fences, queues, compaction admission and no-fallback/no-replay behavior. Add a controlled-clock store regression for a valid nineteen-second response and a stalled thirty-five-second read, preserving known permissions/Forms and refusing ordinary-list fallback. No new development report or installed-app/daemon restart.
## Root cause The installed 0.20.1-dev-20261008-027f5094 includes #877, but slow valid broker reads can still be classified as incomplete. The server gives directory/Git authorization and the native loaded-only snapshot a 30-second budget; the frontend aborts the broker at 10 seconds. On the live Windows Tauri workspace (253 inventoried worktrees, none missing), a bounded read of eight existing worktrees returned HTTP 200 / complete coverage after **19.4 seconds**. Repeating the same batch with the current frontend deadline aborted at **10.0 seconds**. A later warm read with a 35-second cap returned complete coverage in 4.1 seconds. These are variable-latency observations and a reproduction of the premature-abort mechanism, not a latency guarantee or attribution of every historical notification. ## Change Share the existing server budget through the API contract; only loaded-only broker reads get that budget plus a 5-second transport margin. Ordinary queue/status reads keep 10 seconds. No warning suppression, added retry, cold-worktree loading, prompt replay, weaker ownership or queue clearing. ## Validation - 41/41 UI store tests: delayed valid recovery, bounded real failure, preserved permissions/Forms, compaction, cancellation, tombstones, global Forms and no ordinary-list fallback. - UI/server typechecks, UI production build and diff checks pass. - Server broker suite: 19/20 pass in two full runs; the unchanged real-Git 64-directory deadline-sensitive case reaches the same existing 30-second budget under load. That case passes alone (22.1 seconds). No deadline increase or test weakening to conceal it; the server deadline value is unchanged. - Independent gatekeeper rerun: 41/41 UI and 20/20 broker tests pass (including the 64-directory case at 26.9 seconds), plus both typechecks. Published review: zero actionable findings. Prior under-load deadline sensitivity remains disclosed. - No installed application or shared daemon restart, no new development documentation. Existing large files touched: packages/ui/src/stores/instances.ts (~2,335 lines), packages/server/src/api-types.ts (~738 lines). No unrelated refactor.
## Summary - Give each conversation its own browser preview, keyed by project folder and session ID, rather than reusing the project's URL across conversations. - Preserve the actual native guest when returning to chat, selecting another session, showing Info or hiding the project. Page state and native Back history survive these transitions. - Keep guest DOM order stable. Only explicitly opened browser shells remain mounted; inactive transcripts and composers still unmount and the existing transcript-memory budget remains independent. - Both the conversation toolbar toggle and the preview's X return to chat while keeping the browser, document state and native history intact. The X is not a destructive browser close. - Adopt an old project-wide saved URL once for the first restoring conversation. - Persist a bounded URL history and cursor per session. After restart, browsers are restored only on explicit opening: load the current URL, never replay intermediate visits or eagerly create saved guests. - Add Back/Forward traversal using owned native CDP history IDs for live entries. When an entry no longer exists natively, load only that selected saved URL. Persist neither native pageState, POST bodies nor form/DOM/JavaScript state; existing cookies/site storage remain native. ## Why The preview was conditionally mounted inside the active session/transcript view. Going back to chat or changing sessions destroyed its webview; reopening recreated only the last URL, losing the native history. The preview store was also keyed by project folder despite the native guest being session-bound. This fixes the lifetime and ownership at their existing shared UI boundaries. Electron unregisters hidden guests from automation without destroying them; Tauri hides and reuses its existing child. Native controllers, authentication and browser storage partitions are reused. ## Validation - UI, Electron and server typechecks passed. - Full-shell browser/history suite: **9/9 passed**. Real Electron guests and the production controller cover guest/form retention, X/chat/session/project/Info transitions, renderer restart, lazy restore, no intermediate replay, Back/Forward and hidden navigation. Also covers interrupted native/iframe traversal, inactive transcript/composer disposal, project/session separation, Tauri hide/reuse and one-time legacy migration. - Tauri native suite: **197/197 passed** (serial rerun after an unrelated Windows service-fixture failure under parallel load). - Focused Electron browser controller/preload: **23/23 passed**, including hidden owned-history access without automation visibility and foreign-owner/unsafe-entry refusal. - Existing BrowserFrame native/renderer regressions: **19/19 passed**. - Focused existing header/session/preview-close regressions: **3/3 passed**. - Preview persistence/native adapter unit cases and the browser-conditioned transcript-budget regression passed. - `git diff --check` passed. The broad local Electron suite hits unrelated, unchanged Windows process-identity/service-start fixtures; focused browser/native checks pass. The broad header run exceeded the local command timeout; relevant cases were rerun separately. Tauri browser interaction is exercised through the real Solid shell with mocked native IPC and Rust controller regressions, not a packaged WebView2 smoke. History is capped at 32 URLs per session within the existing 4 KB aggregate layout-value budget; trim history before evicting saved previews. Application/project closure ends the live document: restored history preserves URLs/cursor, not unsent forms or scroll. ## Autonomous gatekeeper loop Independent pass 1 found hidden Tauri navigation loss and explicit Go superseding a pending Back corrupting an entry. Pass 2 found hidden Electron navigation loss before restart and stale iframe Back callbacks after Go/Refresh. All four findings were fixed with regression tests; the final independent pass reports **zero actionable findings**. The final review will be published separately on the exact pushed head before the requested admin merge. Prior-head CI also exposed three failing clipboard-diff tests. An independent diagnostic reproduced them unchanged on exact `dev` baseline `027f5094`: the fixture omitted the session context required since #848. The fixture-only correction seeds/passes its session and all three cases pass. Production permission/approval behavior is untouched. ## Size notes Existing large files touched: `packages/ui/src/components/instance/instance-shell2.tsx` (~1334 lines), `packages/ui/src/components/browser-frame.tsx` (~1005), `packages/ui/src/components/session/session-view.tsx` (~723), `packages/tauri-app/src-tauri/src/main.rs` (~2712), and `packages/tauri-app/src-tauri/src/browser_controller.rs` (~1674).
…ory (#1107) ## Summary - The notification history's **Clear all** and **Settings** text buttons become icon buttons (red trash can, gear), like the panel's close button. - Their labels stay as tooltips (`title`) and accessible names (`aria-label`), with the existing translations. **Mark all as read** keeps its text. - Shared `window-icon-button` geometry; the existing toast-history action classes keep hover, danger and disabled styling. ## Validation - Screenshots of the real `ToastHistoryPanel` with two notifications, dark and light themes, including the hover state. - `npm run typecheck --workspace @codenomad/ui`.
## Summary The app icon looked smaller than its neighbours in the Windows taskbar: the square source SVG kept an empty ~4 % margin on each side, so the 24 px icon drew the CN in 22 x 12 px on a transparent background. - `images/CodeNomad-Icon.svg` is cropped to a square centred on the mark, touching the left and right edges (height stays about half: the CN is twice as wide as tall). - Master PNG, in-app copy, Electron/Tauri `.ico`/`.icns`/`.png` and Linux sizes regenerated: 24 px now 24 x 14 px, 32 px now 32 x 18 px. - In-app logos use the same PNG, so their heights shrink by the same ratio to keep the approved on-screen sizes (5.55rem, 4.44rem narrow, 7.4rem loading); `dev-docs/UI_CONVENTIONS.md` updated. ## Validation - Regenerated `icon.png` loses no opaque pixel of the master; the mark spans columns 0-1023. - Measured bounding boxes in the 16/24/32/48 px `.ico` entries before and after. - `npm run typecheck --workspace @codenomad/ui`.
…permission (#1109) ## Summary System notifications on Windows: everything about them in one PR. 1. **Windows data profiles never showed system notifications** (`fix(windows): show system notifications from every data profile`). Tauri runs each data profile, such as **dev**, under its own AppUserModelID (`…client.scope.s<hash>`), and its notifications carry that ID; Windows shows a desktop app's notifications only under an ID it knows, and the installer's Start menu shortcut carries the stable ID alone. Windows recorded every notification (100 on the affected machine) and displayed none. Every launch now registers the running ID under `HKCU\Software\Classes\AppUserModelId\<identifier>` (`DisplayName` CodeNomad, `IconUri` the bundled web app icon `resources\server\public\pwa-192x192.png`, which the packaged-resource smoke check requires; `windows_notification_identity.rs`). Electron always uses the stable ID. 2. **The permission was lost at every restart on Windows.** The notification plugin's page script reports *denied* there until the page requests permission, though Windows never asks, so Settings asked again after each restart. The check now asks the native plugin command, which answers granted on desktop: granted once, kept. 3. **Notifications were held back whenever the window was visible** (`fix(notifications): hold system notifications back only while focused`). With **Notify when the app is focused** off (the default), an open window stays visible behind other applications or on another screen, so nothing was sent unless CodeNomad was minimized. Delivery is now skipped only while the window is visible and focused (`document.hasFocus()`). The setting's subtitle and the Settings help say *focused* in all ten languages; `dev-docs/SETTINGS.md` records the rule. Out of scope by decision: several CodeNomad windows open on the same project may each send the event's notification (as they already do when the setting is on), and focus inside a browser preview counts as leaving the page. ## Validation - Affected machine: no profile notification showed before; after registering its ID as above, a notification sent under it showed in the notification centre under CodeNomad. - `cargo test --bins -- windows_notification_identity` (writes the key, reads back both values). - `tests/browser/system-notification-focus.test.ts`: real routed notification from a visible page; nothing while focused, one once focus is lost, one while focused with the setting on; red on the previous visibility check. - `npm run typecheck --workspace @codenomad/ui`, `npm run test:help`.
…bound (#1106) ## Problem Long model reasoning still appears to freeze roughly 30 seconds in, even after #1088 kept the store streaming across shared-stream reconnects. The visible thinking text stops growing while the panel keeps visibly refreshing — the live duration keeps ticking, the transcript keeps following, and the reasoning scroller stays pinned to its bottom. To a user watching a long think, it is indistinguishable from the earlier store freeze, which is why the previous fix looked like it had not worked. ## Root cause The record display projection caps every reasoning part's text at `REASONING_RENDER_CHARACTER_LIMIT` (10 000 characters — `extractReasoningTextForRender` inside `buildRecordDisplayData`, introduced by #648's memory bounding). The cap applies while the part streams, not only once it settles: - A reasoning stream at typical model speed crosses 10 000 characters around 30 seconds in — the same moment the connection-recheck freeze used to surface, so the two bugs produced nearly identical symptoms. - Past the bound, every delta still re-projects the message (the row re-renders, the header duration ticks, the transcript keeps following — "refreshing, just no content"), but the displayed text is byte-for-byte the same 10 000-character prefix, so `ReasoningStreamOutput`'s `<pre>` never changes again until the part completes. - The store keeps the whole text the whole time and copy actions read it whole; only the display copy is silently capped, with no reveal. ## Changes - `stores/message-v2/record-display-cache.ts`: a reasoning part without `time.completed` (still streaming) now projects its whole `text`. That is a reference to the store's string, not a copy — per delta it is cheaper than the previous sliced 10 000-character copy. Once the part completes, the projection returns to the bounded 10 000-character prefix, preserving #648's retained-copy bound for settled transcripts. - `dev-docs/TEXT_DISPLAY_BOUNDS.md` describes the split: completed reasoning keeps the bounded prefix; a still-streaming part renders whole. ## Behavior compatibility - Completed reasoning renders exactly as before (bounded prefix, whole-text copy). - Timeline markers, hover previews and search slice their own text from the raw parts (`message-timeline.tsx` still bounds previews at 4096 characters) and are unchanged. - A reasoning part that never settles (interrupted mid-think) keeps its whole text by reference — it renders live and retains no extra copy. - No help-page change: the bound was never documented in the user help and no labels, controls or defaults changed. ## Validation - Red→green unit regression in `instance-store.test.ts`: the streaming projection keeps the whole text past the bound; the completed projection keeps the bounded prefix. Pre-fix it fails at the first assertion (10 000 vs 10 020 characters). - New browser regression `tests/browser/reasoning-stream.test.ts` (real `SessionView`, native SSE dispatcher): three ~6.9K-character reasoning deltas keep rendering whole past the bound, and `session.reasoning.ended` returns the card to the 10 000-character prefix. Pre-fix it fails exactly like the live bug: `AssertionError: delta 2 renders whole (got 10000)`. - The `session.tsx` fixture gains `startReasoning` / `reasoningDelta` / `endReasoning` emitters plus an opt-in `revealThinking` preferences hook (thinking rows are hidden by default). - `tsc --noEmit` clean; `instance-store` 30/30; `empty-content` + `message-part-grouping` + `render-text-window` 18/18. - Shared-fixture `message-scroll` suite: 127/128 **identically on this branch and on the clean base commit**; the single failure is the first test's page-load navigation timeout, a pre-existing local Vite cold-start issue (the same environment phenomenon class #1088 documented), not a regression. --------- Co-authored-by: Pascal André <pascalandr@gmail.com>
) ## Summary - New logo: a hexagon framing a C and an n, in equal bands (ring, gap, strokes, counters share one width), readable down to 16 px. - **App icon**: white ring and letters over black gaps, transparent canvas, hexagon spanning top to bottom; one fixed icon for light and dark taskbars, docks and tabs. - **In the UI** (`components/brand-logo.tsx`): black hexagon with white gaps on light palettes, white version on dark ones, picked in CSS from `data-theme` (system appearance when unset), so it also works outside ThemeProvider (title bar). Loading screen (always dark) uses the white one. Sizes: 4rem beside a text-3xl title, 3.2rem narrow column, 5.3rem loading screen, 16px title bar. - **Icons rendered from the vector**: `scripts/generate-icons.mjs` draws every `.ico` entry (16-256 px), `.icns` slot, Linux size and the 1024 px master straight from `images/CodeNomad-Icon.svg` with Chromium, instead of shrinking one large PNG; it writes the containers itself, so Electron drops `png2icons`/`pngjs`. One command replaces BUILD.md's four manual steps. ## Validation - New `tests/browser/brand-logo.test.ts`: real title bar + home page; which hexagon each logo shows on light, dark and system (both ways) palettes, with heights; red without the logo stylesheet. - UI + Electron typechecks, Electron tests (283), `macos-titlebar` and `notification-icon-badge` browser tests, `npm run test:help`. - Icon checks: ICO entries 16-256 (DIB, PNG at 256), ICNS slots icp4-ic14; UI captures on porcelain, linen, mist and ember palettes.
## Summary At 16 px the title bar's hexagon was too small for its C and n to read. Compared in the Windows and macOS title bars on light and dark palettes at 16, 20 and 24 px, 20 px reads clearly, stays close to the menu text and leaves margins in macOS's 28 px bar (24 px nearly filled it). ## Validation - `brand-logo` browser test expects the 20 px title bar logo; `macos-titlebar` still finds it centred and clear of the traffic lights. - `dev-docs/UI_CONVENTIONS.md` records the size.
…1117) A follow-up sent while the agent works (follow-up behaviour "queue") shows the "Queued" badge until the engine delivers it. After some turns the badge never cleared: the message was answered, the engine went idle, and only closing and reopening the session removed it (#1112). The stale pending entry also kept the message pinned below the running turn. The session view lists queued prompts from the session reducer's inbox through a memo. CodeNomad replaces that reducer while the session stays open: an authoritative resync after an event-queue overflow, a rotation failure or a reconnect, and a pruning invalidation. The replacement was a plain property write, so the memo kept reading the disposed reducer, which never sees `session.inbox.delivered`. On 0.20.1 nothing rebound it until the view remounted; on dev the reducer retirement at settlement happened to rebind it at the end of the turn, but the badge stayed for the rest of the turn, and indefinitely when retirement waits (another prompt still parked, an unsettled tool or shell). Every replacement now goes through replaceTranscriptEntry, which assigns the new reducer, disposes the previous one and bumps a per-transcript entryRevision signal that getOpenCodeSessionInbox tracks. Only that session's inbox observers re-run; a transcript destroyed and recreated is still rebound by the instance revision. Several queued follow-ups keep their badges until each is delivered; steer-mode actions on a delivered prompt disappear the same way. Validation: opencode-inbox-rebinding.test.ts queues two follow-ups, replaces the reducer by pruning invalidation and by an event-queue overflow, then delivers them one by one with no terminal event: each leaves the memo at once. Both cases fail without the fix. A browser test in session-rendering.test.ts runs the real SessionView and SSE dispatcher: queued badge, a pruning event, delivery, badge gone while the turn still runs; it fails without the fix with the badge still visible. The session fixture's native inbox now lists parked prompts as an array and stubs the permission and form lists, as a real daemon does, so an authoritative resync completes. The new unit file is listed in the PR build's UI unit step, which passes locally (64 files, 562 tests), as do the UI own-tsconfig and root typechecks and the six browser suites using the session fixture (206 tests).
…1118) A session whose history holds image tool results (for example `read` on PNG files) never opened over a slow link (#1113): the 200-message page was 16.8 MB, 15.7 MB of it base64 in five tool results. It took 20 s at 6.5 Mbit/s, and a reverse proxy cut the transfer, so the UI showed "Failed to fetch". Every open, reload and history window paid for every image, shown or not. Transcript pages now carry large tool images by reference. The UI's native message list reads (createInstanceFetch) and history windows send the `x-codenomad-media: deferred` opt-in. For those reads only, the server replaces each tool image whose data URI exceeds 32 KiB with a `/api/workspaces/<id>/session-media/<session>/<message>/<part>/<index>/ <sha256>` path, in the instance proxy (forwardRuntimeRequest gains an optional whole-JSON transform for successful JSON responses) and in the history window route. toolImageSource resolves that path on the API base, so the existing lazy `<img>` loads only the images that are shown, as binary rather than base64. The new session-media route checks that the workspace owns the session, reads the native message, and refuses a session that moved during the read and messages at or after an undo boundary. It serves the bytes only when the image still matches the digest, as an immutable, nosniff, sandboxed image; anything else falls back to "Unable to display this image". What stays whole: - Single-message reads (`session.message.get`), so pruning revisions keep hashing native content. - Live events, user attachments, small images, non-image files and error responses. - Requests without the opt-in. The opt-in header is never forwarded to OpenCode. On the reported session, the page drops from 16.8 MB to about 1.1 MB. Validation: - session-media.test.ts: only large renderable tool images change, and only their URI. - routes/session-media.test.ts: exact bytes and headers; invalid references, digest and position mismatches, the undo boundary, ownership and a move during the read. - proxy.test.ts: the transform applies to successful JSON only and releases once. - instance-proxy.test.ts: an opted-in list read is deferred, the opt-in is not forwarded, and plain list or single-message reads stay whole. - session-navigation.test.ts: history windows. - sdk-manager.test.ts: only list reads opt in, keeping other headers. - tool-content.test.ts: path resolution, forged paths rejected; it is now listed in the PR build. - tool-images.test.ts: a deferred image decodes from the route in the real ToolCall renderer, and a missing one shows the fallback. The UI own-tsconfig, server and root typechecks pass, as do: - the server suite (2,467 passed; one index.test.ts process test timed out under load and passes alone, as on dev); - the UI unit step of the PR build (564 tests); - seven browser suites (278 tests).
…1121) The manifest host's analytics showed one address fetching version.json about every six seconds for a whole day. The server reads the manifest once per start, so that is a server restarting in a loop, but every request carried the same bare "CodeNomad-CLI" User-Agent: nothing told which CodeNomad version was involved. The UI manifest read and the UI package download now send "CodeNomad-CLI/<server version>". Nothing else changes: the manifest is still read once per start, and a failed read still falls back to the cached or bundled UI. Validation: a new remote-ui test serves the manifest from a local HTTP host and asserts the exact User-Agent it receives; it fails with the bare User-Agent. Server own-tsconfig and root typechecks pass.
…tup row (#1122) ## Summary - **Updates** is its own card again (About → Updates → Diagnostics → connectivity), subtitle restored in 10 languages: latest version, install/download + Refresh, then the **update feed** with its help and save error last. Rows resuming after actions open with their separator. Help speaks of the Updates card again (10 locales). - **Data profile** moves from About to General's startup card (Restore previous state), above Other saved profiles; still only for an explicit non-default profile (`current-profile-settings-row.tsx`, shared by inline settings and Preferences). Label key moved in 10 languages; desktop help and `DESKTOP_DATA_PROFILES.md` point to the new place. - The Clear saved startup state button keeps space above the rows' separator. ## Validation - `server-info`: card order, feed out of About, after the actions, with its separator; no data profile in Info. - `other-profiles`: running profile named above other saved profiles, clear of the button, Electron and Tauri Preferences; default profile never named. - `desktop-updates`, `npm run test:help`, UI typecheck.
…stion (#1123) Choosing a desktop data profile needed `CODENOMAD_PROFILE` or, on a first packaged launch with several restorable profiles, a native question that blocked startup. Settings only named a non-default profile and offered to delete all the other profiles at once. Settings > General > Restore previous state now ends with one folded line, "Data profile: <name>". Unfolded, it lists every profile on the computer, the open one first and the others by last use, each with its size, creation date and last use. A radio chooses the profile the next launch opens (any profile of this configuration; choosing the open one again cancels), "New profile" creates one by name, "Restart in <name>" restarts into the choice, and each other profile has its own delete button with a confirmation. A launch pinned by `CODENOMAD_PROFILE`, its alias or a development run shows the profiles without letting the user choose; deletion still works. Without a remembered choice, a packaged launch no longer asks: it opens the most recently used of the default, `dev` and `dev-v2` profiles (ties go in that order) and remembers it, as it already did with zero or one candidate. A launch that finds the selection lock held opens the detected profile without remembering it instead of waiting. Implementation: the existing host listing gains the open profile, creation (folder birth time, links not followed) and last-use (newest client-state write) dates, the remembered next-launch profile and whether the launch is pinned. Two host operations are added on both hosts, granted to local and Preferences windows only and serialized with list and delete: choosing the next launch's profile (validated with the `CODENOMAD_PROFILE` grammar, written under the selection lock, overwriting this configuration's entry, creating a new profile's scope folder inside the lock and removing it again if the write fails) and restarting through the graceful developer-mode relaunch. Electron's throwaway question storage, relaunch and private hand-offs are removed; it still sweeps leftover question folders and drops the two hand-off variables an older build's relaunch can carry. Tauri keeps only the invalid-profile error dialog. `CODENOMAD_DESKTOP_PROFILE` and the server's `desktopProfile` meta field are removed, since nothing displays them. Only a profile whose name leads back to its own folder can be chosen, so a folder the deprecated alias made under another profile's name (such as default-<hash>) is listed under its stored name but not offered. The listing reports the next launch's profile only when the launch would open it (the launch's own remembered-profile check), and Restart in <name> lists again first and restarts only while that still names the shown profile. Choosing with the keyboard keeps focus on the chosen radio. Validation: UI browser tests for the manager (listing, choose and restart, new profile and name validation, single deletion, macOS note, pinned launches, plain browser), Electron native tests (listing dates, current, next launch, pinned, set-next-launch outcomes, relaunch wiring, preload, automatic choice, lock and sweep) and Tauri tests (the same cases, grants and command wiring). Developer doc and help (10 languages) updated.
…get (#1124) The authentication hook decided whether a request needs a session from the raw request target, while Fastify's router matches a decoded path. A percent-encoded or absolute-form target therefore reached protected routes without a session: "/%61pi/workspaces" routed as "/api/workspaces", and "/%73idecars/<id>/..." reached a SideCar, on any listener the server exposes, including LAN listeners protected by the server password. Remote Control was not affected: its gate already judged a decoded path. Both checks now share `routedPath()` (server/routed-path.ts), which returns exactly the path find-my-way matches: cut at the first "?" or ";" (Fastify's default semicolon delimiter) and decoded with decodeURI, so reserved characters such as %2F stay encoded and %25 is never decoded twice. Targets the router would reinterpret (absolute-form, a leading "//", a fragment) or reject (malformed percent-encoding) are refused with 400 before any access decision. The Remote Control gate used a broader decodeURIComponent variant; sharing the router-exact helper keeps the two classifications identical to routing. Validation: `routed-path.test.ts` checks the helper against the decoder of the router Fastify itself loads and its refusals. `request-path-auth.test.ts` drives the real HTTP application over raw sockets: encoded /api, /sidecars and /workspaces targets, queries and semicolons get 401 without a session, reinterpreted or malformed targets get 400, public routes stay public and a session still reaches encoded paths. It fails on the previous hook ("/%61pi/test/echo" answered 200). The Remote Control surface tests and the whole server suite pass, and the server typecheck is clean.
…1125) When an iframe preview loads, the browser sends the CodeNomad origin's cookies with the frame's document request: the parent page initiates that navigation, so the SameSite=Lax session cookie and any SideCar service cookie set at the app origin are attached. The HTTP preview proxy forwarded that Cookie header unchanged to the preview target, which can be any external site. Opening an untrusted page in a browser or mobile client's preview therefore handed it a working CodeNomad session. Preview HTTP requests now drop the Cookie header, matching preview WebSocket upgrades, which already forwarded none. Target Set-Cookie headers were and remain stripped, so previews keep their behavior: the path proxy never carried cookies a previewed site could have set. All three entry points share proxyPreviewTargetRequest: the /previews/<token> path proxy, the per-token preview.localhost capability host and the root-relative asset fallback resolved from a preview Referer. Desktop native guests load the target directly and are unaffected. Validation: a new sidecar-proxy regression sends the CodeNomad session and a SideCar service cookie through each entry point and asserts the preview upstream receives no Cookie header. It fails on the previous proxy (both cookies reached the upstream through all three). The server proxy, preview, SideCar and Remote Control suites pass (192 tests) and the server typecheck is clean.
## Problem OpenCode 2.1.4 ([#58184](anomalyco/opencode#58184)) delivers MCP elicitation requests live, as global-session Forms (`sessionID: "global"`) whose `form.created` event carries the server's location. CodeNomad's live event path (`stores/instances.ts`) queued `event.data.form`, which has no `location`. `formRequestOptions()` reads `form.location`, so the dock's reply and cancellation went out **without `x-opencode-directory`**. For a Form created in a worktree or subdirectory, OpenCode answered `FormNotFoundError` until a pending-request rescan replaced the entry with its located copy. Found by the independent review of the 2.1.4 qualification (#1126), which reproduced the headerless `FormNotFoundError` on an isolated 2.1.4 daemon. ## Fix Recovery already attaches the snapshot location to global Forms. The live path now does the same with the event location before queuing. Session-owned Forms are unchanged, since their replies need no location header. `dev-docs/NATIVE_INTERRUPTION_UX.md` states that live and recovered global Forms keep their location. ## Tests - New regression in `instances-pending-requests.test.ts`: a real SSE dispatch of two global Forms from a worktree, then a reply and a cancellation. Both must send `x-opencode-directory` for that worktree. It **fails without the fix**, because the queued Form has no location. - With the fix: - pending-request, compaction and Form store tests: 55/55; - full UI unit suite: 1700/1700; - interruption dock and mobile interruption browser tests: 43/43; - UI typecheck.
## Summary - Qualify OpenCode **2.1.4** (latest stable, 23 October) with the existing locked **2.1.0 client/plugin** dependencies, and **recommend** it. - Keep the technical **minimum at 2.1.2**: no consumed contract changed, so the minimum has no new reason to move. - 2.1.2 and 2.1.3 daemons stay ready and get an optional upgrade offer. 2.1.4 is the `tested` version. Newer and custom labels keep authenticated contract recognition. - The reviewed-contract fast path lists the 2.1.2 minimum and the 2.1.4 target. - The recommended version is updated in the help (all ten locales), both READMEs, `CONTRIBUTING.md`, `dev-docs/OPENCODE_COMPATIBILITY.md` and the architecture skill. ## Contract review (v2.1.3 → v2.1.4, 72 commits) - **Authenticated OpenAPI:** 121 → **124 paths**, 146 → **149 operations**. No operation changed. The changes: - added `POST /api/experimental/client-mcp/token`; - added `GET /api/experimental/client-mcp` (WebSocket); - added `POST /api/debug/heap-dump`; - `Config.InfoEncoded` gains the opt-in `experimental.background_compaction`. The session event (`V2EventEncoded`) and message schemas are unchanged. None of the new routes is on the instance proxy allowlist, and the proxy relays WebSockets only for SideCars and previews. - **Published declarations:** - the client adds `mcp.client.token` and `debug.heapDump`; - the schema and plugin changes are type refactors and unused-export removals, among them `SessionID.descending`, `SessionEvent.Source` and `PromptInput.FileAttachment.create`; `Session.Message.ID.fromEvent` now takes any string instead of an event ID. CodeNomad uses none of these, and every host module its native plugin bundles import (`@opencode/plugin`, `/effect`, `/promise/adapter`, `/rpc`, `@opencode/schema/location`, `/session`) still exists. - **MCP elicitation forms** ([#58184](anomalyco/opencode#58184)): an MCP server asking for input during a tool call now creates a global-session Form whose `form.created` event carries the server's location. CodeNomad's live path requires that location for global Forms and shows them as a **Project request**. Review found that the live path dropped the location from the queued Form, so its reply lacked `x-opencode-directory` and failed for a worktree or subdirectory until a pending-request rescan. **#1127** fixes that; recovery already kept it. A native probe (minimal stdio MCP server, a real Code Mode `execute` call, CodeNomad-style reply) gives: | Runtime | Form listed for the location | `form.created` carries the location | Reply completes the tool | | --- | --- | --- | --- | | 2.1.3 | yes | **no** | yes | | 2.1.4 | yes | **yes** | yes (`action: accept`, `channel: stable`) | On 2.1.3 such a request only appeared after a pending-request rescan; on 2.1.4 it appears live. The probe sends the location header itself, so it checks the runtime contract; #1127 covers CodeNomad's live reply path. - **Other changes** are covered by the native suites below: - compaction (oldest-first shortening, ignored buffers, overflow detection); - the agent's model for sessions without one; - V2 agent files; - V1 global-session import attribution; - MCP lifecycle fixes. - **Live check:** this machine's shared daemon runs 2.1.4, and the CodeNomad desktop session works through it. ## Isolated Windows qualification Base: dev `9ac792fff`; Node **24.20.0**; exact official CLI **2.1.4**; unchanged locked client/plugin **2.1.0**. - **Build and checks:** production server/UI/native plugin builds, server and root typechecks, native bundle guard. - **Native runtime (9/9):** - Code Mode job ordering, plugin runtime, automation; - complete pruning, history, ownership, worktree and event relay; - loaded-only pending snapshot; - Missions contract, family control, native and Compare/Wayfinder trajectory. - **Sessions (15/15):** environment, fork, aside, interrupt, lifecycle, blank cleanup, prompt skills, provider usage/accounts/selection, service usage, web search, plugin packages, output limit, Promise-tool failure. - **Recurring (5/5):** all **11 recurring Mission journeys**, subagent depth, **2 MiB** compaction, permission receipts. - **Migrations (10/10):** - history from **2.0.3, beta-19271, 2.0.32, 2.1.0, 2.1.1, 2.1.2 and 2.1.3** to 2.1.4; - Git degraded/init; - temporary workspaces. - **Installation (3/3), with the 2.1.4 recommendation:** - fresh install of the 2.1.2 minimum; - native **2.0.15 → 2.1.4** upgrade, after which the already-running daemon keeps its PID and 2.0.15 version; - explicit OpenCode **1.18.10 → 2.1.4** replacement. - **After the recommendation change:** - admission, transport, update, installation and instance proxy units **116 passed, 1 POSIX-only skipped**; - full server **2,471 passed, 8 skipped**, no failure or cancellation; - UI units **1,699/1,699**; - focused browser **126/126**; - native pruning with the real rendered UI; - the exact CI invocation of the Code Mode regression (without tsx); - ten-locale help checks (**9/9**). This is Windows automation evidence. In CI, `latest` resolves to 2.1.4: the compatibility job runs the native suites against the minimum and latest on Windows, and the migration and Git-degraded certification runs them on Ubuntu, Windows and macOS. WSL, packaged desktop, installers/updater end-to-end and real mobile devices keep their separate release gates.
…ote Control (#1128) Phones lost their only entry to the session web preview when the conversation actions were reorganized: on mobile, the Full screen action took the preview's place instead of joining it. Previews still work there through direct (LAN) access, which serves them through the capability iframe proxy. Remote Control, on the other hand, serves no preview content (`/previews/*` is host-only), so its clients, desktop browsers included, were offered a preview that could only fail to load. The conversation header now offers the preview on every platform, inline and in its overflow menu, with Full screen added on mobile. `/api/meta` reports `remoteControl: true` for requests that arrived through the Remote Control ingress, `lib/server-meta.ts` exposes it as `remoteControlClient()`, and the shell hides the preview entry for those clients. The shell asks for the server metadata on mount; the read is cached and shared with the other callers, and the entry stays visible until a Remote Control answer arrives. The Remote Control help page says, in all ten locales, that conversation actions hide Open web preview there; dev-docs/UI_SHELL.md records the convention. Validation: a header-windows browser test drives the real conversation header on a Pixel 5 profile and on desktop Chrome, with and without the Remote Control metadata, and checks the inline buttons and the overflow menu. It fails on the previous shell (no preview entry on the phone, and a preview entry kept through Remote Control). meta.test.ts and the Remote Control surface test cover the flag locally and through the real ingress (the surface fixture's metadata gains the `host` field /api/meta needs). The UI unit tests run by CI, the server routes, proxy and Remote Control suites, the help checks and both typechecks pass.
pascalandr
marked this pull request as ready for review
October 24, 2026 13:37
pascalandr
added a commit
that referenced
this pull request
Oct 24, 2026
A stable release is meant to open with the description of its dev to main PR, followed by GitHub's generated change list. The v1.0.0 release (and, before it, v0.20.1) got only the generated list. The workflow found the PR through commits/<sha>/pulls. For the v1.0.0 merge commit, which exists only on main while the default branch is dev, that endpoint returned no PR, still minutes after the merge, so the notes fell back to --generate-notes alone. The Create GitHub release step now lists the closed PRs based on main and picks the merged one whose merge_commit_sha is the release commit, through .github/scripts/release-pr-notes.cjs. That does not depend on the default branch. A release commit without such a PR still gets the generated notes only, and the existing-release path is unchanged. Validation: the script's tests cover the matching rules, an unchanged Unicode body through the command and the workflow wiring; they run with the other .github/scripts tests in PR Build Validation. Run against the real data, the workflow's exact command returns #1028's description for the v1.0.0 merge commit (the old lookup returns nothing), #843's for v0.20.1, and an empty body for a commit without a release PR. The v1.0.0 release notes were repaired with the same lookup.
pascalandr
added a commit
that referenced
this pull request
Oct 24, 2026
) ## Problem A stable release should open with the description of its `dev → main` PR, followed by GitHub's generated change list. **v1.0.0** (and before it **v0.20.1**, whose notes were completed by hand) got only the generated list. The `Create GitHub release` step found the PR through `commits/<sha>/pulls`. For the v1.0.0 merge commit, which exists only on `main` while the **default branch** is `dev`, that endpoint returned no PR, still minutes after the merge, so the notes fell back to `--generate-notes` alone. ## Fix The step now lists the closed PRs based on `main` and picks the merged one whose `merge_commit_sha` is the release commit, through `.github/scripts/release-pr-notes.cjs`. This does not depend on the default branch. A release commit without such a PR still gets the generated notes only, and the existing-release path is unchanged. ## Validation - `release-pr-notes.test.cjs` covers the matching rules (merged, base `main`, exact merge commit), a Unicode body passed through the command unchanged, and the workflow wiring. It runs with the other `.github/scripts` tests in PR Build Validation (3/3 locally). - The workflow's exact command, run against real data: | Commit | Old lookup | New lookup | | --- | --- | --- | | v1.0.0 merge (`8370937`) | empty | #1028's description (8,759 chars) | | v0.20.1 merge (`a8545a3`) | #843 (now on `dev`) | #843's description | | `dev` HEAD (no release PR) | — | empty → generated notes only | - The **v1.0.0 release notes were repaired** with the same lookup: #1028's description followed by the generated "What's Changed" list.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CodeNomad 1.0.0 — OpenCode V2, on desktop and mobile
The best desktop and mobile client for OpenCode V2.
0.20.0 brought CodeNomad to OpenCode V2. 1.0.0 turns more of its native power into a complete workspace: coordinated agents, deeper history access and visual automation, with speed, efficiency and everyday stability at its core.
Highlights
Built for demanding workflows
Built around OpenCode V2
@; inspect Code Mode scripts, nested tool calls and web-search sources. Search providers support global defaults and project overrides.Missions and native multi-agent coordination
From your desktop to your phone
History and visual automation
Files, Git and everyday work
/btwbuild on 0.20.0. After sending, use the conversation for keyboard reading; typing resumes the composer.Extensions, help and customization
Desktop updates and setup
Upgrading
.exeor Electron.zip; Linux Tauri AppImage or Electron.deb; Tauri or Electron macOS builds, separate for Intel and Apple Silicon. The Electron.debreplaces the former Tauri.deb—choose AppImage to stay on Tauri.Thanks for contributions
Thanks to creator @shantur, @pascalandr, @heunghingwan, and everyone who contributed ideas, reports and testing.
Changes since 0.20.0: v0.20.0...v1.0.0