Repository navigation
Keep database-sourced nodes persisted under skipPersistence (closes #2940) - #2944
Conversation
…2940) skipPersistence outranked the database source in determinePersistenceBehavior, so NavigationService.resolveNodeTarget (and the SSE, Tauri domain-event, ai-chat poll and node-card ingress paths) inserted backend rows without adding them to persistedNodeIds. doLoadChildrenTree skips an already-cached root, so the navigated-to root stayed untracked and its first edit took the create path, which the daemon rejected as a duplicate insert. skipPersistence now suppresses only the write; a database source still marks the node persisted. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Pragmatic Code Review: PR #2944 (closes #2940)Review Type: Initial review. The PR had no prior reviews or comments. Requirements Check
Code Review FindingsI checked whether marking any of the affected ingress paths as persisted could be wrong. I found no case where it is.
🟡 Suggested Improvements
🟢 Nitpicks
RecommendationAPPROVE The fix is a single-line precedence correction in the one function that owns the decision. It restores the documented |
malibio
left a comment
There was a problem hiding this comment.
Automated pragmatic-code-review: APPROVE (posted as a comment — GitHub blocks self-approval). Full findings in the review comment above.
…ntract - ai-chats: the domain-event echo now does mark the node persisted; the seed exists to beat the echo, not because the echo never marks it - determinePersistenceBehavior JSDoc: skipPersistence suppresses the write only - navigation-service: note the database source is what records persisted state - unit test: database source + skipPersistence -> isNodePersisted true Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Review feedback addressed (81c0d15)✅ Addressed (4/4):
⏭️ Skipped: none. Tests: the three affected files pass (218 tests). Re-review decision: not needed. The changes are comments plus one additive unit test, with no logic changes. |
Root cause
NavigationService.resolveNodeTarget()puts a fetched node into the store withsetNode(node, { type: 'database' }, true). IndeterminePersistenceBehavior,skipPersistence(priority 2) ranked above the database source (priority 4) and returnedshouldMarkAsPersisted: false. The node landed in the store but never inpersistedNodeIds.doLoadChildrenTreethen skips a root that is already cached, so nothing marked it later either. The first edit took the create path, and the daemon rejected the duplicate insert (POST /api/nodes→ 500).Fix
skipPersistencenow only suppresses the write. Adatabasesource still marks the node persisted.The same
database+skipPersistence=truepairing is used by five other ingress paths, all of which had the same latent defect:browser-sync-service.ts(SSE sync)tauri-sync-listener.ts(domain events)ai-chat-node-viewer.svelte(poll)node-card-inline.sveltenavigation-service.tsFixing the precedence covers all of them in one place, with no per-write existence query.
Tauri mode: also affected.
navigation-servicedoesn't depend on the transport, andtauri-sync-listeneruses the same pairing.Verification
navigated-root-persisted-regression.test.ts: navigation fetch →loadChildrenTree→ root is inpersistedNodeIds→updateNodecallsbackendAdapter.updateNode, nevercreateNode. Fails without the fix (expected false to be true), passes with it.PATCH /api/nodes/<id>→ 200, with noPOSTand no "Database write failed".GET /api/nodes/<id>returnslast_name: "Byron"at version 2.architecture-benchmarksfailed under load on the first run and passed 13/13 in isolation. The pre-push gate passed.🤖 Generated with Claude Code