co-mono/packages/coding-agent/docs/session-tree-plan.md
Mario Zechner c58d5f20a4 Session tree structure with id/parentId linking
- Add TreeNode base type with id, parentId, timestamp
- Add *Content types for clean input/output separation
- Entry types are now TreeNode & *Content intersections
- SessionManager assigns id/parentId on save, tracks leafId
- Add migrateSessionEntries() for v1 to v2 conversion
- Migration runs on load, rewrites file
- buildSessionContext() uses tree traversal from leaf
- Compaction returns CompactionResult (content only)
- Hooks return compaction content, not full entries
- Add firstKeptEntryId to before_compact hook event
- Update mom package for tree fields
- Better error messages for compaction failures
2025-12-30 22:42:17 +01:00

3.2 KiB

Session Tree Implementation Plan

Reference: session-tree.md

Phase 1: SessionManager Core

  • Update entry types with id, parentId fields (using TreeNode intersection)
  • Add version field to SessionHeader
  • Change CompactionEntry.firstKeptEntryIndexfirstKeptEntryId
  • Add BranchSummaryEntry type
  • Add byId: Map<string, ConversationEntry> index
  • Add leafId: string tracking
  • Implement getPath(fromId?) tree traversal
  • Implement getEntry(id) lookup
  • Implement getLeafId() helper
  • Update _buildIndex() to populate byId map
  • Update saveMessage() to include id/parentId (returns id)
  • Update saveCompaction() signature and fields (returns id)
  • Update saveThinkingLevelChange() to include id/parentId (returns id)
  • Update saveModelChange() to include id/parentId (returns id)
  • Update buildSessionContext() to use getPath() traversal

Type Hierarchy

// Tree fields (added by SessionManager)
interface TreeNode { id, parentId, timestamp }

// Content types (for input)
interface MessageContent { type: "message"; message: AppMessage }
interface CompactionContent { type: "compaction"; summary; firstKeptEntryId; tokensBefore }
// etc...

// Full entry types (TreeNode & Content)
type SessionMessageEntry = TreeNode & MessageContent;
type CompactionEntry = TreeNode & CompactionContent;
// etc...

Phase 2: Migration

  • Add CURRENT_SESSION_VERSION = 2 constant
  • Implement _migrateToV2() for v1→v2
  • Update setSessionFile() to detect version and migrate
  • Implement _rewriteFile() for post-migration persistence
  • Handle firstKeptEntryIndexfirstKeptEntryId conversion in migration

Phase 3: Branching

  • Implement branchInPlace(id) - switch leaf pointer
  • Implement branchWithSummary(id, summary) - create summary entry
  • Update branchToNewFile() to use IDs (no remapping)
  • Update AgentSession.branch() to use new API

Phase 4: Compaction Integration

  • Update compaction.ts to work with IDs
  • Update prepareCompaction() to return firstKeptEntryId
  • Update compact() to return CompactionResult with firstKeptEntryId
  • Update AgentSession compaction methods
  • Add firstKeptEntryId to before_compact hook event

Phase 5: Testing

  • Add test fixtures from existing sessions
  • Test migration of v1 sessions
  • Test context building with tree structure
  • Test branching operations
  • Test compaction with IDs
  • Update existing tests for new types

Phase 6: UI Integration

  • Update /branch command for new API
  • Add /branch-here command for in-place branching
  • Add /branches command to list branches (future)
  • Update session display to show tree info (future)

Notes

  • All save methods return the new entry's ID
  • Migration rewrites file on first load if version < CURRENT_VERSION
  • Existing sessions become linear chains after migration (parentId = previous entry)
  • Tree features available immediately after migration
  • SessionHeader does NOT have id/parentId (it's metadata, not part of tree)
  • Content types allow clean input/output separation