24. Session fork and branch summaries (Log-backed, inter-session)

Copy Markdown View Source

Date: 2026-06-19 Status: Accepted Implementation status: Fork write path, SessionTree projection, and deterministic --summarize shipped; model-assisted summarize deferred (#28)

Context

Pixir needs a Pi-inspired fork surface without adopting Pi's intra-file message tree or TUI /tree navigator (ADR 0017). CONTEXT.md already defines Fork as an inter-Session branch and Branch Summary as an optional lossy synthesis at fork creation — distinct from Pi's /tree trigger and from Compaction.

ADR 0020 fixed prompt-cache routing so fork_root_session_id can keep a fork tree on one s_ family, but no producer sets that field yet. Issue #29 tracks the CLI-first slice.

Decision

1. Inter-session fork only. ./pixir fork <parent-session-id> creates a new child Session Log by replaying a prefix of the parent's canonical Events. Pixir does not add parent_event_id pointers inside a single Log.

2. Canonical session_fork at seq 0 in the child Log. The first durable Event records lineage: parent_session_id, fork_root_session_id, forked_to_seq, workspaces, replay_event_count, and strategy: "replay_v1". Sequence numbering stays 0-based like today's Sessions.

3. Replay copy rules. Copy conversational canonical types through forked_to_seq. Exclude provider_usage (audit evidence, never model context), history_compaction (parent checkpoint ranges do not survive child renumbering until a rewrite slice), existing session_fork, and branch_summary. Copied Events get new id, child session_id, and child seq starting at 1; content data is preserved. Referenced Session Resource payloads are copied into the child store when present.

4. fork_root_session_id. Child inherits the parent's fork root when the parent Log contains session_fork; otherwise the root is parent_session_id. Child Turns must forward this into Provider cache metadata (Session start_turn follow-up).

5. branch_summary. Separate canonical type, optional via --summarize. When present it is recorded after the replayed prefix in the child Log and is interpretive Provider context with explicit limitations; it does not delete or replace replayed prefix Events. The first slice uses deterministic_operational_summary_v1; model-assisted summarize remains deferred (#28). Dry-run reports would_record_branch_summary.

6. CLI contract (ADR 0005). pixir fork <parent> [--to-seq N] [--summarize] [--dry-run] [--json]. Default to_seq is the highest seq among replayable parent Events (full conversational prefix). Same workspace as parent. Parent Log is read-only.

7. Session Tree. Fork children are discovered by scanning workspace Logs for session_fork.parent_session_id — a read-only projection, not a replay index.

Consequences

  • Forks share warm prompt-cache families when prefixes match (ADR 0020).
  • Child Logs are self-describing for resume/fork/debug without a sidecar header file.
  • Log duplication is accepted for audit clarity; compaction remains the path to bound Provider input on long child Sessions.
  • Branch summary at fork time is intentionally different from Pi /tree navigation.

Non-goals

  • No intra-Log sibling branches or TUI /tree navigator.
  • No ACP session/fork in this slice.
  • No parent Log mutation, merge-back, or deletion.
  • No model-assisted --summarize until #28.
  • branch_summary Provider fold is minimal in the deterministic slice; richer shaping may follow model-assisted summarize (#28).

Verification Direction

mix test test/pixir/fork_test.exs
mix test test/pixir/event_test.exs
mix test test/pixir/cli_test.exs
mix test

Regression coverage should prove:

  • session_fork and branch_summary are canonical types.
  • pixir fork --dry-run --json returns structured plan without mutating Logs.
  • Write path creates child Log with session_fork at seq 0 and replayed prefix.
  • provider_usage and history_compaction are excluded from replay.
  • fork_root_session_id inherits from parent fork lineage.
  • forked child Sessions keep referenced resource payloads addressable.
  • pixir tree --json discovers fork children from session_fork lineage metadata.

References

  • ADR 0004: unified Event envelope.
  • ADR 0017: Presenter boundary, no TUI tree.
  • ADR 0018: compaction is a separate lifecycle.
  • ADR 0020: fork-root cache family.
  • CONTEXT.md: Fork, Branch Summary, Session Tree.