Breaking Changes
AssumptionError API Redesign
The AssumptionError / AssumptionException type has been redesigned across all 7 languages:
- Removed
functionNameparameter from all factory methods. Violations are now identified solely by(id, subject)pairs, simplifying the error model. - New
Domainassumption ID (priority 1, between Validity and Positivity). Used for parameter-level domain violations (e.g., misrate out of range, sample too small for requested precision). - New
Misratesubject added alongsideXandY. Allows violations to report which specific parameter was invalid. - Priority order changed: Validity (0) > Domain (1) > Positivity (2) > Sparity (3). Previously Positivity was 1, Sparity was 2.
Migration: Update any code that constructs or pattern-matches on AssumptionError factory methods (e.g., Validity(functionName, subject) becomes Validity(subject)).
Removed Deprecated Rng.UniformInt (C#)
The Rng.UniformInt(long, long) method deprecated in v6 has been removed. Use Rng.UniformInt64 instead.
Two-Sample Bounds: Min-Misrate Domain Guard
ShiftBounds and RatioBounds now reject misrate values below the minimum achievable misrate for the given sample sizes. Previously, impossible misrate values would silently produce degenerate bounds. This will surface as a Domain error for callers passing very small misrate with small samples.
RatioBounds: Domain Check Before Positivity
RatioBounds now checks the Domain assumption (misrate validity) before checking Positivity. This changes which error is reported first when both violations are present.
Go Number Constraint Expanded
The Number generic constraint now includes unsigned integer types (uint, uint8, ..., uint64). This is technically additive but may affect type inference in edge cases.
Test Data Overhaul
Cross-language reference test data has been substantially reorganized:
- Removed:
tests/assumptions/directory and all assumption-specific test suites. Error cases are now co-located with each estimator's test data usingexpected_errorfields. - Regenerated:
shift-bounds/andratio-bounds/test files with larger minimum sample sizes (5 instead of 1-3) and new error test cases. - Renamed: Many test files to follow the new naming taxonomy (
natural-5-5instead ofnatural-3-2, etc.).
New Features
CenterBounds Estimator
Exact distribution-free confidence bounds for the Hodges-Lehmann pseudomedian (Center). One-sample analog of ShiftBounds/RatioBounds, based on Wilcoxon signed-rank theory. Uses the FastCenterQuantiles algorithm to extract order statistics from the implicit pairwise average matrix without materializing all N(N+1)/2 pairs.
from pragmastat import center_bounds
bounds = center_bounds([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0.05)
# Bounds(lower=3.5, upper=7.5)
Available in all 7 languages: CenterBounds (C#), center_bounds (Python/Rust/R), centerBounds (TypeScript/Kotlin/Go).
SignedRankMargin Function
Computes the critical margin for one-sample signed-rank bounds, analogous to PairwiseMargin for two-sample bounds. Uses exact Wilcoxon signed-rank distribution via dynamic programming for n <= 63 and Edgeworth approximation for larger n.
from pragmastat import signed_rank_margin
margin = signed_rank_margin(10, 0.05) # 18
Available in all 7 languages.
Rng.resample (Bootstrap Sampling)
New method for sampling with replacement (bootstrap resampling):
from pragmastat import Rng
rng = Rng("demo-resample")
rng.resample([1, 2, 3, 4, 5], 7) # [5, 1, 1, 3, 3, 4, 5]
Available in all 7 languages. Cross-language reproducibility verified via reference test data in tests/resample/.
GaussCdf Shared Module
Extracted standard normal CDF implementation (ACM Algorithm 209) into a shared internal module, replacing code previously inlined in PairwiseMargin. Now shared between PairwiseMargin and SignedRankMargin.
Bug Fixes
fast_spreadbounds corruption under parallel load (Rust): Changed internal index types fromusizetou32/u64to prevent overflow with large inputs. Added bounds-checking guards and fixed accumulator types for count variables.Multiplicquantile guards (C#): Removed overly aggressive epsilon guards (1e-9) in the quantile function. Now only returns boundary values at exact 0 and 1.- Go
Medianoverflow: Now computes(float64(a) + float64(b)) / 2instead offloat64(a + b) / 2, preventing integer overflow with large values.
Infrastructure
Version Management
- Version is now managed via a single
VERSIONfile at the repository root, replacing the previousmanual/version.typapproach. - New
mise run version <ver>task propagates the version to all language manifests. - New
mise run publish <ver>task bumps version, pushes, and triggers the publish workflow.
CI Improvements
- Added
ci-successgate job aggregating all language CI results for branch protection. - Added
cs:checkstep to C# CI pipeline. - Go CI now uses mise tasks (
go:check,go:test) instead of raw commands. - Dev branch excluded from push-triggered CI.
Publish Workflow
- Publish is now triggered via
workflow_dispatchinstead of tag push. - Tags are created programmatically during the publish job.
- Version is read from
VERSIONfile instead of parsed from Typst source.
TypeScript: ESLint 8 to 9 Migration
Migrated from .eslintrc.js (legacy config) to eslint.config.js (flat config). ESLint upgraded from v8 to v9, @typescript-eslint packages upgraded from v6 to v8.
Tooling
- Replaced deprecated
serde_yamlwithserde_ymlin the tools crate. - Removed deprecated
UniformIntmethods from Rust RNG internals. - Added
typstto mise-managed tools. - Downgraded Java toolchain from Temurin 23 to Temurin 11 (Kotlin compatibility).
- Added
ts:restoreas dependency forts:build. - Fixed
cs:cleanto not rundotnet clean(which requires restore). - Added
r:restoreas dependency forr:checkandr:ci.
Simulation Infrastructure
- New Rust simulation crate (
rs/pragmastat-sim): Parallel simulation runner withindicatifprogress bars, supporting avg-drift, disp-drift, center-bounds, shift-bounds, and ratio-bounds simulations. - C# simulation improvements: Split monolithic coverage simulation into 4 dedicated commands, migrated to
Rng-based sampling with string seeds for reproducibility, switched to Release builds, addedAssumptionExceptionrecording in output, 10x default sample count. - New mise tasks:
rs:sim,rs:sim:all,cs:sim:all.
Documentation
- New manual sections: one-sample bounds methodology,
CenterBoundstoolkit reference,SignedRankMargintoolkit reference,resampletoolkit reference. - New algorithm documentation:
FastCenterQuantiles,FastSignedRankMargin. - New study: bootstrap vs signed-rank approaches for center bounds.
- New study: median bounds efficiency analysis.
- Test suite documentation added for
center-boundsandsigned-rank-margin. - Comprehensive
tests/README.mddocumenting test file format, naming taxonomy, and tolerance values. - Updated AGENTS.md API list to reflect new one-sample bounds and margin functions.
Test Data
New test suites:
tests/center-bounds/(40 files): natural, symmetric, asymmetric, additive, uniform, edge cases, properties, error casestests/signed-rank-margin/(40 files): exact, medium-n approximation, boundary, demo, error casestests/resample/(16 files): cross-language bootstrap reproducibility
Removed:
tests/assumptions/(4 files): assumption error tests moved inline to each estimator's test suite usingexpected_errorfields
Regenerated with larger minimum sample sizes:
tests/shift-bounds/andtests/ratio-bounds/: minimum sample size increased from 1-3 to 5, new error test cases for min-misrate domain guard
Full Changelog: https://github.com/AndreyAkinshin/pragmastat/compare/v6.0.1...v7.0.0