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 aValueErrornaming both fields instead of being silently overridden.synthesize_missing_oot—None(default) resolves to the legacy behavior: a run without real OOT rows gets an OOS copy as a stand-in, now with a loudUserWarning("stand-in OOT"). SetFalseto 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_datasetsare exempt.forbidden_splits— a hard gate enforced at every consumption site: any component about to consume a forbidden split raises aValueErrornaming the component — including splits smuggled in throughoptuna_params["common"]["eval_sets"]orbackward_params["init"]["test_data_dict"].search_eval_splits/search_objective_when_no_oot— both_run_lr_searchand_run_optuna(the audit named only LR search; optuna had the identical hard-codedeval_sets) now build their eval sets from governed config.Noneresolves 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 tomax_primary; an explicitobjective="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.Noneresolves to the legacy["oot"]report set.- Run provenance —
CreditModelPipelineResult.split_governanceand saved model metadata recordcandidate_mode,oot_synthesized,oot_withheld,evaluation_splits, andforbidden_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.Falsekeeps 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::UserWarningon OOT-less data should setsynthesize_missing_oot=Falseor handle the warning. - Announced default flip (next minor, 0.7.0):
synthesize_missing_ootNone→False,search_eval_splitsNone→["oos"],backward_report_splitsNone→[]. 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.