Sibling node order not preserved after page refresh - #658
Conversation
## Problem
Nodes created via Enter key displayed in correct order during session,
but after page refresh appeared in wrong order. The sibling ordering
information (insertAfterNodeId) was not being passed to the backend
during node creation.
## Root Cause
- ReactiveNodeService.createNode() created nodes with parentId but
WITHOUT insertAfterNodeId
- Backend received no positioning hint for sibling order
- Database stored incorrect order values
## Solution
Pass insertAfterNodeId from frontend to backend during node creation:
1. **Rust backend** (`commands/nodes.rs`):
- Added `insert_after_node_id` field to `CreateNodeInput` struct
- Pass field to `CreateNodeParams` instead of hardcoding `None`
2. **TypeScript frontend** (`backend-adapter.ts`):
- Added `insertAfterNodeId` to `CreateNodeInput` interface
- Updated TauriAdapter and HttpAdapter to pass field to backend
3. **ReactiveNodeService** (`reactive-node-service.svelte.ts`):
- Calculate insertAfterNodeId based on insertion position:
- `insertAtBeginning=true` → null (insert at start)
- `insertAtBeginning=false` → afterNodeId (insert after ref node)
- Include in node object passed to sharedNodeStore.setNode()
## Testing
- No new test failures (baseline: 1445 pass/5 fail frontend, 538 pass/4 fail backend)
- Pre-existing failures are unrelated sibling ordering tests in Rust
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Additional Fix: Rename before_sibling_id → insert_after_node_id The backend had a confusing semantic mismatch where: - Frontend sent `insertAfterNodeId` = "insert AFTER this sibling" - Backend parameter named `before_sibling_id` = "insert BEFORE this sibling" - Translation logic converted "BEFORE X" → "AFTER node-before-X" This caused nodes to be inserted in reverse order. ## Changes **1. node_service.rs (create_parent_edge)**: - Renamed parameter: `before_sibling_id` → `insert_after_node_id` - Removed confusing translation logic (BEFORE → AFTER conversion) - Now directly passes `insert_after_node_id` to `store.move_node()` - Only translates None case: None → find last child (append at end) **2. operations/mod.rs**: - Renamed variable: `final_sibling_id` → `last_sibling_id` - Updated debug log: "before_sibling" → "insert_after" - Updated doc comments to reflect "insert after" semantics **3. dev-proxy.rs**: - Added debug logging to show insert_after_node_id values ## Test Results **Before**: 538 passed, 4 failed (sibling ordering tests failing) **After**: 542 passed, 0 failed (all tests pass!) The 4 previously-failing sibling ordering tests now pass: - test_sibling_chain_ordering - test_get_children_tree_sibling_ordering - test_get_children_tree_single_level - test_get_children_ordered_with_multiple_insertions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Additional Fix: Semantic Mismatch in BackendAfter testing, discovered the backend had a semantic mismatch:
This caused nodes to be inserted in reverse order. Second Commit (ce8bd19)Renamed
Test ResultsBefore fix:
After fix:
Fixed tests:
Database VerificationTested with fresh database - nodes now have correct fractional ordering:
Related IssueCreated #659 for dev-proxy abstraction cleanup (separate from this fix) |
Code Review Report - PR #658Review Type: Initial Review PR: Sibling node order not preserved after page refresh Requirements Check (Issue #657)
Code Review FindingsArchitecture & Design (Critical)No Critical Issues Found The fix correctly addresses the semantic mismatch between frontend and backend. The changes are well-scoped and follow the existing architecture patterns:
Functionality & Correctness (Critical)No Critical Issues Found The implementation correctly handles all cases:
Security (Non-Negotiable)No Issues Found
Maintainability & Readability (High Priority)PASS - Excellent code quality
Suggested Improvements[Improvement] The type extension // Current (acceptable):
const newNode: Node & { insertAfterNodeId?: string | null } = { ... };
// Alternative for future consideration:
interface NodeCreationInput extends Node {
insertAfterNodeId?: string | null;
}Rationale: Type safety principle - explicit types prevent accidental misuse. However, this is acceptable for now as it is a single-use pattern. Testing (High Priority)PASS - Excellent test coverage improvement
The 4 previously failing tests now pass:
Performance (Important)No Issues Found The Documentation (Important)PASS - Well documented
SummaryThis PR correctly fixes the sibling ordering persistence bug through a two-commit approach:
The changes are:
Recommendation: APPROVEThis PR is a clear net improvement to code health. It fixes a user-facing bug, improves code clarity, and adds no new technical debt. Reviewed by: Principal Engineer AI Reviewer |
Address Review SummaryAll recommendations analyzed - no changes required. Recommendations Addressed
Summary
Re-Review Decision: NOT NEEDEDThe original review found no critical or important issues. The single suggestion was explicitly marked as "acceptable for now" by the reviewer. The PR is ready for merge. Address Review completed by: Implementation Agent |
* Fix sibling node order not preserved after page refresh (#657) ## Problem Nodes created via Enter key displayed in correct order during session, but after page refresh appeared in wrong order. The sibling ordering information (insertAfterNodeId) was not being passed to the backend during node creation. ## Root Cause - ReactiveNodeService.createNode() created nodes with parentId but WITHOUT insertAfterNodeId - Backend received no positioning hint for sibling order - Database stored incorrect order values ## Solution Pass insertAfterNodeId from frontend to backend during node creation: 1. **Rust backend** (`commands/nodes.rs`): - Added `insert_after_node_id` field to `CreateNodeInput` struct - Pass field to `CreateNodeParams` instead of hardcoding `None` 2. **TypeScript frontend** (`backend-adapter.ts`): - Added `insertAfterNodeId` to `CreateNodeInput` interface - Updated TauriAdapter and HttpAdapter to pass field to backend 3. **ReactiveNodeService** (`reactive-node-service.svelte.ts`): - Calculate insertAfterNodeId based on insertion position: - `insertAtBeginning=true` → null (insert at start) - `insertAtBeginning=false` → afterNodeId (insert after ref node) - Include in node object passed to sharedNodeStore.setNode() ## Testing - No new test failures (baseline: 1445 pass/5 fail frontend, 538 pass/4 fail backend) - Pre-existing failures are unrelated sibling ordering tests in Rust 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix semantic mismatch in sibling ordering (#657) ## Additional Fix: Rename before_sibling_id → insert_after_node_id The backend had a confusing semantic mismatch where: - Frontend sent `insertAfterNodeId` = "insert AFTER this sibling" - Backend parameter named `before_sibling_id` = "insert BEFORE this sibling" - Translation logic converted "BEFORE X" → "AFTER node-before-X" This caused nodes to be inserted in reverse order. ## Changes **1. node_service.rs (create_parent_edge)**: - Renamed parameter: `before_sibling_id` → `insert_after_node_id` - Removed confusing translation logic (BEFORE → AFTER conversion) - Now directly passes `insert_after_node_id` to `store.move_node()` - Only translates None case: None → find last child (append at end) **2. operations/mod.rs**: - Renamed variable: `final_sibling_id` → `last_sibling_id` - Updated debug log: "before_sibling" → "insert_after" - Updated doc comments to reflect "insert after" semantics **3. dev-proxy.rs**: - Added debug logging to show insert_after_node_id values ## Test Results **Before**: 538 passed, 4 failed (sibling ordering tests failing) **After**: 542 passed, 0 failed (all tests pass!) The 4 previously-failing sibling ordering tests now pass: - test_sibling_chain_ordering - test_get_children_tree_sibling_ordering - test_get_children_tree_single_level - test_get_children_ordered_with_multiple_insertions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
* Fix sibling node order not preserved after page refresh (#657) ## Problem Nodes created via Enter key displayed in correct order during session, but after page refresh appeared in wrong order. The sibling ordering information (insertAfterNodeId) was not being passed to the backend during node creation. ## Root Cause - ReactiveNodeService.createNode() created nodes with parentId but WITHOUT insertAfterNodeId - Backend received no positioning hint for sibling order - Database stored incorrect order values ## Solution Pass insertAfterNodeId from frontend to backend during node creation: 1. **Rust backend** (`commands/nodes.rs`): - Added `insert_after_node_id` field to `CreateNodeInput` struct - Pass field to `CreateNodeParams` instead of hardcoding `None` 2. **TypeScript frontend** (`backend-adapter.ts`): - Added `insertAfterNodeId` to `CreateNodeInput` interface - Updated TauriAdapter and HttpAdapter to pass field to backend 3. **ReactiveNodeService** (`reactive-node-service.svelte.ts`): - Calculate insertAfterNodeId based on insertion position: - `insertAtBeginning=true` → null (insert at start) - `insertAtBeginning=false` → afterNodeId (insert after ref node) - Include in node object passed to sharedNodeStore.setNode() ## Testing - No new test failures (baseline: 1445 pass/5 fail frontend, 538 pass/4 fail backend) - Pre-existing failures are unrelated sibling ordering tests in Rust 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix semantic mismatch in sibling ordering (#657) ## Additional Fix: Rename before_sibling_id → insert_after_node_id The backend had a confusing semantic mismatch where: - Frontend sent `insertAfterNodeId` = "insert AFTER this sibling" - Backend parameter named `before_sibling_id` = "insert BEFORE this sibling" - Translation logic converted "BEFORE X" → "AFTER node-before-X" This caused nodes to be inserted in reverse order. ## Changes **1. node_service.rs (create_parent_edge)**: - Renamed parameter: `before_sibling_id` → `insert_after_node_id` - Removed confusing translation logic (BEFORE → AFTER conversion) - Now directly passes `insert_after_node_id` to `store.move_node()` - Only translates None case: None → find last child (append at end) **2. operations/mod.rs**: - Renamed variable: `final_sibling_id` → `last_sibling_id` - Updated debug log: "before_sibling" → "insert_after" - Updated doc comments to reflect "insert after" semantics **3. dev-proxy.rs**: - Added debug logging to show insert_after_node_id values ## Test Results **Before**: 538 passed, 4 failed (sibling ordering tests failing) **After**: 542 passed, 0 failed (all tests pass!) The 4 previously-failing sibling ordering tests now pass: - test_sibling_chain_ordering - test_get_children_tree_sibling_ordering - test_get_children_tree_single_level - test_get_children_ordered_with_multiple_insertions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
* Fix sibling node order not preserved after page refresh (#657) ## Problem Nodes created via Enter key displayed in correct order during session, but after page refresh appeared in wrong order. The sibling ordering information (insertAfterNodeId) was not being passed to the backend during node creation. ## Root Cause - ReactiveNodeService.createNode() created nodes with parentId but WITHOUT insertAfterNodeId - Backend received no positioning hint for sibling order - Database stored incorrect order values ## Solution Pass insertAfterNodeId from frontend to backend during node creation: 1. **Rust backend** (`commands/nodes.rs`): - Added `insert_after_node_id` field to `CreateNodeInput` struct - Pass field to `CreateNodeParams` instead of hardcoding `None` 2. **TypeScript frontend** (`backend-adapter.ts`): - Added `insertAfterNodeId` to `CreateNodeInput` interface - Updated TauriAdapter and HttpAdapter to pass field to backend 3. **ReactiveNodeService** (`reactive-node-service.svelte.ts`): - Calculate insertAfterNodeId based on insertion position: - `insertAtBeginning=true` → null (insert at start) - `insertAtBeginning=false` → afterNodeId (insert after ref node) - Include in node object passed to sharedNodeStore.setNode() ## Testing - No new test failures (baseline: 1445 pass/5 fail frontend, 538 pass/4 fail backend) - Pre-existing failures are unrelated sibling ordering tests in Rust 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * Fix semantic mismatch in sibling ordering (#657) ## Additional Fix: Rename before_sibling_id → insert_after_node_id The backend had a confusing semantic mismatch where: - Frontend sent `insertAfterNodeId` = "insert AFTER this sibling" - Backend parameter named `before_sibling_id` = "insert BEFORE this sibling" - Translation logic converted "BEFORE X" → "AFTER node-before-X" This caused nodes to be inserted in reverse order. ## Changes **1. node_service.rs (create_parent_edge)**: - Renamed parameter: `before_sibling_id` → `insert_after_node_id` - Removed confusing translation logic (BEFORE → AFTER conversion) - Now directly passes `insert_after_node_id` to `store.move_node()` - Only translates None case: None → find last child (append at end) **2. operations/mod.rs**: - Renamed variable: `final_sibling_id` → `last_sibling_id` - Updated debug log: "before_sibling" → "insert_after" - Updated doc comments to reflect "insert after" semantics **3. dev-proxy.rs**: - Added debug logging to show insert_after_node_id values ## Test Results **Before**: 538 passed, 4 failed (sibling ordering tests failing) **After**: 542 passed, 0 failed (all tests pass!) The 4 previously-failing sibling ordering tests now pass: - test_sibling_chain_ordering - test_get_children_tree_sibling_ordering - test_get_children_tree_single_level - test_get_children_ordered_with_multiple_insertions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
Closes #657