Problem. Sessions are linear. No fork, no try-this-instead, no compare-two-replies, no place for an extension to persist state without polluting the LLM context.
Shape.
- Add columns to the message table in
crates/state/src/lib.rs:
parent_entry_id TEXT (null on first message = legacy linear)
current_leaf_id TEXT pointer on the thread row
message_type TEXT with values user, assistant, tool_result, custom, custom_message
- Add
StateStore::fork_at_message(message_id) → returns new leaf id.
- DDL migration; idempotent.
Acceptance.
- Migration runs cleanly on existing sessions.
- Unit test forks a 5-message session and proves both leaves are queryable independently.
- Existing reads return all legacy messages unchanged (parent_entry_id null behaves as the linear default).
Existing issues this resolves on PR merge
Partially addresses:
Related:
When opening a PR for this issue, the PR body must include the Closes #N lines for every issue above that this PR fully resolves, so they auto-close on merge.
Slate item 9/18. Tracking doc: .private/issue-slate.md (maintainer-only).
Problem. Sessions are linear. No fork, no try-this-instead, no compare-two-replies, no place for an extension to persist state without polluting the LLM context.
Shape.
crates/state/src/lib.rs:parent_entry_id TEXT(null on first message = legacy linear)current_leaf_id TEXTpointer on the thread rowmessage_type TEXTwith valuesuser,assistant,tool_result,custom,custom_messageStateStore::fork_at_message(message_id)→ returns new leaf id.Acceptance.
Existing issues this resolves on PR merge
Partially addresses:
Related:
When opening a PR for this issue, the PR body must include the
Closes #Nlines for every issue above that this PR fully resolves, so they auto-close on merge.Slate item 9/18. Tracking doc:
.private/issue-slate.md(maintainer-only).