Lab is where emerging methods, unconventional ideas and new analytical techniques are tested against real-world media data. It is a space for researchers, technologists, academics and curious minds to explore what might come next, collaborate on live experiments, and help shape which ideas move from research into product.
An experiment run against real CivicSignal data: bucket articles by time, link them by shared entities, and see what structure falls out — without a single LLM call deciding which stories connect. This section documents the method, a failure mode it took two tries to avoid, and three real chains it actually found.
CivicSignal's Major Events panel groups articles that are almost certainly about the same real-world incident — shared entities, a tight date window, a minimum bar of independent publishers. That answers "did multiple outlets cover this?"
This experiment asks something else: can individual stories be linked across a longer window to see a narrative move — a demand, then a response, then a consequence — even when the entities only partially overlap from one link to the next? And separately: can we tell, without reading the text ourselves, whether two linked articles are actually the same report re-published, or a genuinely new development?
This was built, run, and re-run as plain code against content.db. Anyone can re-run the same script on the same data and get the same graph.
extract_entities.py via spaCy's en_core_web_sm model. Not this experiment's work, and not an LLM — a real, offline, free NER model.set_a & set_b and a length check — no text is read at this step.difflib.SequenceMatcher, the Ratcliff/Obershelp algorithm — string matching, not meaning) and the share of the later article's entities that are genuinely new. High title similarity → labeled duplicate/republished. Low similarity but mostly new entities → new development. Neither → ambiguous.Run against 1,075 real "Conflict & Security" articles from Nigeria (three weeks, Aug 2026) with loose settings — any 2 shared entities, a 10-day window, a weak frequency cutoff — one single connected component swallowed 649 of the 1,075 articles. Not a narrative graph, just a blob: everything touches everything eventually once "the Nigeria Police Force" or "Abuja" counts as a real link.
| Setting | Max entity freq. | Min shared entities | Day window | Result |
|---|---|---|---|---|
| Too loose | >3% of corpus | 2 | 10 days | one 649-article blob |
| Tightened | >1.5% | 3 | 7 days | 140 components, largest 31 |
| Used below | >1% | 3 | 5 days | 157 components, largest 10 |
This is the same anti-chaining problem CivicSignal's Major Events detector already solves in production (detect_events.py's MAX_ENTITY_DF / MIN_SHARED_ENTITIES safeguards) — this experiment just re-discovered why those exist by hitting the same wall first.
Each dot is a real published article, positioned chronologically top to bottom. Each line is a real computed edge between two articles that shared 3+ surviving entities within 5 days of each other, colored by the duplicate/development label above.
Mostly green toward the end — a demand from Northern senators (Aug 21) evolves into a government response and a named appointment to a policing working group (Aug 25–26), with genuinely new entities entering at each step.
Starts almost entirely amber — five outlets reporting the same killing within hours, high title similarity, few new entities — then shifts as arrests are reported a day later.
A genuine mix, not a clean verdict either way — some links are near-identical rewrites (amber), others introduce a different suspect's name or detail the metric correctly flags as new (green). The first read of this chain called it "just duplicate coverage"; the actual metric says otherwise.
A second, related question: not "did this story develop," but "how does it cast its actors" — and does that casting cluster into recognisable patterns across outlets, before anyone tells the model which outlet leans which way. Adapted from published methods (Chambers & Jurafsky's narrative event chains and narrative schemas; Das et al.'s structured clustering (code), ACL 2026), tested here against a real, independently-labelled corpus.
The same event can cast the same actor as protector in one outlet and threat in another — "police restore order" versus "police crack down." This experiment annotates each article's actors as Hero, Threat, Victim or Neutral, then clusters articles so that stories with genuinely conflicting casts of the same actor are pushed apart ("cannot-link" constraints) rather than lumped together by topic alone. Outlet identity and any bias label are withheld from the clustering step, and only checked afterward, against the resulting clusters.
Rather than invent an example, this ran against the Narrative Frames Corpus (Frermann, Li, Khanehzar & Mikolajczak, ACL 2023) — 428 English-language climate-change articles from the NELA news archive, human-coded for Hero/Villain/Victim roles, Media Bias/Fact Check (MBFC) rating and topical frame. A balanced 45-article subset (15 right-leaning, 15 left-centre, 15 left-leaning by MBFC) was clustered with and without the role constraints:
Semantic-only clustering vs. role-constrained clustering — higher means actors keep a more consistent role within their assigned cluster.
Cases where two stories with conflicting actor roles still ended up in the same cluster — fewer is better.
Stories sharing an identical full role assignment, clustered together — this went down, not up. Not every metric improved.
Seven named clusters came out legible enough to read directly — real outlets, real dates, real role counts, no synthetic examples:
Fox News (2019-02-05) · PoliticusUSA (2019-05-14) — the same policy push cast as economic threat by one outlet, mobilising response by the other.
Mother Jones (2019-07-31) · The New York Times (2019-05-21) — government and policy cast as Hero, climate impact as the Threat.
BBC (2019-04-29) · PBS (2019-05-27) — nature and local communities cast as Victim; fire/deforestation as Threat.
The Daily Caller (2019-03-13) · CBS News (2019-09-06) — state and industry actors split between Hero and Threat depending on outlet.
Numbers and cluster labels above are a specific reproduction run, not a claim of exactly replicating the original Das et al. paper's own reported results.
Real CivicSignal data, working methods and honest failure modes — open for a joint study, a pilot integration, or a second opinion.