跳转至

v0.6.5

Patch release landing the OOT-governance switches for CreditModelPipeline and FeatureValidationPipeline (audit items G10/G11/G12). All new fields default to legacy behavior — runs that previously produced numbers produce identical numbers — with one visibility change: silently synthesized OOT placeholders now warn loudly.

OOT Governance (CreditModelPipeline)

  • candidate_mode — one-switch preset for pre-freeze iteration: OOT is forbidden everywhere (forbidden_splits ∪ {"oot"}), never synthesized, evaluation restricted to ins/oos, hyperparameter search restricted to oos, backward reports nothing. Real OOT rows in the input are split out but never consumed (oot_withheld=True). Explicitly contradicting settings raise a ValueError naming both fields instead of being silently overridden.
  • synthesize_missing_ootNone (default) resolves to the legacy behavior: a run without real OOT rows gets an OOS copy as a stand-in, now with a loud UserWarning ("stand-in OOT"). Set False to drop the placeholder: splits carry no "oot" key and every downstream stage (evaluation, plots, Excel, search, backward) skips it automatically.
  • evaluation_splits — optional whitelist for _evaluate_models; perf tables, figures, and Excel sheets share the same filtered scope. extra_eval_datasets are exempt.
  • forbidden_splits — a hard gate enforced at every consumption site: any component about to consume a forbidden split raises a ValueError naming the component — including splits smuggled in through optuna_params["common"]["eval_sets"] or backward_params["init"]["test_data_dict"].
  • search_eval_splits / search_objective_when_no_oot — both _run_lr_search and _run_optuna (the audit named only LR search; optuna had the identical hard-coded eval_sets) now build their eval sets from governed config. None resolves to the legacy ["oos", "oot"], degrading to available splits; an explicit list is validated strictly. When no OOT is available and no objective was set explicitly, the search objective falls back to max_primary; an explicit objective="oot_gap_penalized" with no usable gap-reference split raises instead of silently degrading.
  • backward_validation_split / backward_report_splits — backward elimination declares its validation and report splits explicitly. None resolves to the legacy ["oot"] report set.
  • Run provenanceCreditModelPipelineResult.split_governance and saved model metadata record candidate_mode, oot_synthesized, oot_withheld, evaluation_splits, and forbidden_splits, so an artifact reviewer can tell real OOT metrics from placeholders without re-reading the notebook.

OOT Governance (FeatureValidationPipeline)

  • synthesize_missing_oot — same semantics as CMP. False keeps the OOT frame empty instead of copying OOS; OOT-labeled outputs (psi_ins_oot, per-split WOE/distribution tables) are simply absent rather than duplicating OOS.

Behavior Notes

  • No numeric changes under default configs: legacy synthesis, search eval sets, objectives, and backward inputs are byte-identical to 0.6.4 (regression-asserted).
  • New UserWarning ("stand-in OOT") fires whenever a missing OOT is synthesized. Suites running -W error::UserWarning on OOT-less data should set synthesize_missing_oot=False or handle the warning.
  • Announced default flip (next minor, 0.7.0): synthesize_missing_oot NoneFalse, search_eval_splits None["oos"], backward_report_splits None[]. Pass explicit values today to freeze either behavior across the flip.

Validation

  • Full local pytest suite: 710 passed, 0 skipped (22 new OOT-governance regressions).
  • Source package verification and wheel/sdist build passed (tasks.py verify).
  • Documentation passed mkdocs build --strict.