Skip to content

Notes: defects deferred from the stack's pre-merge review #241

Closed

Description

@BunsDev

A pre-merge review of the combined notes stack (#226, #227, #230, #238, with the #235 and #237 repairs) found these defects. They were not fixed before landing. Three others were fixed in #227: agent turns failing when the notes folder cannot be read, Open notes re-focusing on every poll, and quadratic tree layout. Line numbers refer to c32217a (the stack before those fixes). In notes-store.ts, lines after about 605 sit 19 lines later on main.

Main process

  1. A settlement journal can wedge every read. notes-store.ts:392-396 (written at 261, validated at 772-778): the folder-rename journal is written before the safe() checks. Dragging a folder whose name contains \ (legal on macOS, e.g. one made in Finder with its folder note) leaves .modex/settlement.json behind. Every later read then throws "Invalid folder rename intent", even after a restart. Fix: validate before writing the journal, and do not let a journal that fails validation block reads forever. Confirmed by probe.
  2. Scoped restore can write into another project. notes-store.ts:196-200, 1188-1190, reached from pages-agents.ts restore: a child trashed in project A whose parent folder was later dragged into project B can still be restored by A's agent. The note lands under B and a version is written to B's parent page. Fix: before a scoped restore, check that the target directory and every ancestor it restores are in scope, as the revert check already does. Confirmed by probe.
  3. Trashed notes keep stale original paths after moves. notes-store.ts:694-702 (place), 1184 (restoreFile): moving or renaming a workspace, project or folder updates live notes only. Restoring a note trashed earlier recreates the old path (e.g. Personal/Notes) as a ghost project with no marker, outside the linked Modex project. Fix: rewrite the trashed and deleted originals under the moved folder in place() and in folder-move rebase. Confirmed by probe.
  4. Import copies on the main thread. notes-store.ts:498: copyFileSync, up to 50 files of 100 MB. A real copy (another volume, a network share, iCloud placeholders) freezes the UI. Fix: fs.promises.copyFile.
  5. Knowledge scoping misses nested folders. index.ts:121, knowledge-agents.ts:172: project scoping applies only when the knowledge folder equals the notes folder exactly. A knowledge base set to a workspace or project folder inside notes/, or to the Modex home, is unscoped. Fix: scope whenever either folder contains the other, or refuse such folders.

Renderer

  1. Tree render cost grows with the square of the tree size, on every keystroke. NotesTree.tsx:51-57, 134-137, 160: each row filters all nodes for its children, targetsFor() runs twice per row, and the Move to items are built even while the menu is closed. SpaceView re-renders on each page edit. Measured outside React: 1,056 nodes / 55 folders take 343 ms per render; 2,111 / 110 take 2.9 s. Fix: memoize parent→children and id maps, build move targets only for an open menu, and React.memo the tree with stable actions.
  2. A duplicated workspace or project folder shares the original's id. notes-store.ts:626, shown at NotesTree.tsx:119: Finder Duplicate copies .modex-project.json, so the two rows collide. Renaming the original by id renames the copy, and the copy claims the same Modex project. Fix: give a repeated marker id a new id and set modexProjectId: null, as pages already do (notes-store.ts:995). Reproduced.
  3. Open in knowledge base can send the old path. SpaceView.tsx:250 with :188: after a title rename, the menu action reads the tree from the render that built the menu, so knowledge:open can get Untitled.md and fail with ENOENT. Fix: have refresh() return the fresh tree, or ask main for pageRel.
  4. New workspace re-opens after a remount. NotesTree.tsx:40: the newWorkspace counter is never reset. After creating one workspace, typing in and then clearing the page search remounts the tree, and focus jumps into an empty "New workspace name" field. Keystrokes land there, and blurring it creates a workspace. Fix: keep the request in SpaceView and clear it on commit or cancel.

Coven-Harness: Claude Code / claude-opus-5-5

Activity

  1. self-assigned this
    on Oct 15, 2026
  2. BunsDev commented on Oct 16, 2026

    @BunsDev
    ContributorAuthor

    Rechecked against main at f17608d.

    Fixed on main by #246

    • 5. Knowledge scoping misses nested folders. Knowledge tools now fence by real path. A path that resolves inside the notes folder must resolve inside the turn's own project. That holds whether the knowledge base is the notes root, a workspace in it, a folder that contains it (such as ~/.modex), a content.dir, or another project's folder (which then refuses everything). Tests in knowledge-agents.test.ts: "a knowledge base set to a workspace of the notes folder keeps each project's agents in their own notes" and "a knowledge base inside another project's notes holds nothing this project may reach".
    • 7. A duplicated workspace or project folder shares the original's id. A folder whose marker id is already held by another place gets a new id. It is no longer the default, and for a project modexProjectId: null (notes-store.ts, the walk in look). The test "a project folder copied in Finder becomes a project of its own instead of making the notes unreadable" (notes-projects.test.ts) covers a copied default project and a copied linked project.

    Still open, each getting its own PR with a regression test of the probe above

    1. Settlement journal written before validation (\ in a folder name)
    2. Scoped restore can write into another project
    3. Trashed notes keep stale original paths after moves
    4. Import copies on the main thread
    5. NotesTree render cost
    6. Open in knowledge base can send the old path
    7. New workspace re-opens after a remount

    I'll link each PR here as it opens and close this issue when they have all landed.

    Coven-Harness: Claude Code / claude-opus-5-5

  3. BunsDev commented on Oct 16, 2026

    @BunsDev
    ContributorAuthor

    Each remaining finding now has its own PR, with a regression test that failed on main before the fix:

    Finding PR
    1. Settlement journal written before validation (\ in a folder name) #259
    2. Scoped restore can write into another project #254
    3. Trashed notes keep stale original paths after moves #258
    4. Import copies on the main thread #261
    6. NotesTree render cost #264
    8. Open in knowledge base can send the old path #263
    9. New workspace re-opens after a remount #260

    Findings 5 and 7 were fixed by #246 (see the previous comment). I'll close this issue once these PRs land.

    Coven-Harness: Claude Code / claude-opus-5-5

  4. BunsDev commented on Oct 16, 2026

    @BunsDev
    ContributorAuthor

    All nine findings are fixed on main:

    Finding Fixed by
    1. Settlement journal written before validation (\ in a folder name) #259: the journal is validated before it is written; a journal that fails validation is set aside instead of blocking every read
    2. Scoped restore can write into another project #254: restore checks every ancestor it brings back is in the turn's project
    3. Trashed notes keep stale original paths after moves #258: renames and moves also move trashed and deleted originals
    4. Import copies on the main thread #261: async copy into .modex/, then a no-overwrite link into place
    5. Knowledge scoping misses nested folders #246
    6. NotesTree render cost #264: indexes built once per tree, Move to built only for an open menu, stable actions. A 2,101-node render went from 3.4 s to 80 ms
    7. A duplicated workspace or project folder shares the original's id #246
    8. Open in knowledge base can send the old path #263: asks main for the page's file at click time
    9. New workspace re-opens after a remount #260

    Each fix PR has a regression test that failed on main before the change.

    One change from the review's suggested fix for finding 6: the tree isn't wrapped in React.memo. Instead, #264 keeps each row unless something the row shows changes, and SpaceView passes one stable actions object. Typing in a page body therefore no longer rebuilds the rows, without changing NotesTreeView's signature, which #260 also edited.

    Coven-Harness: Claude Code / claude-opus-5-5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions