fix(#727): mask ISO-8601 dates as dates, not phone numbers - #744
Conversation
…eck ratchet passes The new dedupSpans lexical-fallback test destructured its pairs from an inferred string[][], so under noUncheckedIndexedAccess both elements were string | undefined and mk() rejected them (4x TS2345). tsx strips types without checking, so a local test run stayed green while the byte5ai#573 test/scripts typecheck ratchet failed in CI. Widen nothing: the pairs are declared as a readonly tuple array, the assertions are unchanged.
… and dotted 30-06-2027 (the dashed form byte5ai#482 added for nl/fr) was broken by the exact mechanism the issue reported for the ISO shape: the phone pattern's \b0 branch grabs its 06-2027 tail and word-boundary extension grows that span over the whole token, tying the date span. Verified against the raw detector: 30-06-2027 -> [[phone,06-2027],[date,30-06-2027]], the same arrangement as 2026-07-02. The issue only named the ISO form and the C0 eval cannot surface either, because it scores span coverage rather than surrogate type. Pinning all three separator styles in one loop keeps them from drifting apart.
|
Pushed two commits to this branch (maintainer edit) while prepping it for merge, plus a branch update from 1. Not the test run: the #573 test/scripts typecheck ratchet. Worth flagging for next time: 2. The issue named only the ISO shape, but the dashed The trigger class is any date whose segment after a This also sharpens why RESULTS.md is right that the eval reproduces byte-for-byte — the eval scores span coverage, not surrogate type, so it is structurally blind to this entire class. Re-ran it independently and confirm your numbers: de/en 100%, es/fr/it 99.1% PASS, nl 89.0% FAIL (address-only, pre-existing since Run 2), precision 32/32 in every locale. Verification on the rebased head
One note on the mutation results: removing Not changed, flagging instead: the module doc says the date-column residual is "tracked as a follow-up" to #430, but there is no such issue open. The decision itself is fine and AC #4 explicitly allows |
What
Closes #727 : ISO-8601 date (2026-07-02) masked as a phone surrogate. dedupSpans now breaks exact overlap ties by a documented, order-independent rule; CSV import skips date columns so stored data matches its declared type.
Why
Phone pattern grabbed the date's -07-02 tail, extension grew it to the full token, tying the date span — and the tie fell through to C0_PATTERNS insertion order, so phone won. On the dataset path that's permanent corruption at rest. Tiebreak is now native match length, then a fixed lexical order for determinism only.
Test plan
Risk / blast radius
Shared path (chat masking + dataset import). Change affects only which surrogate type replaces a masked span, never whether it's masked — eval recall/precision unmoved. Documented residual: a bare-PII date column (birth_date) persists un-redacted; reversible date masking is a #430 follow-up.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.