fix: prevent canonical-csv merge from collapsing distinct conferences - #404
Merged
Merged
Conversation
A canonical-csv run (d76e737) renamed PyCon South Africa to PyCon Africa and deleted the real PyCon Africa entry. Root cause: conference_scorer takes the max of several fuzzy strategies, and token_set_ratio returns 100 whenever one name's tokens are a subset of the other's - so 'PyCon South Africa' vs 'PyCon Africa' scored 100 and was auto-merged as an 'exact' match with no confirmation. Both YAML rows then mapped to the same remote row and were collapsed into one by deduplication. Fixes: - fuzzy_match only auto-merges when names are genuinely identical; score-100-but-different pairs now go through the confirmation path, which defaults to 'no' in CI - remote rows already claimed by an identically-named YAML entry can never be fuzzy-merged by another conference - add PyCon Africa <-> PyCon South Africa to rejections.yml - add utils/check_data_loss.py and a workflow step that fails the canonical-source-update run before committing if any (conference, year) entry disappears from the data files - regression tests reproducing the incident Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH
TBA enrichment's generic Mastodon fallback accepted any URL with '/@' in the path, so a venue map link like google.com/maps/place/Venue/@52.386807,4.8698442,17z was written into the mastodon field (29e9231, FastAPI Conference). The generic fallback now requires the path to be exactly /@handle (or /@user@instance). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH
Upstream sources sometimes fill every URL column with the conference homepage (e.g. python-organizers' Proposal URL gave PyCon DE 2027 'cfp_link: https://2027.pycon.de/'). A cfp_link/sponsor/finaid identical to the main link carries no information, so the sort pipeline now drops them. URLs only count as identical when they differ at most by scheme, 'www.' prefix, or trailing slash - a different path, subdomain, query, or #anchor is a different pointer and survives. Existing offenders on main (PyCon Hong Kong cfp_link, PyCon Greece finaid, PyCon Italy finaid, PyCon Germany finaid) will be cleaned by the next recurring sort run. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH
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.
Root cause analysis
A canonical-csv run (d76e737) renamed PyCon South Africa to PyCon Africa (grafting on africa.pycon.org sponsor/finaid/youtube links) and deleted the real PyCon Africa (Kampala, Uganda) entry.
Why it happened:
conference_scorertakes the max of several fuzzy strategies.token_set_ratioreturns 100 whenever one name's tokens are a subset of the other's —token_set_ratio("pycon africa", "pycon south africa") == 100(verified;token_sortis 80, plainratio80,partial74).fuzzy_matchtreated any score>= EXACT_MATCH_THRESHOLD (100)as an exact match and auto-merged with no confirmation prompt — so the CI-safe "default to no" path inquery_yes_nonever got a chance to reject it.title_matchindex, and were silently collapsed into one chimera row bydeduplicate()(bfill().ffill().iloc[0]).The existing
rejections.ymlmechanism would have prevented this (it's checked before the exact-match branch), but the pair wasn't listed — this is the same class of bug as the already-listed PyCon Austria / PyCon Australia collision.Fixes
utils/tidy_conf/interactive_merge.pyutils/tidy_conf/data/rejections.yml— addedPyCon Africa↔PyCon South Africa/PyCon ZA/PyConZAas a known false-positive pair.utils/check_data_loss.py+canonical-source-update.yml— new workflow step after the merge scripts that fails the run before anything is committed if any(conference, year)entry disappeared fromconferences.yml/archive.yml/legacy.yml. Verified it flags the actual d76e737 diff (PyCon South Africa (2026)missing) and passes on identity.tests/test_fuzzy_match.py— two regression tests reproducing the incident (with and without the identically-named YAML entry present); both conferences must survive with their own data.Second bug: Google Maps link detected as Mastodon profile
The TBA-enrichment commit on the same PR (29e9231) wrote
mastodon: https://www.google.com/maps/place/Transformatorhuis/@52.386807,...onto the FastAPI Conference entry. The generic Mastodon fallback inutils/enrich_tba.pyaccepted any URL with/@in the path — and Google Maps viewports are/@lat,lng,zoom. The fallback now requires the path to be exactly/@handle(or/@user@instance), with regression tests intests/test_youtube_extraction.py.Third fix: sub-page links that just repeat the homepage
Upstream sources sometimes fill every URL column with the conference homepage — python-organizers' Proposal URL gave PyCon DE 2027
cfp_link: https://2027.pycon.de/, and main has more (PyCon Hong Kongcfp_link, PyCon Greece / PyCon Italy / PyCon Germany 2026finaid). Acfp_link/sponsor/finaididentical to the mainlinkcarries no information, so the sort pipeline (drop_redundant_link_fieldsinutils/tidy_conf/links.py, wired intosort_yaml.py) now drops them. URLs count as identical only when they differ at most by scheme,www.prefix, or trailing slash — a different path, subdomain, query, or#anchoris a different pointer and survives (e.g. PyCon SG'ssponsor: …/index.html#sponsors). Existing offenders on main get cleaned by the next weekly recurring-sort run; new ones are dropped before every automated commit. Tests intests/test_redundant_links.py.Testing
tests/test_fuzzy_match.py: 18 passed (16 existing + 2 new);test_interactive_merge.py: all pass;test_youtube_extraction.py: 10 passed (8 existing + 2 new);test_redundant_links.py: 13 new tests pass.main(the failures there are pre-existing environment/version artifacts, none touched by this change).The corresponding data repairs for the open conference-updates PR were pushed separately to
auto/conference-updates(53e458a, ec8011a, fba6015). Note: until this PR is merged, a canonical-csv webhook run could still re-introduce the bad merge, since the workflow runs the merge scripts from the accumulator branch's code.🤖 Generated with Claude Code
https://claude.ai/code/session_019bLVuyt4qdsvSpucA2qvgH