Skip to content

feat(notes,board): cross-project drag + fix live project-rename folder move - #90

Merged
ddutchie merged 4 commits into
mainfrom
ddutchie/agentfixes
Jul 22, 2026
Merged

ddutchie merged 4 commits into
mainfrom
ddutchie/agentfixes

Conversation

@ddutchie

@ddutchie ddutchie commented Jul 22, 2026 •

Copy link
Copy Markdown
Owner

What does this PR do?

Two groups of changes:

Bug fix — project rename now relocates the notes folder on disk immediately (no restart). When a project was renamed while a note was open, the note's autosave wrote the .md under the new-slug folder before the rename ran, forcing renameProjectNotesDir into its merge path. The same-name collision-skip left a stale duplicate (and the now-empty old folder) on disk until the next launch. mergeDirInto now removes same-note-id duplicates and clears the old directory (including OS cruft like .DS_Store); the update handler falls back to reconcileProjectFolders when the primary move no-ops (empty project / vault-root).

New drag-and-drop reorganisation:

  • Drag a folder in the notes sidebar onto another folder (or "Move to root") to reparent the whole subtree.
  • Drag a folder, a single note, or a task card onto a project row in the leftmost sidebar to move it to another project. Cards land in the target project's same-type column (In Progress → In Progress), falling back to Backlog / the first column.

A shared cross-project-dnd payload module bridges the notes sidebar's native HTML5 DnD and the board's dnd-kit drag (which has no over outside its context) via a data-project-drop-id pointer hit-test.

Note: this branch also carries the earlier feat(chat): subagent mode commit, which is included here since it wasn't yet in main.

Type of change

  • Bug fix
  • New feature
  • Refactor / code quality
  • Docs / changelog
  • Tests

Screenshots / recording

Checklist

  • npm run type-check:all passes
  • npm run lint passes (0 errors; only pre-existing warnings)
  • npm test passes (ran the affected suites: notes/board slice + notes-files — 79 passing; full npm test not run here)
  • npm run test:e2e passes (run before merging UI changes or cutting a release)
  • No hardcoded colours — CSS variables only
  • No text-[Npx] pixel font classes — rem equivalents only
  • New IPC handlers wrapped in handle() and return IpcResult<T> (no new IPC handlers added; reused existing note.moveToFolder / note.moveToProject / card.update)
  • New DB migrations appended (not edited) in schema.ts (none needed)
  • New SQL goes in electron/db/queries.ts (none added; reused existing queries)
  • New dependencies/devDependencies (none added)
  • New MCP tools registered (none added)
  • No --external:<pkg> flags changed

Notes for reviewer

  • The main design decision is the cross-project DnD bridge: notes use native HTML5 DnD, the board uses dnd-kit. Rather than register the sidebar as a dnd-kit droppable (it lives outside the board's DndContext), the board publishes the drag payload to a module singleton and hit-tests the live pointer against data-project-drop-id rows on drag end. Worth a look at src/lib/cross-project-dnd.ts, the handleDragEnd cross-project branch in board.tsx, and the sidebar handleCrossProjectDrop.
  • moveFolder re-prefixes descendant note paths and rejects nesting a folder inside itself/a descendant (unit-tested).
  • The rename fix is verified by a regression test in electron/notes-files.test.ts reproducing the racing-autosave merge case.

Summary by CodeRabbit

  • New Features
    • Drag and drop folders, notes, and task cards between projects.
    • Preserve task card status when moving between compatible columns, with sensible fallbacks.
    • Enable optional AI subagent chat mode with expandable research and writing activity traces.
  • Bug Fixes
    • Project renames now immediately update notes folders and remove stale duplicates.
  • Documentation
    • Added release notes for version 2.5.4.

ddutchie added 2 commits July 22, 2026 12:12
… toggle + live trace

Adds an optional subagent architecture to the in-app AI chat: a thin dispatcher
delegates read-only research and write work to focused sub-agents, each with a
reduced tool set. On capable models this cut prompt tokens ~43% on research-heavy
tasks at equal output quality (benchmarks + LLM-as-judge scorer included).

- Extract runToolLoop into shared electron/lib/chat-loop.ts (behaviour unchanged),
  add optional tool-array override + test-only arg hook.
- electron/lib/chat-subagent-loop.ts: runDispatchLoop with research/write sub-agents,
  forced final-synthesis turn to rescue empty output on weak models, streaming
  SubagentEvents (start/done/token/thought/tool/usage).
- Context accounting: main ring shows the DISPATCHER's context (system + briefs);
  each sub-agent reports its own usage for a dedicated ring.
- Per-thread toggle persisted via schema v29 (chat_threads.use_subagents,
  chat_messages.subagents) + idempotent ensureColumns guard for version drift.
- Renderer: useChatStream accumulates subagents; ChatSubagentBlock renders an
  expandable live/persisted trace; toolbar toggle (hidden on on-device Llama).
- Tests: token/latency benchmark, fault-injection recovery, quality scorer,
  streaming smoke.
…r move

- Fix: renaming a project now relocates its notes folder on disk
  immediately (no restart). A racing autosave could pre-create the
  new-slug folder, forcing renameProjectNotesDir into a merge whose
  collision-skip left a stale duplicate + the old folder behind until
  the next launch. mergeDirInto now removes same-note-id duplicates and
  clears the old dir (incl. OS cruft); db-handlers reconciles as a
  fallback when the primary move no-ops. Regression test added.
- Feat: drag a folder in the notes sidebar onto another folder (or
  "Move to root") to reparent the whole subtree (moveFolder).
- Feat: drag a folder, a single note, or a task card onto a project row
  in the leftmost sidebar to move it cross-project. Cards land in the
  target project's same-type column (fallback backlog/first). Shared
  cross-project-dnd payload bridges native DnD (notes) and dnd-kit
  (board) via a data-project-drop-id hit-test.
@coderabbitai

coderabbitai Bot commented Jul 22, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@ddutchie, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 24 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 860fa70b-7980-424b-8294-4c768419c12c

📥 Commits

Reviewing files that changed from the base of the PR and between 279a2d4 and 59bf9b2.

📒 Files selected for processing (13)
  • electron/ipc/chat.ts
  • electron/lib/bench-endpoint.ts
  • electron/lib/chat-agent-benchmark.test.ts
  • electron/lib/chat-quality-scorer.test.ts
  • electron/lib/chat-subagent-loop.ts
  • electron/lib/chat-subagent-stream.test.ts
  • electron/lib/chat-write-recovery-benchmark.test.ts
  • electron/shared/notes-io.ts
  • src/components/kanban/board.tsx
  • src/hooks/useChatStream.ts
  • src/lib/cross-project-dnd.ts
  • src/store/slices/notes.test.ts
  • src/store/slices/notes.ts
📝 Walkthrough

Walkthrough

This PR adds cross-project drag-and-drop for notes, folders, and cards; introduces optional dispatcher-based subagent chat with streamed and persisted traces; extracts shared chat-loop logic; hardens project rename cleanup; and adds benchmarks and quality-scoring tests.

Changes

Cross-project drag-and-drop

Layer / File(s) Summary
Drag payloads and move operations
src/lib/cross-project-dnd.ts, src/store/slices/notes.ts, src/store/slices/board.ts, src/store/slices/*test.ts
Adds shared folder, note, and card drag payloads, folder movement operations, and same-type board-column placement with backlog and first-column fallbacks.
Notes and project drop targets
src/components/notes/..., src/components/layout/sidebar.tsx, src/app/globals.css
Makes folders draggable and project rows valid drop targets for moving folders, notes, and cards across projects.
Kanban card dragging
src/components/kanban/board.tsx
Tracks sidebar hit targets during card drags and dispatches cross-project moves while retaining normal board drag behavior.

Subagent chat

Layer / File(s) Summary
Subagent data contracts and storage
src/types/index.ts, src/store/slices/chat.ts, electron/db/{schema,queries}.ts, electron/shared/db-mappers.ts
Adds per-thread subagent settings and persisted per-message execution traces.
Shared tool loop
electron/lib/chat-loop.ts, electron/ipc/chat.ts
Moves streaming tool execution into a reusable loop supporting provider-specific streaming, tool overrides, callbacks, and error results.
Dispatcher and subagent execution
electron/lib/chat-subagent-loop.ts, electron/ipc/chat.ts, electron/lib/tools.ts
Adds dispatcher research/write tools, restricted subagent tool sets, metrics, streamed events, and final-answer recovery.
IPC streaming and trace rendering
electron/preload.ts, src/hooks/useChatStream.ts, src/components/chat/chat-panel/*
Streams subagent lifecycle events to the renderer, provides a per-thread toggle, and renders expandable live and persisted traces.
Subagent benchmarks and evaluation
electron/lib/*benchmark.test.ts, electron/lib/chat-quality-scorer.test.ts, electron/lib/chat-subagent-stream.test.ts
Adds gated live comparisons, write-recovery tests, streaming smoke coverage, CSV reports, and judge-based rubric scoring.

Project rename cleanup

Layer / File(s) Summary
Rename reconciliation and duplicate cleanup
electron/shared/notes-io.ts, electron/ipc/db-handlers.ts, electron/notes-files.test.ts, changelogs/v2.5.4.md
Reconciles stranded project folders and removes stale same-note duplicates while preserving the destination copy and cleaning non-note residue.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.19% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: cross-project drag-and-drop and the project-rename folder-move fix.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ddutchie/agentfixes

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Remove unnecessary eslint-disable no-console directives and an unused
afterEach import from the subagent test harnesses.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (5)
electron/lib/chat-agent-benchmark.test.ts (1)

73-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Extract the duplicated live-endpoint harness into a shared test helper. All four new benchmark files re-declare the same BASE_URL/MODEL/API_KEY env parsing (via normaliseBaseUrl) plus an identical endpointUp() reachability probe. Consolidating into one helper (e.g. electron/lib/__testutils__/live-endpoint.ts exporting the config + endpointUp) removes drift risk when the probe or endpoint convention changes.

  • electron/lib/chat-agent-benchmark.test.ts#L73-L83: replace endpointUp (and reuse shared BASE_URL/MODEL/API_KEY from L52-56) with the shared helper.
  • electron/lib/chat-quality-scorer.test.ts#L133-L138: replace the parameterized endpointUp(url, key) and config L43-45 with the shared helper (keep the judge-endpoint override wiring).
  • electron/lib/chat-subagent-stream.test.ts#L28-L33: replace endpointUp and config L24-26 with the shared helper.
  • electron/lib/chat-write-recovery-benchmark.test.ts#L92-L100: replace endpointUp and config L48-50 with the shared helper.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@electron/lib/chat-agent-benchmark.test.ts` around lines 73 - 83, Extract the
duplicated live-endpoint configuration and reachability probe into a shared
helper exporting BASE_URL, MODEL, API_KEY, and endpointUp. Update
electron/lib/chat-agent-benchmark.test.ts:73-83,
electron/lib/chat-quality-scorer.test.ts:133-138,
electron/lib/chat-subagent-stream.test.ts:28-33, and
electron/lib/chat-write-recovery-benchmark.test.ts:92-100 to consume it;
preserve the quality scorer’s judge-endpoint override wiring while removing
local config parsing and endpointUp implementations.
src/store/slices/notes.ts (1)

207-277: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate "collect affected notes in a folder subtree" logic between moveFolder and moveFolderToProject.

The srcLower/affected filter block is identical in both methods (only the projectId field name differs). Extract a small helper, e.g. notesInFolderSubtree(notes, projectId, source), to avoid divergent fixes later (e.g. if the case-insensitive matching rule ever changes, it'd need updating in two places).

♻️ Proposed extraction
+function notesInFolderSubtree(notes: Note[], projectId: ID, source: string): Note[] {
+  const srcLower = source.toLowerCase();
+  return notes.filter((n) => {
+    if (n.projectId !== projectId) return false;
+    const f = normalizeFolderPath(n.folder).toLowerCase();
+    return f === srcLower || f.startsWith(`${srcLower}/`);
+  });
+}

Then call notesInFolderSubtree(get().notes, projectId, source) / notesInFolderSubtree(get().notes, sourceProjectId, source) in place of the two duplicated blocks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/store/slices/notes.ts` around lines 207 - 277, Extract the duplicated
subtree-filtering logic from moveFolder and moveFolderToProject into a shared
notesInFolderSubtree helper accepting notes, project ID, and normalized source
path. Preserve the existing case-insensitive folder matching and descendant
inclusion, then call the helper from both methods with their respective project
IDs.
src/components/kanban/board.tsx (1)

452-473: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Minor: sidebar highlight is updated from two places during the same drag.

updateSidebarDropHighlight is called both here (on every raw pointermove/touchmove) and again in handleDragMove (line 306) using the same livePointer value that this effect just set. The second call is redundant — by the time handleDragMove runs, this effect's listener has already updated the highlight for that pointer position.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/kanban/board.tsx` around lines 452 - 473, Remove the redundant
updateSidebarDropHighlight call from handleDragMove, while preserving its use of
livePointer for other drag-move behavior. Keep the pointermove and touchmove
listeners in the activeCard effect as the sole source of sidebar highlight
updates, including existing cleanup via clearSidebarDropHighlight.
src/store/slices/notes.test.ts (1)

1-89: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Good coverage for moveFolder; moveFolderToProject has none.

This file thoroughly covers moveFolder (reparent, root move, self/descendant no-ops, cross-project isolation), but the new moveFolderToProject action — which also mutates projectId/workspaceId for a whole subtree — has no dedicated test here. Given it's a new bulk-mutating action, worth mirroring the moveCardToProject test pattern from board.test.ts (project validation, subtree matching, no-op when source===target).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/store/slices/notes.test.ts` around lines 1 - 89, Add dedicated tests in
the moveFolder suite for moveFolderToProject, covering destination-project
validation, updating projectId and workspaceId for the entire folder subtree
while leaving unrelated notes unchanged, and the no-op behavior when source and
target projects are identical. Reuse setup, note, and folderOf, and mirror the
existing moveCardToProject test pattern from board.test.ts.
src/lib/cross-project-dnd.ts (1)

38-63: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unused drag helpers writeCrossProjectDrag and readCrossProjectDrag aren’t imported outside src/lib/cross-project-dnd.ts; the current consumers still call setActiveCrossProjectDrag/getActiveCrossProjectDrag directly. Either delete these exports or switch the callers over so the DataTransfer path is actually used.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/lib/cross-project-dnd.ts` around lines 38 - 63, Remove the unused
exported helpers writeCrossProjectDrag and readCrossProjectDrag from the
cross-project drag module, since consumers directly use
setActiveCrossProjectDrag and getActiveCrossProjectDrag. Keep the directly used
mirror functions and related behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@electron/ipc/chat.ts`:
- Around line 217-233: Thread abortCtrl.signal from the chat IPC handler through
runDispatchLoop, runSubagent, forceFinalAnswer, and the nested runToolLoop call
so every model/tool fetch observes user cancellation. Wrap the runDispatchLoop
await in error-safe cleanup that always removes the abort controller and sends
chat:done, including when cancellation or fetch errors throw.

In `@electron/lib/chat-agent-benchmark.test.ts`:
- Line 31: Remove the unused afterEach import from the Vitest import declaration
in chat-agent-benchmark.test.ts, while retaining describe, it, beforeEach, and
expect.

In `@electron/lib/chat-subagent-loop.ts`:
- Around line 422-444: Update the fetch request inside runDispatchLoop to catch
network or other request failures and return the same graceful error-result
shape used by the single-agent loop, preserving the existing HTTP error
handling. Do not address AbortSignal propagation here; keep the change scoped to
preventing fetch rejection from escaping the dispatch loop.

In `@electron/shared/notes-io.ts`:
- Around line 315-377: Update removeDirIfNoNotesLeft and dirContainsNote so
directory cleanup preserves every leftover file except explicitly recognized OS
cruft, rather than treating only .md files as data. Replace the note-extension
check with a helper such as dirContainsRealData that recursively considers
non-cruft files as blocking deletion, while allowing .DS_Store and other
explicitly listed OS-cruft names; have removeDirIfNoNotesLeft call this helper.

In `@src/hooks/useChatStream.ts`:
- Around line 245-247: Update the hydrate/refresh trigger in useChatStream to
include tool calls from finalSubagents when determining hasPersistedWrite, not
just finalToolCalls. Reuse the existing subagent tool-call data and preserve the
current refresh behavior for top-level tool calls.

---

Nitpick comments:
In `@electron/lib/chat-agent-benchmark.test.ts`:
- Around line 73-83: Extract the duplicated live-endpoint configuration and
reachability probe into a shared helper exporting BASE_URL, MODEL, API_KEY, and
endpointUp. Update electron/lib/chat-agent-benchmark.test.ts:73-83,
electron/lib/chat-quality-scorer.test.ts:133-138,
electron/lib/chat-subagent-stream.test.ts:28-33, and
electron/lib/chat-write-recovery-benchmark.test.ts:92-100 to consume it;
preserve the quality scorer’s judge-endpoint override wiring while removing
local config parsing and endpointUp implementations.

In `@src/components/kanban/board.tsx`:
- Around line 452-473: Remove the redundant updateSidebarDropHighlight call from
handleDragMove, while preserving its use of livePointer for other drag-move
behavior. Keep the pointermove and touchmove listeners in the activeCard effect
as the sole source of sidebar highlight updates, including existing cleanup via
clearSidebarDropHighlight.

In `@src/lib/cross-project-dnd.ts`:
- Around line 38-63: Remove the unused exported helpers writeCrossProjectDrag
and readCrossProjectDrag from the cross-project drag module, since consumers
directly use setActiveCrossProjectDrag and getActiveCrossProjectDrag. Keep the
directly used mirror functions and related behavior unchanged.

In `@src/store/slices/notes.test.ts`:
- Around line 1-89: Add dedicated tests in the moveFolder suite for
moveFolderToProject, covering destination-project validation, updating projectId
and workspaceId for the entire folder subtree while leaving unrelated notes
unchanged, and the no-op behavior when source and target projects are identical.
Reuse setup, note, and folderOf, and mirror the existing moveCardToProject test
pattern from board.test.ts.

In `@src/store/slices/notes.ts`:
- Around line 207-277: Extract the duplicated subtree-filtering logic from
moveFolder and moveFolderToProject into a shared notesInFolderSubtree helper
accepting notes, project ID, and normalized source path. Preserve the existing
case-insensitive folder matching and descendant inclusion, then call the helper
from both methods with their respective project IDs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0d90c231-65ba-4562-815c-ef8f439a4567

📥 Commits

Reviewing files that changed from the base of the PR and between 4fdad6b and 279a2d4.

📒 Files selected for processing (32)
  • changelogs/v2.5.4.md
  • electron/db/queries.ts
  • electron/db/schema.ts
  • electron/ipc/chat.ts
  • electron/ipc/db-handlers.ts
  • electron/lib/chat-agent-benchmark.test.ts
  • electron/lib/chat-loop.ts
  • electron/lib/chat-quality-scorer.test.ts
  • electron/lib/chat-subagent-loop.ts
  • electron/lib/chat-subagent-stream.test.ts
  • electron/lib/chat-write-recovery-benchmark.test.ts
  • electron/lib/tools.ts
  • electron/notes-files.test.ts
  • electron/preload.ts
  • electron/shared/db-mappers.ts
  • electron/shared/notes-io.ts
  • src/app/globals.css
  • src/components/chat/chat-panel/ChatMessageBubble.tsx
  • src/components/chat/chat-panel/ChatSubagentBlock.tsx
  • src/components/chat/chat-panel/index.tsx
  • src/components/kanban/board.tsx
  • src/components/layout/sidebar.tsx
  • src/components/notes/notes-view.tsx
  • src/components/notes/notes-view/FolderTreeNode.tsx
  • src/hooks/useChatStream.ts
  • src/lib/cross-project-dnd.ts
  • src/store/slices/board.test.ts
  • src/store/slices/board.ts
  • src/store/slices/chat.ts
  • src/store/slices/notes.test.ts
  • src/store/slices/notes.ts
  • src/types/index.ts

Comment thread electron/ipc/chat.ts Outdated
Comment thread electron/lib/chat-agent-benchmark.test.ts Outdated
Comment thread electron/lib/chat-subagent-loop.ts
Comment thread electron/shared/notes-io.ts
Comment thread src/hooks/useChatStream.ts
Subagent chat:
- Thread abortCtrl.signal through runDispatchLoop → runSubagent →
  forceFinalAnswer and the nested runToolLoop so user cancellation stops
  every model/tool fetch; wrap the dispatch call in try/catch/finally that
  always removes the abort controller and emits chat:done (cancel or error).
- Catch network failures in the dispatch fetch and return the same graceful
  error-result shape as the single-agent loop instead of throwing.
- useChatStream: include write sub-agent tool calls when deciding
  hasPersistedWrite so subagent-mode writes still refresh the board/notes.

Cross-project drag / notes:
- notes-io: replace .md-only dir check with dirContainsRealData so directory
  cleanup preserves any non-cruft file (attachments, .canvas, images) and only
  deletes recognised OS cruft (.DS_Store, Thumbs.db, …).
- notes slice: extract shared notesInFolderSubtree helper used by moveFolder
  and moveFolderToProject; add moveFolderToProject unit tests.
- board: drop redundant sidebar-highlight call in handleDragMove (listeners
  are the sole source).
- cross-project-dnd: remove unused write/readCrossProjectDrag exports.

Tests:
- Extract shared electron/lib/bench-endpoint.ts (BASE_URL/MODEL/API_KEY/
  endpointUp) consumed by the four benchmark tests; preserve the quality
  scorer's judge-endpoint override.
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.

1 participant