Branch staging: create → write → review → merge in the app chrome (P6)#19
Merged
Conversation
Every notebook write previously landed straight on the graph's main
branch — no review step, no undo. This adds session branch staging to
the web app over the server's first-class branches.
Client facade
- createBranch/mergeBranch/deleteBranch/snapshot on Client. mergeBranch
returns a discriminated result ({ok, outcome} | {ok:false, conflicts})
— conflicts are an EXPECTED review outcome, not an exception. SDK
0.7/0.8 never populate ConflictError.mergeConflicts (they read
camelCase from a snake_case error body), so the facade falls back to
the raw body.
Switch = keyed remount with carried state
- BranchedApp holds the session branch ABOVE the runtime; switching
remounts RuntimeApp with a source targeting the branch
(defaultTarget + ServerSource opts stay in lockstep) and the previous
snapshot state as initialState, so selections survive. ?branch=
follows via replaceState. The session branch is distinct from the
DECLARED base (CLI --branch / injected config, never the URL param):
a ?branch= reload lands back ON the working branch while merges still
target the declared base.
BranchBar (header chrome)
- Branch dropdown (refreshes on open, so branches created elsewhere
appear), inline create prefilled work-<local date> (409 = "exists" →
switch to it), and on a working branch a Review & merge popover:
table-level deltas from two /snapshot reads, two-step-confirmed merge
(outcome toast; structured conflict list on 409 with the base
untouched), delete-to-abandon. Merge never auto-deletes the branch.
- Table deltas compare version + row_count + WRITER lineage: versions
are per-lineage counters, so two diverged branches can collide
numerically while contents differ — same numbers with a different
last-writer render as "diverged" instead of a false "no changes".
Tests 219 → (client 31, web 71 here). Verified live on the RustFS demo:
branch isolation (writes stayed off main), delta review, fast-forward
merge + delete, and a real divergent_update conflict rendering
structured while main stayed intact; prod smoke read-only.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011TrhtF1SiJghJASMWECzBh
Greptile: computeTableDeltas iterated only the branch's tables, so a
table present on the base but gone on the branch vanished from the
review summary — the merge could be disabled ("no changes") or a
destructive removal omitted. The union is now walked: base-only tables
appear as removed deltas (badge "removed", -N rows).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011TrhtF1SiJghJASMWECzBh
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.
Every notebook write previously landed straight on the graph's main branch — live edits against prod with no review step and no undo story. omnigraph-server 0.7+ has first-class branches (copy-on-write forks, three-way all-or-nothing merge with structured conflicts); this slice plumbs them into the web app as session branch staging.
Client facade
createBranch/mergeBranch/deleteBranch/snapshotonClient.mergeBranchreturns a discriminated result ({ok, outcome}|{ok: false, conflicts}) — a conflict is an expected outcome of reviewing staged work, and the target is untouched, so callers render it and continue. Includes a raw-body fallback for the SDK bug whereConflictError.mergeConflictsis alwaysundefined(camelCase read of a snake_case error body; present in 0.7.0 and 0.8.0).Switch = keyed remount with carried state
The session branch is React state above the runtime; switching remounts
RuntimeAppwith a source targeting the branch (runtimedefaultTargetandServerSourceopts stay in lockstep by construction) and the previous snapshot's state asinitialState— selections survive the hop.?branch=follows viareplaceState, and the session branch is deliberately distinct from the declared base (CLI--branch/ injected config, never the URL param): reloading a shared?branch=work-xlink lands you back ON the working branch while "merge into" still targets the declared base. Zero core-runtime changes.BranchBar (header chrome)
work-<local date>(a 409 name collision means "exists" → switch to it)./snapshotreads, two-step-confirmed merge (outcome toast on success; the structured conflict list renders on 409 with the base untouched), and delete-to-abandon. Merge never auto-deletes the source branch.divergedinstead of a false "No changes". (Found live: the naive compare disabled a merge that would conflict.)Verification
Task ±0, v10 → v12) → fast-forward merge picked up by main → delete. Conflict path: divergentapprovevsrejecton the same row → second merge blocked withdivergent_updaterendered structured, main intact. Prod smoke read-only./changesroute over the existing Rustdiff_betweenengine).🤖 Generated with Claude Code
https://claude.ai/code/session_011TrhtF1SiJghJASMWECzBh
Greptile Summary
This PR adds branch staging to the notebook web app. The main changes are:
Confidence Score: 5/5
This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "Delta summary covers base-only tables (s..." | Re-trigger Greptile
Context used: