Commit e8af8c2
feat(phase 2): sibling-branch pruning on compress + rewind with notification (#70)
Phase 2 of the 6-phase plan. Reference pattern: opencode's
`packages/opencode/src/session/compaction.ts:386-396` — drop branches
outside the preserved tail with no special preservation. dirge adds
an explicit "discarded N forked branches" notification on top so the
user sees the loss instead of finding it later in `/tree`.
## Problem
When `Session::compress` (or `rewind_session`) drops messages from
the active path, any sibling branches whose parent nodes were among
the dropped ids end up with `tree.entries[child].parent` pointing
at a removed id. Subsequent `switch_to_leaf` / `/tree` walks
either fail silently or render dangling phantom branches.
Before Phase 2: dropped messages removed from tree + store, but
their forked descendants were left orphaned.
## Fix
New `Session::compress_reporting(summary, cut_idx, savings) -> usize`:
- Builds the to-drop set from active-path ids (`messages[..cut_idx]`).
- Builds an EXCLUSION set of currently-active ids (messages still
in `self.messages` after drain + summary insert) — without this
the new first-kept message gets caught because its parent is
still pointing at a dropped id at this point in the function.
- Fixed-point walk: each pass finds tree entries whose parent is
in `to_prune` but which aren't excluded, adds them; repeat until
no change. O(N * K) where K = avg branch depth.
- Prunes the union from `tree.entries` + `message_store`.
- Returns the count of non-active-path nodes pruned (subtracts
the direct dropped count) so the caller can notify.
`Session::compress` becomes a thin `#[cfg(test)]` wrapper that
calls `compress_reporting` and discards the count, kept for the
4 existing compress tests that didn't care about the count.
Mirror the same walk in `ui::mod.rs::rewind_session` — both paths
that prune active-path messages now also prune dependent siblings.
`handle_compress` (slash.rs) renders a red
`discarded N forked branch node(s) that were rooted in the
compressed region` line when the count is non-zero. Same for
rewind. opencode handles this silently; dirge surfaces it
because branched sessions are intentional and a silent loss
would surprise users.
## Tests
3 new session tests:
- `compress_prunes_sibling_branches_rooted_at_dropped_messages` —
builds a branched fixture (u1 → a1 → u2 → a2 with a sibling
subtree `sib1 → sib2` rooted at u1), compresses past u1, asserts
both sibs are gone from tree + store and the count is 2.
- `compress_reports_zero_pruned_when_no_siblings` — linear
session, count should be 0.
Plus the existing rewind tests still pass (the new prune logic
doesn't fire when there are no siblings, so linear rewind is
unaffected).
639 pass total (was 637), 0 warnings across all build profiles.
## Test plan
- [x] `cargo test --features plugin` -> 639 pass.
- [x] `cargo build --all-features` -> 0 warnings.
## Up next: Phase 3 (tool-call structured persistence)
When a session is resumed, prior tool calls + results are
currently lost (only assistant text is in `SessionMessage`). The
LLM sees text-only traces and may re-attempt the same tools.
Phase 3 will add structured `tool_calls: Vec<ToolCallEntry>` to
`SessionMessage` (opencode's `ToolPart` pattern with interrupted-
state pairing for Anthropic compatibility).
Co-authored-by: Yogthos <yogthos@gmail.com>1 parent d209366 commit e8af8c2
3 files changed
Lines changed: 243 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
550 | 550 | | |
551 | 551 | | |
552 | 552 | | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
553 | 558 | | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
554 | 577 | | |
555 | 578 | | |
556 | 579 | | |
| |||
593 | 616 | | |
594 | 617 | | |
595 | 618 | | |
596 | | - | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
597 | 676 | | |
598 | 677 | | |
599 | 678 | | |
| |||
653 | 732 | | |
654 | 733 | | |
655 | 734 | | |
| 735 | + | |
656 | 736 | | |
657 | 737 | | |
658 | 738 | | |
| |||
1163 | 1243 | | |
1164 | 1244 | | |
1165 | 1245 | | |
| 1246 | + | |
| 1247 | + | |
| 1248 | + | |
| 1249 | + | |
| 1250 | + | |
| 1251 | + | |
| 1252 | + | |
| 1253 | + | |
| 1254 | + | |
| 1255 | + | |
| 1256 | + | |
| 1257 | + | |
| 1258 | + | |
| 1259 | + | |
| 1260 | + | |
| 1261 | + | |
| 1262 | + | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
| 1274 | + | |
| 1275 | + | |
| 1276 | + | |
| 1277 | + | |
| 1278 | + | |
| 1279 | + | |
| 1280 | + | |
| 1281 | + | |
| 1282 | + | |
| 1283 | + | |
| 1284 | + | |
| 1285 | + | |
| 1286 | + | |
| 1287 | + | |
| 1288 | + | |
| 1289 | + | |
| 1290 | + | |
| 1291 | + | |
| 1292 | + | |
| 1293 | + | |
| 1294 | + | |
| 1295 | + | |
| 1296 | + | |
| 1297 | + | |
| 1298 | + | |
| 1299 | + | |
| 1300 | + | |
| 1301 | + | |
| 1302 | + | |
| 1303 | + | |
| 1304 | + | |
| 1305 | + | |
| 1306 | + | |
| 1307 | + | |
| 1308 | + | |
| 1309 | + | |
| 1310 | + | |
| 1311 | + | |
| 1312 | + | |
| 1313 | + | |
| 1314 | + | |
| 1315 | + | |
| 1316 | + | |
| 1317 | + | |
| 1318 | + | |
| 1319 | + | |
| 1320 | + | |
| 1321 | + | |
| 1322 | + | |
| 1323 | + | |
| 1324 | + | |
| 1325 | + | |
| 1326 | + | |
| 1327 | + | |
| 1328 | + | |
| 1329 | + | |
| 1330 | + | |
| 1331 | + | |
| 1332 | + | |
| 1333 | + | |
| 1334 | + | |
| 1335 | + | |
| 1336 | + | |
| 1337 | + | |
| 1338 | + | |
| 1339 | + | |
| 1340 | + | |
| 1341 | + | |
| 1342 | + | |
1166 | 1343 | | |
1167 | 1344 | | |
1168 | 1345 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3230 | 3230 | | |
3231 | 3231 | | |
3232 | 3232 | | |
3233 | | - | |
| 3233 | + | |
| 3234 | + | |
| 3235 | + | |
| 3236 | + | |
| 3237 | + | |
| 3238 | + | |
| 3239 | + | |
| 3240 | + | |
| 3241 | + | |
| 3242 | + | |
| 3243 | + | |
| 3244 | + | |
| 3245 | + | |
| 3246 | + | |
| 3247 | + | |
| 3248 | + | |
| 3249 | + | |
| 3250 | + | |
| 3251 | + | |
| 3252 | + | |
| 3253 | + | |
| 3254 | + | |
| 3255 | + | |
| 3256 | + | |
| 3257 | + | |
| 3258 | + | |
| 3259 | + | |
| 3260 | + | |
| 3261 | + | |
| 3262 | + | |
| 3263 | + | |
| 3264 | + | |
| 3265 | + | |
| 3266 | + | |
3234 | 3267 | | |
3235 | 3268 | | |
3236 | 3269 | | |
| 3270 | + | |
3237 | 3271 | | |
3238 | 3272 | | |
3239 | 3273 | | |
3240 | 3274 | | |
3241 | 3275 | | |
3242 | 3276 | | |
| 3277 | + | |
| 3278 | + | |
| 3279 | + | |
| 3280 | + | |
| 3281 | + | |
| 3282 | + | |
| 3283 | + | |
| 3284 | + | |
| 3285 | + | |
| 3286 | + | |
3243 | 3287 | | |
3244 | 3288 | | |
3245 | 3289 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
122 | 122 | | |
123 | 123 | | |
124 | 124 | | |
125 | | - | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
126 | 132 | | |
127 | 133 | | |
128 | 134 | | |
| |||
147 | 153 | | |
148 | 154 | | |
149 | 155 | | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
150 | 169 | | |
151 | 170 | | |
152 | 171 | | |
| |||
0 commit comments