Skip to content

Improve Rust SDK query ergonomics#322

Merged
willwashburn merged 5 commits intomainfrom
codex/rust-sdk-idioms
May 7, 2026
Merged

Improve Rust SDK query ergonomics#322
willwashburn merged 5 commits intomainfrom
codex/rust-sdk-idioms

Conversation

@willwashburn
Copy link
Copy Markdown
Member

Summary

  • add the Rust SDK compare verb, typed result shape, NAPI binding, and coverage in the ten-verb integration test
  • add ledger enrichment filtering so workflow/agent filters compose through Query instead of post-hoc scans
  • thread explicit ledger_home through ingest config and pending-stamp sidecars, and wire ghost-surface findings into Rust hotspots

Tests

  • cargo test --workspace
  • cargo clippy --workspace --all-targets (passes with existing repo warnings)

Wire `burn overhead` and `burn overhead trim` as thin presenters over
`relayburn_sdk::overhead` / `::overhead_trim`. Output (human + `--json`)
is byte-equivalent with the TS CLI; the four overhead golden invocations
flip to `enabled: true`.

To make the JSON shape match TS, widen `OverheadAttributionDetail` to
include `totalTokens` + `sessionCosts` (in TS field order) and let
`OverheadSectionCost.section` carry the full `MarkdownSection` rather
than a slim projection. The CLI's `--json` writer post-processes
integer-valued `f64`s back to bare integers (`0` not `0.0`) so the
golden snapshots stay byte-identical to `JSON.stringify` output.

Smoke test: drop `overhead` from the not-yet-implemented gate.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

📝 Walkthrough

Walkthrough

Adds a new synchronous compare verb to the SDK (with LedgerHandle and free-function forms), threads an optional ledger_home through ingest/pending-stamp flows, enforces query enrichment filtering, exposes Node N-API bindings for compare with BigInt promotion, and serializes fidelity summaries for JSON output.

Changes

Compare verb, ingest scoping, query enrichment, and Node bindings

Layer / File(s) Summary
Data Shape / Serialization
crates/relayburn-sdk/src/analyze/fidelity.rs
FidelitySummary now derives serde::Serialize with #[serde(rename_all = "camelCase")].
Query Shape
crates/relayburn-sdk/src/ledger/query.rs
Query gains enrichment: Option<Enrichment> to filter by stamp enrichment.
Query Filtering
crates/relayburn-sdk/src/ledger/reader.rs
turn_passes now enforces q.enrichment by requiring exact key/value matches on a turn's enrichment map.
Compare Implementation
crates/relayburn-sdk/src/query_verbs.rs
Introduces CompareOptions, compare result types (CompareResult, CompareFidelityBlock, CompareCellResult, CompareModelTotal, etc.), LedgerHandle::compare, free compare(opts), fidelity filtering, provider/model filtering, table construction, rounding, and excluded-fidelity breakdown; adds unit tests for validation, structure, and enrichment filtering.
Ingest Scoping
crates/relayburn-sdk/src/ingest/pending_stamps.rs
Adds WriteOptions.ledger_home: Option<PathBuf>, functions to compute pending-stamps dir for an explicit ledger home, scoped cleanup/listing (*_in variants), and session-resolution helpers that accept ledger_home; includes unit test covering explicit home.
Ingest Wiring
crates/relayburn-sdk/src/ingest/ingest.rs, crates/relayburn-sdk/src/ingest_verb.rs
IngestOptions gains ledger_home: Option<PathBuf>; resolve_content_mode and pending-stamp resolution accept an optional ledger home; LedgerHandle::ingest fills opts.ledger_home from the open ledger when omitted; tests updated to pass explicit ledger_home and remove RELAYBURN_HOME use.
Node.js Bindings / BigInt Promotion
crates/relayburn-sdk-node/src/lib.rs
Expands BIGINT_FIELDS with compare-related u64 keys; adds CompareOptions N-API type and exported compare(opts) binding that parses min_fidelity, converts optional min_sample BigInt→u64, calls sdk::compare, serializes via serde_json, and returns BigIntPromoting.
Exports & Docs
crates/relayburn-sdk/src/lib.rs
Public re-exports extended to include compare-related analysis types and docs updated to reflect ten verbs.
CLI, Tests & Minor Formatting
crates/relayburn-cli/src/commands/compare.rs, crates/relayburn-cli/src/harnesses/pending_stamp.rs, crates/relayburn-sdk/tests/integration.rs
CLI import formatting adjusted; harness writes explicit ledger_home: None; integration test extended to exercise the compare verb (handle and free forms), includes content/stamp fixture writes, and other tests updated for BigInt export behavior and parse_fidelity_class coverage.
Small refactors/formatting
multiple files (reader.rs, lib.rs, Node binding mappings)
Minor reflows of function signatures/attributes and multi-line serde_json::to_value(...).map_err(...) refactors preserving behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant CompareVerb as compare()
    participant Query as Query Builder
    participant Ledger as Ledger Reader
    participant Enrichment as Enrichment Filter
    participant Result as Result Shaper

    Client->>CompareVerb: compare(models, provider?, workflow?, min_fidelity?, min_sample?)
    CompareVerb->>CompareVerb: validate ≥2 models
    CompareVerb->>Query: build_query(session?, provider?, enrichment?)
    Query->>Ledger: query_turns(q)
    Ledger->>Enrichment: evaluate turn enrichment
    Enrichment-->>Ledger: filtered turns
    Ledger-->>CompareVerb: EnrichedTurn[]
    CompareVerb->>CompareVerb: filter by fidelity >= min_fidelity and model/provider
    CompareVerb->>Result: build comparison table, round values, compute excluded breakdown
    Result-->>CompareVerb: CompareResult
    CompareVerb-->>Client: serialized CompareResult (BigInt-promoted for u64 fields)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • AgentWorkforce/burn#302: Threads ledger_home through ingest and LedgerHandle::ingest — closely related to ingest scoping changes.
  • AgentWorkforce/burn#309: Prior work on CLI compare and rendering helpers that this PR integrates with SDK compare.
  • AgentWorkforce/burn#301: Related edits to query_verbs.rs; overlaps with the new compare API and HotspotsResult changes.

Poem

🐰 I hopped through code with nimble paws,

Counted models, fenced the laws,
Ledger homes tucked neat and tight,
BigInts glowing in the night,
Compare now bounds the orchard's cause.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Improve Rust SDK query ergonomics' is vague and generic, not clearly describing the main changes (compare verb, enrichment filtering, ledger_home threading). Consider a more specific title that highlights the primary changes, such as 'Add compare verb and enrichment filtering to Rust SDK' or 'Add compare verb and ledger enrichment support to Rust SDK'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description directly relates to the changeset, covering the main additions: compare verb, enrichment filtering, ledger_home threading, and ghost-surface findings.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/rust-sdk-idioms

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 343ada00b7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/relayburn-sdk/src/ingest_verb.rs
# Conflicts:
#	CHANGELOG.md
#	crates/relayburn-cli/src/commands/overhead.rs
#	crates/relayburn-cli/src/main.rs
#	crates/relayburn-cli/tests/smoke.rs
#	crates/relayburn-sdk/src/ingest_verb.rs
#	crates/relayburn-sdk/src/lib.rs
#	crates/relayburn-sdk/src/query_verbs.rs
#	crates/relayburn-sdk/tests/integration.rs
#	tests/fixtures/cli-golden/ledger/.gitignore
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/relayburn-sdk/src/query_verbs.rs`:
- Around line 1370-1398: The code computes fidelity_summary and other metadata
from the full turns set before applying the models subset passed into
build_compare_table, causing top-level counts to mismatch cells/totals; modify
the flow so that the turns vector is filtered by the requested models
(opts.models) before calling summarize_fidelity_from_iter and before applying
min_fidelity filtering and build_compare_table. In practice, apply the models
filter to turns (using the same model-identification logic used by
build_compare_table/AnalyzeCompareOptions) immediately after the provider filter
step so that summarize_fidelity_from_iter, has_minimum_fidelity checks, and the
call to build_compare_table all operate on the same filtered turns set, then
pass that filtered turns into shape_compare_result.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: af6ca046-f2f5-4a36-802a-500d0919118f

📥 Commits

Reviewing files that changed from the base of the PR and between 343ada0 and 209dfd7.

📒 Files selected for processing (4)
  • crates/relayburn-cli/src/commands/compare.rs
  • crates/relayburn-sdk-node/src/lib.rs
  • crates/relayburn-sdk/src/lib.rs
  • crates/relayburn-sdk/src/query_verbs.rs
✅ Files skipped from review due to trivial changes (1)
  • crates/relayburn-cli/src/commands/compare.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/relayburn-sdk/src/lib.rs

Comment thread crates/relayburn-sdk/src/query_verbs.rs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/relayburn-cli/src/harnesses/pending_stamp.rs`:
- Around line 203-206: The PendingStampWriteOptions currently hard-codes
ledger_home: None which forces default-home behavior and can break resolution
when ingest uses a non-default ledger; update the creation of
PendingStampWriteOptions to propagate the explicit ledger_home used by the
harness/ingest instead of None (use the ledger_home field from the harness or
the context—e.g., the same ledger_home value passed to or stored on self.harness
or available on ctx) so that write and read directories remain consistent for
PendingStamp resolution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7413ac3f-9d74-4e50-acec-7593ebc1ea33

📥 Commits

Reviewing files that changed from the base of the PR and between 209dfd7 and 62a064d.

📒 Files selected for processing (3)
  • crates/relayburn-cli/src/harnesses/pending_stamp.rs
  • crates/relayburn-sdk/src/ingest/pending_stamps.rs
  • crates/relayburn-sdk/src/query_verbs.rs

Comment thread crates/relayburn-cli/src/harnesses/pending_stamp.rs
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
crates/relayburn-cli/src/harnesses/claude.rs (1)

148-151: 💤 Low value

Consider using explicit ledger_home for consistency with codex/opencode.

The claude adapter relies on LedgerOpenOptions::default() which picks up the RELAYBURN_HOME env var set by the driver. While this works, codex/opencode adapters use the explicit ctx.ledger_home field. For consistency, consider threading ctx.ledger_home through here as well.

This isn't a bug (env var fallback works correctly), but explicit propagation would make the data flow more visible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/relayburn-cli/src/harnesses/claude.rs` around lines 148 - 151, The
code opens the ledger with Ledger::open(LedgerOpenOptions::default()) which
relies on RELAYBURN_HOME env var; instead propagate ctx.ledger_home explicitly
by constructing LedgerOpenOptions with ledger_home set from ctx.ledger_home and
pass that to Ledger::open (retain subsequent calls to handle.raw_mut() and
ingest_claude_session). Update the call site where LedgerOpenOptions::default()
is used so Ledger::open receives an options struct created from ctx.ledger_home
to match codex/opencode patterns.
crates/relayburn-cli/src/harnesses/pending_stamp.rs (1)

378-389: 💤 Low value

Consider using tempfile crate for automatic cleanup.

The tempdir helper creates unique directories but relies on OS temp cleanup. For test isolation and avoiding accumulation of test artifacts, consider using the tempfile crate which provides automatic cleanup on drop.

That said, this is a minor improvement and the current approach works correctly for the test's purpose.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/relayburn-cli/src/harnesses/pending_stamp.rs` around lines 378 - 389,
Replace the manual tempdir helper with tempfile's TempDir: change the tempdir
function to return tempfile::TempDir and create the directory via
tempfile::Builder::new().prefix(&format!("burn-pending-stamp-{label}-{}",
std::process::id())).tempdir()? (or use .tempdir_in(std::env::temp_dir()) if you
want it under the OS temp dir); add tempfile to Cargo.toml, and update any
callers of tempdir (in this file) to either hold the TempDir so it isn't dropped
prematurely or use tempdir.path() while keeping the TempDir alive for the
lifetime of the test/harness. Ensure function name tempdir and its call sites
are updated to the new return type (tempfile::TempDir) so automatic cleanup
occurs on drop.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@crates/relayburn-cli/src/harnesses/claude.rs`:
- Around line 148-151: The code opens the ledger with
Ledger::open(LedgerOpenOptions::default()) which relies on RELAYBURN_HOME env
var; instead propagate ctx.ledger_home explicitly by constructing
LedgerOpenOptions with ledger_home set from ctx.ledger_home and pass that to
Ledger::open (retain subsequent calls to handle.raw_mut() and
ingest_claude_session). Update the call site where LedgerOpenOptions::default()
is used so Ledger::open receives an options struct created from ctx.ledger_home
to match codex/opencode patterns.

In `@crates/relayburn-cli/src/harnesses/pending_stamp.rs`:
- Around line 378-389: Replace the manual tempdir helper with tempfile's
TempDir: change the tempdir function to return tempfile::TempDir and create the
directory via
tempfile::Builder::new().prefix(&format!("burn-pending-stamp-{label}-{}",
std::process::id())).tempdir()? (or use .tempdir_in(std::env::temp_dir()) if you
want it under the OS temp dir); add tempfile to Cargo.toml, and update any
callers of tempdir (in this file) to either hold the TempDir so it isn't dropped
prematurely or use tempdir.path() while keeping the TempDir alive for the
lifetime of the test/harness. Ensure function name tempdir and its call sites
are updated to the new return type (tempfile::TempDir) so automatic cleanup
occurs on drop.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bec65118-3d12-4ee7-9e46-8a5d210e46e9

📥 Commits

Reviewing files that changed from the base of the PR and between 62a064d and 261470a.

📒 Files selected for processing (7)
  • crates/relayburn-cli/src/commands/run.rs
  • crates/relayburn-cli/src/harnesses/claude.rs
  • crates/relayburn-cli/src/harnesses/codex.rs
  • crates/relayburn-cli/src/harnesses/mod.rs
  • crates/relayburn-cli/src/harnesses/opencode.rs
  • crates/relayburn-cli/src/harnesses/pending_stamp.rs
  • crates/relayburn-cli/src/harnesses/registry.rs

@willwashburn willwashburn merged commit e3feb7b into main May 7, 2026
8 checks passed
@willwashburn willwashburn deleted the codex/rust-sdk-idioms branch May 7, 2026 03:08
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