Skip to content

fix(claude): .orphaned-* segments no longer vanish from chained conversations - #237

Open
bdelanghe wants to merge 2 commits into
mainfrom
fix/orphaned-chain-stems
Open

fix(claude): .orphaned-* segments no longer vanish from chained conversations#237
bdelanghe wants to merge 2 commits into
mainfrom
fix/orphaned-chain-stems

Conversation

@bdelanghe

@bdelanghe bdelanghe commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Defect 2 from the #236 root-cause analysis (#236 (comment)).

ChainIndex::refresh classified any stem whose first entry carried a foreign sessionId as a chain successor. Rotation artifacts (<uuid>.orphaned-<ts>-<hash>) always do — their entries keep the original session's id while the stem is mangled — so they were chained in, whereupon is_bridge_entry matched every entry of the segment and the merge dropped the whole thing: turns and token_usage silently gone, while claude_chain_stamp still summed the segment's bytes into the freshness stamp. A session stem never contains a dot; dotted stems now stand alone as their own conversations.

Second, read_conversation applied the bridge filter to every entry of every segment, though bridge entries are only ever the predecessor's tail copied to the top of a successor file (as chain.rs's own docs say). The filter now skips only the leading bridge run — a foreign sessionId deeper in a segment is data, kept.

toolpath-claude 0.13.0 → 0.13.1 (crate + workspace Cargo.toml, site/_data/crates.json, CHANGELOG).

Run sheet

  1. Independent PR — no bundled or speculative changes
  2. Changed codepaths verified — targeted unit and full integration tests
    • test_orphaned_stem_is_not_a_successor (new), test_bridge_skip_is_leading_run_only (new), full cargo test -p toolpath-claude — 259 green
    • path-cli integration: 42 passed / 20 failed identically on unmodified main in the same local nix-shell env — pre-existing environment failures, not regressions; this CI run is the arbiter
  3. Root cause identified — every failure traced to source
    • Orphaned stems misread as successors (chain.rs:94-101) + bridge filter applied beyond the leading run (lib.rs:156-161); live repro: 50357658-….orphaned-1787626221622-ac84712d.jsonl, 8 entries, all silently dropped
  4. No duplication — refactoring preferred over copy/paste
    • N/A — filter logic tightened in place
  5. No unrelated changes — housekeeping isolated to its own branch
    • Version-bump files are the required release checklist for the fix itself

🤖 Generated with Claude Code

https://claude.ai/code/session_01EbQMJRxBqTQyP7nE7qqzsr


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…rsations

Two related fixes in chain handling (#236, defect 2):

ChainIndex::refresh classified any stem whose first entry carried a
foreign sessionId as a chain successor. Rotation artifacts
(`<uuid>.orphaned-<ts>-<hash>`) always do — their entries keep the
original session's id while the stem is mangled — so they were chained
in, whereupon is_bridge_entry matched every entry of the segment and
the merge dropped the whole thing: turns and token_usage silently gone
while claude_chain_stamp still counted its bytes. A session stem never
contains a dot; dotted stems now stand alone as their own conversations.

read_conversation applied the bridge filter to every entry of every
segment, though bridge entries are only ever the predecessor tail
copied to the top of a successor file. The filter now skips only the
leading bridge run, so a foreign sessionId deeper in a segment is data,
not a discard.

toolpath-claude 0.13.0 → 0.13.1 (Cargo.tomls, crates.json, CHANGELOG).

Verified: cargo test -p toolpath-claude — 259 tests green including the
two new cases (orphaned stem stays unchained; mid-segment foreign id is
kept). path-cli integration suite: 42 passed / 20 failed both on this
branch AND on unmodified main in the same local nix-shell env —
pre-existing environment failures, not regressions; CI is the arbiter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EbQMJRxBqTQyP7nE7qqzsr
@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown

🔍 Preview deployed: https://eb632988.toolpath.pages.dev

@bdelanghe
bdelanghe marked this pull request as ready for review August 25, 2026 16:55
@bdelanghe
bdelanghe marked this pull request as draft August 25, 2026 17:05
Standalone orphans must not become listed conversations yet: a derived
document id truncates the stem to its first 8 characters, which for
`<uuid>.orphaned-*` equals the parent session's prefix — the orphan doc
and the full session doc would overwrite each other in the cache
(defect 3 interaction, caught against the kind spec's summing
guarantee). Orphans are now neither chained nor listed; read_segment
reads them directly. Ingestion arrives with the full-stem id work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EbQMJRxBqTQyP7nE7qqzsr
@bdelanghe

Copy link
Copy Markdown
Collaborator Author

Amended after checking the fix against the kind spec (toolpath.net/kinds/agent-coding-session/v1.1.0): as first pushed, standalone orphans would have become listed conversations, and derive_path truncates the view id to 8 chars — for <uuid>.orphaned-* that's the parent session's prefix, so the orphan doc and the full session doc would have overwritten each other in the cache (a defect-3 interaction the spec's Σ-guarantee makes obvious). Dotted stems are now excluded from chain_heads() too: neither chained (the data-loss bug) nor listed (the collision). read_segment reads them directly; ingesting them lands with the full-stem id work. New assertion added to test_orphaned_stem_is_not_a_successor.

@bdelanghe
bdelanghe marked this pull request as ready for review August 25, 2026 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant