fix(clustering): re-title events from their cluster, not their seed article - #75
Merged
Merged
Conversation
…rticle An event's title was the title of whichever article created it, and nothing ever updated it as the cluster grew. The summary, regenerated from every article, follows the majority story — so a cluster seeded by one story and later dominated by another ends up with a headline its own summary contradicts. Production had an 18-article event titled "Adjuncta șefului cabinetului lui Zelenski a fost arestată" whose other 17 articles, and its summary, were about the CIA director's visit to Moscow. A 7-article event titled with an Oana Țoiu CNN quote carried a summary about Nicușor Dan's Fox News editorial. Roughly 4-6% of recent events were affected. lib/eventTitle.ts picks the medoid of the cluster's article titles under token overlap: the majority story's titles score high against each other, the outlier scores near zero. Pure string logic — no embeddings, no model call — and it runs inside summarization, which already holds every article, so it costs no extra reads. A rename needs to beat the incumbent by a margin so near-ties cannot flip a published headline back and forth. Title and summary are now written in the same patch from the same inputs, which is the invariant that was missing. `slug` is deliberately left alone: it is the permanent URL and is already shared and indexed, so a repaired event keeps its old slug. Adds retitleDivergentEvents to repair events already stored, and tests built on the real Moscow cluster. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MpkuigW6T4N1exXip6bRp
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
flvvius
added a commit
that referenced
this pull request
Aug 27, 2026
The margin-based rule shipped in #75 over-fired. A dry run of the backfill renamed 52 of 200 events (26%), and the samples showed why: most were same-story swaps, e.g. "Două explozii la Damasc, lângă hotelul unde a fost cazat Macron" replaced by "Explozii la Damasc, lângă hotelul în care este cazat Macron". That is churn on a published headline, not a repair. Calibrating against 26 production clusters showed the discriminator is the incumbent's absolute centrality, not its gap to the winner: Zelensky -> Moscow incumbent 0.014 genuine divergence Oana Țoiu -> Nicușor Dan incumbent 0.014 genuine divergence Damen Mangalia shipyard incumbent 0.163 same story Air alert incumbent 0.158 same story Helicopter / cable car incumbent 0.086 same story A title is now treated as the outlier only when it shares essentially nothing with its cluster (< 0.05), the replacement is itself representative (>= 0.05), and it dominates by 3x rather than edging ahead. Both real divergent events still get renamed; the same-story swaps no longer do. Adds the Damascus cluster as a churn regression test. Claude-Session: https://claude.ai/code/session_012MpkuigW6T4N1exXip6bRp Co-authored-by: Claude <noreply@anthropic.com>
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.
Summary
Fixes events whose title and summary describe different stories.
Root cause
An event's title is the title of whichever article created it, and nothing ever updated it as the cluster grew (
clustering.tssetstitleatinsert("events")and never patches it). The summary, by contrast, is regenerated from every article in the cluster.So when a cluster is seeded by one story and later dominated by another, the summary follows the majority and the title does not.
Two production examples:
Roughly 4–6% of recent events were affected. (A naive title/summary word-overlap scan reports more, but many are false positives — the prompt mandates paraphrase, so low overlap is often correct.)
Fix
lib/eventTitle.tspicks the medoid of the cluster's article titles under token overlap: the majority story's titles score high against one another, the outlier scores near zero. In the Moscow cluster the seventeen Moscow headlines sharemoscova/ratcliffe/directorul; the lone arrest headline shares almost nothing and loses.RETITLE_MARGINso near-ties cannot flip a published headline back and forth as articles trickle in.slugis deliberately not touchedIt is the permanent URL and is already shared and indexed. A repaired event keeps its old slug and gains a correct title; changing slugs would break shared links, canonicals and the sitemap.
Backfill
retitleDivergentEventsrepairs events already stored, which would otherwise keep a wrong headline until something happened to re-summarize them. Paginated,dryRun: trueby default, returns before/after samples.Testing
338 passed, 4 skipped across 40 files. New tests are built on the real Moscow cluster: the outlier scores lowest, the event gets renamed to a Moscow headline, a coherent cluster is left alone, small clusters never rename, and unrelated titles don't oscillate.
Also fixed two bugs in my own stopword list before shipping: a stray Cyrillic token, and
china— which would have stripped a meaningful word from headlines.🤖 Generated with Claude Code
Generated by Claude Code