Skip to content

Fork from point in chat buffer (f key)#124

Merged
dnouri merged 1 commit intomasterfrom
fork-from-point
Feb 13, 2026
Merged

Fork from point in chat buffer (f key)#124
dnouri merged 1 commit intomasterfrom
fork-from-point

Conversation

@dnouri
Copy link
Owner

@dnouri dnouri commented Feb 13, 2026

What

Press f on any user turn in the chat buffer to fork the conversation from that point. Confirms with a preview, then creates a new session branching from that message.

Also fixes n/p navigation — the old pattern searched for the never-present You: instead of setext headings — and recenters the heading to the top of the window.

How it works

  1. Detect which user turn point is in via setext heading scan
  2. Fetch the conversation tree (get_tree RPC)
  3. Walk from leaf to root to find user message IDs on the active branch
  4. Align visible buffer headings to tree IDs using a last-N strategy (handles compaction — compacted-away turns aren't rendered but exist in the tree)
  5. Confirm with y-or-n-p, then fork via the existing fork RPC

Upstream enhancements that would simplify this

The main complexity here is mapping a buffer position to an entry ID. We render user turns from get_messages, but forking requires an entry ID from get_tree — two different RPCs with no shared identifiers. This forces us to:

  • Fetch the full tree and walk it leaf-to-root
  • Count visible headings and align them to tree user IDs via last-N (to handle compaction)

Two possible upstream improvements:

  1. Include entryId in get_messages responses. If each message carried its entry ID, fork-at-point would be a single lookup — no tree walk, no alignment heuristic.

  2. A fork_at_index RPC that accepts a 0-based user turn index (from the active branch) instead of an entry ID. The server already knows the active branch and could resolve the index internally.

Either would eliminate flatten-tree, active-branch-user-ids, resolve-fork-entry, and the last-N alignment logic (~50 lines of production code and ~20 tests).

Press f on any user turn in the chat buffer to fork the conversation
from that point.  Uses the get_tree RPC to map visible buffer position
to entry ID, handling compaction (compacted-away turns aren't rendered,
so the last-N visible headings are aligned to the active branch).

Also fixes chat navigation (n/p): the old pattern searched for the
never-present "You:" instead of setext headings, and now recenters
the heading to the top of the window.

Changes:
- Setext heading detection: regex + underline predicate, shared across
  navigation and fork-at-point
- Turn detection: collect headings, map point to 0-based turn index
- Tree helpers: flatten-tree (hash index) and active-branch-user-ids
  (leaf-to-root walk)
- execute-fork: extracted shared fork logic (RPC + state refresh +
  history reload + input prefill), used by both fork-at-point and
  the menu fork selector
- resolve-fork-entry: tree-to-entryId mapping, independently testable
- build-tree test helper: flat specs replace deeply nested tree
  construction in tests

49 new tests covering heading detection, navigation, turn indexing,
tree walk scenarios, and fork-at-point integration.
@dnouri dnouri merged commit f5af70c into master Feb 13, 2026
6 of 7 checks passed
@dnouri dnouri deleted the fork-from-point branch February 13, 2026 21:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant