Skip to content

relayburn-reader: port parseClaudeSessionIncremental to Rust (#255)#265

Merged
willwashburn merged 1 commit into
mainfrom
claude/port-claude-incremental-rust
May 4, 2026
Merged

relayburn-reader: port parseClaudeSessionIncremental to Rust (#255)#265
willwashburn merged 1 commit into
mainfrom
claude/port-claude-incremental-rust

Conversation

@willwashburn

Copy link
Copy Markdown
Member

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.rs exports the same surface as parseClaudeSession / parseClaudeSessionIncremental / reconcileClaudeSessionRelationships").

Summary

  • parse_claude_session_incremental / parse_claude_session_incremental_with_counter — public entry points mirroring parseClaudeSessionIncremental in TS. Read from start_offset, compute end_offset as 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. Carry start_offset and last_user_text in; surface end_offset and last_user_text out so callers can drive multi-pass ingest.
  • prescan_nodes — port of TS prescanNodes. When start_offset > 0, pre-reads [0, start_offset) and seeds nodes_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 right call_index / event_index, and userTurns get their preceding_message_id populated 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 so pending_relationships can be filtered by end_offset at emit time.
  • Re-exports the new surface from 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 per it() case in the describe('parseClaudeSessionIncremental', ...) block of packages/reader/src/claude.test.ts:478-985:

  • 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
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)

  • The non-incremental parity sweep across the rest of 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-targets
  • cargo test -p relayburn-reader --lib (124 pass)
  • cargo test --workspace
  • Existing 113 reader tests still pass

🤖 Generated with Claude Code

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>
@willwashburn willwashburn merged commit 5142aa2 into main May 4, 2026
2 checks passed
@willwashburn willwashburn deleted the claude/port-claude-incremental-rust branch May 4, 2026 21:59
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