test: exhaustive Tier-3 gates for fold/slug/whitespace/dot/preset invariants - #524
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds deterministic Tier-3 (#[ignore]) exhaustive test gates to prove key invariants for per-code-point or bounded-window transforms in the Rust core, reducing reliance on probabilistic \PC* proptests for classes of bugs like #523/#498.
Changes:
- Add exhaustive idempotency/invariant gates for
fold_caseacross all scalar values. - Add exhaustive codomain gate for
slugifyoutput charset across all scalar values. - Add exhaustive state-machine gates for whitespace collapsing, dot-sequence collapsing, and preset idempotency (single code point + BMP base×combining mark).
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/whitespace.rs | Adds Tier-3 exhaustive gate for collapse_whitespace idempotency + trimming/no-double-space invariants. |
| src/slugify.rs | Adds Tier-3 exhaustive gate proving slug output is ASCII and within [a-z0-9-] for every code point. |
| src/presets.rs | Adds Tier-3 exhaustive preset idempotency gate over all scalar values and BMP base×combining-diacritic pairs. |
| src/filename.rs | Adds Tier-3 exhaustive gate for collapse_dot_sequences over dot patterns and all non-dot code points. |
| src/case_fold.rs | Adds Tier-3 exhaustive gate validating fold_case invariants over every code point. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ariants Follow-up to #523: where an invariant is *local* (decidable per code point or per small window) but guarded only by a random `\PC*` proptest, random generation merely samples the failure space — exactly how the confusables idempotency bug hid for so long. These invariants are bounded and enumerable, so add deterministic exhaustive Tier-3 gates (all `#[ignore]`, run by the `--lib -- --ignored` step wired in #523; ~11s combined in release). No production code changes; all pass — the confusables fix (#523) plus the already-exhaustive case-fold / transliterate layers leave the higher-level transforms clean. - case_fold (`exhaustive_fold_case_invariants`): every code point. fold_case is composition-free and per-code-point, so single-code-point enumeration is a *complete proof* for all strings — idempotency, no residual ASCII uppercase, no drop, ASCII-in⇒ASCII-out. - slugify (`exhaustive_slug_codomain`): every code point. The slug charset is a per-code-point property, so this completely proves `output_is_ascii` and the charset-membership half of `output_charset` (separator *position* stays with the proptests). - whitespace (`exhaustive_collapse_whitespace`): every code point in a run context + every pattern over {SPACE, NBSP, x} to length 7 — the collapse/trim state machine (uniform whitespace handling). - filename (`exhaustive_collapse_dot_sequences`): every dot pattern over {., a} to length 12 + every non-dot code point preserved — the dot-collapse machine. - presets (`exhaustive_preset_idempotency`): every code point (the #498 class) + every BMP base × combining diacritical U+0300–036F (the #523 class), for canonicalize / sort_key / search_key / catalog_key / ml_normalize. Signed-off-by: Richard Quinn <quinn.richard@gmail.com> Assisted-by: Claude Code:claude-opus-4-8
raeq
force-pushed
the
test/exhaustive-tier3-gates
branch
from
July 13, 2026 21:49
d469c7d to
835fe72
Compare
Owner
Author
|
Both addressed in the latest push:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #523. When an invariant is local (decidable per code point or per small window) but guarded only by a random
\PC*proptest, random generation merely samples the failure space — which is exactly how the confusables idempotency bug (#523) stayed hidden until an unlucky CI seed. These invariants are bounded and enumerable, so this adds deterministic exhaustive Tier-3 gates.All
#[ignore](run by the--lib -- --ignoredstep wired in #523), ~11s combined in release. No production code changes — every gate passes, confirming the #523 fix plus the already-exhaustive case-fold / transliterate layers leave the higher-level transforms clean.exhaustive_fold_case_invariantsfold_caseis composition-free + per-code-point ⇒ single-code-point enumeration is a complete proof for all strings (idempotency, no residual ASCII uppercase, no drop, ASCII→ASCII)exhaustive_slug_codomainslugify_output_is_ascii+ charset membership (a per-char codomain property)exhaustive_collapse_whitespaceexhaustive_collapse_dot_sequences.,a} to len 12 + every non-dot code point.., idempotent, single-dot preserved)exhaustive_preset_idempotencycanonicalize/sort_key/search_key/catalog_key/ml_normalizeidempotencyThe proptests stay for multi-cluster / long-range cases the bounded sweeps can't reach.
Assisted-by: Claude Code:claude-opus-4-8