You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(sessions): fork a session — the what-if branch
The largest designed-but-unbuilt piece of the triad. §313: "resume a copy from
any point, leaving the original intact — the what-if-I'd-told-it-to-do-X-instead
branch." Fork-from-END, as §411 settles the scoping: per-turn fork needs a
transcript picker, which is separate work.
WHICH EVENTS TRAVEL is the entire design, and the answer is not "all of them":
user / agent / assistant YES — this is the conversation being forked
title YES, then overridden, so the fork is not a second
row with an identical name
end NO — that is the ORIGINAL's terminal state. Copying
it renders a live fork as `done` while you type
label NO — lifecycle and pinning are the original's. A
fork of an archived session must arrive visible, and
must not silently take a second pin
The copy records `forkedFrom` in its meta — §4 provenance, and what a later
branch-graph draws from. The key is written ONLY on a fork, so every existing
session file stays byte-identical and an older build reading a forked session
simply does not know it was forked rather than failing to read it.
A fork IS a resume, into a copy, so the handler calls resumeSession() on the new
id rather than duplicating the replay, the budget planning, or the honest
"resumed from a summary" note.
The sixth card button: labels now collapse below 420px (chat) / 400px (panel),
up from 360/340 — six labelled buttons need ~370px against five at ~300px, and
the row is nowrap so overshoot overflows rather than wraps. The guard added with
export already covered this; only the threshold moved.
Tests: 8 in sessions.test.js against a fixture that is sealed AND archived AND
pinned — every state a fork must not inherit. Verified non-vacuous:
copy the end event 20/25 copy label events 20/25
drop the (fork) suffix 21/25 drop provenance 22/25
do not go live 23/25
All 32 suites green.
One test bug worth recording: `m.list().find(e => e.id === m.fork(id))` calls
fork() once per row against a list fetched before any fork existed. Hoisted.
Copy file name to clipboardExpand all lines: docs/levelcode-sessions-experience.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -310,7 +310,7 @@ Global rule: **nothing animates on scroll at all** — the sparkline lives in th
310
310
311
311
Beyond the card and the search, the "wow" list — each grounded in the JSONL substrate so it's cheap to build:
312
312
313
-
-**Fork a session**(`⇧⏎`) — resume a *copy*from any point, leaving the original intact. The "what if I'd told it to do X instead" branch. Cursor's checkpoints rewind *files*; forking rewinds the *conversation*. Both, together, is new.
313
+
-**Fork a session**✅ *(fork-from-end shipped)* — resume a *copy*, leaving the original intact. `sessions.fork()` seeds a new session with the original's conversation and **drops its `end` and `label` events**: a copied `end` would render a live fork as `done` while you typed into it, and a copied `label` would have a fork of an archived session born invisible in the default Active scope, or silently taking a second pin. The copy is titled `… (fork)`, records `forkedFrom` in its meta (§4 provenance, and what a later branch-graph would draw from), and becomes live — a fork *is* a resume, into a copy, so it reuses the resume path wholesale. Per-turn fork still awaits the transcript picker (§411). The "what if I'd told it to do X instead" branch. Cursor's checkpoints rewind *files*; forking rewinds the *conversation*. Both, together, is new.
314
314
-**Files-touched search & chips** (§4.2/4.4) — find work by what it changed. The structural lead over Cursor.
315
315
-**Activity sparkline** (§4.2) — session *shape* at a glance.
316
316
-**The honesty layer as UI** — interrupted / reloaded / summarized states are pills and strips, not silence (§4.5, §4.7).
0 commit comments