release #5582: keep fork children out of compression stitch - #5625
Conversation
_webui_sidecar_lineage_messages_for_display stitches a session's pre-compression snapshot parents for full-transcript display. A cleared fork child could resurrect its ORIGINAL (non-fork) parent's transcript when that parent was later compressed. Now, when the root session is itself a fork (session_source=='fork'), the stitch walk allows fork-sourced snapshot parents but stops at the first non-fork ancestor — so a compressed fork continuation still shows its own pre-compression turns, while an ordinary fork child stays isolated from the original parent. Additive guard (one extra break condition); non-fork lineage display unchanged. Contributor stage; gate-pass. Co-authored-by: rodboev <rodboev@users.noreply.github.com>
|
| Filename | Overview |
|---|---|
| api/routes.py | Two lines + one break added to _webui_sidecar_lineage_messages_for_display; non-fork path is entirely unchanged, and the guard is safely gated behind root_is_fork. |
| tests/test_session_lineage_full_transcript.py | Four new tests added: two cover the fixed function directly (fork-with-snapshot-parent isolation, multiply-compressed-fork stitching), and two are regression guards for the already-correct _merged_webui_lineage_messages_for_display isolation path. |
| CHANGELOG.md | Release changelog entry prepended; accurate description of the fix and attribution. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Start: root session] --> B[Read session_source\nroot_is_fork = source == 'fork']
B --> C{Loop: next parent_id}
C -->|no parent_id / seen / unsafe| DONE[Return merged segments]
C --> D[Session.load parent_id]
D -->|not found or\nnot pre_compression_snapshot| DONE
D --> E{root_is_fork AND\nparent_source != 'fork'?}
E -->|Yes| DONE
E -->|No| F{segments empty AND\nmessages already have prefix?}
F -->|Yes| EARLY[Return session_messages as-is]
F -->|No| G[Append parent to segments\ncurrent = parent]
G --> C
DONE --> H{segments empty?}
H -->|Yes| I[Return session.messages]
H -->|No| J[Reverse-merge all segments\n+ append session messages]
J --> K[Return stitched transcript]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[Start: root session] --> B[Read session_source\nroot_is_fork = source == 'fork']
B --> C{Loop: next parent_id}
C -->|no parent_id / seen / unsafe| DONE[Return merged segments]
C --> D[Session.load parent_id]
D -->|not found or\nnot pre_compression_snapshot| DONE
D --> E{root_is_fork AND\nparent_source != 'fork'?}
E -->|Yes| DONE
E -->|No| F{segments empty AND\nmessages already have prefix?}
F -->|Yes| EARLY[Return session_messages as-is]
F -->|No| G[Append parent to segments\ncurrent = parent]
G --> C
DONE --> H{segments empty?}
H -->|Yes| I[Return session.messages]
H -->|No| J[Reverse-merge all segments\n+ append session messages]
J --> K[Return stitched transcript]
Reviews (1): Last reviewed commit: "release #5582: keep fork children out of..." | Re-trigger Greptile
Release: #5582 — keep fork children out of compression stitch (#5571)
Contributor @rodboev; gate-pass. Rebuilt on current
master, fresh-gated.The bug (#5571)
_webui_sidecar_lineage_messages_for_displaystitches a session's pre-compression snapshot parents for full-transcript display. A cleared/compressed fork child could resurrect its original non-fork parent's transcript once that parent was later compressed.The fix
When the root session is itself a fork (
session_source=='fork'), the parent-walk now allows fork-sourced snapshot parents but stops at the first non-fork ancestor. So a compressed fork continuation still shows its own pre-compression turns, while an ordinary fork child stays isolated from the original parent. Additive guard (one extrabreakcondition); non-fork lineage display is byte-identical.Gate (green)
root_is_forkis false); no legitimate fork-sourced turns dropped; the legacy missing-session_sourceedge falls back to prior behavior (not a regression); no seen-set/loop issue. Display-only path, no writes.Attribution: original author @rodboev (
Co-authored-bypreserved).Closes #5582
Closes #5571