feat(columnkit): implement one trait, inherit the bounded contract (SDK) - #37
Merged
Conversation
A builder who wants their own per-locus metric (methylation, coverage/QC, ML features, a genotyper) would otherwise fork into the raw pileup engine and re-implement, by hand, the whole-genome contig walk, the working-set bound that plan/--enforce admit, and the canonical-JSON + BLAKE3 receipt — silently dropping the soundness invariants. ColumnKit turns "extend the substrate" into a first-class SDK: - ColumnAnalyzer trait (header / params / on_column) + run_bounded_whole_genome driver (src/call/columnkit.rs). Implement the trait, run it through the driver, inherit the SAME bounded per-contig stream + working-set bound + receipt the shipped subcommands enjoy. - The trait is WELDED to the kernel: the driver runs the exact same column stream as the shipped features egress, so the estimator that admits a run provably upper-bounds the realized working set of the builder's analyzer too. - features is now the FIRST ColumnAnalyzer: run_features is refactored onto the driver (FeatureAnalyzer), so the SDK IS the production path, not a parallel one — byte-identical output pinned by the golden TSV test. - examples/columnkit_coverage.rs: a ~25-line custom analyzer that runs and reports its inherited bounded working set. Crate-root re-exports + README. No other genomics library can offer "implement this trait, inherit a machine-checkable memory budget + a hash-verifiable receipt" — none has a memory contract to inherit. Tests: 2 columnkit unit tests (byte-identical-to-direct-path + custom-analyzer bounded WS); golden feature TSV guards the dogfood; feature writers take ?Sized writers. Full suite green; rustc 0 warnings; additions clippy-clean. Co-Authored-By: Claude Opus 4.8 (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.
Summary
Act 2, the top-scored proposal (audit 46.3; build 10, moat 10, feasibility 9). Turn "extend the substrate" into a first-class SDK. A builder who wants their own per-locus metric — methylation, a coverage/QC track, custom ML features, a star-allele genotyper — would otherwise fork into the raw pileup engine and re-implement, by hand, the whole-genome contig walk, the working-set bound that
plan/--enforceadmit, and the canonical-JSON + BLAKE3 receipt — silently dropping the soundness invariants.With ColumnKit they implement one trait and run it through one driver, inheriting all of it for free.
What's new
ColumnAnalyzertrait (header/params/on_column) +run_bounded_whole_genomedriver (src/call/columnkit.rs). Implement the trait → inherit the same bounded per-contig column stream, the same working-set bound, and the same verifiable receipt the shipped subcommands enjoy.featuresegress, so the estimator that admits a run provably upper-bounds the realized working set of the builder's analyzer too. It's the contract made composable, not a feature bolted beside it.featuresis now the firstColumnAnalyzer:run_featuresis refactored onto the driver (FeatureAnalyzer), so the SDK is the production path, not a parallel one — byte-identical output pinned by the golden TSV test. (The audit explicitly warned against the legacy plugin's parallel, non-contract path; this avoids that trap.)examples/columnkit_coverage.rs— a ~25-line custom analyzer that runs and reports its inherited bounded working set. Crate-root re-exports (rosalind::{ColumnAnalyzer, run_bounded_whole_genome, FeatureAnalyzer}) + a README section.Test plan
feature_analyzer_via_driver_equals_the_direct_features_path— driver output byte-identical to the hand-wired path, same bounded working seta_custom_analyzer_inherits_the_bounded_working_set— a custom analyzer's WS is coverage-bounded, independent of read countrun_featuresdogfood (zero behavior change)examples/columnkit_coverage.rsbuilds and runsfeaturesre-verified byte-identical across runs, receiptfeature_rowsintactWhy this matters
No other genomics library can offer "implement this trait, inherit a machine-checkable memory budget + a hash-verifiable receipt" — because none has a memory contract to inherit. This is the move that converts a watching forker into a building one. Next Act-2 candidates: bounded gVCF (42.7), verify-attest signed receipts (43).
🤖 Generated with Claude Code