Development Changelog
Development history and milestone releases for vfairness. Version 0.1.0, cut on 2026-08-23, is the first public beta; its v0.1.0 tag triggers the TestPyPI-then-PyPI publish, which is the pending release step. The API is not frozen until the stable 1.0.0. We follow Keep a Changelog and Semantic Versioning conventions.
vfairness 0.1.0 is the first public beta. The release is cut and pip install vfairness is the intended install command, with the first PyPI publish as the pending release step. The API is not frozen until the stable 1.0.0 release. We welcome feedback and contributions via GitHub.
Roadmap to 1.0.0
The following features are planned for the stable 1.0.0 release:
Stable API
Finalized, documented API with backward compatibility guarantees.
Complete Test Coverage
Comprehensive unit and integration tests with >90% coverage.
Production Documentation
Full API reference, tutorials, and deployment guides.
PyPI Publication
Cut with the 0.1.0 beta; the v0.1.0 tag triggers the TestPyPI-then-PyPI publish (the pending release step). 1.0.0 will be the first stable release under the backwards-compatibility contract.
Unreleased
Unreleased August 27, 2026
The [Unreleased] block of CHANGELOG.md: two
library-polish improvements that landed after the 0.1.0 cut.
FairnessReport)get_report, classification_fairness_report and regression_fairness_report is now documented and type-checked by a set of TypedDict definitions (FairnessReport plus AssessmentReport, DataInfo, ExplanationsReport, MetricStatusEntry and InsufficientEvidenceGroup), re-exported from the top-level vfairness package and from vfairness.evaluation and added to the frozen public surface. These are static-only annotations: the report stays the same plain, JSON-serialisable dict, so every existing consumer, subscript access and json.dumps is unchanged; a type checker now catches a mistyped key such as report["assessement"].FairnessReport
AssessmentReport
DataInfo
ExplanationsReport
MetricStatusEntry
InsufficientEvidenceGroup
*_ratio metrics are higher-is-better). A fair model therefore draws a large round shape and a failing metric caves inward, and every threshold maps to a single clean reference ring (a dot outside the ring passes, inside it fails). Raw values stay on the dot labels; the auto-generated radar explanation was rewritten to match. The interactive Plotly radar plot_metrics_radar was brought into line with the same fairness axis, so the SVG and interactive radars now read the same way, and the docs-site gallery visual was regenerated.radar_chart_to_svg
plot_metrics_radar
v0.1.0
Beta August 23, 2026
The first public beta: a plain SemVer 0.x release carrying the
Development Status :: 4 - Beta classifier, installable with a normal
pip install vfairness. This section is the release cut; the
v0.1.0 tag triggers the TestPyPI-then-PyPI publish. The API is not
frozen until 1.0.0. This section highlights the [0.1.0] block of
CHANGELOG.md.
set_branding() and branding_enabled() remove the validant.ai mark from generated SVGs and reports, honouring an explicit call, then the VFAIRNESS_BRANDING environment variable, then a branded default. A single chart can opt out with render_svg(name, {"branding": False}). An unbranded chart contains no occurrence of the brand string at all, and the switch is unconditional by design: nothing verifies a licence or calls home.set_branding
branding_enabled
vfairness.net)validate_endpoint resolves and vets the target, guarded_post is a drop-in for requests.post, PinnedIPAdapter pins the vetted IP against DNS rebinding, and a refusal raises SSRFError. Wired into the LLM api_proxy, so assessment traffic cannot be pointed at loopback, private, link-local or cloud-metadata targets. A local model server needs the explicit allow_loopback=True opt-in, which unlocks loopback only.vfairness.net
validate_endpoint
guarded_post
PinnedIPAdapter
SSRFError
vfairness.validity)VG_* metric identifiers (faithfulness, groundedness, hallucination rate, citation accuracy, context precision and recall, answer correctness), a GroundednessScorer, a fail-closed judge ladder (GroundednessJudge / LlmGroundednessJudge) and aggregate_validity. Deliberately not registered in the capability manifest yet, so nothing can be sealed on it before its gold set lands.vfairness.validity
GroundednessScorer
aggregate_validity
*_with_ci variants cover disparate impact, FPR parity, negative predictive value, conditional demographic disparity, pricing disparity, the integrated calibration index and multicalibration. Custom-shape statistics get an interval from a new bootstrap_over_index helper that resamples row indices stratified by group. The interval width feeds the three-state verdict.bootstrap_over_index
disparate_impact_ratio_with_ci
multicalibration_with_ci
disparate_impact_ratio (the four-fifths selection-rate ratio), conditional_demographic_disparity (the CJEU objective-justification mirror), negative_predictive_value_difference, auroc_parity (a validity gate against levelling-down), grid-free integrated_calibration_index and multicalibration, the TRIPOD recalibration diagnostics calibration_in_the_large and calibration_slope, plus pricing_disparity, net_benefit_parity and conditional_adverse_impact. The error-rate metrics the catalogue referenced but the engine lacked (fpr_parity_difference, fnr_parity_difference, accuracy_parity_difference, worst_group_accuracy) also landed, closing the overclaims found in the knowledge-graph spine audit.ruff check src tests and mypy src are both blocking on every library change, with the toolchain declared in the dev extra so CI, pre-commit and local runs agree. The type burndown reached zero errors and surfaced three real bugs (a dead subgroup-robustness audit in Pulse, a crash on list-valued sample_weight in FairRegressor.fit, and a no-op correlation proxy detector). Also added: mutation testing on the band logic, new property-based / determinism / deserialization-safety / reference-parity suites, an sdist allowlist, beta-programme materials, and the supply-chain governance files.NOTICE file alongside the LICENSE.requires-python is now >=3.11, following Scientific Python SPEC 0.predictive_parity_difference, fpr_parity_difference, fnr_parity_difference and equalized_odds_difference collapsed a NaN per-group rate (a group with no positive predictions, no negatives, or no positives) into a 0.0 “perfect parity” result, which read as PASS with a deceptively tight [0.0, 0.0] bootstrap CI. They now return NaN so the verdict routes to insufficient_evidence, mirroring the earlier NPV fix.multicalibration, negative_predictive_value_difference, auroc_parity and conditional_demographic_disparity now return NaN when there is no evidence, and the last of those renormalises its stratum weights instead of biasing toward “fair” in proportion to the un-assessable population.MetricResult gains a three-state verdict (fair / unfair / insufficient_evidence), and is_fair becomes an alias for verdict == 'fair'. A wide small-sample interval is no longer reported as a pass or a fail. predictive_parity_difference_with_ci closes the last sufficiency metric that shipped as a bare point estimate.trust_input / VFAIRNESS_TRUST_MODEL_INPUT), closing a remote-code-execution vector. An AST guard test also stops the metric core from swallowing computation errors silently.load_dataframe tool rejects remote data_path URLs, so an agent-supplied path cannot become network egress; the Pulse artifact download pins the scheme to https and caps the response size; and the deserialization-safety scan now resolves aliased imports and covers marshal, pandas.read_pickle, jsonpickle and shelve.v0.0.9
Alpha August 2026A deep correctness-and-honesty hardening milestone. Five audit waves swept every subsystem for silently-wrong results, false fairness certificates and band inconsistencies; the rendering layer gained self-explaining, accessible SVGs and a single unified design language (Blanco); and the test/CI infrastructure was strengthened with golden-file value pins, render-smoke coverage across every template, and coverage measurement in CI. This was the last 0.0.x milestone before the 0.1.0 public beta.
render_svg choke point (so every adapter and .to_svg() inherits it): an auto-generated on-canvas explanation (concept → how to read it → the finding on this chart → recommended action) plus an accessible, machine-readable layer (role="img", <title>, a one-line <desc>, and a <metadata> JSON block). Severity is derived from the same data the badge uses, so the explanation can never contradict the badge. Curated content covers every template.vfairness.rendering.explain
CHART_META
render_svg applies Blanco (“The Silent Gallery”) by default: a single post-render transform giving sharp corners, editorial type (Plus Jakarta Sans / JetBrains Mono), desaturated graphite chrome, and colour reserved for the four semantic tones. It never touches the templates or adapters themselves.apply_skin
list_skins
SKINS
FairnessAnalyzer report, so a numeric regression fails loudly instead of drifting silently.tests/test_golden_metrics.py
render_svg for every registered SVG template and asserts well-formed XML with no unrendered Jinja tokens.tests/test_rendering.py
TaskResult dataclass formalises the task-handler result envelope (schema_version, task_type, success, data/error, optional warnings) with a backward-compatible to_dict(). Coverage is now measured in CI (--cov=vfairness) behind a ratcheting --cov-fail-under gate.vfairness.result.TaskResult
-m fairness marker matched zero tests (so CI silently ran nothing); the filter was removed from both GitHub and GitLab pipelines, and both now install the extras the suite exercises.TaskResult.to_dict(). The success/data/error semantics are unchanged; the envelope gains additive schema_version and task_type keys.y_true) is now surfaced in assessment.not_assessable_metrics and excluded from the fairness score, instead of being mis-scored as a FAIL. The classification report gains a not_assessable_metrics field.fisher_exact_test uses the real exact test (no silent chi-square degrade); Bayesian credible intervals delegate to scipy (the homegrown Beta PPF had collapsed “95%” intervals to ~55% coverage); Wilson score intervals replace NaN bounds for large groups; multiple-testing correction runs real two-proportion z-tests instead of inverted pseudo p-values.NOT ASSESSABLE instead of certifying fairness_score 1.0; critical findings floor the overall risk band (1+ → MEDIUM, 3+ → HIGH) so three critical issues can no longer average out to a green badge; constant-probability ECE/MCE report the true error instead of a “perfect” 0.0.vfairness._bands module drives every severity/threshold decision, so the badge, radar chart, detailed report and explanation text can no longer give contradictory verdicts for the same input; the divergent 0.2/0.4/0.6/0.8 risk scale was eliminated everywhere; NaN scores render a neutral N/A badge rather than a green MINIMAL.BetaCalibrator is now real Kull et al. 2017 beta calibration; GridSearch predicts with the classifier it reports; FairRegressor raises instead of silently fitting an unconstrained model for unsupported objectives; the adversarial debiasing loss trains its adversary in the correct direction; the outcome column is no longer scanned as its own proxy.DeepExplainer had made every deep job fail); SHAP attributions, base value and prediction now come from one class; causal identification and refuter-crash disclosure fixed; monitoring/drift windows and health-score trends corrected.requirements.txt now includes the hard runtime deps requests and scikit-learn (a minimal install previously could not even import vfairness); the mcp extra is gated to Python ≥ 3.10 so the project locks again; frozen-surface exports (calibration_difference, r2_parity_difference, residual_bias) restored; ~800 new regression tests across tests/test_audit_wave1–5 pin every fix. Documentation examples corrected against the real APIs.v0.0.8
Alpha March 2026Release consolidating all v0.0.x development work into a stable alpha milestone. Includes 43 historical discrimination patterns across US, EU, EU AI Act & Swiss jurisdictions, finalized APIs for the full pipeline, expanded test coverage, and polished documentation across all modules.
repair_level (0 = no change, 1 = full repair) with a tie-robust empirical-CDF mapping. Registered under dispatch key disparate_impact_removal and wired into the platform's pre-processing step (with a configurable repair-strength control).DisparateImpactRemover
disparate_impact_removal
get_massaged_labels() hook and a max_flip_fraction safety cap. Wired into the platform's pre-processing step.LabelMassager
label_massaging
get_resampled_data() hook with configurable strategy and balance_by. The platform rebalances the training split only, leaving the held-out test split intact for honest evaluation.Resampler
resampling
BCE + λ · GroupFairnessRegularizer. The fairness metric (demographic parity, equalized odds, equal opportunity, or FPR parity) is selected from the chosen fairness definition, and the penalty strength gives continuous control over the accuracy-fairness trade-off. Registered under dispatch key fairness_regularization; falls back to reweighting if torch is unavailable.GroupFairnessRegularizer
fairness_regularization
transform returns the latent columns (rep_0..). Tunable representation_dim and lambda_fairness; multiple attributes handled via their intersection. Registered as fair_representation and wired into the pre-processing step + Pareto sweep. Requires torch.FairRepresentationTransformer
fair_representation
DisparateImpactRemover, LabelMassager, Resampler, FairRepresentationTransformer and the fairness-regularization training loop now operate on the intersection of all protected attributes rather than only the first (e.g. they repair / rebalance / penalize race x gender jointly); (2) the regularizer accepts secondary fairness constraints (penalized jointly); (3) a degenerate-collapse guard detects and softens penalties that drive the model to a single class; (4) a training-row cap keeps the torch sweep responsive on large datasets; (5) pre-processing techniques (Disparate Impact Removal, Label Massaging, Resampling, Fair Representation) gained Pareto strength sweeps; and (6) results surface proxy-survival notes and small-sample / confidence warnings so a near-unchanged metric is explained rather than mistaken for a no-op.get_massaged_labels
get_resampled_data
secondary_constraints
attribute_historical_pattern(attribute, domain) helper resolves 24 documented (attribute class × regulated domain) precedents -- race / gender / age / national-origin / religion / disability / geographic proxy across hiring, lending, healthcare, justice, insurance and education. Pulse attaches the citation-backed envelope onto bias findings so the “Historical pattern” channel keys off a structured flag instead of regex-matching evidence text.attribute_historical_pattern
CRITICAL
HIGH
MEDIUM
_statistics.pybootstrap_ci
stratified_bootstrap_ci
bayesian_proportion_ci
bayesian_difference_ci
compute_metric_with_ci
proportion_z_test
fisher_exact_test
cohens_h
minimum_detectable_effect
power_warning
intersectional_disparity.svg) with ground truth overlay, severity-colored bars, prediction delta indicators, most/least advantaged comparison cards, and insight cards. 44th SVG template in the rendering module.intersectional_disparity_to_svg()
identify_privileged_groups() and intersectional_disparity_analysis() now compute ground truth rates, false positive rates, and prediction deltas per subgroup. New outcome_polarity parameter supports both favorable (loan approval) and unfavorable (recidivism) outcome directions.ground_truth_rate
false_positive_rate
prediction_delta
outcome_polarity
data_validation_to_svg() now safely handles nested dicts and lists, truncates overly long string representations, and only includes scalar values in metric cards. Previously, raw Python repr output (e.g., {'count': 5}) could appear in the SVG text.outcome_polarity='positive_unfavorable'. Previously, the ratio calculation was inverted for unfavorable outcomes, making insights misleading.
v0.0.7
Alpha
February 2026
Show details
Documentation quality overhaul and major feature release. Complete site redesign with gradient theme system, plus new Reporting & Dashboards, Experimentation & A/B Testing, and Workflow Integration modules. 43 SVG templates across 15 adapter modules, 114 gallery illustrations.
v0.0.7
Alpha February 2026 Show detailsvfairness.operations.reportingMetricsStore
FairnessDashboard
ReportGenerator
InteractiveDashboard
vfairness.operations.experimentationFairnessExperiment
FairnessPowerAnalyzer
ExperimentAnalysis
FairnessDriftDetector
AdaptiveThresholdManager
FairnessAlertPrioritizer
monitoring_dashboard
drift_report
alert_timeline
temporal_analysis
vfairness.operations.cicdHierarchicalGateConfig
FairnessReportCard
SmallSampleWarning
log_fairness_to_wandb()@auto_log_fairnessvfairness-check-config
vfairness-check-model-card
pytest11 entry point with marker, fixture, and terminal summary.@pytest.mark.fairness
fairness_gate
fairness-checks.yml
workflow_overview
hierarchical_gate
report_card
reporting_units_3.ipynb
experimentation_unit_4.ipynb
vfairness_8_workflow_integration.ipynb
correlation_matrix
causal_decomposition
robustness_testing
ranking_fairness
data_validation
auto_discovery
regression_fairness
reporting_dashboard
adapters_robustness.py
adapters_ranking.py
adapters_validation.py
adapters_discovery.py
adapters_regression.py
adapters_reporting.py
sys.modules aliasing.pyproject.tomlcorrelation_heatmap and correlation_matrix templates were painted over by grid cells. Fixed text-anchor from end to start, increased font size to 12px, and added 100px panel headroom.dot_x computation around the axis position and added smart label placement for negative values.
Major feature and documentation release. New modules require optional dependencies: pip install vfairness[reporting], pip install vfairness[experimentation], or pip install vfairness[mlops].
v0.0.5-dev
Alpha
February 2026
Show details
Post-processing expansion and SVG rendering engine. Added threshold optimisation, prediction reweighting, operations/monitoring modules for production deployment, and 28 purpose-built SVG templates for server-side report generation.
v0.0.5-dev
Alpha February 2026 Show detailsThresholdOptimizer
GroupThresholdOptimizer
PredictionReweighter
RejectionOptionClassifier
CalibratedEqualizer
DataBiasValidator
ModelFairnessGate
BiasMonitor
DriftAlert
FairnessConstraintType
FairnessTestSuite
@fairness_test
vfairness.rendering
evaluation.integrations to dedicated operations.cicd module.
v0.0.3-dev
Alpha
January – February 2026
Show details
Full pipeline expansion. Post-processing calibration, feature engineering, in-processing training interventions, and enhanced visualisation. Expanded vfairness from detection-only to a full-pipeline fairness toolkit.
v0.0.3-dev
Alpha January – February 2026 Show detailsFairExplAIner
GroupCalibrator
IntersectionalCalibrator
CalibrationAnalyzer
vfairness.preprocessing.feature_engineering
FeatureEngineeringAnalyzer
vfairness.in_processing
ExponentiatedGradient
FairClassifier
TemperatureScaling
PlattScaling
TrainableGroupCalibrator
classification_fairness_report()
FairnessTrainingAnalyzer
FairClassifier
FairRegressor
vfairness is no longer detection-only. With in-processing and post-processing modules, it now covers the full ML fairness pipeline.
v0.0.1-alpha
Alpha
December 2025
Show details
Initial development release. Core fairness metrics, statistical validation, bias detection module, and MLOps integration foundations.
v0.0.1-alpha
Alpha December 2025 Show detailsFairnessAnalyzer
BiasDetector
log_fairness_to_mlflow()
First public development release. Not recommended for production use. Install from source or GitHub.
What's Next
Some of the most interesting parts of vfairness are already in the code and maturing toward a full documentation page and a frozen API; others are planned. Here is where the work is heading.
In progress (already in the code)
- Explainability & XAI: the SHAP family, the Lundberg fairness decomposition and DiCE counterfactuals (shipping in the code today; full documentation page landing this release)
- Validity / groundedness axis: the VG-* metric family with a fail-closed LLM judge (interim, live)
- Vision representation fairness: Skew / NDKL / bias-amplification math shipped, plus an optional FairFace demographic sidecar
- Causal fairness graphs and fairness-aware model selection
Planned
- A per-symbol API reference for every top-level export
- An owned groundedness detector to succeed the interim LLM judge
- Continuous monitoring dashboard
- Enterprise compliance reports
Found a bug or have a feature request? Please open an issue on GitHub. We welcome contributions from the community.