Conversation
Desktop-managed zn installations still receive CLI 0.6.0. Pin the released 0.6.1 archives and their source commit (4c4038e) for all four supported desktop targets, keeping integration protocol 1, and bring the in-app manual's terminal entry up to date with what 0.6.1 changes for desktop users: `zn vault list` now says which entries this app saved and which zn saved, so `zn vault remove` stops being trial and error; every command starts without waiting on a terminal that never answers a background-color query; and the help output lines up. The four digests were read from the release's asset digests and matched against its checksums.txt. Each archive was staged through `npm run terminal:stage`, the same download, checksum and native architecture validation packaging runs, and the native darwin-arm64 integration probe answered protocol 1, version 0.6.1.
…880) Switching notes in a large vault froze the window for seconds. The status bar shows how many notes link to the open one, and it counted them by resolving every wikilink in the vault, while each resolution filtered and searched the whole notes list. That is links x notes on every switch, even for a note nobody links to and for one already open in a tab. Yago Fernandes measured 4.8 s per switch in a 6,577-note vault with 13,672 links and traced 94% of the CPU time to that count. Resolution now reads lookup tables built once per notes array: first note per normalized title, first note and count per normalized path, and the same per `/`-led path tail, which is every string `endsWith` could match. backlinksForNote resolves the vault's links once into an incoming map, so a note switch is a lookup. Store updates replace the notes array, so its identity is the revision; length and both ends are rechecked so a caller growing an array in place cannot read a stale table. Matching does not change: `first` is the note the old find returned, `count` is the length the old filter saw, trash is still skipped and anchors are still stripped. A differential run over 35,411 targets (every link plus each note's title and path in 19 spellings) and 224 edge cases returned identical notes, and identical backlink lists for all 6,577 notes. Atlas, wikilink rendering, link clicks and the Connections panel's wikilink matching share the tables. In the built app, a vault shaped like the report (6,542 notes, 12,973 links) went from 1,077 ms to 77 ms click to paint per switch, and from 1,077 ms to 61 ms to reopen a note, with the same backlink counts. A test counts title reads across 200 switches: the old code made 1.2 billion, the new one at most 2,000. This leaves the Connections panel's disk scan and Markdown-link matching as they were, and adds no exclusions (#431).
The desktop runtime benchmark could not see #880. Its synthetic vault had no wikilinks, so resolving every link against every note cost nothing, and its note-open budget reads the store's note.open.* sample, which finishes before React renders the note. On the 2.59.0 code with links seeded, that sample stayed at 30.6 ms while the window froze for 1.5 s per switch. ZEN_PERF_WIKILINKS_PER_NOTE seeds links into every synthetic note with a fixed seed and the report's mix: about half resolve (titles, #Details and ^block anchors, inbox/ and / paths), the rest name notes that do not exist, which were the expensive ones. It defaults to 0, and a 0 run seeds a vault byte-identical to before (checked on 5,000 notes), so older numbers stay comparable. ZEN_PERF_DESKTOP_NOTES=6577 with 2 per note is roughly the reported vault. Every run now also opens 5 notes and reopens 2, timed from click until the editor's doc sync for that path, the matching active tab and two frames. That finish line lands after the commit that renders the note and the status bar, and reads no seeded content, so it works on an external vault. The step runs after the heap, DOM and long-task numbers are taken, and `note switch wall p50` gets a 150 ms budget (enforced only under ZEN_PERF_ENFORCE, like the rest, and in perf:runtime-repeat). Same harness, 6,577 notes, 13,154 links: 1,513.6 ms on the 2.59.0 code, 33.7 ms now. The search step sends Ctrl+P instead of Meta+P off macOS; the reporter had to patch that to run the harness on Linux. The web harness is unchanged.
Open CLI Settings in the command palette only opened Settings, and Settings reopens on whatever page it showed last (Appearance on a fresh launch), so the command never reached the page its name promises. It now asks for the CLI page through the same settings-navigation target the status bar uses for Cloud and :unbind uses for Keymaps. Found while driving the CLI update flow over CDP, where the command landed on Appearance every time.
Every CLI fix needed a desktop release: the app copied its bundled zn back over the managed one whenever the bytes differed, and zn update refused desktop-owned installs. 2.59.0 existed only to ship CLI 0.6.0, and the pin moved five times in two weeks. For a zn that ZenNotes put on PATH, the app now checks the latest ZenNotes/tui release 90 seconds after launch and then daily. Each release carries terminal-release.json (the same schema as this repo's pin) and an Ed25519 signature over its exact bytes; RELEASE_KEYS holds the public key for zn-release-1. The manifest is verified before it is parsed, its download URL must be the release asset its version names, the archive must match the signed sha256, and the extracted zn must answer the integration probe with that version before `current` moves. A failed or tampered download never replaces a working CLI, and the version it replaced stays on disk. The bundle becomes the floor: a newer verified copy survives restarts, a tie goes to the bundle (whose copy carries this build's signature), and a desktop update that ships something newer takes over. A release on a protocol this build does not speak waits for a ZenNotes update. Settings > CLI > Updates shows the running and bundled versions, Check for updates, and Update zn automatically; off still checks and offers the install. State is pushed to open windows, so a scheduled check that lands while Settings is open shows up. The palette gains Check for zn Updates. The switch lives in the per-machine zennotes.config.json rather than config.toml: it governs this machine's copy under userData, like the install location. Homebrew, Go and manual installs are untouched, and nothing is downloaded without a ZenNotes-installed zn, the same condition MCP setups use to pick the managed binary. Verified against the real v0.6.1 release: a build bundling 0.6.0 installed it on its own, kept it across a relaunch, offered it with automatic updates off, refused a manifest edited after signing, and skipped the download with no managed zn, with PATH isolated through a stand-in login shell. The packaged, Developer ID signed, hardened app ran the ad-hoc signed download fine. 14 new tests.
The bundled CLI is the floor a desktop build guarantees, and 0.6.2 is the newest release. It is also the first one signed by the ZenNotes/tui release workflow itself, so the pin is that release's terminal-release.json copied byte for byte after it verified against packaging/release-signing/zn-release-1.pub there and against RELEASE_KEYS here (source commit 140a38f, integration protocol 1, all four archives matching checksums.txt). Staged through `npm run terminal:stage`; the native darwin-arm64 binary reports zn v0.6.2. The in-app manual's CLI card says 0.6.2 and that it is the first release this app can update its managed zn from.
Windows CI failed three parseReleaseManifest tests in the release PR. They built their manifest for the machine running the test, and on Windows that is win32, a platform ZenNotes deliberately manages no CLI on, so parsing threw "does not manage a CLI on this platform" before the assertion it was meant to reach. The install tests in the same file, which execute a real zn, were already skipped on Windows. The manifest and parsing tests now name a platform ZenNotes manages (linux on Windows, this machine's own elsewhere). App code is unchanged. Checked by forcing process.platform to win32 around the file: the old version fails exactly the three CI tests, this one passes 9 with the 5 install tests skipped, and the native run passes all 14.
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.
Summary
znupdates itself from signed ZenNotes/tui releases (Ed25519 manifest, checksum and integration probe before the swap, previous version kept). Settings > CLI > Updates and a palette command; only for aznZenNotes installed.terminal-release.jsonbyte for byte.Verification
npm run pack) launched isolated with a CDP page target in 1.4 s, reporting 2.60.0 and bundling CLI 0.6.2.zn) on the dev and packaged builds.No new demo media.