fix: refresh magic notes after external updates
Subscribe the open Magic Notes workspace to committed database changes from desktop and Agent/MCP writes. Preserve selections and unsaved drafts during refresh and external deletion. File-level commit includes existing runtime edits in shared files; their remaining dependencies are still in the working tree. Release note: Magic Notes now updates automatically after Agent/MCP edits while preserving your selection and unsaved drafts.
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# Magic Notes
|
||||
|
||||
Magic Notes is the local notes, checklist and AI-comment workbench. Desktop
|
||||
actions and authorized Agent/MCP tools write to the same desktop SQLite store.
|
||||
The open workbench subscribes to successful writes so users can see external
|
||||
changes without leaving the page or clicking a refresh button.
|
||||
|
||||
## Documents
|
||||
|
||||
- [Technical design](./technical-design.md): database notifications, process
|
||||
boundaries, refresh lifecycle and regression coverage.
|
||||
- [Progress](./progress.md): implementation and validation evidence.
|
||||
- [UI design system](../../../UI-DESIGN.md#137-魔法笔记): authoritative workbench
|
||||
interaction rules, including selection and draft preservation.
|
||||
|
||||
An entry is a saved rich-text record within a note. A todo is a checklist item
|
||||
derived from an entry. An unsaved draft belongs to the open editor; it is not
|
||||
written to storage by a background refresh.
|
||||
@@ -0,0 +1,26 @@
|
||||
# Magic Notes Progress
|
||||
|
||||
## 2026-09-15: Automatic External Refresh
|
||||
|
||||
- Implemented the shared-database notification and Main/preload subscription
|
||||
described in [technical design](./technical-design.md).
|
||||
- The open workbench reloads external changes while retaining current selection
|
||||
and unsaved drafts. Deleted notes and edited entries retain drafts with an
|
||||
explicit explanation. The cancelled manual-refresh proposal is not implemented.
|
||||
- An initial completed `npm test` run passed 357 files and 4,201 tests, with
|
||||
9 files and 67 tests skipped (680.45 seconds). The first invocation had exceeded
|
||||
the command tool's 120-second limit.
|
||||
- After three additional renderer race/retry tests, the final `npm test` run
|
||||
reported 355 files and 4,202 tests passed, 9 files and 67 tests skipped, and two
|
||||
unrelated timeout failures: the large offline dependency inventory test in
|
||||
`tests/agent-package.test.ts` (60 seconds), and the two-project OpenCode case in
|
||||
`src/main/agent/local-runtime-reuse.test.ts` (40-second request timeout).
|
||||
- Rerunning those two files together passed 24 tests with one skipped in
|
||||
103.71 seconds, without source or timeout changes. The final renderer/preload
|
||||
focused run also passed all 38 tests. No Magic Notes regression failed.
|
||||
- `npm run typecheck` and `npm run lint`: passed. The new required subscription
|
||||
method is also present in the application test API fixture.
|
||||
- Validation uses production SQLite and Agent/MCP gateway code, the production
|
||||
preload with mocked Electron transport, and renderer interaction tests. An
|
||||
interactive Electron window was not exercised. No deployed Agent code or
|
||||
desktop-to-Agent protocol changed, so no separate Linux Host scenario applies.
|
||||
@@ -0,0 +1,60 @@
|
||||
# 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
|
||||
|
||||
`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](../../../UI-DESIGN.md#137-魔法笔记).
|
||||
|
||||
## 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.
|
||||
- `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.
|
||||
|
||||
No schema migration, dependency, refresh control or network service is added.
|
||||
Reference in New Issue
Block a user