This article is part of the SaskPoly story. Read how it all started.
The Loop, Part 1: The Clock — One Machine Instead of Six Alarms
Every prediction this site makes flows through one daemon that ticks every six hours, walks nineteen stations on an assembly line, grades its own homework, and leaves a heartbeat where anyone can see it — this is the machine behind the picks, explained for people who don't gamble.
At 8:28 this morning the machine woke up, walked nineteen stations on an assembly line, graded its own homework, filed a report on itself, and went back to sleep. It does this four times a day. It has done it 81 times since September. This post is about the machine — what it is, why it is one machine instead of many, and what it does when something breaks. No team names are required. The machine is indifferent to all of them, which is the entire point.
The problem: six alarms nobody hears
Most prediction setups are not systems. They are collections. A cron job that fetches odds at 9 AM. A script someone runs by hand when they remember. A spreadsheet with a formula nobody dares touch. Each piece works alone, fails alone, and — this is the expensive part — fails silently. The odds script breaks on a Tuesday and nobody finds out until Saturday's pick comes from stale numbers.
We had the scattered version. Replacing it took one decision, made on
2026-09-07: one clock owns everything. Not a pile of independent cron
entries — a single daemon, clock.py, that walks a fixed chain of phases
every tick. If you have ever worked a conveyor line, you already understand
the architecture. One belt. Stations in order. A part that fails at station
four does not stop the belt — it gets logged, and the belt carries on to
station five.
What one tick looks like
A tick runs every six hours (21,600 seconds — precise timing matters less than never being down for long). Each station does one job:
| Station | What it fetches or does | Source |
|---|---|---|
| fetch_mlb / fetch_cfl / fetch_nfl / fetch_nflverse | today's schedules, standings, playoff stakes, NFL history | MLB Stats API, cfl-sdk, nflverse, ESPN |
| fetch_lines | the betting board, scraped in one browser pass | SportSelect PRO•LINE via Playwright |
| fetch_injuries | the daily per-team injury digest | nflverse injuries release + scraped CFL reports |
| fetch_news / fetch_odds_espn / fetch_outcomes / fetch_funding | news signals, US-book consensus, prediction-market prices, funding rates | NewsAPI, ESPN, Hyperliquid, Hyperliquid |
| teaser / predict | builds teaser cards, logs prediction rows | the loop's own engines |
| audit | re-derives from raw data what predict should have written | read-only verifier |
| settle | grades finished games, computes scores | same snapshots, finals included |
| recap / render / content | the nightly write-up, the daily sheet, draft articles | the ledger |
Nineteen stations, one belt. The slowest station is the odds scrape at 30 to 60 seconds of browser automation. The whole tick finishes in about two minutes.
Failures are data
Here is the rule that makes the machine trustworthy: a phase that fails
returns failed with the error string, and the chain continues. When the
odds site changes its layout and the scrape dies — and scrapes die; that is
what scrapes do — the tick records the failure and predicts anyway, with the
market columns honestly blank rather than quietly stale. When the news API
rate-limits, the phase waits for the next tick rather than hammering it.
(We learned that one empirically: six rapid requests got this IP address
banned for an hour. Now the phase makes one polite request per tick. Failed
is data, and the next tick picks it up.)
After every tick the clock rewrites a heartbeat — last run, status, tick count, every station's result — into the living state file, and appends a row to an append-only ledger of ticks going back to day one. Eighty-one ticks. Every one accounted for. A machine that files a report on itself every six hours has nowhere to hide, which is exactly the design intent.
The confession: the night the clock ate the ledger
Honesty is cheaper than discovery, so here is the system's worst night. On 2026-09-08 the long-running daemon was holding old code in memory while the ledger's schema had changed on disk. The settlement phase crashed on the new column — and the crash came after the file-open had already truncated the prediction ledger. Twenty-three rows, gone, including a graded win.
The rows were reconstructed from a verbatim session dump, every one marked "reconstructed" in its own lesson column, and the lesson was mechanized: any long-running process gets restarted after a schema change, every time, no exceptions. The rebuilt ledger now carries 199 rows and the audit phase — added the following week — re-derives from the raw snapshots what predict should have written. Its first live run flagged 31 malformed row IDs the same night. Caught, fixed, backed up, green since. The belt did not stop, and the fix is now part of the belt.
Nothing publishes itself
One boundary deserves its own paragraph, because it is the one we will not relax: the loop never publishes and never wagers. The daily sheet is a local file. The article drafts it generates go to a review folder; a human edits them before anything reaches this site. Stakes live on the sheet as accounting, not instructions — the machine prices tickets, it does not buy them. The deploy button is a human's hand on it, the same way the pencil at the pool is. Anyone selling you a system that skips that step is selling a story.
The series
This was the clock. The rest of the machine, one concept at a time:
- Part 2 — The Ledger: what a prediction row actually is: a binary question, an explicit probability, both sides of the case, and a grade that follows it forever. /articles/the-loop-part-2-the-ledger
- Part 3 — The Rules: how a cold, uncalibrated model picks bets without lying to you — and the night it discovered it had been pricing the wrong ticket all season. /articles/the-loop-part-3-the-rules
- Part 4 — The Teaser Engine: buying points instead of predicting games, and why the number six is the whole business. /articles/the-loop-part-4-the-teaser-engine
- Part 5 — The Gates: the same discipline, pointed at trading desks — rules that say GO or NO-GO and then grade themselves. /articles/the-loop-part-5-the-gates
One belt, nineteen stations, a report card every six hours. The picks get the byline. The clock does the work.