Repository navigation
Redesign branching UX: auto-branch on edit-in-past, tags, unified timeline graph - #6
Merged
Merged
Conversation
…eline graph
Branching is now implicit and the history timeline IS the network graph.
Behaviour
- Time travel is editable. Editing while scrubbed into the past auto-forks a new
branch AT that instant (checkout + land the edit there); main is never touched.
No manual "create branch" step — a non-blocking banner names the new branch.
- Tags: name any moment on the timeline (synced Kind::Tag log rows, reconciled
last-writer-wins like branch records). Tag flags render on the timeline and
jump the playhead when clicked — find/return to points among thousands of edits.
- The bottom history timeline became the network graph: one lane per branch,
fork edges where a branch diverged, events positioned by time (distance = time),
keeping zoom, pan and the playhead slider. The branch dropdown + the separate
network-graph modal are removed; a branch pill + clickable lane labels replace them.
Backend (asp-core / wasm / desktop engine / Tauri)
- New Kind::Tag + tag.rs (Tag record, derive_id, reconcile_tags); create_tag /
tags / delete_tag on both the native (SqliteEngine) and wasm (MemEngine) engines,
a log_kind_tag partial index, and the graph now carries tags on their lane.
- MemEngine gains history / file_at / restore_file_at so the web build has real
time travel + fork-on-edit-in-the-past (previously desktop-only), and wasm
now_unix() uses the browser clock so web timestamps aren't epoch 0.
- HistEvent carries branch_id for lane placement.
Perf ("Loading your vaults…")
- capture_rescan/scan_disk report (done, total, phase) progress; the shell emits
vault-scan-progress and the connect screen shows a determinate progress bar
instead of an indeterminate spinner on a large (28k-file) reconcile.
Tests
- asp-core: tag reconcile LWW/order-invariance, engine tag lifecycle + reopen,
scan-progress callback, MemEngine tag/history/PITR parity.
- frontend: timeline layout unit tests, auto-branch + tag + editable-time-travel
integration tests, progress-bar test. Full suites green (482 FE, 91+ core).
- Verified end-to-end in a real headed browser (chromium/Xvfb) on the real wasm
engine: create vault, edit, tag, time-travel, auto-branch, branch lanes, switch.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D5zbJaE8dCFXiBRNRZhqbE
Drives the REAL desktop Tauri app (native SqliteEngine, real Tauri IPC) headed under Xvfb to verify the redesign end-to-end: open a pre-registered vault, the timeline network graph, tagging, jump-to-tag time travel, auto-branch on edit-in-the-past, and branch lanes. Complements the web (wasm) browser drive. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D5zbJaE8dCFXiBRNRZhqbE
capture_rescan_progress calls scan_disk_progress directly; the old parameterless scan_disk wrapper had no callers. Removes the `method is never used` warning. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D5zbJaE8dCFXiBRNRZhqbE
Timeline - A connecting line runs through each lane's dots, so history reads as one continuous strand per branch. - Clicking a dot opens a diff popup showing exactly what changed at that point (before/after via a tiny line diff), and scrubs the playhead there. - Branch labels moved to the RIGHT, anchored next to each lane's most-recent dot instead of far-left aligned. - New Time/Edits toggle: space dots by wall-clock time (default) or evenly by edit order (a clean, uniform view when edits cluster in time). - The status bar shows the vault's file count after the fingerprint. Tags - Deleting a tag now asks for confirmation. - Clicking outside the tag-name input closes it. Perf: instant branch switching - checkout used to blow away the fold cache and do a full O(all-rows) refold every time. Added a small per-branch FoldState LRU (native Engine) / materialized-files LRU (wasm MemEngine): the outgoing branch's fold is parked and the target's restored if cached, so switching among a few branches is near-instant. Remote integrates invalidate the cache. Correctness pinned by a warm-vs-cold-fold test. Clone hardening (desktop → web) - The browser clone had no read timeout: a stalled relay left "Receiving notes…" hanging forever. Added a per-frame idle timeout so a stall surfaces as an error, and the connect dialog now shows clone failures instead of silently resetting. Also: openVault fetches vault status immediately so the status bar (file count) is populated on a freshly opened/created vault. Tests: diffLines unit tests; checkout warm/cold parity; browser drive extended to 18 checks (connecting line, diff popup, file count, layout toggle, tag confirm + outside-click) — all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D5zbJaE8dCFXiBRNRZhqbE
… harness - Reduce catch-up chunk size 4 MiB/512 rows → 1 MiB/256 rows. The browser can only reach a listener over a relay (no direct UDP), where one large frame streams slowly and stalls "Receiving notes…". Smaller frames keep bytes flowing, advance progress smoothly, and stay under the connector's new per-frame idle timeout. Verified: a 6,000-file catch-up over real iroh loopback converges, 0 failures. - Document the real-engine computer-use drives (web wasm via Playwright/chromium, desktop Tauri via tauri-driver/WebKitWebDriver) in desktop/e2e/README.md so the verification process is reproducible. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D5zbJaE8dCFXiBRNRZhqbE
Reproduces the browser clone's receive path hermetically (no relay needed): a source authors N files; a fresh MemEngine (the wasm engine) integrates the catch-up in 256-row pages under batch — exactly what iroh_wasm::drive does — folds once, then round-trips through export_state/import_state (the OPFS save/load). Confirms the receiver is O(N), not O(N²), and that a large state survives save→load byte-identically. Ran at 28,000 files locally (~8s, no OOM); committed at 4,000 for CI speed. This isolates the earlier "Receiving notes…" hang to the relay transport (addressed separately by smaller frames + a per-frame idle timeout), not the engine. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D5zbJaE8dCFXiBRNRZhqbE
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Branching is now implicit and the history timeline IS the network graph.
Behaviour
branch AT that instant (checkout + land the edit there); main is never touched.
No manual "create branch" step — a non-blocking banner names the new branch.
last-writer-wins like branch records). Tag flags render on the timeline and
jump the playhead when clicked — find/return to points among thousands of edits.
fork edges where a branch diverged, events positioned by time (distance = time),
keeping zoom, pan and the playhead slider. The branch dropdown + the separate
network-graph modal are removed; a branch pill + clickable lane labels replace them.
Backend (asp-core / wasm / desktop engine / Tauri)
tags / delete_tag on both the native (SqliteEngine) and wasm (MemEngine) engines,
a log_kind_tag partial index, and the graph now carries tags on their lane.
time travel + fork-on-edit-in-the-past (previously desktop-only), and wasm
now_unix() uses the browser clock so web timestamps aren't epoch 0.
Perf ("Loading your vaults…")
vault-scan-progress and the connect screen shows a determinate progress bar
instead of an indeterminate spinner on a large (28k-file) reconcile.
Tests
scan-progress callback, MemEngine tag/history/PITR parity.
integration tests, progress-bar test. Full suites green (482 FE, 91+ core).
engine: create vault, edit, tag, time-travel, auto-branch, branch lanes, switch.
Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01D5zbJaE8dCFXiBRNRZhqbE