@@ -6,7 +6,63 @@ adheres to [Semantic Versioning](https://semver.org/).
66
77## [ Unreleased]
88
9+ ### Added
10+ - ** Validation Gauntlet** (` benchmarks/gauntlet/ ` , ` docs/validation-gauntlet.md ` ):
11+ a gold-labelled disposition benchmark for the validation, domain and
12+ text-cleaning surfaces. Five deterministic fixtures (finance, healthcare,
13+ CRM, e-commerce, adversarial text) label every injected defect with the
14+ disposition FreshData should choose (preserve / repair / flag / review) and
15+ the harness scores detection P/R/F1, repair accuracy, review routing,
16+ preservation, corruption, escapes, false positives, audit completeness,
17+ determinism, trust monotonicity and runtime/memory. Runs on every PR
18+ (` gauntlet.yml ` ) with absolute gates plus no-regression checks against the
19+ stored ` baseline.json ` .
20+ - ` CleanReport.coerced_cells ` : per-cell record (` {column: {row: original}} ` )
21+ of values that ` fix_dtypes ` nulled because they did not parse as the
22+ column's inferred type — the recovery source for quarantined cells, also
23+ included in ` report.to_dict() ` .
24+ - Date-field range validation in ` fd.validate_fields ` : ` FieldSpec.min_value `
25+ / ` max_value ` now accept a date string or timestamp for ` date ` /` datetime `
26+ fields, so a future date of birth or an 1875 admission date is flagged as a
27+ ` domain_mismatch ` (gauntlet finding).
28+ - Case-variant vocabulary suggestions in ` fd.validate_fields ` : a value that
29+ matches an ` allowed_values ` entry except for case (` ACTIVE ` vs ` active ` ) is
30+ no longer silently accepted — it gets a warning-severity issue with the
31+ canonical form as ` suggestion ` and action ` accept_with_warning ` (gauntlet
32+ finding).
33+
934### Fixed
35+ - ** Unparseable values are quarantined, never fabricated** (gauntlet finding,
36+ the ` 'apple' ` -in-a-price-column case): when ` fix_dtypes ` converts a
37+ mostly-numeric (or datetime) text column, cells that fail to parse used to
38+ become ` NaN ` and then be silently imputed by the auto engine — turning
39+ junk into a fabricated median. They now stay missing, are excluded from
40+ auto-imputation, keep their originals in ` report.coerced_cells ` , and the
41+ decision is a ` human_review ` action in the audit trail. Genuine missing
42+ values (true ` NaN ` , sentinels like ` "N/A" ` ) keep the documented
43+ auto-impute behaviour, and an explicit ` impute= ` request still fills
44+ everything.
45+ - Formatted-number stragglers (` "$1,234.56" ` , ` "1,200,500.00" ` ) in a
46+ mostly-plain numeric column are now parsed by the existing locale-aware
47+ rescue instead of being coerced to missing — the rescue previously only
48+ engaged when the plain parse failed the threshold entirely (gauntlet
49+ finding).
50+ - ` fd.validate_fields ` consensus inference now honours the same
51+ contamination boundary as the ` fix_dtypes ` warning that points users at it
52+ (dominant share ≥ 60% with at most a handful of stragglers). Previously
53+ the warning fired from a 60% parse share but the consensus gate required
54+ 80%, so the exact frame the warning named sailed through
55+ ` validate_fields ` silently (gauntlet finding).
56+ - Explicitly allowed values are no longer swallowed by null-marker
57+ heuristics in ` fd.validate_fields ` : with
58+ ` FieldSpec(allowed_values={"US", "DE", "NA"}) ` , ` "NA" ` is Namibia, not a
59+ missing value (gauntlet finding).
60+ - ` clean_text ` / ` validate_fields ` text normalization no longer rewrites
61+ typography in content-bearing fields: for ` free_text ` , ` text ` and entity
62+ name types, the punctuation→ASCII mapping (curly quotes, em-dashes, prime
63+ marks — ` 12″ ` became ` 12" ` ) is withheld, matching the field-aware safety
64+ contract. Untyped columns keep the existing behaviour (gauntlet finding).
65+
1066- ` anonymize() ` called with no ` rules ` and no ` detection_config ` now emits
1167 a ` UserWarning ` instead of silently returning the data unchanged — a
1268 privacy call that does nothing must say so. Behavior is otherwise
0 commit comments