Skip to content

feat: workspace-linked notes for @file: and Claude cwd (#461)#476

Merged
otomatty merged 9 commits into
developfrom
feature/461-workspace-linked-notes
Apr 4, 2026
Merged

feat: workspace-linked notes for @file: and Claude cwd (#461)#476
otomatty merged 9 commits into
developfrom
feature/461-workspace-linked-notes

Conversation

@otomatty
Copy link
Copy Markdown
Owner

@otomatty otomatty commented Apr 4, 2026

概要

ノートごとにローカルディレクトリを紐付け(デスクトップ)、@file: で相対パスをマークしてクリック時にプレビューし、Claude Code / エージェントスラッシュ・実行可能コード・AI チャットにそのルートを cwd として渡します。パスはルート配下に正規化してから読み取ります(Issue #461)。

変更点

領域 主な変更
src-tauri/ workspace_paths(正規化・読取・一覧)、tauri-plugin-dialog、capabilities
src/lib/noteWorkspace/ ローカル永続ストア、フォルダ選択、プレビューイベント、Tauri I/O
src/contexts/src/components/note/ NoteWorkspaceContext、ツールバー、FilePreviewDialogHost
src/components/editor/ FileReferenceExtension@file:)、useEditorSetup のワークスペース連携、スラッシュ補完・実行コード
src/hooks/src/lib/ AI 実行・aiService・エージェントスラッシュに claudeWorkspaceRoot を伝播
package.json / lock @tauri-apps/plugin-dialog ほか

変更の種類

  • 🐛 バグ修正 (Bug fix)
  • ✨ 新機能 (New feature)
  • 💥 破壊的変更 (Breaking change)
  • 📝 ドキュメント (Documentation)
  • 🎨 スタイル/リファクタリング (Style/Refactor)
  • 🧪 テスト (Tests)
  • 🔧 ビルド/CI (Build/CI)

テスト方法

  1. bun run lint(エラー 0)、変更ファイルに対する prettier --checkbun run test:run を実行済み。
  2. Tauri デスクトップでノートを開き、ワークスペースフォルダを選択する。
  3. エディタで @file:相対パス を入力し、クリックでプレビューダイアログが開くことを確認する。
  4. Claude / エージェントスラッシュや実行可能コードが、選択したルートを cwd として扱うことを確認する(可能な範囲で)。

チェックリスト

  • テストがすべてパスする
  • Lint エラーがない
  • 必要に応じてドキュメントを更新した(該当なし)
  • コミットメッセージが Conventional Commits に従っている

スクリーンショット(UI 変更がある場合)

ワークスペースツールバー・@file: プレビューがあるため、可能なら Before/After を追記してください。

関連 Issue

Closes #461


Open with Devin

Summary by CodeRabbit

  • New Features

    • ノート単位でワークスペースフォルダをリンク可能にし、エディタ内のファイル参照(@file:...)をクリックでプレビューするダイアログとツールバーを追加。
    • スラッシュ補完がノートに紐づくワークスペースを参照できるように拡張。AI呼び出しやコード実行でワークスペースを作業ディレクトリ(cwd)として利用。
    • デスクトップ向けネイティブダイアログ対応とローカル権限の追加、i18n文字列を追加。
  • Tests

    • 永続化、イベント、プレビュー周りのユニットテストを追加。

- Tauri: safe path resolution under root, read/list workspace files, dialog plugin
- Editor: FileReference @file: mark, preview dialog host, slash path completions
- AI: workspace root as Claude cwd for agent slash, executable code, chat
- ESLint: pass workspaceRoot string + useEditor dep instead of ref during render

Made-with: Cursor
Copilot AI review requested due to automatic review settings April 4, 2026 13:33
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

ノートごとにローカルワークスペースを紐付け可能にし、Tauri 側に register/clear/read/list ハンドラを追加。フロントで FileReference 拡張、ファイルプレビュー UI、NoteWorkspace コンテキスト/ツールバー、パス補完と Claude Code 実行時の cwd 伝播を導入した。

Changes

Cohort / File(s) Summary
Tauri プラグイン & マニフェスト
package.json, src-tauri/Cargo.toml, src-tauri/capabilities/default.json, src-tauri/src/lib.rs
tauri-plugin-dialog 追加、capability に dialog:default を追加、Rust 側で tauri_plugin_dialog 登録と新コマンドを公開。
Tauri パス解決 & API
src-tauri/src/workspace_paths.rs
CWD ベースから note-scoped root 対応へ移行。resolve_under_root、TOCTOU チェック、最長既存接頭辞正規化、永続化 registry(JSON + 原子書込)、read/list 実装を追加。
フロント IO / 永続化 / イベント
src/lib/noteWorkspace/...
src/lib/noteWorkspace/noteWorkspaceStore.ts, noteWorkspaceIo.ts, filePreviewEvents.ts, pickNoteWorkspaceDirectory.ts, tests
localStorage ベースの note→workspace マップ(プロトタイプ汚染防止)、Tauri invoke ラッパー、ファイルプレビュー CustomEvent と dispatcher、ディレクトリピッカー、ユニットテストを追加。
コンテキスト & Provider
src/contexts/NoteWorkspaceContext.tsx
NoteWorkspaceProvideruseNoteWorkspaceOptional() を追加。永続化読み書き、pick/clear API、Tauri レジストリ同期の直列化を実装。
エディタ拡張 (FileReference)
src/components/editor/extensions/FileReferenceExtension.ts, src/components/editor/TiptapEditor/editorConfig.ts
@file: 記法を扱う TipTap Mark を追加。クリックで workspaceRoot/noteId を参照し Tauri 経由で読み取り、プレビューイベントを dispatch。エディタ初期化チェーンへ組込。
UI コンポーネント
src/components/note/NoteWorkspaceToolbar.tsx, src/components/note/FilePreviewDialogHost.tsx, src/App.tsx
ワークスペース選択/ブラウズツールバーとファイルプレビュー ダイアログホストを追加し App にマウント。エラー・no-workspace・切り詰め表示対応。
エディタコントローラ・Prop 伝播
src/components/editor/TiptapEditor/..., useEditorSetup.ts, useTiptapEditorController.ts, SlashSuggestionLayer.tsx, slashSuggestionMenuProps.ts
workspaceRoot / noteId を refs/props 経由で伝播。コントローラが claudeWorkspaceRoot / claudeWorkspaceNoteId を公開し型・フック署名を更新。
スラッシュ補完 / パス補完
src/components/editor/TiptapEditor/useSlashSuggestionMenu.ts, useSlashSuggestionMenuData.ts, useWorkspacePathCompletions.ts
補完フローが note 固有 root を受け取り、listNoteWorkspaceEntries を呼ぶ分岐を追加。スラッシュ実行で claudeCwd を渡す配線を追加。
AI / 実行コンテキスト
src/lib/aiService.ts, src/lib/executableCode/executeExecutableCode.ts, src/lib/agentSlashCommands/executeAgentSlashCommand.ts, src/hooks/useAIChatExecute*.ts, useExecutableCodeBlockController.ts
AI リクエスト型に任意の cwd を追加し、Claude Code 呼び出しに転送。実行系でノートの workspaceRoot を cwd として渡すよう変更。
ページ統合 / 型
src/pages/NotePageView.tsx, src/types/aiChat.ts
NotePage を NoteWorkspaceProvider でラップし、ページコンテキストに noteIdclaudeWorkspaceRoot を含める。NotePageEditorEditablenoteId を追加。
i18n / テスト
src/i18n/locales/en/editor.json, src/i18n/locales/ja/editor.json, src/lib/noteWorkspace/*.test.ts
英日翻訳キー追加、ファイルプレビューイベントとノートストアのユニットテスト追加。

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant Editor as TipTap Editor
    participant FileRef as FileReference
    participant Window as Browser Window
    participant Frontend as Frontend Invoke
    participant Rust as Tauri/Rust
    participant Dialog as FilePreviewDialogHost

    User->>Editor: クリック `@file:...`
    Editor->>FileRef: クリックイベント処理
    FileRef->>Window: getWorkspaceRoot() / getNoteId()
    alt no workspace
        FileRef->>Window: dispatchFilePreview({ noWorkspace: true })
    else has workspace
        FileRef->>Frontend: invoke("read_note_workspace_file", { noteId, relativePath })
        Frontend->>Rust: read_note_workspace_file(noteId, relativePath)
        Rust->>Rust: resolve_under_root + read (cap)
        Rust-->>Frontend: content | error
        Frontend-->>FileRef: content | error
        FileRef->>Window: dispatchFilePreview({ content | error, truncated? })
    end
    Window->>Dialog: FILE_PREVIEW_EVENT を受信して表示
    Dialog->>User: プレビュー表示
Loading
sequenceDiagram
    participant User as User
    participant Slash as Slash Menu
    participant Agent as Agent Executor
    participant AI as AI Service / Sidecar

    User->>Slash: スラッシュコマンド実行
    Slash->>Agent: executeAgentSlashCommand(..., claudeCwd)
    Agent->>AI: streamAssistantCompletion(request with cwd)
    AI-->>Agent: completion
    Agent-->>Slash: 結果を挿入
    Slash->>User: 応答表示
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

enhancement

Poem

🐇 小さな耳でパスを聞き、ノートに根を結ぶよ。
クリック一つで中身を覗き、短い断片を運ぶ。
Claude に cwd を渡せば、コードも歌い出す。
ダイアログはひらきて、プレビューはぴょんと映る。
ぴょん、さあ作業だ。

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PRタイトルは主な機能変更(ワークスペース連動ノート、@file:記法、Claude cwd)を明確かつ簡潔に要約している。
Linked Issues check ✅ Passed コード変更は #461 の全要件(ワークスペースパス設定、ディレクトリピッカー、Claude cwd自動設定、@file:記法のプレビュー、永続化)を充たしている。
Out of Scope Changes check ✅ Passed 全ての変更が #461 の要件に直接関連するもので、範囲外の変更は存在しない。
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/461-workspace-linked-notes

Comment @coderabbitai help to get the list of available commands and usage tips.

@otomatty otomatty self-assigned this Apr 4, 2026
@otomatty otomatty linked an issue Apr 4, 2026 that may be closed by this pull request
6 tasks
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces note-linked workspaces for the desktop application, allowing users to associate local folders with specific notes to enable file path completion, in-editor file previews, and context-aware AI agent commands. The implementation includes a new Tiptap extension for @file: references, a workspace management toolbar, and secure Tauri-based file system operations. Feedback focuses on optimizing the Rust path resolution logic to minimize system calls, preventing disruptive editor re-initializations when workspace links change by using a stable getter, and adopting more idiomatic TypeScript patterns for local storage management.

Comment on lines +21 to +62
pub(crate) fn resolve_under_root(root_canon: &PathBuf, relative: &str) -> Result<PathBuf, String> {
let trimmed = relative.trim();
if trimmed.is_empty() {
return Ok(root_canon.clone());
}
let mut acc = root_canon.clone();
for comp in Path::new(trimmed).components() {
match comp {
Component::Normal(c) => {
acc.push(c);
if acc.exists() {
let canon = acc.canonicalize().map_err(|e| e.to_string())?;
if !canon.starts_with(root_canon) {
return Err("path outside workspace".into());
}
acc = canon;
}
}
Component::ParentDir => {
acc.pop();
if !acc.starts_with(root_canon) {
return Err("path outside workspace".into());
}
}
Component::CurDir => {}
Component::RootDir | Component::Prefix(_) => {
return Err("invalid path".into());
}
}
}
if acc.exists() {
let canon = acc.canonicalize().map_err(|e| e.to_string())?;
if !canon.starts_with(root_canon) {
return Err("path outside workspace".into());
}
return Ok(canon);
}
if !acc.starts_with(root_canon) {
return Err("path outside workspace".into());
}
Ok(acc)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The resolve_under_root function is inefficient because it performs exists() and canonicalize() syscalls for every component of the path in a loop. Since this function is primarily used for reading existing files or listing existing directories, a more efficient approach is to perform lexical path resolution first to prevent traversal, and then perform a single canonicalize() call at the end to handle symlinks and verify the final path is still within the root.

pub(crate) fn resolve_under_root(root_canon: &Path, relative: &str) -> Result<PathBuf, String> {
    let mut acc = root_canon.to_path_buf();
    for comp in Path::new(relative).components() {
        match comp {
            Component::Normal(c) => acc.push(c),
            Component::ParentDir => {
                acc.pop();
            }
            Component::CurDir => {}
            Component::RootDir | Component::Prefix(_) => {
                return Err("invalid path".into());
            }
        }
        if !acc.starts_with(root_canon) {
            return Err("path outside workspace".into());
        }
    }
    if acc.exists() {
        let canon = acc.canonicalize().map_err(|e| e.to_string())?;
        if !canon.starts_with(root_canon) {
            return Err("path outside workspace".into());
        }
        Ok(canon)
    } else {
        Ok(acc)
    }
}

Copy link
Copy Markdown
Owner Author

@otomatty otomatty Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

対応しました。resolve_under_root を字句結合ベースにし、存在する終端パス、または非存在時は最長の存在接頭辞へ遡って一度 canonicalize する形に変更しました(セグメント毎の exists/canonicalize 呼び出しを削減)。シンボリックリンク越しのエスケープ検出は維持しています。

},
},
[pageId, useCollaborationMode],
[pageId, useCollaborationMode, workspaceRoot],
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Including workspaceRoot in the useEditor dependency array causes the entire Tiptap editor to be re-initialized whenever a workspace is linked or unlinked. This is disruptive as it can cause loss of focus, cursor position, and scroll state.

Instead, you should use a useRef to store the current workspaceRoot and pass a stable getter function to the FileReference extension. This allows the extension to access the latest workspace root without requiring an editor restart.

Suggested change
[pageId, useCollaborationMode, workspaceRoot],
[pageId, useCollaborationMode],

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

対応しました。useEditor の依存から workspaceRoot を外し、useWorkspaceRootRef(useLayoutEffect で同期)経由で getWorkspaceRoot が最新値を返すようにしました。createEditorExtensions 周りは react-hooks/refs のためブロック抑制を付与しています。

Comment on lines +59 to +65
export function clearNoteWorkspacePath(noteId: string): void {
const map = readMap();
if (!(noteId in map)) return;
const { [noteId]: _removed, ...rest } = map;
void _removed;
writeMap(rest);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The implementation of clearNoteWorkspacePath uses a non-idiomatic destructuring pattern to remove a key from the map. Since map is a local object, using the delete operator is simpler and more readable.

export function clearNoteWorkspacePath(noteId: string): void {
  const map = readMap();
  if (!(noteId in map)) return;
  delete map[noteId];
  writeMap(map);
}

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

意図的に分割代入にしています。@typescript-eslint/no-dynamic-delete が error のため delete 演算子は使えません。

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a per-note “linked workspace folder” for the desktop app, enabling @file: relative file references with click-to-preview, and propagating that workspace root as Claude Code’s working directory (cwd) for chat, agent slash commands, and executable code.

Changes:

  • Introduces a local-only noteId → workspaceRoot store + React context, plus a toolbar to link/change/clear and browse the workspace tree.
  • Adds @file: support in the editor (mark + click handler) and a global dialog host to preview file contents via Tauri commands.
  • Extends Claude Code integrations (AI chat, agent slash, executable code) to pass cwd, and adds new Tauri commands for workspace-rooted file read/list with traversal protection.

Reviewed changes

Copilot reviewed 35 out of 37 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/types/aiChat.ts Extends page context with noteId and claudeWorkspaceRoot for local desktop-only behavior.
src/pages/NotePageView.tsx Wraps editor with NoteWorkspaceProvider and injects workspace root into AI chat page context; adds toolbar.
src/lib/noteWorkspace/pickNoteWorkspaceDirectory.ts Desktop-only folder picker using Tauri dialog plugin.
src/lib/noteWorkspace/noteWorkspaceStore.ts LocalStorage persistence for note → workspace path mapping.
src/lib/noteWorkspace/noteWorkspaceStore.test.ts Tests for local workspace persistence helpers.
src/lib/noteWorkspace/noteWorkspaceIo.ts Tauri invoke wrappers for reading files and listing entries under a note-linked root.
src/lib/noteWorkspace/filePreviewEvents.ts Defines and dispatches a window CustomEvent for preview requests/results.
src/lib/noteWorkspace/filePreviewEvents.test.ts Tests for preview event dispatch behavior.
src/lib/executableCode/executeExecutableCode.ts Adds optional cwd forwarding into Claude Code execution options.
src/lib/aiService.ts Adds cwd option and forwards it to the Claude Code provider query options.
src/lib/agentSlashCommands/executeAgentSlashCommand.ts Adds optional claudeCwd and forwards as cwd to Claude Code query options.
src/i18n/locales/ja/editor.json Adds JA strings for workspace toolbar and file preview dialog.
src/i18n/locales/en/editor.json Adds EN strings for workspace toolbar and file preview dialog.
src/hooks/useAIChatExecuteRegenerate.ts Sends cwd when provider is claude-code and context has a workspace root.
src/hooks/useAIChatExecute.ts Sends cwd when provider is claude-code and context has a workspace root.
src/contexts/NoteWorkspaceContext.tsx New context/provider for per-note workspace root and actions (pick/clear/set).
src/components/note/NoteWorkspaceToolbar.tsx UI for linking a folder, browsing entries, and clearing the workspace link.
src/components/note/FilePreviewDialogHost.tsx Global event listener that shows a dialog with file preview content/errors.
src/components/editor/TiptapEditor/useWorkspacePathCompletions.ts Path completion now supports listing from note workspace root or process cwd.
src/components/editor/TiptapEditor/useTiptapEditorController.ts Plumbs workspaceRoot through editor setup and returns claudeWorkspaceRoot for slash menu/cwd.
src/components/editor/TiptapEditor/useSlashSuggestionMenuData.ts Passes noteWorkspaceRoot to path completion hook.
src/components/editor/TiptapEditor/useSlashSuggestionMenu.ts Forwards claudeWorkspaceRoot for path completion and as cwd for agent slash execution.
src/components/editor/TiptapEditor/useEditorSetup.ts Adds fileReference extension wiring and workspace root propagation into editor extensions.
src/components/editor/TiptapEditor/slashSuggestionMenuProps.ts Adds claudeWorkspaceRoot to slash menu props.
src/components/editor/TiptapEditor/SlashSuggestionLayer.tsx Passes claudeWorkspaceRoot through to slash suggestion menu.
src/components/editor/TiptapEditor/editorConfig.ts Registers FileReference extension with getWorkspaceRoot option.
src/components/editor/TiptapEditor.tsx Passes claudeWorkspaceRoot into SlashSuggestionLayer.
src/components/editor/extensions/FileReferenceExtension.ts New @file: mark + click handler that reads file via Tauri and dispatches preview events.
src/components/editor/executableCodeBlock/useExecutableCodeBlockController.ts Forwards note workspace root as cwd when running executable notebook code.
src/App.tsx Mounts the global FilePreviewDialogHost.
src-tauri/src/workspace_paths.rs Adds traversal-safe root resolution + new Tauri commands to read/list under a note-linked workspace root.
src-tauri/src/lib.rs Registers dialog plugin and new workspace commands in the invoke handler.
src-tauri/Cargo.toml Adds tauri-plugin-dialog dependency and tempfile dev-dependency for tests.
src-tauri/Cargo.lock Lockfile updates for new Rust dependencies.
src-tauri/capabilities/default.json Enables dialog capability.
package.json Adds @tauri-apps/plugin-dialog dependency.
bun.lock Lockfile updates for @tauri-apps/plugin-dialog and related dependency shifts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@@ -1,4 +1,4 @@
import { useRef, useState } from "react";
import { useRef, useState, type MutableRefObject } from "react";
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MutableRefObject is imported twice (once as a value+type import and again via import type), which will cause a TypeScript compile error due to duplicate import bindings. Remove one of the imports (e.g., keep the import type line and drop type MutableRefObject from the first import).

Suggested change
import { useRef, useState, type MutableRefObject } from "react";
import { useRef, useState } from "react";

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

対応しました。MutableRefObject の重複 import を1行にまとめています。

Comment on lines +46 to 53
/**
*
*/
export function useEditorSetup(options: UseEditorSetupOptions) {
/**
*
*/
const {
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These JSDoc blocks have blank descriptions (only *), which violates the repo ESLint rule jsdoc/no-blank-block-descriptions (configured as error) and will fail lint. Either add a real description body or remove the empty JSDoc blocks entirely.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

対応しました。空の JSDoc を削除し、useEditorSetup の説明・handleInsertMermaid の説明を追加しました。

Comment on lines 156 to 159
/**
*
*/
const r = await fetch(url, {
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This empty JSDoc block inside getAuthenticatedImageUrl will trip jsdoc/no-blank-block-descriptions and fail lint. Remove it or replace it with a meaningful description.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同じく空の JSDoc を削除しました(getAuthenticatedImageUrl 内)。

Comment on lines 207 to 210
/**
*
*/
const { from, to } = editor.state.selection;
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This blank JSDoc block in onSelectionUpdate violates jsdoc/no-blank-block-descriptions and will fail lint. Please remove it or add an actual description.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同じく onSelectionUpdate 前の空 JSDoc を削除しました。

}, [editor, editorRef]);

/**
*
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This empty JSDoc block before handleInsertMermaid violates jsdoc/no-blank-block-descriptions and will fail lint. Remove it or replace with a proper description.

Suggested change
*
* Inserts a Mermaid diagram at the current selection.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleInsertMermaid に説明コメントを追加しました(上のまとめコメント参照)。

Comment on lines 217 to 219
},
[pageId, useCollaborationMode],
[pageId, useCollaborationMode, workspaceRoot],
);
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Including workspaceRoot in the useEditor dependency array will destroy/recreate the Tiptap editor whenever the workspace is linked/changed, which can reset selection/history and cause visible editor state loss while editing. Prefer keeping the editor instance stable and pass a getWorkspaceRoot that reads from a ref (updated on workspace changes), so the extension can see the latest root without re-initializing the editor.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上記と同じ対応です(useEditor の依存から workspaceRoot を外し、useWorkspaceRootRef + createEditorExtensions 周りの eslint ブロック)。

devin-ai-integration[bot]

This comment was marked as resolved.

…JSDoc)

- useEditor: stable deps + useWorkspaceRootRef + eslint block for extension config
- workspace_paths: lexical resolve_under_root with fewer canonicalize calls
- useTiptapEditorController: single React import line

Made-with: Cursor
@otomatty
Copy link
Copy Markdown
Owner Author

otomatty commented Apr 4, 2026

レビューコメントへの対応をコミットしました(fb9df0a)。最新の変更に対する再レビューをお願いします。

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

@otomatty 承知しました!最新のコミット(fb9df0a)を含む変更内容を再レビューします。


🧠 Learnings used
Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR review focus areas: check for security and performance impacts, breaking changes in public APIs or types, proper error handling and logging, and ensure comments in Japanese/English match project tone.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: Review PRs for security and performance impact, API/type breaking changes, appropriate error handling and logging, and adherence to project communication tone in Japanese and English.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: PR titles must accurately represent the changes made. Use Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). For single-topic PRs, use the representative commit message directly. Match the language (Japanese or English) to the majority language of commits.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: PR titles must follow Conventional Commits format and accurately describe the changes (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). Avoid unrelated or generic descriptions.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR titles must follow Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`) and accurately represent the changes. When using Cursor Cloud Agent, include instructions in the prompt to ensure PR titles follow Conventional Commits format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-29T06:01:24.318Z
Learning: 日本語・英語のコメント・ドキュメントがプロジェクトのトーンに合っているか確認する。
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]

This comment was marked as resolved.

- Rust: re-canonicalize before open; document openat limitation
- FileReference: spaces in path regex; stale preview guard
- FilePreviewDialogHost: CustomEvent + detail guard
- Note workspace: clear entries on tree open; normalize empty root; safe map keys
- JSDoc: Japanese for useEditorSetup, aiService cwd, PageContext noteId

Made-with: Cursor
@otomatty
Copy link
Copy Markdown
Owner Author

otomatty commented Apr 4, 2026

CodeRabbit の指摘に対応しました(036e1db)。再レビューをお願いします。

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

@otomatty ご対応ありがとうございます!コミット(036e1db)を含む最新の変更内容を再レビューします。


🧠 Learnings used
Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR review focus areas: check for security and performance impacts, breaking changes in public APIs or types, proper error handling and logging, and ensure comments in Japanese/English match project tone.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR titles must follow Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`) and accurately represent the changes. When using Cursor Cloud Agent, include instructions in the prompt to ensure PR titles follow Conventional Commits format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: Review PRs for security and performance impact, API/type breaking changes, appropriate error handling and logging, and adherence to project communication tone in Japanese and English.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: PR titles must accurately represent the changes made. Use Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). For single-topic PRs, use the representative commit message directly. Match the language (Japanese or English) to the majority language of commits.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: PR titles must follow Conventional Commits format and accurately describe the changes (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). Avoid unrelated or generic descriptions.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]

This comment was marked as resolved.

- Rust: persist note_id→root registry, read/list by note_id only, enforce size cap with single File::take
- TS: register/clear registry from NoteWorkspaceContext; readNoteWorkspaceFile/listNoteWorkspaceEntries use noteId
- Editor @file: and slash path completion thread noteId; agent cwd still uses absolute workspace path

Made-with: Cursor
@otomatty
Copy link
Copy Markdown
Owner Author

otomatty commented Apr 4, 2026

レビュー(CodeRabbit Major 2 件)に対応しました(0490396)。ワークスペースはノート ID レジストリ経由のみ解決し、サイズ上限は単一ハンドル + take で強制しています。再レビューをお願いします。

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

@otomatty ご対応ありがとうございます!コミット 0490396 を含む最新の変更内容を再レビューします。


🧠 Learnings used
Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR titles must follow Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`) and accurately represent the changes. When using Cursor Cloud Agent, include instructions in the prompt to ensure PR titles follow Conventional Commits format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR review focus areas: check for security and performance impacts, breaking changes in public APIs or types, proper error handling and logging, and ensure comments in Japanese/English match project tone.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: Review PRs for security and performance impact, API/type breaking changes, appropriate error handling and logging, and adherence to project communication tone in Japanese and English.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: PR titles must accurately represent the changes made. Use Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). For single-topic PRs, use the representative commit message directly. Match the language (Japanese or English) to the majority language of commits.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: Branch names should follow the format `feature/説明` or `fix/説明` (e.g., `feature/ai-models-ui`, `fix/search-crash`), or `feature/123` for Issue-based branches. Cursor Cloud Agent may auto-generate branches with `cursor/` prefix, but manual PR creation should use the recommended format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: PR titles must follow Conventional Commits format and accurately describe the changes (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). Avoid unrelated or generic descriptions.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

devin-ai-integration[bot]

This comment was marked as resolved.

coderabbitai[bot]

This comment was marked as resolved.

…/O errors (#476)

- Rust: write registry via temp file + rename; mutex around register/clear RMW
- Toolbar: sequence ref so only the latest list result applies
- noteWorkspaceIo: propagate invoke errors; callers log or clear UI

Made-with: Cursor
@otomatty
Copy link
Copy Markdown
Owner Author

otomatty commented Apr 4, 2026

CodeRabbit の未返信 3 件に対応しました(8f6bb54)。再レビューをお願いします。

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

@otomatty ご対応ありがとうございます!コミット 8f6bb54 を含む最新の変更内容を再レビューします。


🧠 Learnings used
Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR titles must follow Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`) and accurately represent the changes. When using Cursor Cloud Agent, include instructions in the prompt to ensure PR titles follow Conventional Commits format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR review focus areas: check for security and performance impacts, breaking changes in public APIs or types, proper error handling and logging, and ensure comments in Japanese/English match project tone.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: Review PRs for security and performance impact, API/type breaking changes, appropriate error handling and logging, and adherence to project communication tone in Japanese and English.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: PR titles must accurately represent the changes made. Use Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). For single-topic PRs, use the representative commit message directly. Match the language (Japanese or English) to the majority language of commits.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]

This comment was marked as resolved.

- Remount NoteWorkspaceProvider on note.id to avoid noteId/workspaceRoot mismatch
- Queue register/clear invocations so async completions cannot reorder

Made-with: Cursor
@otomatty
Copy link
Copy Markdown
Owner Author

otomatty commented Apr 4, 2026

未返信レビュー 2 件に対応しました(44f9370)。再レビューをお願いします。

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

@otomatty ご対応ありがとうございます!コミット 44f9370 を含む最新の変更内容を再レビューします。


🧠 Learnings used
Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR titles must follow Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`) and accurately represent the changes. When using Cursor Cloud Agent, include instructions in the prompt to ensure PR titles follow Conventional Commits format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR review focus areas: check for security and performance impacts, breaking changes in public APIs or types, proper error handling and logging, and ensure comments in Japanese/English match project tone.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: Review PRs for security and performance impact, API/type breaking changes, appropriate error handling and logging, and adherence to project communication tone in Japanese and English.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: PR titles must accurately represent the changes made. Use Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). For single-topic PRs, use the representative commit message directly. Match the language (Japanese or English) to the majority language of commits.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

- NotePageEditorEditable: explicit React.JSX.Element return type
- NoteWorkspace: Rust sync only in effect (remove duplicate enqueue from setters)
- workspace_paths: parse_note_id_key returns trimmed key for registry I/O

Made-with: Cursor
@otomatty
Copy link
Copy Markdown
Owner Author

otomatty commented Apr 4, 2026

レビュー 3 件に対応しました(d3d2439)。再レビューをお願いします。

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

@otomatty ご対応ありがとうございます!コミット d3d2439 を含む最新の変更内容を再レビューします。


🧠 Learnings used
Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR titles must follow Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`) and accurately represent the changes. When using Cursor Cloud Agent, include instructions in the prompt to ensure PR titles follow Conventional Commits format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR review focus areas: check for security and performance impacts, breaking changes in public APIs or types, proper error handling and logging, and ensure comments in Japanese/English match project tone.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: Review PRs for security and performance impact, API/type breaking changes, appropriate error handling and logging, and adherence to project communication tone in Japanese and English.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: PR titles must accurately represent the changes made. Use Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). For single-topic PRs, use the representative commit message directly. Match the language (Japanese or English) to the majority language of commits.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]

This comment was marked as resolved.

- atomic_write_file: rely on fs::rename replace on Windows (drop pre-remove)
- list_note_workspace_entries: optional namePrefix filter before cap
- NotePageView: NoteWorkspaceProvider wraps read-only editor for @file: context

Made-with: Cursor
@otomatty
Copy link
Copy Markdown
Owner Author

otomatty commented Apr 4, 2026

レビュー 3 件に対応しました(1722093)。再レビューをお願いします。

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

@otomatty ご対応ありがとうございます!コミット 1722093 を含む最新の変更内容を再レビューします。


🧠 Learnings used
Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR titles must follow Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`) and accurately represent the changes. When using Cursor Cloud Agent, include instructions in the prompt to ensure PR titles follow Conventional Commits format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR review focus areas: check for security and performance impacts, breaking changes in public APIs or types, proper error handling and logging, and ensure comments in Japanese/English match project tone.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: Review PRs for security and performance impact, API/type breaking changes, appropriate error handling and logging, and adherence to project communication tone in Japanese and English.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: PR titles must accurately represent the changes made. Use Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). For single-topic PRs, use the representative commit message directly. Match the language (Japanese or English) to the majority language of commits.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]

This comment was marked as resolved.

- list_directory_names: allow .zedi directory in listings (Issue #461)
- NoteWorkspace: enqueue Rust sync on mount + in setters; drop deferred workspaceRoot effect

Made-with: Cursor
@otomatty
Copy link
Copy Markdown
Owner Author

otomatty commented Apr 4, 2026

レビュー 2 件に対応しました(7729a1b)。再レビューをお願いします。

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 4, 2026

@otomatty ご対応ありがとうございます!コミット 7729a1b を含む最新の変更内容を再レビューします。


🧠 Learnings used
Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR titles must follow Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`) and accurately represent the changes. When using Cursor Cloud Agent, include instructions in the prompt to ensure PR titles follow Conventional Commits format.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-14T12:40:46.017Z
Learning: PR review focus areas: check for security and performance impacts, breaking changes in public APIs or types, proper error handling and logging, and ensure comments in Japanese/English match project tone.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-03-29T06:01:47.717Z
Learning: Review PRs for security and performance impact, API/type breaking changes, appropriate error handling and logging, and adherence to project communication tone in Japanese and English.

Learnt from: CR
Repo: otomatty/zedi PR: 0
File: .cursor/rules/pr-and-branch-naming.mdc:0-0
Timestamp: 2026-03-08T07:34:11.938Z
Learning: PR titles must accurately represent the changes made. Use Conventional Commits format (e.g., `feat(admin): AIモデル管理UI拡張 (`#218`)`). For single-topic PRs, use the representative commit message directly. Match the language (Japanese or English) to the majority language of commits.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/contexts/NoteWorkspaceContext.tsx (1)

78-87: useEffect での localStorage 再読み込みについて

useState の初期化関数(Line 56-58)で既に readNoteWorkspacePath(noteId) を呼び出しているため、useEffect 内(Line 79)での再読み込みは冗長に見えます。ただし、key={note.id} によるリマウント時に Rust レジストリ同期を確実に行う目的であれば、現在の workspaceRoot state を使用する方が一貫性があります。

💡 提案差分(state を直接使用)
   useEffect(() => {
-    const path = readNoteWorkspacePath(noteId);
     enqueueRustRegistrySync(async () => {
-      if (path) {
+      if (workspaceRoot) {
         await registerNoteWorkspaceRoot(noteId, workspaceRoot);
       } else {
         await clearNoteWorkspaceRoot(noteId);
       }
     });
-  }, [noteId, enqueueRustRegistrySync]);
+  }, [noteId, workspaceRoot, enqueueRustRegistrySync]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/contexts/NoteWorkspaceContext.tsx` around lines 78 - 87, The effect is
re-reading localStorage via readNoteWorkspacePath(noteId) even though the
component already initializes workspaceRoot state with that value; change the
useEffect to use the existing workspaceRoot state (instead of calling
readNoteWorkspacePath again) when deciding whether to call
registerNoteWorkspaceRoot(noteId, path) or clearNoteWorkspaceRoot(noteId), and
update the dependency array to include workspaceRoot (and keep noteId and
enqueueRustRegistrySync) so the Rust registry sync uses the current state;
ensure the effect still wraps calls with enqueueRustRegistrySync and references
registerNoteWorkspaceRoot and clearNoteWorkspaceRoot.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/contexts/NoteWorkspaceContext.tsx`:
- Around line 78-87: The effect is re-reading localStorage via
readNoteWorkspacePath(noteId) even though the component already initializes
workspaceRoot state with that value; change the useEffect to use the existing
workspaceRoot state (instead of calling readNoteWorkspacePath again) when
deciding whether to call registerNoteWorkspaceRoot(noteId, path) or
clearNoteWorkspaceRoot(noteId), and update the dependency array to include
workspaceRoot (and keep noteId and enqueueRustRegistrySync) so the Rust registry
sync uses the current state; ensure the effect still wraps calls with
enqueueRustRegistrySync and references registerNoteWorkspaceRoot and
clearNoteWorkspaceRoot.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 21854ed1-836a-4328-b532-81325a121215

📥 Commits

Reviewing files that changed from the base of the PR and between 1722093 and 7729a1b.

📒 Files selected for processing (2)
  • src-tauri/src/workspace_paths.rs
  • src/contexts/NoteWorkspaceContext.tsx

Copy link
Copy Markdown

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 16 additional findings in Devin Review.

Open in Devin Review

if !target.is_dir() {
return Ok(vec![]);
}
list_directory_names(&target, DEFAULT_NOTE_WORKSPACE_MAX_ENTRIES, None)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 cwd-based list_workspace_directory_entries now truncates before client-side prefix filter, missing matches in large directories

The refactored list_workspace_directory_entries now delegates to list_directory_names with DEFAULT_NOTE_WORKSPACE_MAX_ENTRIES (500) as the cap and None for name_prefix (src-tauri/src/workspace_paths.rs:258). Previously, this function returned all entries with no cap. The client-side code in useWorkspacePathCompletions.ts:53-55 applies prefix filtering AFTER receiving the Rust results. Because entries are sorted alphabetically then truncated to 500 server-side (without a prefix filter), any matching entries alphabetically beyond the 500th position are silently dropped before the client can filter them.

For example, in a directory with 1000 non-hidden entries, files starting with letters near z would be truncated away before the client-side startsWith(fp) filter runs. The note-workspace variant (list_note_workspace_entries) doesn't have this problem because it passes name_prefix to Rust for server-side filtering before the cap.

Contrast with note-workspace path which handles this correctly

In useWorkspacePathCompletions.ts:51-52, the note-workspace branch calls listNoteWorkspaceEntries(noteWorkspaceNoteId, dir, 40, filePrefix) which passes filePrefix as namePrefix to Rust for server-side filtering before truncation. The cwd branch does not pass a prefix, relying entirely on post-truncation client filtering.

Prompt for agents
The function list_workspace_directory_entries at src-tauri/src/workspace_paths.rs:258 now calls list_directory_names with DEFAULT_NOTE_WORKSPACE_MAX_ENTRIES (500) as a cap but None for name_prefix. The client-side code in src/components/editor/TiptapEditor/useWorkspacePathCompletions.ts:53-55 does prefix filtering AFTER receiving the capped results, meaning matching entries beyond the 500th alphabetically-sorted position are lost.

Two possible fixes:
1. Either remove the cap for list_workspace_directory_entries (e.g. pass u32::MAX or a very large value to list_directory_names), matching the old unbounded behavior.
2. Or propagate the filePrefix from the TypeScript side through to list_workspace_directory_entries as a name_prefix parameter so filtering happens server-side before truncation (matching the pattern used by list_note_workspace_entries).
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@otomatty otomatty merged commit a5dd4fc into develop Apr 4, 2026
10 checks passed
@otomatty otomatty deleted the feature/461-workspace-linked-notes branch April 4, 2026 23:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[F6] ワークスペース連動ノート

2 participants