Files
goodbuddy/docs/features/magic-notes/technical-design.md
T
mesalogo a8d1dbc11f
GoodBuddy Agents / Validate Agent source (push) Canceled after 0s
GoodBuddy Agents / Build darwin arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build linux arm64 Agent (push) Canceled after 0s
GoodBuddy Agents / Build linux x64 Agent (push) Canceled after 0s
Cross-platform packages / Validate source (push) Canceled after 0s
Cross-platform packages / Authorize desktop packaging (push) Canceled after 0s
Cross-platform packages / linux arm64 (push) Canceled after 0s
Cross-platform packages / macos arm64 (push) Canceled after 0s
Cross-platform packages / windows arm64 (push) Canceled after 0s
Cross-platform packages / linux x64 (push) Canceled after 0s
Cross-platform packages / macos x64 (push) Canceled after 0s
Cross-platform packages / windows x64 (push) Canceled after 0s
Cross-platform packages / Publish GitHub and OSS release (push) Canceled after 0s
fix: give notes and todos dedicated workspace layouts
Replace the crowded note sidebar with a card overview and full note detail. Keep tasks in a stable split view with source content and AI comments, compact header navigation, and search-adjacent status filters. Preserve drafts and return context.

Validation: 93 focused tests, typecheck, lint, and isolated Electron renderer checks passed. Full suite was interrupted; renderer probes used in-memory APIs.

Release note: Notes now open from a card overview, while todos keep a stable task list beside their details. Compact view and filter controls leave more room for reading and editing.
2026-09-18 21:22:58 +08:00

7.4 KiB

Magic Notes Technical Design

Change Notifications

AssistantDatabase accepts onMagicNotesChanged: () => void. Every successful note/entry create, update or delete emits once after the write commits, including empty-note creation, initial content, title/pin updates and cascading deletion. Saved note analysis, todo completion, saved todo analysis and assistant-data clearing also emit. Revision conflicts, missing rows, rolled-back writes and unchanged todo completion do not emit. Startup schema migrations run before the workbench loads and do not publish notifications.

Desktop IPC and KnowledgeMcpGateway use this same database instance. The latter also serves Agent tools; no tool-specific notification or daemon protocol change is needed. Raw SQL writes from an unrelated process are outside this callback contract.

Main queues notification delivery to the live window on magic-notes:changed. The typed preload method magicNotes.onChanged(listener) exposes no Electron objects and returns a function removing that listener. The existing onTodoStatusChanged event remains the separate sidebar-count signal.

Refresh Lifecycle

The overview's libraryView and the optional note-only detailView are independent: opening a todo's source note does not lose the originating task view. The overview remains mounted but hidden while detail is open, retaining scroll position and filters. Returning restores the initiating control's focus and invalidates outstanding detail requests. Initial loading fetches summaries and todos without selecting the first note or task. Navigation away from unsaved content or an unsaved title uses the existing draft confirmation; active writes finish before navigation. No new persistence or IPC contract is required.

MagicNotesWorkspace subscribes on mount and coalesces notifications with a 100 ms debounce. Pending notifications wait for an active local save or analysis to finish. Cleanup removes the listener, clears its timer and invalidates pending refresh results. This does not introduce periodic database polling.

The existing list/detail loader reloads notes and todos, then the preferred note. Request counters reject superseded results and preserve newer user selections. Todo selection survives list reordering while the item exists; replacing the todo snapshot also reloads the selected todo's source entry. Search, filters and layout state are not reset.

Background application of a detail reads the current draft state after the asynchronous fetch. A dirty title is retained, and the composer is not remounted. An entry editor uses its original editing content and revision for both its React key and save request; external revisions cannot remount it or bypass optimistic concurrency checks. Deleted entries remain displayed only while their editor is open. If an externally deleted note has a draft, its editor remains available with a deletion explanation instead of moving the draft to another note.

Read failures use the existing retryable refresh error and retain successful data and drafts. Retry uses the same draft-preserving loader. Interaction rules are owned by the UI design system.

Todo Task View

The To-dos panel has its own search/status toolbar and independently scrolling task list, grouped by source note. selectedTodoId controls one sibling detail pane; the selected item is derived from the filtered list. Completion updates the existing item and source cache without selecting or opening another task. Items that no longer match the status filter leave the list. A removed focused control returns focus to an available list/filter control.

Detail content includes instructions, the source entry, its existing note navigation action, and AI controls/comments. AI requests still use the existing analysis options and streaming subscription; failed analysis retains saved comments. Source reads are guarded against superseded selections, report failures through notifications and offer inline retry. The grid reserves both columns even without a selection, so selecting or switching tasks cannot move list rows. The detail is keyed by task ID to start each newly selected task at its top. At a page container width of 700px or less, CSS hides the mounted list while a task is selected and shows an explicit return button in the detail area. Returning clears selection and restores row focus without scrolling; source-note return retains selection and focuses this visible return button on narrow layouts. There is no todo detail route, separate AI sidebar or resize handle. Note detail retains its existing AI pane preferences.

The shared segmented PageTabs lives in PageHeader.actions before New note, retaining tab/panel IDs, roving focus and arrow-key navigation. Its width follows content at all sizes. The shared status SegmentedControl follows search in one wrapping toolbar. These layout changes do not change Main, preload or storage.

Note List Actions

Each overview card has an open-detail button and a sibling action-menu button. The menu uses the conversation action styles and shared DestructiveConfirmActions, and is portalled to document.body. Its position follows the trigger on scrolling, window resizing and confirmation-size changes. Entering detail, filtering out the target or leaving the notes panel closes the menu.

Pinning uses the target summary's ID and revision through the existing update IPC. It updates the sorted summary and matching selected detail without resetting title, composer or entry-edit drafts. Deleting uses the explicitly confirmed target ID and refreshes the overview after success, without opening another note. These actions are available only in the overview. Database and Agent contracts are unchanged.

Agent Search Contract

note_search accepts an integer limit from 1 to 100, defaulting to 8. The shared schema supplies both model tool definitions and MCP validation; the existing 128 KiB output budget can reduce the returned result count. The built-in MCP gateway returns invalid scoped-tool arguments as an isError: true tool result with the field and validation message, allowing the model to correct its arguments without an MCP internal-error response. Validation failures do not execute the tool.

These note tools run in the desktop gateway. Remote gbagent ACP sessions currently inject only the image MCP server, so this change requires no daemon implementation update.

Validation

  • assistant-database.test.ts checks committed writes with a second SQLite connection, successful mutation coverage, failures, no-op completion and reset.
  • knowledge-mcp-gateway.test.ts exercises real database CRUD through Agent/MCP access, including revision failure without an extra notification. A real HTTP MCP client also checks searches above ten results, the published limit schema, invalid arguments and successful retry against SQLite.
  • magic-notes-events.test.ts executes the production preload, checking the channel, payload-free callback and listener removal.
  • MagicNotesWorkspace.test.tsx covers external updates and deletion, selection, source reload, editor identity and draft saves, coalescing, deferred writes, asynchronous selection races, error retry and unmount cleanup. List-action coverage includes portal placement, keyboard navigation, dismissal, delete confirmation, target selection, revision failures and draft preservation.

No schema migration, dependency, refresh control or network service is added.