Repository navigation
Conversation
…replaces that note Renaming a note, an asset or a folder first asks whether the destination already exists, and lets it through only when the destination is the file itself, which is how a case-only rename looks on a case-insensitive disk. That question compared fs.stat().ino as a JS number. A Windows file id is 64 bits, a reuse count above the record number, and once that count passes 31, two files saved one after the other round to the same number. The guard then took the other note for the one being renamed, and the rename replaced it. The MCP server's rename and the shared sidecar mover asked the same way; a workflow rename's cleanup did too, and kept the old file instead of removing it. Every one of these guards now compares bigint stats (device and inode) through main/same-file.ts, the way cloud sync and the CLI's vault check already did. Six tests report the ids Node gives on Windows, the full id from a bigint stat and a rounded number otherwise, and fail on the old guards with the symptom CI showed: note and folder renames for the desktop and the MCP server, an asset rename, and a workflow rename. CI caught the note case once, on the windows-11-arm job on main after 2.69.0 was tagged (vault.test.ts, "says when another note already has the name": the rename resolved). The guard dates from 2.55 (#839). The Go server and zn compare with os.SameFile, which reads the whole id, and are not affected.
…p release release.yml fired on tags matching "v*", and the share viewer's boundary tags start with a v too (viewer-2.69.0-viewer.h5e7ef0f99f145d0a). Publishing a viewer draft creates its tag, so every viewer publish since 2.63.0 ran the whole desktop release: about 45 runner-minutes, two notarizations, and every installer and update feed uploaded onto the viewer pre-release. The desktop's own release and its assets were never touched; only the viewer pre-releases carry the extra files. Desktop tags are a v and a digit, so the trigger is now "v[0-9]*". The manual rebuild path (workflow_dispatch with a tag) is unchanged. Removing the stray files from the old viewer pre-releases is left for its own decision.
What's New opens on the first launch after the update with one highlight: on Windows, renaming a note or an attachment to a name another one already has always stops and says so, instead of sometimes replacing the other file. An update from 2.68.0 shows the 2.69.0 highlights after it.
… in a long note too
Convert to database offers a name from the nearest heading above the table, read from the syntax tree when the parse has reached the table and by a line scan otherwise. "Has reached" was syntaxTree(state).length >= pos, but noteMarkdown's outer tree spans the whole note even while its body parse is still short of the table. In a long note, converting a table before the background parse got there offered an earlier heading's name. It asks ensureSyntaxTree now, which parses up to the table within 50 ms or returns no tree, and then the line scan answers.
The name was always editable before saving, so nothing was written under the wrong name unseen. A new test cuts the first parse short with a clock that moves 30 ms per read; it failed on the old check ("Early" for "Roadmap").
…and a port race stop
Five failures on main since September had no cause written down. None is a product bug, and each has its fix:
- task-rollup.test.ts read syntaxTree(state), the tree from creation after a 20 ms parse budget, which a slow runner left partial (macOS 09-14, Windows 10-08). An empty transaction picks up the tree ensureSyntaxTree finished.
- The incremental parsing tests in cm-markdown-language.test.ts ran out of an update's 20 ms budget ("no block at 634", Windows 09-23). A frozen clock lets the update's own parse, the one that reuses blocks, finish.
- search-codeblock.test.ts read code tokens before the first parse reached the code block (macOS 10-02). It forces the parse, as cm-math-render.test.ts does.
- The first note relocation test pays for the store's cold import (Windows 10-09), and workflow-apply's serialization test ran 4 to 6 times slower on one runner (Windows 09-16). Those two get longer timeouts.
- test-app-core-browser.mjs closed each port before asking for the next, so the API server and Chrome could get the same one, and /json/list then answered with the app's HTML. That is the Ubuntu "Exercise the installed editor in Chrome" failure the release runbook listed as a known flake. The three ports are now read while every listener is still open.
| * the table, it does not delete files. | ||
| */ | ||
| import { syntaxTree } from '@codemirror/language' | ||
| import { ensureSyntaxTree, syntaxTree } from '@codemirror/language' |
…p does The app's Tasks view reads task lines with @shared/tasklists' TASK_LINE_RE: bullets, ordered lists (`1. [ ]`, `1) [ ]`) and quoted tasks (`> - [ ]`). The MCP server scanned with its own copy, commented "kept in sync" but bullets only, so list_tasks never showed an ordered or quoted task, toggle_task could not reach one, and every task below one in the same note got a different index than the app counts. The copy now matches the same lines; toggling still changes only the character inside the brackets, so ordered numbers and quote markers stay as written. Two tests: the scanner sees exactly the lines the shared regex matches in a note with every shape, and an ordered and a quoted task toggle in place. Both failed on the old copy. The Go server's and zn's task regexes still differ from the app's (no quoted tasks; the server also has no `1)`), which is theirs to fix in their repos.
On 2.69.1's release PR, Ubuntu's "Exercise the installed editor in Chrome" failed with "Chrome startup: The operation was aborted due to timeout". The ports were distinct this time (server 35179, preview 42673, DevTools 34861), so it was not the port race fixed in 65d30da: Chrome printed nothing for 20 seconds after launch and opened DevTools about 26 seconds in, against a 30 second wait. The same step on the previous push finished the whole browser check in 21 seconds. Chrome's startup wait is now 90 seconds; the servers keep 30.
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.
ZenNotes 2.69.1, desktop only.
Fix
On Windows, a rename onto another note's (or attachment's) name could replace that file (
6d750154). The "is the destination the file itself?" guards comparedfs.stat().inoas a JS number; a Windows file id is 64 bits and two neighbouring files round to one number once the id's reuse count passes 31. Every guard now goes throughmain/same-file.ts(bigint stats, device and inode): note, asset and folder renames, the sidecar mover, a workflow rename's cleanup and the MCP server's rename. Six new tests report Node's Windows ids and fail on the old guards. Found by thewindows-11-armjob on main after 2.69.0 was tagged; the guard dates from 2.55 ([Bug] Creating new note and changing the titel does not work #839).Convert Table to Database could offer an earlier heading's name in a long note (
ba74c54f):headingAbove()tooksyntaxTree(state).length >= posfor "parsed that far", butnoteMarkdown's outer tree spans the whole note while its body parse is short. It asksensureSyntaxTree(state, pos, 50)now. Found while reading the CI backlog.MCP
list_tasks/toggle_taskmiss tasks in ordered lists and quotes (a2b4bfe7): the MCP copy ofTASK_LINE_REwas bullets-only while the app's matches1.,1)and> - [ ]. Now the same lines, with a parity test. Found by the new hazard scan's synced-copies check.Tests
65d30daf): partial-parse reads in the task rollup, incremental parsing and code-block search tests; a cold import and a slow runner (two timeouts); a port race intest-app-core-browser.mjs(Ubuntu's "Exercise the installed editor in Chrome"). Then, on this PR, that step timed out once more for a different reason, read before re-running: a cold Chrome took 26 s to open DevTools against a 30 s wait; it gets 90 s (86e98b49).Release workflow
release.ymlstarts onv[0-9]*instead ofv*(c35ae438): every boundary viewer publish since 2.63.0 built a whole desktop release onto the viewer pre-release.Also
15dc5229); version bump (e2317078).Gates on this head:
a2b4bfe7: 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=highclean. Pack: Developer ID signed, deep strict codesign OK, bundledzn v0.7.1in a drwxr-xr-xResources/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.