relayburn-reader: port parseClaudeSessionIncremental to Rust (#255)#265
Merged
Conversation
Adds the byte-offset resumable Claude parser to `crates/relayburn-reader/src/claude.rs`, mirroring `parseClaudeSessionIncremental` in `packages/reader/src/claude.ts`. PR #262 landed the synchronous core; this finishes the public surface called out in #255 acceptance gate 3. ## What's new - `parse_claude_session_incremental` / `_with_counter` — the public entry points. Read from `start_offset`, back `end_offset` up to the byte position of the earliest in-progress assistant message, and filter every offset-tagged buffer (events / relationships / tool-result events / user turns / content) so a resumed call doesn't double-emit. - `ParseIncrementalOptions` / `ParseIncrementalResult` — the option / result types. Carry `start_offset` and `last_user_text` in, surface `end_offset` and `last_user_text` out. - `prescan_nodes` — pre-reads `[0, start_offset)` on resume to seed `nodes_by_uuid`, evidence, tool-result counters, the next event index, and the last assistant messageId so sidechain turns landing in the resumed region can still resolve their invocation tree, system notifications get the right call/event indices, and userTurns get their `precedingMessageId` populated even when the prior assistant was already ingested. - `record_root_incremental` / `collect_explicit_claude_relationships_incremental` — offset-tagged variants of the sync-flow root + explicit-fork/continuation collectors. ## Conformance 11 new tests against the shared `tests/fixtures/claude/` JSONL fixtures — one per `it()` case in the `describe('parseClaudeSessionIncremental', ...)` block of `packages/reader/src/claude.test.ts`: - `incremental_reads_whole_file_from_start` - `incremental_returns_zero_turns_when_start_at_eof` - `incremental_appended_turn_emitted_on_resume` - `incremental_defers_in_progress_trailing_message` - `incremental_defers_content_for_in_progress_then_emits_after_completion` - `incremental_defers_assistant_content_after_in_progress_message` - `incremental_skips_incomplete_turn_then_emits_when_completion_arrives` - `incremental_preserves_user_prompt_across_resume` - `incremental_user_turns_emitted_once_across_resumed_passes` - `incremental_seeds_tool_result_event_counters_from_prescan` - `incremental_resolves_subagent_tree_via_prescan` `cargo test -p relayburn-reader --lib` now reports 124 passing (113 → 124). The remaining sync-flow parity sweep across the rest of `claude.test.ts` (content capture, fork/continuation, user-turn block sizes) stays as the follow-up tracked under #255. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes-progress-on #255.
Continues the Rust port of
packages/reader/src/claude.ts. PR #262 landed the synchronous core (parse_claude_session+reconcile_claude_session_relationships). This PR fills in the byte-offset resumable variant called out in the issue's acceptance gate ("claude.rsexports the same surface asparseClaudeSession/parseClaudeSessionIncremental/reconcileClaudeSessionRelationships").Summary
parse_claude_session_incremental/parse_claude_session_incremental_with_counter— public entry points mirroringparseClaudeSessionIncrementalin TS. Read fromstart_offset, computeend_offsetas the byte position of the earliest in-progress assistant message (or the cursor past the last complete newline), and filter every offset-tagged buffer so a resumed call doesn't double-emit.ParseIncrementalOptions/ParseIncrementalResult— the option / result types. Carrystart_offsetandlast_user_textin; surfaceend_offsetandlast_user_textout so callers can drive multi-pass ingest.prescan_nodes— port of TSprescanNodes. Whenstart_offset > 0, pre-reads[0, start_offset)and seedsnodes_by_uuid, evidence, tool-result counters, the next event index, and the last assistant messageId so sidechain turns discovered in the resumed region still resolve their invocation tree, system notifications get the rightcall_index/event_index, and userTurns get theirpreceding_message_idpopulated even when the prior assistant was already ingested.record_root_incremental+collect_explicit_claude_relationships_incremental— small offset-tagged variants of the sync-flow root + explicit-fork/continuation collectors sopending_relationshipscan be filtered byend_offsetat emit time.crates/relayburn-reader/src/lib.rs.The synchronous parser, reconciler, and all existing tests are untouched.
Conformance
11 new lib tests against the shared
tests/fixtures/claude/JSONL fixtures — one perit()case in thedescribe('parseClaudeSessionIncremental', ...)block ofpackages/reader/src/claude.test.ts:478-985:incremental_reads_whole_file_from_startincremental_returns_zero_turns_when_start_at_eofincremental_appended_turn_emitted_on_resumeincremental_defers_in_progress_trailing_messageincremental_defers_content_for_in_progress_then_emits_after_completionincremental_defers_assistant_content_after_in_progress_messageincremental_skips_incomplete_turn_then_emits_when_completion_arrivesincremental_preserves_user_prompt_across_resumeincremental_user_turns_emitted_once_across_resumed_passesincremental_seeds_tool_result_event_counters_from_prescanincremental_resolves_subagent_tree_via_prescan```
$ cargo test -p relayburn-reader --lib
test result: ok. 124 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
```
(113 → 124 — no existing test broken.)
Not in this PR (still tracked under #255)
claude.test.ts— fork/continuation reconciliation cases, user-turn block sizes, content capture variants. The fixtures already exist; the gap is Rust assertion code, not parser behavior. Landing iteratively keeps each PR reviewable.Test plan
cargo build --workspace --all-targetscargo test -p relayburn-reader --lib(124 pass)cargo test --workspace🤖 Generated with Claude Code