Newsroom — About the project

Inspiration

I grew up watching two Indias on the same television. On the screen, a protest was a "law and order problem," a mob, a nuisance blocking traffic. On the ground — where a cousin actually stood — it was farmers, students, and ordinary people asking a question the anchor never repeated. When the farmers sat on the borders of Delhi for months, prime-time told one story; the fields told another. When neighbourhoods were reported as riots, groups like Citizens for Justice and Peace spent years documenting what the cameras had already decided.

Two things broke my trust for good. First, there were never any corrections. A channel could be flatly wrong at 9 p.m. and simply move on by morning — no retraction, no accountability, the false frame left standing as the record. Second, the people in the story had no way into it. A citizen with a photo, a witness with a video, a whole district saying "this is not what happened" — none of it counted. The loudest microphone won, and it wasn't theirs.

So the question that started this project was simple: what would news look like if no editor — biased, bought, or just tired — got to decide what was true, and if the people on the ground could put their evidence on the record and watch it be verified in the open?

What it does

Newsroom is verified open media for India, with no human editor — only rules anyone can read. Citizens submit reports; a deterministic desk corroborates them against each other and against official sources (PIB, RBI, SEBI, MyGov); verified stories return to a public feed carrying their full evidence chain, links to the originals, and — when later evidence contradicts them — a visible, automated correction. An AI anchor reads the verified news aloud, and every sentence it speaks is journaled on the record, linked to the evidence behind it.

The core promise is that truth is decided by counting, not by opinion. A claim is only promoted when independent sources agree:

$$\text{verified} \iff (\text{distinct corroborating sources}) \ge 2$$

For citizen reports, significance climbs a published ladder on the number of distinct submitters $n$ (with one device or one coordinated burst counting as a single citizen):

$$ \text{tier}(n)= \begin{cases} \text{community report}, & 3 \le n < 10\ \text{news}, & 10 \le n < 50\ \text{urgent}, & n \ge 50 \end{cases} \qquad\text{(a single official source short-circuits to an attributed fact).} $$

Reputation is earned, not bought. Credibility is accuracy over a track record,

$$c=\frac{\text{earned}}{\text{earned}+\text{lost}},$$

and it buys only priority in the queue — never a vote on what is true. And a correction fires when new evidence genuinely replaces the old story rather than merely adding to it — when most of the original entity set disappears:

$$\frac{|E_{\text{old}}\cap E_{\text{new}}|}{|E_{\text{old}}|} < 0.5 .$$

How I built it

The whole system was implemented with Codex running GPT‑5.6, driven by a spec‑first, review‑gated loop: I wrote the design and task briefs, Codex built each task end to end, I reviewed every diff, and fixes went back as their own tasks. Codex produced, in order:

  • The platform (T1–T8): FastAPI + Postgres, citizen submissions with media and anti‑abuse dedupe, a NATS JetStream ingest adapter, the tier‑ladder verifier, points, the public feed, and an operator kill switch.
  • Fixes from review (F1–F6): growth‑safe corroboration, once‑per‑tier point awards, a stranded‑submission sweeper, evidence‑weighted credibility bands, and a self‑healing demo.
  • The web app (U1–U7): the feed, story pages with the evidence ledger, the submit flow, the My Reports status ladder, media, and the AI anchor — bulletin playback plus a grounded, citation‑only voice Q&A.
  • The design pass (D1): our Iron design system applied across the UI.

Underneath, everything runs on Iron, an agent runtime with durable, journaled flows and event‑sourced memory, so the pipeline — collect → corroborate → publish → correct — survives crashes and never double‑files or double‑pays. The newsroom "mesh" is just declarative flows the runtime executes; the LLM only reconciles entities and writes prose, and is never allowed to decide truth.

What I learned

  • Neutrality is an architecture, not a promise. The moment a model is allowed to decide what counts as verified, you've rebuilt the biased editor in code. Making the tier ladder deterministic — and keeping the LLM strictly to phrasing and ranking — is what makes the claim of impartiality actually true.
  • Corrections are a feature, not an embarrassment. Designing the correction path as a first‑class, public event flipped my instinct: the honest thing to show off is the system correcting itself, timestamped, in the open.
  • Trust is legible or it's nothing. People believe a story when they can see why — "52 citizens and RBI," with links to the originals — not when a brand tells them to.
  • Working with Codex is a discipline of specs. GPT‑5.6 was fastest and safest when I handed it a precise contract and reviewed the diff; vague asks produced plausible code that quietly broke invariants.

Challenges I faced

  • Making "same story" mean the same thing. Deciding when two reports — one a citizen's sentence, one a press headline — are the same event took a fingerprinting scheme plus a token‑overlap merge, all deterministic and unit tested, so grouping could never become a hidden editorial judgment.
  • Punishing growth by accident. An early version treated a story gaining corroborators as a "contradiction," publicly correcting and penalising its own success. The fix — the containment rule above — only fires on genuine replacement, never on support.
  • Money and truth must be idempotent. Under a durable runtime that retries, the same story could pay points twice or file a claim twice. Getting once‑per‑tier awards and physically impossible re‑filing right, on both the runtime and database sides, was the difference between a demo and a system.
  • The boring failures were the real ones. The single hardest bug wasn't in the algorithm — it was a runtime call whose fifth positional argument was silently the wrong one, breaking event de‑duplication; and a config typo that crashed the catalog builder at boot, so nothing new ever took effect while the tests stayed green. Rehearsing the full stack end‑to‑end, not just unit tests, is what caught them.
  • A voice that sounds human, for free. Browser text‑to‑speech was robotic and unlistenable, and there was no paid voice key. I proxied a free, no‑key voice (with Hindi support) through the platform so the anchor sounds like a person — and the whole system still runs with zero API keys.

The result is a newsroom that a district could actually use: submit what you saw, watch it be verified in the open against everyone else and against the official record, and — if it turns out wrong — see it correct itself, publicly, on the record. The thing television never did.

Codex /feedback session ID: 019f84f1-d117-7df1-94c9-347b366ed9b8

Built With

Share this project:

Updates