The Algorithm

The whole point of this feed is that you can see how it works. Every number below is imported from the same file the pipeline reads — when we tune the feed, this page changes with it. Nothing here is a press release.

01 · Compiling

One story, not fifteen copies

Every ~15 minutes the feed pulls its sources. Exact duplicates — the same article arriving from different feeds — collapse first: links are stripped of tracking noise and reduced to one canonical address, so a story can only enter once.

Then coverage of the same story is threaded together. Each new report is compared against every thread born in the last 72 hours using word-overlap similarity, with headline words counted — the headline is the story’s identity. Score at least 0.3 against a thread and the report joins it; otherwise it starts a new one. One guard: a report that only echoes a single earlier report must also loosely resemble the thread as a whole (at least 0.12) — that’s what keeps one stray match from chaining unrelated stories into a mega-thread.

Inside a thread, the original is simply the earliest published report — even one that arrives late. That’s the promise: the first report keeps its credit. The headline a thread wears is the original while it’s fresh — and “fresh” follows your dial: the original holds the headline for as long as your chosen window (a 1H view flips a headline older than an hour), up to a ceiling of 24 hours on the widest views. Once it’s past that and newer coverage exists, the newest report takes the headline — a running story reads as its current development, with the first report still credited beneath.

02 · Sorting

Coverage × independence × freshness × velocity

score = log2(1 + reports) × √sources × ½^(hours since last report ÷ half-life) × breaking boost

breaking boost = min(1 + 0.6 × log2(1 + sources per hour since first report), 3)

× 0.25 in the main feed when a story is routine weather (see below)

Every input is counted inside your chosen window — the dial picks the timeframe the math sees. A story that has been running for days counts, on the 5M view, only for the coverage it drew inside that slice — often a single syndicated echo — so a story genuinely breaking now outranks it. Widen to 2D and that same running story’s fuller record counts again, and it climbs back. That’s why the top of the feed actually changes as you turn the dial. Coverage — how much reporting a story has drawn, counted as distinct write-ups: one story syndicated word-for-word to five sites scores as one report, not five. Log-dampened so forty reports isn’t worth forty times one. Independence — how many different outlets are on it: the smaller of distinct outlets and distinct write-ups, so neither sixteen posts from one outlet (a live-blog) nor one identical story on sixteen sites (a syndication chain) counts as sixteen independent sources. This is the heart of the ranking. (The “N reports / M sources” labels on the feed stay the honest raw counts — the discount is a ranking input only.) Freshness — a story’s score halves for every half-life since its last new report, and the half-life scales with your dial: about half the window you’re viewing. On the live front page it’s roughly 30 minutes, so the newest report leads; widen to 2D and it stretches to about 24 hours, so accumulated coverage leads instead. Same stories, re-sorted as you turn the dial — narrow is recency-first, wide is coverage-first. Fresh coverage resets the clock; silence sinks the story. Velocity — how fast a story is gathering independent sources. Three sources in thirty minutes is breaking; three sources in a day is not. Fast-gathering stories get a boost (weight 0.6, capped at , with threads younger than 15 minutes scored as that age) that fades naturally as a thread ages — so brand-new news can reach the top ranks while it is still news.

How freshness fades · per window

full
half
5M · 8m
1H · 30m
2D · 24h

time since last report →

Freshness decay curve per window
WindowRecency half-life
5M8m
1H30m
2D24h

Every story loses half its freshness weight each half-life — and the half-life is set by the window you’re viewing. On the 5M live feed it’s minutes, so the newest report leads and a story two hours quiet is all but gone. On the 2D view it’s about a day, so steady coverage leads and freshness barely moves the order. The dots mark where each curve crosses half — the same story, re-sorted as you turn the dial.

Half-life scales with your dial

Recency half-life per window
WindowRecency half-life
5M8 min
15M15 min
1H30 min
6H3 h
12H6 h
24H12 h
2D24 h

Roughly half the window, floored so the narrow feed doesn’t decay on noise: the front page halves freshness every 30 minutes, the widest view every day. That single knob is what turns the dial from recency-first to coverage-first.

Four story shapes, ranked as the widest (2D) view sees them — wide enough that a day-quiet story still counts, so the established coverage leads. Narrow the dial and the freshness term bites harder: the brand-new story climbs past the big-but-slowing one.

Worked scoring examples computed by the live ranking function
Story shapeReportsSourcesFirst reportLast reportScore
Big story, running all day222012h ago1h ago36.3
Big story, quiet for a day222036h ago24h ago14.0
Brand new, 3 sources in 30 minutes3330m ago6m ago9.3
Single fresh report111h ago1h ago1.6

Computed by the live scoring function, not typed in.

One targeted correction rides on top: routine weather. Regional forecast coverage — heat advisories, storm tracks, watch and warning updates — is syndicated across so many local affiliates that one weather system can score like a national mega-story while being irrelevant outside its area. When more than 50% of a story's in-window distinct headlines (syndicated copies count once, as everywhere on this page) read as forecast coverage and none carries a disaster marker, its score is multiplied by 0.25 in the main feed — visible, not vanished. Disaster-grade coverage (evacuations, landfall, deaths, a state of emergency) is exempt and keeps full reach. Your Local feed does not get this de-rank at all: your own metro's weather still leads there, subject only to the local-dominance rule below.

A second correction applies only to the Local and State desks: local dominance. Those desks qualify any story a local outlet ran, and local outlets carry a great deal of national and global wire, so a single reprint used to be enough to put a story from the other side of the world at the top of your metro feed. A story now reaches a geo desk only when sites from that area are at least 75% of the sites covering it that are either from that area or national, counting each site once and measuring across the story's whole life rather than the window you are viewing. Everything in between is left out of the count on purpose: neighboring metros and statewide outlets when you are looking at a metro feed, other states when you are looking at a State feed, and local sites we have not yet tagged with an area. So a story carried across several Texas cities still reaches each of them. Unlike the weather correction this one excludes rather than de-ranks, so a strongly local story that national wire picks up heavily can fall below the bar.

03 · Showing

What makes the page

The feed opens fresh: bare clocking.news shows the last 1H — the live default everyone sees. Signed in, that window becomes your dial (and you can filter by category): the timeframe selector on the feed — inside the category dropdown at the top of the page — narrows it to 5M (live mode) or widens it step by step out to 2D (the ranking runs fresh at read time on exactly your window’s numbers — see above — so no timeframe ever ranks on stale or out-of-window scores). Every timeframe nests: a wider window holds everything a narrower one shows and more, re-sorted as the half-life stretches. At the narrow end, 5M and 15M are pure nested live notches (5M ⊂ 15M) with the shortest half-lives, so the newest report leads — 5M is a true few-minute window, so it can run quiet between pulls, and the empty state widens you one notch. Freshest-first, honestly labeled; the top 100 make the page and the top 10 get the full treatment — the thread’s headline on top (see above), up to 3 reports nested under it: at most one per outlet AND one per headline (chain-syndicated copies don’t fill two slots), newest first — and when the headline has moved on from the original, the last slot is the first report, labeled (unless the headline itself is a syndicated copy of it — no duplicate). New reports arrive with every pull, roughly every 15 minutes, and the ranking re-runs on each page load (cached for 60 seconds).

The card’s photo can come from any report in the thread. The earliest report — the one that keeps the headline and the credit — is often wire copy that ships without art, so when it has no usable image we borrow one from another article covering the same story: the widest available, and never one small enough to visibly upscale (below that floor the card goes text-only rather than blow a thumbnail up to full width). Only the picture is borrowed — the headline, the link, and the credit stay with the original.

The shared ranking has no engagement weighting and no click optimization: signed out, what you see is coverage, independence, and time — nothing else. Signed in, a For You re-rank — on by default, across the main feed and every category — learns from your taste-tuner answers and your reading, and the Raw Feed toggle is always one tap back to the shared order.

04 · Lean

How we read a story's lean

Every article is read for political lean by its framing — word choice, whose sources and quotes lead, sympathetic versus skeptical treatment of a side — not its topic. A story about immigration or a politician is not inherently left or right; how it is told is. A model reads the headline and summary and calls each article left, center, or right with a confidence, and only the confident calls count. A story syndicated to a dozen sites counts once, not a dozen times — the same independence discount the ranking uses.

In the feed, the label under a headline is that headline’s own lean — not an average of everyone covering the story. That matters because the two can disagree completely: an opinion piece can be firmly left or right while the seventy-odd outlets around it average out to nothing, and averaging is what hides it. When we have no confident call on the article, nothing is shown at all rather than a reassuring “center” we did not earn.

The coverage mix still exists — it moved to the story page, where it describes the thread it is actually about. There we take the net of the thread’s confident calls — (right − left) ÷ total — and place a dot on a left↔right rail. Blue leans left, red leans right, and a quiet hollow grey dot rests at center. A near-even mix stays centered; a real tilt pushes the dot toward that side, farther the stronger it is. A thread needs at least three rated articles before it shows a lean — below that it is too thinly covered to say.

The rail, at three shapes

Leans leftCoverage lean: Leans left. 6 left, 4 center, 2 right.
from 6 left · 4 center · 2 right
from 2 left · 6 center · 2 right
Leans rightCoverage lean: Leans right. 0 left, 1 center, 5 right.
from 5 right · 1 center

Two honest caveats. Most news genuinely reads center — we do not manufacture a slant, and a story shows nothing until it is confidently and substantially rated. And the two numbers answer different questions: the label in the feed is this article’sframing, while the rail on a story page is who is covering the story and how they are telling it. Neither is a claim about who is right. The exact split is one hover away, and the label always says it in words, so it never rides on colour alone.

05 · Accounts

What an account stores

Signed out, the feed is read-only: liking, dismissing, and sharing need a free account, and the timeframe + category dials do too. What you read stays anonymous — what exists is anonymous per-story counts with anonymous screen-time totals, and an anonymous page-view log; none of it is tied to you.

Signed in, four things are stored against your account: headlines you click through on the story lists, stories you 👍, and stories you ✕ (clicks logged per event, with rapid repeat taps of the same link best-effort collapsed; a 👍/✕ keeps its FIRST timestamp — the moment you originally acted is the historical truth) — and, passively, which stories crossed your screen — a running count of registered views (a story registers after being at least half-visible for about a second, once per page load) and a running total of time in view, one aggregate row per story (the faint signal the For-You section below describes). That — plus the small derived taste profile the For-You section explains — is the whole reading-data list; the account itself adds your settings (taste-tuner answers, ZIP, reading mode, optional username), your free-or-Pro tier flag, any comments you post under that username, and the operational minimum every sign-in system carries — your email, session records, and short-lived sign-in-link timestamps. It exists so your history and controls follow you across devices, and the first three are yours to see on your history page (the free tier views the window below; Pro views all time) — the passive screen-time totals feed the For-You math and our own internal product analytics, and have no reader-facing view yet. Free accounts view the last 30 days; everything is kept regardless, so upgrading unlocks your past instantly rather than starting over. Removing an interaction removes it server-side too — with one v1 honesty note: a second signed-in device that still holds the old state can re-sync it back until full tombstone sync ships.

One field joined that list when the ✕ options shipped: which reason you picked — Not my thing, Seen enough of this, Depressing, or nothing at all — is stored alongside the dismissal. Only the first is used, and only to adjust your own feed (see the For-You section below). The rest are recorded and currently feed nothing — no ranking, no aggregate, nothing shared. If that ever changes, this page will say so before it does.

The honest part about aggregate data: what the whole readership clicks and skips is a real future ranking signal (everyone engaging = a boost; everyone skipping = a demote), and if we ever feed it into ranking, the formula on this page will say so explicitly — the same way every other number here is public. Today it feeds nothing.

06 · For You

How your For-You feed works

Signed in, your feed defaults to a personal re-rank of the shared one. It learns from your taste-tuner answers and your reading signals: what you click through, 👍, and ✕ — and, most faintly, which stories crossed your screen as you scrolled and how long they stayed there. The signals are weighted by how deliberate they are: a 👍 or ✕ speaks loudest, a click-through counts several times more than a lingering scroll. One important exception: hiding a story only teaches the feed anything when you tell it to. When you ✕ a story we ask why, and only Not my thing counts as a preference. Choosing Seen enough of this or Depressing — or saying nothing at all — hides that story and changes nothing else. That is deliberate: reacting honestly to grim news should not quietly build you a feed with the grim news taken out. From those it keeps a small taste profile on four axes: the desks you read, the lean you tend toward, how meaty you like the headline-and-blurb to read (heft, not article length), and how fast-moving you like your stories.

The mechanics are one line: every story gets an affinity score between 0 and 1 for you, and its neutral position weight is multiplied by (1 + 3 × affinity). Affinity is a fixed blend — 55% topic match, 20% lean proximity, 12.5% headline heft, and 12.5% pace. Topic dominates on purpose: what a story is about matters more than how it reads. Your profile re-learns from fresh activity at most every 2 minutes, so a few dismissals this morning reshape this afternoon's feed.

The honesty rules: the re-rank only reorders what the shared ranking already surfaced — it never adds or removes a story. It runs on every view, category desks included, and the Raw Feed toggle is always one tap back to the shared order. Your Local desk never feeds the topic side of your taste profile — reading your own metro's news is geography, not preference, and treating it as a topic would flood your feed with anything labeled local (local reads still inform the lean/length/pace axes like any other story). And there is no engagement-optimization loop: nothing is boosted because other people clicked it, and every signal above exists to guess what you want to read — not to maximize your time here.

07 · Next

These controls become yours

The plan is for readers to own this page: source toggles, tunable weights, and a view of your own reading model — user-controlled, fully visible, always explained. Transparency isn’t a feature of this feed; it’s the point.