Skip to content

feat(pipeline): add the typed-step pipeline tree with its foundational steps (R1a) - #735

Merged
nh13 merged 2 commits into
main-runallfrom
nh/runall-11-pipeline-steps
Aug 12, 2026
Merged

feat(pipeline): add the typed-step pipeline tree with its foundational steps (R1a)#735
nh13 merged 2 commits into
main-runallfrom
nh/runall-11-pipeline-steps

Conversation

@nh13

@nh13 nh13 commented Aug 10, 2026

Copy link
Copy Markdown
Member

Stacked on #734 (R0). Review that first; this PR's diff is against it.

Additive: nothing in src/lib/commands routes through the new tree, so every command still runs on unified_pipeline. No behaviour changes.

Why this is cheap

feat-runall's src/lib/pipeline/mod.rs does pub use fgumi_pipeline_core as core;. Every crate::pipeline::core::… path inside steps/ resolves through that shim, so the step sources compile unmodified — this is a near-verbatim port plus a module root, not a rewrite.

What

  • src/lib/pipeline/mod.rs — the core re-export shim + steps. (chains follows in a later PR; until it lands nothing routes here.)
  • src/lib/pipeline/steps/mod, types, tuning, and the sink/, sort/, bgzf/, boundaries/, parse/ subtrees.
  • src/lib/template.rsTemplate::heap_size lifted out of the MemoryEstimate impl so the pipeline can budget on it, with estimate_heap_size delegating. Separate commit.
  • Root Cargo.toml — depends on fgumi-pipeline-core and fgumi-pipeline-io. This edge did not previously exist: both crates had landed with no consumer.

Still to come: source/, group/, correct/, the closure-driven mid-steps, and align_and_merge (which needs crate::aligner, not yet ported).

Two deliberate deltas from feat-runall

Both are noted in the commit message:

  1. boundaries/bam.rs uses a let-chain instead of nested ifs. The source predates the toolchain that unlocked them and ci-lint rejects the nested form as collapsible_if. Per CLAUDE.md we adopt the idiom rather than suppress the lint.
  2. tuning.rs demotes an intra-doc link to a code span. [PipelineConfig::auto_tuned] resolves to unified_pipeline::base — the module this whole port exists to retire. Linking it would break again on deletion, so the reference is now prose.

Verification

Full local gate:

Risk: command output changes: none; unsafe: none, and CLAUDE.md allowlist unchanged; memory, queue, and backpressure policy: changed through Template::heap_size and typed-step byte limits. Fix: route the typed pipeline only after command-output parity is validated.

  • Added the foundational typed-step pipeline tree under src/lib/pipeline/.
  • Added BGZF compression and decompression, BAM boundary detection, BAM/SAM parsing, decoding, sorting, sinks, tuning, and pipeline data types.
  • Added re-export shims for pipeline core and IO implementations.
  • Exposed Template::heap_size; MemoryEstimate::estimate_heap_size now delegates to it.
  • Existing commands continue to use unified_pipeline.
  • Tests, formatting, linting, documentation, publishing checks, and crate checks pass: 8,234 tests passed and 30 skipped.

@nh13
nh13 temporarily deployed to github-actions August 10, 2026 00:51 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: dc282f86-0b4d-4db2-a2b5-b0438a676c4e

📥 Commits

Reviewing files that changed from the base of the PR and between 444bb61 and 8a51a99.

📒 Files selected for processing (2)
  • src/lib/pipeline/steps/boundaries/state.rs
  • src/lib/pipeline/steps/parse/bam.rs

Walkthrough

The root crate now exposes a typed pipeline framework with BGZF, BAM, and SAM processing steps, ordered batch types, tuning configuration, sink and sort re-exports, backpressure handling, validation, and capacity-based memory accounting.

Changes

Typed pipeline integration

Layer / File(s) Summary
Pipeline contracts and public data types
Cargo.toml, src/lib/..., src/lib/template.rs
The crate exposes pipeline modules, typed batches, tuning configuration, sink and sort APIs, and capacity-based heap accounting.
BGZF processing and BAM boundary detection
src/lib/pipeline/steps/bgzf/*, src/lib/pipeline/steps/boundaries/*
BGZF blocks are decompressed and compressed with ordered, byte-bounded steps. BAM headers and record boundaries are tracked across blocks with backpressure and EOF handling.
Record parsing and group-key decoding
src/lib/pipeline/steps/parse/*
BAM and SAM inputs are parsed into record batches. Records are validated, grouping keys and UMI positions are computed, and ordered outputs handle contention and completion.
End-to-end pipeline validation
src/lib/pipeline/steps/chain_tests.rs
Integration tests cover BAM and SAM chains, recompression, empty and headerless inputs, multi-thread execution, backpressure, and truncated records.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BgzfInput
  participant BgzfDecompress
  participant FindBamBoundaries
  participant ParseBamRecords
  participant DecodeRecords
  BgzfInput->>BgzfDecompress: BgzfBlock input
  BgzfDecompress->>FindBamBoundaries: DecompressedBlock output
  FindBamBoundaries->>ParseBamRecords: Record-aligned block
  ParseBamRecords->>DecodeRecords: RecordBatch
  DecodeRecords->>DecodeRecords: Validate and compute group keys
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title uses a valid Conventional Commit format and accurately describes the added typed-step pipeline tree.
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.

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

@nh13

nh13 commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai pause

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews paused.

@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.43499% with 128 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main-runall@01284b2). Learn more about missing BASE report.

Files with missing lines Patch % Lines
src/lib/pipeline/steps/parse/bam.rs 85.30% 31 Missing ⚠️
src/lib/pipeline/steps/boundaries/state.rs 92.37% 28 Missing ⚠️
src/lib/pipeline/steps/parse/decode.rs 90.52% 27 Missing ⚠️
src/lib/pipeline/steps/boundaries/bam.rs 87.50% 10 Missing ⚠️
src/lib/pipeline/steps/bgzf/decompress.rs 86.76% 9 Missing ⚠️
src/lib/pipeline/steps/parse/sam.rs 96.40% 9 Missing ⚠️
src/lib/pipeline/steps/bgzf/compress.rs 94.77% 8 Missing ⚠️
src/lib/template.rs 88.23% 4 Missing ⚠️
src/lib/pipeline/steps/types.rs 98.84% 2 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff               @@
##             main-runall     #735   +/-   ##
==============================================
  Coverage               ?   93.96%           
==============================================
  Files                  ?      241           
  Lines                  ?   128338           
  Branches               ?        0           
==============================================
  Hits                   ?   120598           
  Misses                 ?     7740           
  Partials               ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nh13
nh13 force-pushed the nh/runall-12-bam-io-grouping branch from f3698f5 to 804bb73 Compare August 10, 2026 01:47
@nh13
nh13 force-pushed the nh/runall-11-pipeline-steps branch from f9755bb to 964b42c Compare August 10, 2026 01:49
@nh13
nh13 temporarily deployed to github-actions August 10, 2026 01:49 — with GitHub Actions Inactive
@nh13
nh13 force-pushed the nh/runall-12-bam-io-grouping branch from 804bb73 to fbc534f Compare August 10, 2026 02:47
@nh13
nh13 force-pushed the nh/runall-11-pipeline-steps branch from 964b42c to 0c3ef9f Compare August 10, 2026 02:48
@nh13
nh13 temporarily deployed to github-actions August 10, 2026 02:48 — with GitHub Actions Inactive
Base automatically changed from nh/runall-12-bam-io-grouping to main-runall August 10, 2026 03:37
The typed-step pipeline budgets its queues on real allocated bytes, so
`BamTemplateBatch` needs a `Template` heap footprint it can sum. The
capacity-based computation already existed, but only inside the
`MemoryEstimate` impl, where the pipeline cannot reach it.

Lift it to an inherent `heap_size` and make `estimate_heap_size` delegate,
so the queue budget and `MemoryEstimate` cannot drift apart. Adds the
agreement test, which also re-derives the expected floor from the components
rather than from `estimate_heap_size` (that would be tautological once the
trait delegates).
@nh13

nh13 commented Aug 10, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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 `@src/lib/pipeline/steps/boundaries/state.rs`:
- Around line 97-125: Bound all framing lengths with checked arithmetic and the
configured carry limit in src/lib/pipeline/steps/boundaries/state.rs:97-125,
including l_text and l_name before offset updates or slicing; reject invalid
values. In src/lib/pipeline/steps/boundaries/state.rs:170-225, validate each
record’s computed length before retaining incomplete input and return
InvalidData when it exceeds the limit. Apply the same checked calculation and
limit during EOF validation in
src/lib/pipeline/steps/boundaries/state.rs:274-290 so retained memory remains
bounded.

In `@src/lib/pipeline/steps/parse/bam.rs`:
- Around line 139-141: Update parse_record_ranges to initialize ranges with
capacity estimated from bytes.len(), accounting for the 32-byte BAM fixed header
and 4-byte record-length prefix; preserve the existing push and parsing behavior
while avoiding Vec growth during normal batches.

In `@src/lib/pipeline/steps/parse/sam.rs`:
- Around line 99-104: Expose cache_umi_position from decode.rs as pub(crate),
then call it in the SAM parsing flow immediately after
DecodedRecord::from_raw_bytes in the shown logic, using key_config.umi_tag and
the constructed record so SAM records cache their UMI position before being
pushed. Keep the existing name-hash/group-key behavior unchanged.
- Around line 62-71: Validate each range in the loop before slicing bytes: use
bytes.get(...) to confirm start..end is in bounds and non-reversed, returning an
io::Error with ErrorKind::InvalidData when validation fails. Apply the existing
empty-line check only after successful validation, and preserve the current
continue behavior for spans of one byte or less.

In `@src/lib/pipeline/steps/types.rs`:
- Around line 68-70: Update src/lib/pipeline/steps/types.rs:68-70 in the batch
constructor to include records.capacity() multiplied by
size_of::<DecodedRecord>() in total_bytes; update both template constructors at
src/lib/pipeline/steps/types.rs:136-148 to include templates.capacity()
multiplied by size_of::<Template>(), while keeping from_parts limited to summed
template heap usage; and update src/lib/pipeline/steps/types.rs:219-223 to
account for bytes.capacity() and line_offsets.capacity() instead of logical
lengths. Add tests covering excess reserved container capacity for each
accounting path.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2736e68a-2c0c-470e-9f3f-3d906ce19510

📥 Commits

Reviewing files that changed from the base of the PR and between 01284b2 and 4355d9a.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock, !**/*.lock
📒 Files selected for processing (21)
  • Cargo.toml
  • src/lib/mod.rs
  • src/lib/pipeline/mod.rs
  • src/lib/pipeline/steps/bgzf/compress.rs
  • src/lib/pipeline/steps/bgzf/decompress.rs
  • src/lib/pipeline/steps/bgzf/mod.rs
  • src/lib/pipeline/steps/boundaries/bam.rs
  • src/lib/pipeline/steps/boundaries/mod.rs
  • src/lib/pipeline/steps/boundaries/state.rs
  • src/lib/pipeline/steps/mod.rs
  • src/lib/pipeline/steps/parse/bam.rs
  • src/lib/pipeline/steps/parse/decode.rs
  • src/lib/pipeline/steps/parse/mod.rs
  • src/lib/pipeline/steps/parse/sam.rs
  • src/lib/pipeline/steps/sink/mod.rs
  • src/lib/pipeline/steps/sink/write_bgzf.rs
  • src/lib/pipeline/steps/sink/write_raw.rs
  • src/lib/pipeline/steps/sort/mod.rs
  • src/lib/pipeline/steps/tuning.rs
  • src/lib/pipeline/steps/types.rs
  • src/lib/template.rs

Comment thread src/lib/pipeline/steps/boundaries/state.rs
Comment thread src/lib/pipeline/steps/parse/bam.rs
Comment thread src/lib/pipeline/steps/parse/sam.rs Outdated
Comment thread src/lib/pipeline/steps/parse/sam.rs Outdated
Comment thread src/lib/pipeline/steps/types.rs
@nh13
nh13 force-pushed the nh/runall-11-pipeline-steps branch from 4355d9a to 1abf0ae Compare August 11, 2026 00:57
@nh13
nh13 deployed to github-actions August 11, 2026 00:57 — with GitHub Actions Active
@nh13
nh13 force-pushed the nh/runall-11-pipeline-steps branch from 1abf0ae to 3c5ff4d Compare August 11, 2026 01:22
@nh13
nh13 deployed to github-actions August 11, 2026 01:22 — with GitHub Actions Active
@nh13

nh13 commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@src/lib/pipeline/steps/parse/bam.rs`:
- Around line 242-264: Update the error-message prefixes in parse_records to use
the function’s own name, parse_records, instead of ParseBamRecords. Apply this
to both the “record extends past buffer end” and “trailing partial record”
errors, leaving the existing error kinds and details unchanged.

In `@src/lib/pipeline/steps/parse/decode.rs`:
- Around line 86-99: Update the read-name bound calculation in the affected
decode function to derive its fixed-record offset from
fgumi_raw_bam::MIN_BAM_RECORD_LEN instead of the hardcoded 32, keeping it
consistent with the existing length guards and preserving the current
bounds-check behavior.
- Around line 543-562: Add a test alongside
cache_umi_position_leaves_cache_unset_when_tag_missing that uses
SamBuilder::add_int_tag to assign RX a non-Z integer value, then calls
cache_umi_position and asserts cached_umi_position().0 remains
UMI_OFFSET_UNCACHED and cached_umi() is None.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bc6126d2-7aee-4416-9283-b41b7597f146

📥 Commits

Reviewing files that changed from the base of the PR and between 4355d9a and 3c5ff4d.

📒 Files selected for processing (8)
  • src/lib/pipeline/steps/boundaries/state.rs
  • src/lib/pipeline/steps/chain_tests.rs
  • src/lib/pipeline/steps/mod.rs
  • src/lib/pipeline/steps/parse/bam.rs
  • src/lib/pipeline/steps/parse/decode.rs
  • src/lib/pipeline/steps/parse/sam.rs
  • src/lib/pipeline/steps/tuning.rs
  • src/lib/pipeline/steps/types.rs

Comment thread src/lib/pipeline/steps/parse/bam.rs
Comment thread src/lib/pipeline/steps/parse/decode.rs
Comment thread src/lib/pipeline/steps/parse/decode.rs
@nh13
nh13 force-pushed the nh/runall-11-pipeline-steps branch from 3c5ff4d to 444bb61 Compare August 12, 2026 06:19
@nh13
nh13 deployed to github-actions August 12, 2026 06:19 — with GitHub Actions Active
@nh13

nh13 commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@src/lib/pipeline/steps/parse/bam.rs`:
- Around line 161-170: Update both framing parsers around the visible loop and
parse_records frame-end calculations to use checked_add for body_start plus
block_size (and the equivalent cursor plus header plus block_size computation).
Treat arithmetic overflow as an invalid/truncated frame and reject it before
comparing bounds or slicing, ensuring every length-derived range is validated
against the remaining buffer.
🪄 Autofix

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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ddd1bee5-6ec5-4261-a7e9-6b33b7927502

📥 Commits

Reviewing files that changed from the base of the PR and between 3c5ff4d and 444bb61.

📒 Files selected for processing (3)
  • src/lib/pipeline/steps/parse/bam.rs
  • src/lib/pipeline/steps/parse/decode.rs
  • src/lib/pipeline/steps/parse/sam.rs

Comment thread src/lib/pipeline/steps/parse/bam.rs
@nh13
nh13 force-pushed the nh/runall-11-pipeline-steps branch from 444bb61 to 17cc974 Compare August 12, 2026 07:19
@nh13
nh13 deployed to github-actions August 12, 2026 07:19 — with GitHub Actions Active
…l steps

First slice of the umbrella-side port. Additive: nothing in
`src/lib/commands` routes through this tree yet, so every command still runs
on `unified_pipeline`.

`pipeline/mod.rs` re-exports `fgumi_pipeline_core as core`, which is what lets
the step sources compile unmodified — their `crate::pipeline::core::…` paths
resolve through the shim rather than needing a rewrite.

Ports `steps/{types,tuning}` plus the `sink/`, `sort/`, `bgzf/`,
`boundaries/` and `parse/` subtrees. `source/`, `group/`, `correct/` and the
closure-driven mid-steps follow; `align_and_merge` waits on `crate::aligner`.

Two deliberate deltas from the source branch:

- `boundaries/bam.rs` uses a let-chain instead of nested `if`s. The source
  predates the toolchain that unlocked them, and `ci-lint` rejects the nested
  form as `collapsible_if`; per CLAUDE.md we adopt the idiom rather than
  suppress the lint.
- `tuning.rs` demotes the `PipelineConfig::auto_tuned` intra-doc link to a
  code span. The referent lives in `unified_pipeline`, which this port exists
  to retire, so linking it would only break again on deletion.
@nh13
nh13 force-pushed the nh/runall-11-pipeline-steps branch from 17cc974 to 8a51a99 Compare August 12, 2026 07:32
@nh13
nh13 deployed to github-actions August 12, 2026 07:32 — with GitHub Actions Active
@nh13

nh13 commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nh13
nh13 merged commit 4dd6e56 into main-runall Aug 12, 2026
17 checks passed
@nh13
nh13 deleted the nh/runall-11-pipeline-steps branch August 12, 2026 07:55
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