safishamsi and Claude Opus 4.8
0929519ec1
fix(ids): make normalize_id caseless-stable via a casefold+NFKC fixpoint loop
...
casefold and NFKC do not commute and neither is a fixpoint of the other, so a
single NFKC(casefold(...)) pass left normalize_id(s) != normalize_id(s.casefold())
for some combining-mark sequences (e.g. Greek ypogegrammeni U+0345 + a combining
accent): pre-casefolding turned U+0345 into iota, which NFKC then composed with
the accent into a form the single pass never saw. Iterate casefold-then-NFKC to
a bounded fixpoint (casefold first, on the raw input) so the result is stable
regardless of prior casefolds. No churn: letter/digit-bearing ids and every
CONTRACT_CASE are byte-identical; idempotency, word-only, and the Turkish (#2614 )
cases still hold. Adds a deterministic regression pin so the fix does not rely on
hypothesis re-drawing the codepoints.
This was a pre-existing latent bug (present in released 0.9.45), surfaced by the
hypothesis property test; ids.py was untouched by the PRs landed alongside it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-08-17 19:00:46 +01:00
..
2026-08-17 16:05:33 +01:00
2026-07-15 15:09:17 +01:00
2026-08-12 20:56:28 +01:00
2026-08-15 17:16:53 +01:00
2026-07-11 11:52:12 +01:00
2026-07-30 17:13:48 +01:00
2026-08-13 14:17:41 +01:00
2026-08-12 20:57:39 +01:00
2026-07-26 11:52:20 +01:00
2026-08-12 20:56:28 +01:00
2026-07-27 10:46:47 +01:00
2026-08-12 14:20:21 +01:00
2026-07-20 13:29:54 +01:00
2026-08-06 17:29:18 +01:00
2026-08-13 14:17:42 +01:00
2026-08-13 13:30:24 +01:00
2026-08-06 17:29:18 +01:00
2026-07-14 13:19:16 +01:00
2026-07-16 23:48:07 +01:00
2026-07-15 13:13:30 +01:00
2026-08-08 23:37:49 +01:00
2026-07-18 19:07:16 +01:00
2026-07-12 23:57:16 +01:00
2026-08-07 22:49:25 +01:00
2026-07-18 19:07:16 +01:00
2026-08-05 22:08:29 +01:00
2026-08-12 20:56:28 +01:00
2026-07-18 12:04:23 +01:00
2026-08-05 22:08:29 +01:00
2026-08-05 01:41:12 +01:00
2026-08-17 15:35:53 +01:00
2026-08-10 18:06:50 +01:00
2026-08-17 15:36:14 +01:00
2026-08-11 20:09:59 +01:00
2026-07-17 00:09:02 +01:00
2026-07-30 17:13:48 +01:00
2026-08-14 14:26:12 +01:00
2026-08-13 14:17:42 +01:00
2026-07-13 10:29:26 +01:00
2026-08-08 23:37:49 +01:00
2026-07-22 18:40:11 +01:00
2026-08-15 16:46:04 +01:00
2026-07-20 16:35:14 +01:00
2026-07-29 17:02:00 +01:00
2026-07-30 17:13:48 +01:00
2026-08-16 18:35:46 +01:00
2026-07-20 15:35:40 +01:00
2026-07-27 10:46:47 +01:00
2026-07-18 19:07:16 +01:00
2026-08-17 17:53:43 +01:00
2026-08-05 22:08:29 +01:00
2026-08-05 22:08:29 +01:00
2026-08-16 18:28:53 +01:00
2026-08-17 19:00:46 +01:00
2026-08-17 15:40:19 +01:00
2026-08-12 20:56:28 +01:00
2026-07-20 11:29:22 +01:00
2026-07-25 22:53:43 +01:00
2026-08-13 14:21:22 +01:00
2026-07-27 10:46:47 +01:00
2026-08-11 15:18:33 +01:00
2026-08-11 16:54:35 +01:00
2026-08-15 16:43:11 +01:00
2026-08-13 13:30:24 +01:00
2026-08-15 20:11:13 +01:00
2026-07-28 09:37:39 +01:00
2026-08-05 01:41:12 +01:00
2026-08-13 14:17:42 +01:00
2026-08-16 18:34:11 +01:00
2026-08-15 21:54:36 +01:00
2026-08-06 17:29:18 +01:00
2026-08-09 23:19:08 +01:00
2026-08-10 18:07:20 +01:00
2026-08-14 14:49:56 +01:00
2026-07-30 17:13:48 +01:00
2026-08-12 14:20:21 +01:00
2026-07-25 23:16:52 +01:00
2026-08-11 15:18:12 +01:00
2026-08-01 12:21:04 +01:00
2026-08-07 22:49:25 +01:00
2026-08-17 18:42:21 +01:00
2026-08-11 16:54:35 +01:00
2026-08-11 16:54:35 +01:00
2026-07-17 10:54:07 +01:00
2026-08-05 22:08:29 +01:00
2026-08-09 23:19:08 +01:00
2026-07-29 17:25:08 +01:00
2026-08-13 14:20:36 +01:00
2026-08-01 11:36:30 +01:00
2026-08-10 18:06:50 +01:00
2026-08-10 18:06:50 +01:00
2026-08-10 18:06:50 +01:00
2026-08-14 21:09:32 +01:00
2026-08-08 23:37:49 +01:00
2026-08-05 22:08:29 +01:00
2026-08-11 14:40:01 +01:00
2026-07-16 16:36:49 +01:00
2026-08-12 14:20:21 +01:00
2026-07-18 12:03:47 +01:00
2026-08-17 15:33:34 +01:00
2026-07-25 22:53:43 +01:00
2026-08-13 13:30:24 +01:00
2026-07-21 21:45:53 +01:00
2026-08-01 11:36:30 +01:00
2026-07-12 10:36:00 +01:00
2026-07-28 09:37:39 +01:00
2026-08-17 15:25:39 +01:00
2026-08-13 13:30:24 +01:00
2026-08-01 15:36:17 +01:00
2026-07-28 09:37:39 +01:00
2026-07-18 19:07:16 +01:00
2026-07-18 19:09:53 +01:00
2026-07-16 23:36:49 +01:00
2026-07-15 15:14:34 +01:00
2026-07-29 17:02:00 +01:00
2026-08-17 18:30:50 +01:00
2026-07-25 22:53:43 +01:00
2026-08-07 22:49:51 +01:00
2026-07-21 14:22:50 +01:00
2026-07-27 10:46:47 +01:00
2026-08-11 14:40:01 +01:00
2026-07-25 15:44:50 +01:00
2026-07-27 10:22:48 +01:00
2026-08-09 23:19:08 +01:00
2026-08-07 22:49:25 +01:00
2026-08-11 15:18:12 +01:00
2026-08-08 23:37:32 +01:00
2026-07-14 23:32:02 +01:00
2026-07-27 10:46:47 +01:00
2026-07-26 11:52:20 +01:00
2026-08-01 11:36:30 +01:00
2026-08-16 19:22:06 +01:00
2026-08-14 14:21:34 +01:00
2026-08-14 14:20:04 +01:00
2026-08-11 14:40:01 +01:00