From 898607f742460ed289d061404a1b8f4c7c4bf349 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Fri, 26 Dec 2025 02:49:01 +0100 Subject: [PATCH] Update session-tree-plan.md with remaining work --- .../coding-agent/docs/session-tree-plan.md | 132 ++++++++++++------ 1 file changed, 86 insertions(+), 46 deletions(-) diff --git a/packages/coding-agent/docs/session-tree-plan.md b/packages/coding-agent/docs/session-tree-plan.md index 5f2371df..6e45dd85 100644 --- a/packages/coding-agent/docs/session-tree-plan.md +++ b/packages/coding-agent/docs/session-tree-plan.md @@ -2,57 +2,40 @@ Reference: [session-tree.md](./session-tree.md) -## Phase 1: SessionManager Core +## Phase 1: SessionManager Core ✅ -- [x] Update entry types with `id`, `parentId` fields (using TreeNode intersection) +- [x] Update entry types with `id`, `parentId` fields (using SessionEntryBase) - [x] Add `version` field to `SessionHeader` - [x] Change `CompactionEntry.firstKeptEntryIndex` → `firstKeptEntryId` - [x] Add `BranchSummaryEntry` type -- [x] Add `byId: Map` index +- [x] Add `CustomEntry` type for hooks +- [x] Add `byId: Map` index - [x] Add `leafId: string` tracking - [x] Implement `getPath(fromId?)` tree traversal +- [x] Implement `getTree()` returning `SessionTreeNode[]` - [x] Implement `getEntry(id)` lookup -- [x] Implement `getLeafId()` helper +- [x] Implement `getLeafUuid()` and `getLeafEntry()` helpers - [x] Update `_buildIndex()` to populate `byId` map -- [x] Update `saveMessage()` to include id/parentId (returns id) -- [x] Update `saveCompaction()` signature and fields (returns id) -- [x] Update `saveThinkingLevelChange()` to include id/parentId (returns id) -- [x] Update `saveModelChange()` to include id/parentId (returns id) +- [x] Rename `saveXXX()` to `appendXXX()` (returns id, advances leaf) +- [x] Add `appendCustomEntry(customType, data)` for hooks - [x] Update `buildSessionContext()` to use `getPath()` traversal -### Type Hierarchy - -```typescript -// 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 +## Phase 2: Migration ✅ - [x] Add `CURRENT_SESSION_VERSION = 2` constant -- [x] Implement `_migrateToV2()` for v1→v2 +- [x] Implement `migrateV1ToV2()` with extensible migration chain - [x] Update `setSessionFile()` to detect version and migrate - [x] Implement `_rewriteFile()` for post-migration persistence - [x] Handle `firstKeptEntryIndex` → `firstKeptEntryId` conversion in migration -## Phase 3: Branching +## Phase 3: Branching ✅ -- [x] Implement `branchInPlace(id)` - switch leaf pointer +- [x] Implement `branch(id)` - switch leaf pointer - [x] Implement `branchWithSummary(id, summary)` - create summary entry -- [x] Update `branchToNewFile()` to use IDs (no remapping) -- [ ] Update `AgentSession.branch()` to use new API +- [x] Implement `createBranchedSession(leafId)` - extract path to new file +- [x] Update `AgentSession.branch()` to use new API -## Phase 4: Compaction Integration +## Phase 4: Compaction Integration ✅ - [x] Update `compaction.ts` to work with IDs - [x] Update `prepareCompaction()` to return `firstKeptEntryId` @@ -60,27 +43,84 @@ type CompactionEntry = TreeNode & CompactionContent; - [x] Update `AgentSession` compaction methods - [x] Add `firstKeptEntryId` to `before_compact` hook event -## Phase 5: Testing +## 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 -- [x] Update existing tests for new types +- [x] `migration.test.ts` - v1 to v2 migration, idempotency +- [x] `build-context.test.ts` - context building with tree structure, compaction, branches +- [x] `tree-traversal.test.ts` - append operations, getPath, getTree, branching +- [x] `file-operations.test.ts` - loadEntriesFromFile, findMostRecentSession +- [x] `save-entry.test.ts` - custom entry integration +- [x] Update existing compaction 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) +## Remaining Work + +### Compaction Refactor + +- [ ] Clean up types passed to hooks (currently messy mix of `CompactionEntry`, `CompactionResult`, hook's `compaction` content) +- [ ] Ensure consistent API between what hooks receive and what they return + +### Branch Summary Design + +Current type: +```typescript +export interface BranchSummaryEntry extends SessionEntryBase { + type: "branch_summary"; + summary: string; +} +``` + +Questions to resolve: +- [ ] Add `abandonedLeafId` field to reference what was abandoned? +- [ ] Store metadata about why the branch happened? +- [ ] Who generates the summary - user, LLM, or both options? +- [ ] Design and implement branch summarizer +- [ ] Add tests for `branchWithSummary()` flow + +### Entry Labels + +- [ ] Add optional `label?: string` field to `SessionEntryBase` +- [ ] Allow users to label any entry +- [ ] Display labels in UI (tree view, path view) + +### HTML Export + +- [ ] Add collapsible sidebar showing full tree structure +- [ ] Allow selecting any node in tree to view that path +- [ ] Add "reset to session leaf" button +- [ ] Render full path (no compaction resolution needed) +- [ ] Responsive: collapse sidebar on mobile + +### UI Commands + +Design new commands based on refactored SessionManager: + +**`/branch`** - Current behavior (creates new session file from path) +- [ ] Review if this is still the right UX with tree structure +- [ ] Consider: should this use `createBranchedSession()` or `branch()`? + +**`/branch-here`** - In-place branching (new) +- [ ] Use `branch(id)` to move leaf pointer without creating new file +- [ ] Subsequent messages become new branch in same file +- [ ] Design: how to select branch point? (similar to current `/branch` UI?) + +**`/branches`** - List/navigate branches (new) +- [ ] Show tree structure or list of branch points +- [ ] Allow switching between branches (move leaf pointer) +- [ ] Show current position in tree + +**`/label`** - Label entries (new, if labels implemented) +- [ ] Allow labeling current or selected entry +- [ ] Display in tree view + +--- ## Notes -- All save methods return the new entry's ID +- All append 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 +- Session is append-only: entries cannot be modified or deleted, only branching changes the leaf pointer