Repository navigation
Fix(tasks): zn task and zn mcp see tasks in numbered lists and quotes, as the app does - #9
Merged
Merged
Conversation
…, as the app does `zn task list`, `zn task toggle` and the list_tasks and toggle_task tools of `zn mcp` read task lines with the CLI dialect, a bullets-only copy of the grammar kept that way so their task ids matched the desktop's own MCP server. ZenNotes 2.69.1 aligned that server with the app's task lines: numbered lists (`1.` and `1)`) and quoted tasks (`> - [ ]`). The CLI dialect now reads the same lines, so the two MCP servers list the same tasks under the same ids again. Its other differences stay: `@key:value` fields stay in the content, and fences are read only up to three spaces in. Task ids shift once in a note where a numbered or quoted task sits above another task: list again before toggling by an id saved from 0.7.1. TestCLIDialect now expects the four tasks the app sees, and TestCLIDialectReadsEveryTaskShape uses the same note as the desktop's MCP test; both fail with the old grammar. With the built binary on a scratch vault, 0.7.1 listed one task of five and this lists all five, and toggling the quoted one checks it off in place.
renovate Bot
added a commit
to scottames/copr
that referenced
this pull request
Oct 13, 2026
This PR contains the following updates: | Package | Update | Change | |---|---|---| | [ZenNotes/zennotes](https://redirect.github.com/ZenNotes/zennotes) | minor | `2.68.0` → `2.69.1` | --- ### Release Notes <details> <summary>ZenNotes/zennotes</summary> ### [`v2.69.1`](https://redirect.github.com/ZenNotes/zennotes/releases/tag/v2.69.1): ZenNotes v2.69.1 [Compare Source](https://redirect.github.com/ZenNotes/zennotes/compare/v2.69.0...v2.69.1) ZenNotes 2.69.1 fixes renaming on Windows: renaming a note or an attachment to a name another one already has could replace that other file. It always stops and says the name is taken now. Assistants connected through MCP see the tasks in numbered lists and quotes that the app lists, and converting a table to a database in a long note offers the right name. Released from [`86e98b49`](https://redirect.github.com/ZenNotes/zennotes/commit/86e98b49d6a0be5e9c52e4e9b1c414977cbfbd29) through [#​936](https://redirect.github.com/ZenNotes/zennotes/pull/936) on 2026-10-13. All installers are verified. #### Fixes - **A rename onto a name that is taken never replaces the other note (Windows).** Before: on Windows, renaming a note or an attachment to the name of another one in the same folder could go through and replace that other file, instead of saying the name is taken. An assistant renaming a note through MCP could do the same. ZenNotes lets a rename through onto an existing name only when both names reach the same file, which is how a rename that only changes capitals looks on a disk that ignores case. It asked that by comparing file ids as JavaScript numbers, and a Windows file id is 64 bits: two files saved one after the other could round to the same number and read as one file. It compares the whole id now, as Cloud sync already did. On macOS and Linux file ids stay small enough not to round. The check came with 2.55.0 ([#​839](https://redirect.github.com/ZenNotes/zennotes/issues/839)), so every version since then could do this on Windows. - **Converting a table offers the heading right above it, in a long note too.** Before: in a long note, Convert Table to Database could offer the name of an earlier heading when the editor had not yet read as far as the table. The name could be edited before saving, so nothing was saved under it unseen. It now reads the note up to the table before choosing. - **Assistants see tasks in numbered lists and quotes.** Before: an AI assistant connected through MCP saw only bullet tasks. `list_tasks` skipped tasks in numbered lists (`1. [ ]`, `1) [ ]`) and in quotes (`> - [ ]`), and `toggle_task` could not reach them, although the app's Tasks view lists them; a task below one of them also got a different number than the app gives it. The MCP server now reads task lines the way the app does. #### For contributors - `apps/desktop/src/main/same-file.ts` (`6d750154`): `fileIdentity()` is a bigint stat and `isSameFile()` compares its device and inode. Every "is the destination the file itself?" question goes through it: note, asset and folder renames in `vault.ts`, the shared sidecar mover in `note-sidecars.ts`, a workflow rename's cleanup in `workflows.ts` (which kept the old file instead of removing it) and the MCP server's `renameNote`. `windows-file-ids.testing.ts` gives tests the ids Node reports on Windows: the full id from a bigint stat, a rounded number otherwise. Six tests use it, for desktop and MCP note and folder renames, an asset rename and a workflow rename; each failed on the old guards with the same symptom CI showed. - `headingAbove()` in `table-to-database.ts` asks `ensureSyntaxTree(state, pos, 50)` whether the parse reached the table (`ba74c54f`): `noteMarkdown`'s outer tree spans the whole note even while its body parse is short, so `syntaxTree(state).length` always said yes. Its test cuts the first parse short with a clock that moves 30 ms per read. - Five CI failures since September are fixed at their causes (`65d30daf`): tests that read `syntaxTree(state)` after a 20 ms parse budget (task rollups, incremental parsing) or before the first parse reached a code block (search highlighting), two timeouts for a cold import and a slow runner, and a port race in `test-app-core-browser.mjs` that gave the API server and Chrome the same port, the Ubuntu "Exercise the installed editor in Chrome" failure. That step then failed once on this release's PR for a second reason, read before re-running: a cold Chrome on a busy runner took 26 seconds to open DevTools against a 30 second wait; it gets 90 now (`86e98b49`). - The MCP server's `TASK_LINE_RE` matches the lines `@shared/tasklists`' does (`a2b4bfe7`); a test pins that parity on a note with every shape. zn 0.7.2 (`zn task` and `zn mcp`) and server 2.69.1 (the web app's Tasks view), released the same evening, read the same lines; the release runbook now checks every copy of this regex across the three repos before a cut. - The Release workflow starts on tags matching `v[0-9]*` instead of `v*` (`c35ae438`). Publishing a boundary package's draft creates a tag such as `viewer-2.69.0-viewer.h5e7ef0f99f145d0a`, and from 2.63.0 to 2.69.0 every viewer publish built a whole desktop release and uploaded it onto the viewer pre-release. The desktop releases themselves were never touched. #### Verification How to test locally: 1. The guards, on any OS: `cd apps/desktop && npx vitest run src/main/note-sidecars.test.ts src/main/vault.test.ts src/main/workflows.test.ts -t "Windows file id|round to one number|rounds to the same number"`. Six tests pass. In `apps/desktop/src/main/same-file.ts`, drop `{ bigint: true }` from `fileIdentity` (the old number compare) and run them again: all six fail, the rename resolving instead of refusing. 2. On Windows, in a vault with two notes `One` and `Two` in one folder, rename `One` to `Two`. After: "A note named “Two” already exists in this folder", and both notes keep their text. Before, on a disk whose file ids round together, `Two` could end up holding `One`'s text; on a fresh Windows install the ids are small and it would not happen. 3. Convert Table to Database in a long note: put `# Early` at the top of a note, about fifty paragraphs, then `# Roadmap` and a table under it. Open the note and right away choose Convert Table to Database from the table's menu. After: the name offered is "Roadmap". The test `npx vitest run src/lib/table-to-database.test.ts` in `packages/app-core` covers it with a slow clock. 4. Tasks for an assistant: in a note with `1. [ ] numbered` and `> - [ ] quoted`, ask an assistant connected through ZenNotes' MCP server to list your open tasks. Before: neither appeared. After: both do, and it can check them off; `cd apps/desktop && npx vitest run src/mcp/vault-ops.test.ts -t "ordered"` covers it. 5. A rename that only changes capitals still works: rename `One` to `one` on macOS or Windows. The note is renamed in place, and its comments come along. #### Distribution channels - **GitHub release:** installers for macOS (Apple silicon and Intel DMG and zip), Windows (x64 and ARM64 installer and zip) and Linux (x64 and arm64 AppImage, deb, rpm, pacman, tar.gz), with five update manifests. - **AUR:** `zennotes-bin` 2.69.1-1 (AUR clone `4dc9727`, repo `9b754de5`), pinned to `ZenNotes-2.69.1-linux-x64.tar.gz` SHA-256 `e0077164…b4e3` (GitHub's own digest for the asset), after the bump script checked the bundled CLI folder is world-readable; [aur-check](https://redirect.github.com/ZenNotes/zennotes/actions/runs/38456876873) passed. - **Nix:** `packaging/nix/release-data.json` lifted from the update workflow ([run 38456877828](https://redirect.github.com/ZenNotes/zennotes/actions/runs/38456877828), bot PR [#​937](https://redirect.github.com/ZenNotes/zennotes/issues/937) closed) as `dde7064d`; its `desktopHash` is the same digest as the AUR pin, and [nix-build on main](https://redirect.github.com/ZenNotes/zennotes/actions/runs/38457157441) passed. - **nixpkgs:** [NixOS/nixpkgs#572180](https://redirect.github.com/NixOS/nixpkgs/pull/572180), still waiting for review, now proposes 2.64.0 -> 2.69.1 (`17d94f17`); the source hash comes from the tag tarball, by the same prefetch that reproduces the 2.64.0 hash in nixpkgs today. - **Homebrew:** `zennotes` 2.69.1 in the tap (`4cf0b75`), mirrored in `5e01d4f4`; both DMGs were downloaded and their SHA-256 matches the cask and GitHub's digest; `brew style` clean. - **Website:** [ZenNotes/website#78](https://redirect.github.com/ZenNotes/website/pull/78) merged at `d8718ebe` with the 2.69.1 entry (three fixes); Laravel Cloud deployed it and the live check passed: /releases leads with 2.69.1 and all three fixes, and page 2 starts at 2.66.0. `npm run verify:channels -- 2.69.1`: every applicable channel serves v2.69.1. - **zn CLI:** 0.7.2 ([ZenNotes/tui#9](https://redirect.github.com/ZenNotes/tui/pull/9), tag `v0.7.2`, Homebrew formula `8744800`, tap `ebf346c`): `zn task` and `zn mcp` list tasks in numbered lists and quotes, as the desktop's MCP server does in this release. A zn installed from Settings → CLI updates itself; the copy bundled in the app stays 0.7.1 until the next desktop release. - **Server:** [ZenNotes/znserver v2.69.1](https://redirect.github.com/ZenNotes/znserver/releases/tag/v2.69.1) lists the same task lines in the web app's Tasks view and pins `web-2.69.1-web.he3742063f1986fdb`, built from this release's commit ([#​28](https://redirect.github.com/ZenNotes/znserver/pull/28)); its five binaries match `SHA256SUMS`, and the released darwin-arm64 binary reports v2.69.1, serves the app, answers 401 without the token and lists all five tasks of the test note with it. Docker `adibhanna/zennotes:2.69.1`, `2.69` and `latest` (linux/amd64 and arm64, one digest `db6ced3f…`). - **Phones:** unchanged; iPhone 1.25.0 and Android 1.1.39 run `core-2.69.0`. #### Release validation Every CI failure on `main` since September was read before this release. None was a product bug: seven were fixed already or were runner infrastructure, five were test or harness bugs, fixed in `65d30daf`, and reading one of them found the table naming bug. The Windows rename bug was found like this: after 2.69.0 was tagged, the `windows-11-arm` CI job on `main` failed once in `vault.test.ts` ("says when another note already has the name": the rename resolved instead of refusing), on code the release PR had passed on both Windows runners. The release process now reads every CI failure since the previous release before the cut and scans the tree for code patterns that already shipped a bug; on this branch both are clean: the two failures since 2.69.0 are this bug and 16 tests in unrelated suites timing out at 5 seconds on one slow `windows-latest` runner, and the scan, which flags the six old guards on 2.69.0's code, finds nothing. Release-time gates on `a2b4bfe7` (the release commit `86e98b49` adds only the browser check's longer Chrome wait): typecheck 8/8 and test:run 6/6 with no turbo cache (shared-domain 1,994, app-core 3,221, quicklook 15, desktop 1,147), fresh build:prod green, `npm audit --omit=dev --audit-level=high` clean. Pack: Developer ID signed, deep strict codesign OK, bundled `zn v0.7.1` in a drwxr-xr-x `Resources/zn-cli`, the Quick Look extension; packaged launch check: page target and drawn app in 1.5 s, version 2.69.1. Smoke suites vim-editor (12), sidebar-vim (12) and editor-improvements (19) pass on the first run. `ci-sweep.py v2.69.0`: two failures, both explained; `hazard-scan.py --since v2.69.0`: clean. Release PR [#​936](https://redirect.github.com/ZenNotes/zennotes/issues/936): all 10 checks green on `86e98b49`, including the `windows-11-arm` package and launch check. The run before it, on `a2b4bfe7`, failed once in Ubuntu's Chrome step and was read before anything else: the ports were distinct, and a cold Chrome took 26 seconds against a 30 second wait, fixed in `86e98b49`. CI on `main` for `86e98b49` (run [`3845207`](https://redirect.github.com/ZenNotes/zennotes/commit/38452074217)) passed all six jobs before the tag, and again for the packaging commits (`dde7064d`). Release run [`3845506`](https://redirect.github.com/ZenNotes/zennotes/commit/38455066243): all six jobs green in about 45 minutes; `verify-installers.py` ALL GOOD on the five manifests; both DMGs hash to GitHub's digests and the cask, and the app in each is `Notarized Developer ID` with a valid stapled ticket. `npm run verify:channels -- 2.69.1`: every channel serves v2.69.1. What's New on the update from 2.69.0, in the built app over CDP: "What's new in ZenNotes 2.69.1" with the Renames on Windows highlight. ### [`v2.69.0`](https://redirect.github.com/ZenNotes/zennotes/releases/tag/v2.69.0): ZenNotes v2.69.0 [Compare Source](https://redirect.github.com/ZenNotes/zennotes/compare/v2.68.0...v2.69.0) ZenNotes 2.69.0 lets AI assistants reach a ZenNotes Server that needs a token, with one click in Settings instead of a terminal, and makes `zn connect` work for every MCP install. Setup no longer asks a server vault for a layout, the Claude integrations say which tab of the Claude app they reach, the New note form in search names the keys of the field you are in, and a Cloud vault that another device encrypted reads as encrypted, not deleted. Shortcuts no longer act behind What's New, Settings or a palette, and the phones can now start a note in the folder they are browsing. Released from [`d1344076`](https://redirect.github.com/ZenNotes/zennotes/commit/d13440764dfa66263714390fe044e2b2747f645d) through [#​934](https://redirect.github.com/ZenNotes/zennotes/pull/934) on 2026-10-13. All installers are verified. #### New - **Assistants reach your ZenNotes Server without a terminal** ([#​830](https://redirect.github.com/ZenNotes/zennotes/issues/830)). When the app is connected to a ZenNotes Server that needs a token, Settings → MCP → **Server token** now offers **Let assistants use it**. It saves the token the app connects with where `zn connect` saves it, so Claude Code, Codex and any other assistant you installed from Settings → MCP reach the server on their next call, with no terminal and no typing the token a second time. It is your choice, and the section says why: the app keeps its own copy in your system's secure storage, which no assistant can read, and sharing puts a copy in a private file that programs running as you can read. **Stop sharing** takes it out again. The shared copy follows the app: saving a new token for the server replaces it, and forgetting the server in Settings → Vault removes it. A token you saved yourself with `zn connect` is never touched. Thanks to Kevin ([@​diazkev314](https://redirect.github.com/diazkev314)) for the report and for asking for exactly this. - **Start a note in the folder you are browsing, on the phones** ([ZenNotes/zennotesandroid#108](https://redirect.github.com/ZenNotes/zennotesandroid/issues/108), [#​923](https://redirect.github.com/ZenNotes/zennotes/issues/923)). Browse on Android and iPhone gains a **New note** row above New folder, in every folder and at the top level. It opens a new note inside the folder you were looking at, with its title selected so you can type the name. Until now a note could only start at the top and then be moved. The part inside ZenNotes ships here; the row arrives with the next Android and iPhone updates. Thanks to [@​davi-jorge-art](https://redirect.github.com/davi-jorge-art) for the request. #### Fixes - **After `zn connect`, every MCP install reaches the server** ([#​830](https://redirect.github.com/ZenNotes/zennotes/issues/830)). With the app connected to a token-protected server, an assistant could keep answering "The MCP server has no valid token for this ZenNotes server" even after `zn connect`, as the manual says to run. Install registers one of two MCP servers: `zn mcp` when `zn` came from Settings → CLI, and otherwise the server bundled with the app (a `zn` from Homebrew and every Windows install included). Only `zn mcp` read the token `zn connect` saves. Both do now, for the server the app is connected to, and the call after `zn connect` works without restarting the assistant. The error now names the exact `zn connect <url> --no-default` to run, and the new Server token button first. Thanks to Kevin ([@​diazkev314](https://redirect.github.com/diazkev314)). - **Setup skips the layout step for a server vault.** Connecting to a ZenNotes Server in the setup wizard went on to ask how the vault should be organized, a choice the server's vault has already made for every app connected to it. Clicking through it could change the layout for the phones and the web app too. Setup now goes from the vault straight to Done for a server vault; a folder on this machine still gets the layout step. Thanks to Kevin. - **The Claude integrations say which tab of the Claude app they reach.** Settings → MCP read "Claude Code" and "Claude Desktop", which looks like one entry per app. But the Claude desktop app's Code tab runs Claude Code and uses the Claude Code entry, while the Claude Desktop entry reaches only its Chat tab. They now read **Claude Code (CLI + Desktop Code tab)** and **Claude Desktop (Chat)**. Kevin suggested the names. - **The New note form in search names the keys of the field you are in** ([#​933](https://redirect.github.com/ZenNotes/zennotes/pull/933), by [@​uNyanda](https://redirect.github.com/uNyanda)). The form's footer always offered `↑↓ pick` and `↵ create`, which was wrong in most fields: arrows only move through the folder and tag lists, and Enter picks the highlighted row when there is one. Now in Name it reads `↵ create note`; in Folder `↑↓ pick`, and `↵ choose folder` once a row is highlighted; in Tags `↵ add tag`; and text that is not a valid tag drops the Enter hint, while the line above says why. Thanks to [@​uNyanda](https://redirect.github.com/uNyanda), who also wrote the component's first tests. - **Cancelled tasks no longer count as open for assistants** ([#​929](https://redirect.github.com/ZenNotes/zennotes/pull/929), by [@​vishalhabib99](https://redirect.github.com/vishalhabib99)). The MCP `list_tasks` tool's open filter and `zn task list` listed `[-]` cancelled tasks next to the ones still to do, although the calendar and Kanban already leave them out. They are left out now; `status: all` and `--all` still show them. The Go `zn` does the same from 0.7.1. Thanks to [@​vishalhabib99](https://redirect.github.com/vishalhabib99). - **A Cloud vault that another device encrypted says so.** When one device moves a Cloud vault to end-to-end encryption, the other devices linked to the old vault are told it was replaced. The desktop app stopped syncing it but said "Cloud vault deleted", and the phones kept the link and repeated "Update ZenNotes on this device" on every sync, even when up to date. Now every app stops syncing the old vault, the status bar says **Cloud vault now encrypted**, and Settings says the vault was replaced by an end-to-end encrypted one and how to open it: unlock encryption on this device if needed, then choose the encrypted vault. The phones get this with their next update. - **The manual shows bold names and paragraphs.** Thirteen entries of the in-app manual printed `**` around the names of buttons and settings, and longer guides ran their paragraphs together. They now read as intended, and a search phrase that runs through a bold name finds its entry. The end-to-end encryption entry also names the right button (**Save archive** under Backups, in the desktop app; the phone apps send you there) and says what other devices do when a vault is encrypted. - **Shortcuts no longer act behind What's New, Settings or a palette.** What's New opens by itself on the first launch after an update, so the keys you press out of habit land on it, and none of them knew it was there: Cmd+P opened a note search underneath it that you could not see and took your typing, Cmd+N and Shift+Cmd+N made a note behind it, Shift+Cmd+P opened the command palette and Cmd+, opened Settings under it. Now no shortcut acts behind What's New; its own buttons, Tab and Escape still work, and Cmd+, (or Settings… in the macOS menu) replaces it with Settings. Behind Settings or any palette, Ctrl+Tab (previous note), Alt+Left and Alt+Right (note history) and Shift+Cmd+T (reopen closed tab) switched the note you would come back to, and Shift+Cmd+N made a Quick Note and moved your typing into its hidden title. They wait until the overlay is closed, as tab switching already did. Found while recording this release's demos. - **The Tasks calendar's keys no longer change tasks behind a dialog.** With the calendar open under Settings, What's New or a palette, Space on one of the dialog's buttons marked the selected day's task done (x in Vim mode), Tab moved through the calendar's tasks instead of the dialog's buttons, and in Vim mode dd deleted a task. The calendar now leaves the keyboard to the dialog, as the task list and the board already did. - **An encrypted vault shows its name as soon as you unlock.** Settings → Cloud showed an encrypted vault as "Encrypted vault" until this device unlocked encryption, and kept showing that after unlocking until Settings was opened again. It reads the list again when you unlock or lock. On the phones, an encrypted vault's backups no longer offer Save archive, which could only fail there; they say to use Save archive in the desktop app. - **Settings on the phones and iPad offers only what the device has.** Settings search listed the settings of sections the phones hide, so "review" offered Review agent edits and a tap opened an empty page; and Settings → Keymap on an iPad (and in the web app) listed the keys for reviewing an assistant's edits, which only the desktop app can do, and the grammar keys where grammar checking is not available. With the next phone updates. #### For contributors - MCP token lookup ([#​830](https://redirect.github.com/ZenNotes/zennotes/issues/830), `ef122a4b`): `apps/desktop/src/main/remote/zn-credentials.ts` reads and writes zn's `credentials.toml` (`[tokens]`, keyed by the URL trimmed, without trailing slashes, lowercased; `0600`; atomic replace; a file not in zn's format is never overwritten, and errors never quote it), in the portable config dir (`ZENNOTES_CONFIG_DIR`, then `XDG_CONFIG_HOME/zennotes`, then the platform default). The bundled MCP server (`apps/desktop/src/mcp/vault-ops.ts`) and the TypeScript `zn` (`apps/desktop/src/cli/vault-target.ts`) resolve a server's token as `--token`, `ZENNOTES_REMOTE_TOKEN`, a legacy profile token, then the saved one, the Go server's order, for the URL the app already chose, so a saved token never picks a server. - Server token (`dd0f929b`): `apps/desktop/src/main/mcp-server-token.ts` (states `none` with a reason, `missing`, `shared`, `different`, `unreadable`; share, remove only the app's own token, and `followAppServerToken` on profile save and delete), receipts in `userData/mcp/shared-server-tokens.json`. The main process picks the server from the persisted workspace, the way both MCP servers do, and reads the token from the secret store; IPC `MCP_SERVER_TOKEN_STATE`, `_SHARE` and `_REMOVE` take no arguments from the renderer, which only ever sees the state. The bridge methods `mcpGetServerTokenState`, `mcpShareServerToken` and `mcpRemoveServerToken` are optional and desktop only (`faa8f873`): the phone bridges implement `ZenBridge` too, and a required method broke their typecheck against core 2.69. UI: `McpServerTokenSetting` in `SettingsModal.tsx`, Settings search id `mcp-server-token`. - Onboarding (`ed6fb808`): `OnboardingWizard.tsx` takes its steps from the workspace mode (`visibleSteps`, `stepAfter`); connecting sets the vault and the mode in one store update, so the auto-advance already knows the next step, and `goToStep` now records the step it lands on (the rail could not move forward to it after Back). The web app reports no remote workspace and keeps the layout step, which is how a new server vault gets made. - Create form hints ([#​933](https://redirect.github.com/ZenNotes/zennotes/issues/933), `bcc52592`, follow-up `fb9c6fcc`): `SearchCreateForm.tsx` derives `↑↓` and the Enter label from the focused field and reads the highlighted row exactly the way the Enter handlers do, so a list that shrinks under the highlight (a sync dropping a tag while the form is open) cannot make the hint lie. `SearchCreateForm.test.ts` is the component's first test file, `.ts` because `vitest.config.ts` only includes `src/**/*.test.ts`. - Cancelled tasks ([#​929](https://redirect.github.com/ZenNotes/zennotes/issues/929), `c0d25dd2`): `list_tasks` in `apps/desktop/src/mcp/server.ts` and `zn task list` in `apps/desktop/src/cli/commands/tasks.ts`; the Go mirror is ZenNotes/tui `91bb33b` (zn 0.7.1). - Superseded vaults (`00c592bb`): `packages/shared-domain/src/cloud-vault-availability.ts` owns the check (`isCloudVaultSuperseded`: a `CloudServiceRequestError` with 410 and `VAULT_SUPERSEDED`) and `CLOUD_VAULT_SUPERSEDED_MESSAGE`. `CloudSyncHostService`, the phones' sync host, retires the link on it during a sync and the background remote-changes check, as it does for a 404; the desktop main process uses the same two pieces. app-core's removal notice gains a third reason, `encrypted`. - Manual rendering (`a72e97c9`): `packages/app-core/src/lib/help-rich-text.tsx` (`renderHelpRichText`, `helpSearchText`): `**bold**` only outside code spans, a blank line starts a paragraph (block spans, since a section description sits in a `<p>`). Deliberately not the task cards' inline-markdown renderer: the manual mentions `[[` 43 times and shows link syntax as examples to type. `help-rich-text.test.ts` renders every manual string and fails on any `**` left outside code. - Browse (`f9e219b2`): `requestCreateBrowseNote(host, directory)` in the browse boundary beside `requestCreateBrowseFolder`, with the same guards, creating through `createAndOpen` with the title focused. The phone shells add the row: ZenNotes/zennotesandroid `4523a8b` (in [#​111](https://redirect.github.com/ZenNotes/zennotesandroid/pull/111), version 1.1.39) and ZenNotes/zennotesios `e5b5928` (in [#​59](https://redirect.github.com/ZenNotes/zennotesios/pull/59), version 1.25.0). - MCP integration labels (`504c1551`): `packages/shared-domain/src/mcp-clients.ts`; Settings search keyword `code tab`. - Shortcuts behind overlays (`12908407`): in `App.tsx`, the capture-phase handler (Mod+P, Mod+N, pane focus and modes) adds `whatsNewOpen` to the overlays it bails for; the bubble-phase handler returns at once while What's New is open, except `global.openSettings`, which closes it and opens Settings (the `onOpenSettings` listener does the same for the macOS menu, which takes Mod+, before the page). The overlay check that guarded tab selection and the template pickers (`tabSelectBlocked`, now `overlayOpen`) moves to the top of the handler and also guards `global.newQuickNote`, `global.historyBack`, `global.historyForward`, `global.toggleRecentNote` and `global.reopenClosedTab`. View toggles and the command palette's own toggle are unchanged. Harnesses: `docs/releases/v2.69.0/whats-new-overlay/` (local). - Tasks calendar (`6da71c43`): `TasksCalendar.tsx`'s capture-phase window handler bails on `isOverlayOrDialogOpen()`, like `TasksView` and `TasksKanban`. - Settings per host (`803ae295`): each Settings search result carries `data-settings-result-category` (the section id), which the phone shells use to hide the results of the sections they hide; `keymapAvailableOnHost` in `lib/keymaps.ts` leaves the `editor.review*` / `vim.review*` keys out without `supportsAgentEditReview` and the `vim.harper*` keys without `supportsHarper`. - Encrypted vaults in Settings → Cloud (`d1344076`): `CloudSettings` reads the vault list again when the encryption status's `unlocked` changes (not on the first status); the new optional capability `supportsEncryptedBackupArchive` (set by the desktop preload) decides whether an encrypted vault's backups offer Save archive. - Phone shells (on their release branches): Settings search hides the results of hidden sections (Android `b6fea3f`, iPhone `6fa07b5`); an assistant's edit record (`.zennotes/agent-edits/<note>.json`) is a third sidecar in `vault-fs.ts`, moving with renames, moves, Trash and folder renames, going with deletes and Empty Trash, and never inherited by a new note (Android `dc6cb34`, iPhone `329ee69`); the shells' own strings drop the long dash (Android `d72ec37`, iPhone `c17556a`). - Bundled CLI: zn 0.7.1 (`69342fa3`), its `terminal-release.json` copied byte for byte after it verified against `zn-release-1` (source commit `91bb33b`, protocol 1, all four archives matching `checksums.txt`); the staged darwin-arm64 binary reports `zn v0.7.1`. It carries [#​929](https://redirect.github.com/ZenNotes/zennotes/issues/929)'s task filter and a token message that names the Server token button. - What's New: the 2.69.0 entry in `packages/app-core/src/lib/whats-new.ts` (`87c7e216`). - Docs: the in-app manual's MCP card (which server Install registers when, the Code tab, the Server token paragraph) and CLI card; on the website, the MCP section, the Server token docs, the encryption notice, and the CLI version mentions (`website/docs-2.69`). #### Demos In `docs/releases/v2.69.0/media/` (local), 1080p with captions burned in and a `.vtt` beside each, recorded on the 2.69.0 build with scratch vaults; the server clips run a real ZenNotes Server with a token and a real MCP client named `claude-code` driving the app's own MCP server: - [setup-server-vault.mp4](https://redirect.github.com/ZenNotes/zennotes/releases/download/v2.69.0/setup-server-vault.mp4) (12 s): the setup wizard connects to a ZenNotes Server with its token and goes from the vault straight to Done, with no layout step. - [server-token.mp4](https://redirect.github.com/ZenNotes/zennotes/releases/download/v2.69.0/server-token.mp4) (25 s): Settings → MCP shows the renamed Claude entries; Server token's **Let assistants use it** saves the token where `zn connect` would; then Claude Code creates a note on the server through MCP and it shows up in the app. - [new-note-hints.mp4](https://redirect.github.com/ZenNotes/zennotes/releases/download/v2.69.0/new-note-hints.mp4) (28 s): search for a note that does not exist, open the New note form, and watch the footer follow the field: Name, Folder (pick and choose `Inbox › Projects`), Tags (add `#launch`), text that is not a tag, then Create. #### Verification How to test locally. Build once with `npm run build --workspace @zennotes/desktop` and launch with isolated stores: `ZENNOTES_USER_DATA_PATH=$(mktemp -d) ZENNOTES_CONFIG_DIR=$(mktemp -d) npx electron apps/desktop/out/main/index.js`. For the server steps, run a ZenNotes Server with a token, for example ZenNotes/znserver's `go run ./cmd/zennotes-server` with `ZENNOTES_VAULT_PATH=<folder>` and `ZENNOTES_AUTH_TOKEN=<token>` (it listens on `127.0.0.1:7878`). 1. **Setup for a server vault.** With a fresh profile, the wizard opens. On the Vault step choose **Connect to ZenNotes Server**, enter `http://127.0.0.1:7878` and the token. Before: the next step was "Vault layout". After: "You're ready to write", and the step rail reads Welcome, Vim mode, Theme, Vault, Done. Back returns to Vault; **Choose vault folder** with a local folder still leads to the layout step. 2. **Server token.** Connected to that server, open Settings (Cmd+,) → MCP. The Claude entries read "Claude Code (CLI + Desktop Code tab)" and "Claude Desktop (Chat)". Under **Server token**, the section says assistants can't reach the server yet. Choose **Let assistants use it**: `credentials.toml` in your config dir now holds the server's URL and token (mode `0600`), and `zn --server http://127.0.0.1:7878 vault info` answers without `zn connect`. **Stop sharing** removes the line and zn is refused again. A local vault shows a one-line note instead of the button. 3. **zn connect reaches the bundled MCP server** ([#​830](https://redirect.github.com/ZenNotes/zennotes/issues/830)). Without sharing, run `zn connect http://127.0.0.1:7878 --no-default` and enter the token, then call any tool from an MCP client running `apps/desktop/out/main/mcp.js` with `ELECTRON_RUN_AS_NODE=1` and the same `ZENNOTES_CONFIG_DIR`. Before: "no valid token for this ZenNotes server" in the same session and a fresh one. After: the next call reads the server's vault. 4. **New note form hints** ([#​933](https://redirect.github.com/ZenNotes/zennotes/issues/933)). Press Cmd+P, type a name no note has, press Shift+Enter. The footer reads `↵ create note` in Name; Tab to Folder: `↑↓ pick`, and after ↓ `↵ choose folder`; in Tags, ↓ gives `↵ add tag`; type `!!!` and the Enter hint disappears while the line above explains. Before: `↑↓ pick` and `↵ create` everywhere. 5. **Cancelled tasks** ([#​929](https://redirect.github.com/ZenNotes/zennotes/issues/929)). In a vault with `- [ ] open` and `- [-] dropped`: `zn task list` (and the MCP `list_tasks` with its default open filter) lists only "open"; `--all` lists both. 6. **The manual.** Open Help (or `:help`) and search "Encrypt a Cloud vault": two paragraphs and bold button names, no `**`. Search a phrase that runs through a bold name, like "choose encrypt this vault in settings": the entry is found. 7. **Shortcuts behind What's New.** Launch with a fresh `ZENNOTES_USER_DATA_PATH` and an existing `config.toml` in `ZENNOTES_CONFIG_DIR` (that marks a returning user, so What's New opens). Press Cmd+P and type: before, a hidden search took the text and Escape revealed it; after, nothing happens behind the window. Cmd+N: before, `Untitled.md` appeared in the vault; after, nothing. Cmd+,: What's New closes and Settings opens. With What's New closed, open two notes, then Settings, and press Ctrl+Tab: before, the note under Settings changed; after, it stays. 8. **Tasks calendar.** Put a task due today in a note, open Tasks → Calendar, open Settings (Cmd+,) and click Appearance, then press Space. Before: the task was marked done on disk. After: unchanged, and Space toggles it again once Settings is closed. 9. **Phones** (once the updates are out): Browse, open a folder, **New note**: the note opens in that folder, title selected. Settings → search "review": no Review agent edits. #### Distribution channels - **GitHub release:** installers for macOS (Apple silicon and Intel DMG and zip), Windows (x64 and ARM64 installer and zip) and Linux (x64 and arm64 AppImage, deb, rpm, pacman, tar.gz), with five update manifests. - **AUR:** `zennotes-bin` 2.69.0-1 (AUR clone `281358c`, repo `97a16340`), pinned to `ZenNotes-2.69.0-linux-x64.tar.gz` SHA-256 `4e790b5c…208e` (GitHub's own digest for the asset), after the bump script checked the bundled CLI folder is world-readable; [aur-check](https://redirect.github.com/ZenNotes/zennotes/actions/runs/38430995718) passed. - **Nix:** `packaging/nix/release-data.json` lifted from the update workflow ([run 38431006332](https://redirect.github.com/ZenNotes/zennotes/actions/runs/38431006332), bot PR [#​935](https://redirect.github.com/ZenNotes/zennotes/issues/935) closed) as `e0fd70cf`; its `desktopHash` is the same digest as the AUR pin, and [nix-build on main](https://redirect.github.com/ZenNotes/zennotes/actions/runs/38431352262) passed. - **nixpkgs:** [NixOS/nixpkgs#572180](https://redirect.github.com/NixOS/nixpkgs/pull/572180), still waiting for review, now proposes 2.64.0 -> 2.69.0 (`b5870af`); the source hash comes from the tag tarball, by the same prefetch that reproduces the 2.64.0 hash in nixpkgs today. - **Homebrew:** `zennotes` 2.69.0 in the tap (`e317675`), mirrored in `634f67a8`; both DMGs were downloaded and their SHA-256 matches the cask and GitHub's digest; `brew style` clean. - **Website:** [ZenNotes/website#77](https://redirect.github.com/ZenNotes/website/pull/77) merged at `18ceb3eb` with the releases entry and its three clips, the docs for this release (Settings → MCP → Server token, the Claude tabs' names and the zn token the bundled server reads, both MCP servers following a vault switch, the notice for a vault another device encrypted, and CLI 0.7.1 leaving cancelled tasks out), the dashboard's note that an encrypted vault's archive is saved in the desktop app, and the 2.69.0 share viewer (2.68.0 stays installed for pages cached against it). Laravel Cloud deployed it, and the live check passed: the releases page and docs carry 2.69.0, one clip and its captions match the local files byte for byte, a Range request on another answers 206, and the live 2.69.0 and retained 2.68.0 viewer files match their manifests. `npm run verify:channels -- 2.69.0`: every applicable channel serves v2.69.0. - **zn CLI:** 0.7.1 ([ZenNotes/tui#8](https://redirect.github.com/ZenNotes/tui/pull/8), tag `v0.7.1`, Homebrew formula `bac26a2`), bundled here: [#​929](https://redirect.github.com/ZenNotes/zennotes/issues/929)'s task filter and a token message that names the Server token button. - **Server:** [ZenNotes/znserver v2.69.0](https://redirect.github.com/ZenNotes/znserver/releases/tag/v2.69.0) pins the published `web-2.69.0-web.h90d11c06b6e3cf34` browser artifact ([#​26](https://redirect.github.com/ZenNotes/znserver/pull/26)); its five binaries match `SHA256SUMS`, and the released darwin-arm64 binary reports v2.69.0, serves the app and turns away a request without the token. Docker `adibhanna/zennotes:2.69.0`, `2.69` and `latest` (linux/amd64 and arm64, one digest `6328d4c9…`); README [#​27](https://redirect.github.com/ZenNotes/znserver/pull/27). - **Boundary packages:** built by CI from `d1344076` and published as pre-releases, never "latest": `web-2.69.0-web.h90d11c06b6e3cf34`, `viewer-2.69.0-viewer.h5e7ef0f99f145d0a` and `core-2.69.0-core.h27a2c5df8414d1dd`, published once both phone apps had shipped on it; publishing the viewer's draft also started a stray desktop Release run onto the viewer pre-release (the workflow's `v*` trigger matched `viewer-...`), which was cancelled; v2.69.0's own files were never touched, and 2.69.1 narrows the trigger to `v[0-9]*`. - **Phones:** iPhone 1.25.0 (41) and Android 1.1.39 (42), both on `core-2.69.0-core.h27a2c5df8414d1dd`: Browse's New note row ([#​923](https://redirect.github.com/ZenNotes/zennotes/issues/923), [zennotesandroid#108](https://redirect.github.com/zennotesandroid/zennotes/issues/108)), the notice and the name for a Cloud vault another device encrypted, Settings search that offers only what the device has, and an assistant's pending edits that move with a renamed note. iPhone: [zennotesios#59](https://redirect.github.com/ZenNotes/zennotesios/pull/59) merged at `dfa8128`; its UI tests passed on iPhone and iPad simulators, the account-backed Cloud UI tests were not run for this build, and it was submitted to App Review on 2026-10-13. Android: [zennotesandroid#111](https://redirect.github.com/ZenNotes/zennotesandroid/pull/111) merged at `1664759` (tag `v1.1.39`, the same tree as the uploaded bundle) and sent to Google Play review on 2026-10-13 for a full rollout; the [GitHub release v1.1.39](https://redirect.github.com/ZenNotes/zennotesandroid/releases/tag/v1.1.39) carries Play's signed universal APK (31,883,725 bytes, SHA-256 `3e2d5f90…7f5d`, signer `9f1af3a4…`), byte-identical when downloaded again. #### Release validation Cycle checks: - [#​830](https://redirect.github.com/ZenNotes/zennotes/issues/830) end to end with real binaries (`docs/releases/v2.69.0/issue-830/`): a token-protected ZenNotes Server, the Go `zn` built at 0.7.0 running `zn connect`, and `mcp.js` run exactly as Install registers it. Before: `vault_info` still failed after `zn connect`, in the same session and a fresh one. After: the same running session read the server's vault on its next call. Server token over CDP in the dev app, with its `safeStorage` swapped for an in-memory fake so no Keychain was touched: connected from the wizard, **Let assistants use it** wrote `credentials.toml` (`0600`, the app's token under zn's key), and the real Go `zn` and `mcp.js` both reached the server; **Stop sharing** turned both away; sharing again and saving a new token for the server updated the file; forgetting the server emptied it. Unit tests: `zn-credentials.test.ts`, `mcp-server-token.test.ts` and the MCP and resolver tests, five of which fail with the fallback removed. - Setup over CDP with throwaway profiles and a loopback server: before, connecting landed on "Vault layout"; after, on Done, with the server's layout untouched; a local folder still lands on the layout step. - [#​933](https://redirect.github.com/ZenNotes/zennotes/issues/933) in the built app over CDP: the footer in Name, Folder (with and without a highlight, and filtered to nothing) and Tags (with a highlight and with invalid text) matches the PR; the form, search-create and palette-nav suites (42 tests; the follow-up's new test fails on the merged code). The PR's first CI failure (a test seeded `vaultSettings: null`, which vitest does not typecheck) is fixed in `fb9c6fcc`. - Superseded vault: the desktop live test against a local Cloud with `CLOUD_E2EE=beta`, the second device getting the real 410; the new host tests fail against the old service; the status bar and both Settings states over CDP. - Browse New note on an Android emulator with a core built from this tree: Browse, New folder "Projects", into it, New note opened "Untitled" with its title selected and wrote `inbox/Projects/Untitled.md`; the iPhone shell's row in its browser preview. - Manual: `help-rich-text.test.ts` (8), and Open Help over CDP shows two paragraphs with four bold names in the encryption guide. - Found during the release and fixed before it: shortcuts behind What's New and other overlays, reproduced in the built app over CDP with throwaway profiles before the fix (Cmd+P opened a hidden search that took the typed text, Cmd+N wrote `inbox/Untitled.md`, Shift+Cmd+N a Quick Note, Shift+Cmd+P and Cmd+, opened their dialogs under What's New; behind Settings, Ctrl+Tab, Alt+Left and Shift+Cmd+T changed the active note and Shift+Cmd+N wrote a Quick Note) and after it (none acts, focus stays, Cmd+, replaces What's New, and with nothing open all four note shortcuts still work). The Tasks calendar behind Settings: Space (Vim off) and x (Vim on) wrote `- [x]` before and nothing after; with nothing open both still toggle. `CloudSettings.test.ts` gains three tests (unlocking reads the list again; Save archive per host), each failing with its fix removed; `keymaps.test.ts` three. The phone shells: three new vault tests each, failing on the old `vault-fs.ts`; Android 278 and iPhone 253 tests pass. With a rehearsal core from `d1344076` in the iPhone shell's browser preview: at phone width, Settings search hides every MCP, CLI and Keymap result and nothing else; at iPad width, Keymap lists no review key; Browse's New note row creates the note in the browsed folder with its title focused. Release-time gates on `d1344076`: typecheck 8/8 and test:run 6/6 with no turbo cache (shared-domain 1,994, app-core 3,220, quicklook 15, desktop 1,139), `npm audit --omit=dev --audit-level=high` clean (the same 15 low or moderate as 2.68.0). Pack: Developer ID signed, deep strict codesign OK, bundled `zn v0.7.1` in a drwxr-xr-x `Resources/zn-cli`, the Quick Look extension; packaged launch check: page target and drawn app in 1.5 s, version 2.69.0. Smoke suites: sidebar-vim (12) and editor-improvements (19) pass; vim-editor failed one check on its first run (repeated L read the same scroll position twice, a timing flake) and passed all 12 on the re-run. The commit messages carry no long dash except the merged contributor commit `bcc52592`, which stays as its author wrote it. Release PR [#​934](https://redirect.github.com/ZenNotes/zennotes/issues/934): all 11 checks green, including the `windows-11-arm` package and launch check (CI run [`3842635`](https://redirect.github.com/ZenNotes/zennotes/commit/38426359796)). Release run [`3842891`](https://redirect.github.com/ZenNotes/zennotes/commit/38428914590): all six jobs green in about 45 minutes; `verify-installers.py` ALL GOOD on the five manifests; both DMGs hash to GitHub's digests and the cask, and the app in each is `Notarized Developer ID` with a valid stapled ticket. `npm run verify:channels -- 2.69.0` passed locally and from a clean runner (run [`3843749`](https://redirect.github.com/ZenNotes/zennotes/commit/38437499904)). After the cut, CI on `main` failed twice on Windows: 16 tests timing out at 5 seconds on one slow `windows-latest` runner, and, on `windows-11-arm`, one rename test that found a real bug: on Windows, renaming a note onto another note's name could replace that note. It dates from 2.55.0 and is fixed in [2.69.1](https://redirect.github.com/ZenNotes/zennotes/releases/tag/v2.69.1). </details> --- ### Configuration 📅 **Schedule**: (in timezone America/Los_Angeles) - Branch creation - Every minute (`* * * * *`) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Enabled. ♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/scottames/copr). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4xNTUuMiIsInVwZGF0ZWRJblZlciI6IjQ0LjE1NS4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJkZXBlbmRlbmNpZXMiXX0=--> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
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.
Fix(tasks): zn task and zn mcp see tasks in numbered lists and quotes, as the app does
zn task list,zn task toggleand the list_tasks and toggle_task tools ofzn mcpread task lines with the CLI dialect, a bullets-only copy of the grammar kept that way so their task ids matched the desktop's own MCP server. ZenNotes 2.69.1 aligned that server with the app's task lines: numbered lists (1.and1)) and quoted tasks (> - [ ]). The CLI dialect now reads the same lines, so the two MCP servers list the same tasks under the same ids again. Its other differences stay:@key:valuefields stay in the content, and fences are read only up to three spaces in.Task ids shift once in a note where a numbered or quoted task sits above another task: list again before toggling by an id saved from 0.7.1. TestCLIDialect now expects the four tasks the app sees, and TestCLIDialectReadsEveryTaskShape uses the same note as the desktop's MCP test; both fail with the old grammar. With the built binary on a scratch vault, 0.7.1 listed one task of five and this lists all five, and toggling the quoted one checks it off in place.