The AI Read
← Latest
Method

Runbook

26 min read
7 items · 13 citations · 5 primary · 5 secondary · 2 weaker · 1 contested

Operating instructions for scheduled runs of The AI Read. Each scheduled run starts in a fresh session with no memory of previous ones, this document is the entire context.

Read METHODOLOGY.md for the filter, source tiers and editorial standards, VOICE.md for how it has to read, and PERSONAS.md before writing any editorial. This runbook is the procedure.


0. Preflight (every run)

git fetch origin
BRANCH=main
git checkout main && git pull origin main
if [ ! -f docs/RUNBOOK.md ]; then
  BRANCH=claude/ai-landscape-research-reports-abvy4w
  git checkout "$BRANCH" && git pull origin "$BRANCH"
fi
date -u +%F        # NEVER assume the date from training data
python3 tools/predictions.py check

If you land on the fallback branch, say so in the run summary, the site won't deploy until main has it. If neither branch has this runbook, stop and report.


1. Daily brief

Two a day. AM is the full brief. PM catches up on what broke since.

OutputLengthBudget
AMreports/daily/YYYY-MM-DD-am.md20+ stories~35–50 searches
PMreports/daily/YYYY-MM-DD-pm.md20 stories is the target, fewer is fine~20–30 searches

Why two. A reader opens a trusted site in the morning, and around the middle of the day wonders what is new, because there always is something. A site that never moves past breakfast teaches them to check once and forget it. The afternoon brief is there to reward the second visit.

Which means the PM has one job it cannot fail at: being new. A reader who comes back at three and finds the morning's five stories restated stops coming back at three.

  • Same-day repeats need the Update marker. A story from the AM brief may appear in the PM only if it has genuinely moved, and the item has to lead with **Update.** and say what changed. python3 tools/dedupe.py compares every item against the last two days of briefs and fails the run on an unmarked repeat.
  • The PM may be short. Three items on a quiet afternoon is an honest answer. Padding is the failure, not brevity.
  • The PM drops sections it has not earned. No Editorial: the day's argument was made in the morning.
  • Aim for twenty in the afternoon too, and take fewer without apology when the afternoon did not produce twenty.
  • Both halves carry the same byline. It is one person's day and the afternoon piece is their follow-up on it.
  • The AM run owns the three libraries. The floors in catalog.py brief are per day, and the morning run is what clears them. The PM adds to them opportunistically.
  • Sunday runs all three. The weekly is a retrospective on the week; the briefs are the news. A reader opening the site on Sunday morning wants what happened overnight, and giving them an essay about the last seven days instead is answering a different question. The weekly also reads the week's seven daily briefs as its input, so skipping Sunday morning would starve it of the last day.

Both are the same thing: a ranked list of the AI news worth surfacing, most important first.

Front matter

Every daily starts with this block. The site reads it for the byline.

---
author: vera
---

Author is set by weekday, per PERSONAS.md: Mon/Thu → vera, Tue/Fri → elias, Wed/Sat → nour.

Structure

A brief is a ranked list of news stories and nothing else. There is no ## The Lead and no ## The Signal. Those were section names invented to hold stories, and a reader does not need to be told that the first story is the lead story: it is at the top.

# Daily Brief, August 10th 2026

> One paragraph, the way you would tell a friend who is into AI what is going on if you
> ran into them and had a minute.

## The headline for the biggest story

Body. What happened, then what it means. [A](url)[B](url)

## The headline for the second story

Body. [B](url)

… twenty of them, then:

## Editorial
## Sources
  • Twenty stories minimum, ranked, heaviest first, thinning as it goes down. Take thirty on a heavy day; the floor is a floor, not a target.
  • The headline is the H2. The site turns every H2 that is not Editorial or Sources into a numbered story, builds the contents rail from them, and gives each one an anchor. Nobody numbers anything by hand: move a story up and the number follows.
  • Body under the headline, no bold restatement of the headline to open it. The old format needed one because the item was a bullet; it is a heading now.
  • The standfirst is a paragraph, not a slogan. It is the thing a reader gets if they read nothing else, so write it as speech rather than as a subtitle.
  • Editorial, Prediction Watch and Sources keep their names and sit at the end, in that order. They are not stories, so the site does not number them.
  • The evidence strip renders at the foot of the page, after Sources, built from the tier markers. Most readers want the news; the ones who want the sourcing profile want it after they have read it.
  • If a story bears on an open call, say so in that story and name the call. A bare T4 auto-links to the prediction.

Prediction Watch

The section where the day's news meets our open calls. Write it for somebody who has never read the ledger. The old version opened entries with a raw 2026-08-06-T4 and the phrase "moved toward", which told a reader nothing about what was claimed, which way it went, or when anyone finds out.

Every entry is one bolded label, then the claim in plain words, then what today did to it, then when it settles:

**More likely now: nobody solves prompt injection (T4).** We said no architectural fix
would reach broad adoption by next August. Auto mode is a filtering layer, which is
precisely what that call says will not be enough. Settles August 6th 2027.
  • The labels are a closed set, so a reader learns them once: More likely now, Less likely now, No change, Supporting evidence, New call, Settled: we were right, Settled: we were wrong.
  • Name the claim, not the ID. The prediction's own title field is already written in plain English, so use it.
  • Write (Prediction F4), not (F4). The whole phrase becomes the link, so a reader can see where it goes before clicking. A bare F4 mid-sentence in a story still links on its own; the section whose entire job is pointing at predictions should say so.
  • Use the full id when a suffix is ambiguous: (Prediction 2026-08-11-F1). Each issue numbers its calls from T1, so F1 names two different predictions today. An ambiguous reference is left unlinked and the build prints which one, because a confidently wrong link is worse than no link.
  • Say when it settles, in words: "Settles August 6th 2027", never 2027-08-06.
  • End with what did not happen. "Nothing settled today" is a real line and most days it is the true one.
  • The China/ check goes here when there is something to say, and in the run reply either way.

Put the source on the item

Every item carries its own link. Write the tier marker with the URL attached:

Meta says an open-weight Spark will follow. [A](https://research.meta.ai/blog/...)[B](https://www.bloomberg.com/...)

That renders as the same tier chip it always did, now clickable. A reader who wants to go deeper clicks the A next to the claim instead of scrolling to the foot of the page and guessing which of twelve sources backs which of seven stories.

Rules for it:

  • One set of chips per item, at the very end of it. Not per sentence. Marking every clause turns the prose into a minefield, and a chip mid-paragraph interrupts the read. Write them wherever is natural: chips_last() in the generator moves linked chips to the end of their paragraph or list item at build time, so the placement holds either way.
  • [A] is the primary, the announcement or filing itself. [B] is the best outlet write-up. A reader clicking A should land on the thing that happened, not coverage of it.
  • A bare [C] still needs a URL. Secondhand is a reason to link, not an excuse.
  • Unlinked markers still render, so a marker with no URL is not a build error. It is a gap, and it is on you to notice it.
  • The ## Sources list stays complete, including sources no chip points at. The chips are the way in, not the bibliography.

Sweep the beats

Twenty stories is a floor that only clears if every beat gets swept. Skip a beat with nothing new rather than forcing an item, but say in your run reply which beats came back empty. A missed beat has to be a visible decision, and the China/open-weights beat is named explicitly every time, even to say nothing happened.

  • Frontier models, capability results, notable papers
  • Lab business: funding, org changes, senior departures, partnerships
  • Policy and regulation (US federal/state, EU, China)
  • Chips, memory, data centers, power
  • AI markets: moves, earnings, IPO pipeline
  • Safety and security incidents
  • China / open-weight releases
  • Research worth reading: papers, , notable open-source
  • Robotics and physical AI
  • Legal: court rulings, IP, liability

The three libraries

These are separate outputs, not brief sections. The brief is the day's news. The libraries are discovery surfaces, and a run has not finished until all three have been fed. They do not depend on whether anything about them made the news: a good server shipped on a quiet Tuesday is exactly what these are for.

LibraryFeedsDaily target
data/watch.jsonlMust Watch2–4 episodes
data/tools.jsonlNew AI Tech & Tools4–6 entries
data/ventures.jsonlIPOs & Incubators2–4 entries

Targets, not quotas. A thin day is better than padding, and padding is obvious: it reads as a list of things with nothing said about any of them. But three empty days in a row means the sweep is not being done.

Two of them do have floors, because both failed the same way on day one and neither failure is visible from inside the run:

Tools need a spread, on two axes. At least three of the four scale values, including something small (project or tool) and something at platform scale, across at least three categories; and both values of reason, so a day carries something you would not have found and something you have to act on. Both belong: novelty and consequence are each a good reason to list a thing, and the failure is a day that is all of one. The news is about the big labs, so a run that follows the news fills the library with ten models from four companies. The weekend project, the MCP server somebody shipped on Tuesday, the repo with four hundred stars that does one thing properly: nobody issues a press release about those, and they only appear if you go looking on purpose.

Ventures need named company spotlights, at least two a day, from at least two different accelerators. A link to a batch directory is a link to somebody else's list. A spotlight is one company: what it is doing, who is doing it and where they came from, and the terms. Set batch on a company record and it becomes one, which makes founders, deal, site and accelerator required and the note a deep dive rather than a caption. The breadth rule exists because YC has by far the best public directory, which is exactly why a section left alone becomes a YC newsletter. Techstars, Entrepreneur First, South Park Commons, AI House, Neo, Antler and a16z Speedrun all produce AI companies worth a page.

Check both with python3 tools/catalog.py brief, which reads today's additions and says what is missing. Schemas and where to look: §3b.

Charts

Include at least one chart whenever the day has a number worth seeing. Fenced JSON:

{"type":"bar","title":"2026 ","unit":"$B", "data":[["Amazon",200],["Alphabet",180],["Meta",125],["Microsoft",115]]}

Types: bar (ranked magnitudes) · split (diverging +/−) · line (series over time) · donut (share of a whole). Optional keys: sub, note, unit, labelWidth. The label gutter sizes itself to the longest label in the widest theme, so labelWidth is only a floor, you do not need to set it. Charts inherit the reader's theme. See tools/charts.py.

Then

  1. Append to data/timeline.jsonl: anything that will still matter in six months. One JSON object per line: id, date (ISO), display ("Aug 10"), precision (day/month/quarter), tags (one or more from the vocabulary in tools/timeline.py), headline, entities (names from data/entities.json), optional detail for the fuller account. Most events carry two tags, a funding round in an open-weights lab is MONEY and OPEN. Entities are what connect an event to the predictions and issues that touch it, so name them. Validate with python3 tools/timeline.py. Skip the ephemera.
  2. Check data/predictions.jsonl: resolve anything whose criterion was met (see §4); note movement under Prediction Watch.
  3. Confirm all three libraries were fed. The brief can be finished and the run still be incomplete. If a library got nothing, say which and why in the run summary rather than letting the gap pass silently.
  4. Commit and push (§5).

2. Weekly issue, the main event

Runs Sunday. Output: reports/weekly/YYYY-MM-DD.md (the Sunday date) · Budget: ~40–60 searches

A weekly can also be a multi-part issue: a directory reports/weekly/YYYY-MM-DD/ with a README and the components from §3, which is what Vol. 1 is. The site treats a directory as an issue wherever it sits, so the cadence is the folder it is in and nothing in the code decides it. Use the single file unless the week genuinely needs the parts.

The weekly is the full issue. Everything that used to be monthly happens here: the deep read, the finance work, the editorials, winners and losers, the prediction reckoning. A week is the right unit: long enough for signal to separate from noise, short enough that calls stay live.

Read the week's seven daily briefs before searching. This is synthesis, not concatenation: the job is to say what the week meant, which is not visible from any single day.

Sections

HeadingContents
## The WeekWhat it meant, in one tight opening
## What Changed5–8 developments with durability, ranked. Charts where numbers earn them
## Deep ReadOne story taken all the way down. 800+ words
## FinanceMarkets, capex, IPO pipeline, earnings. Theses with explicit falsifiers
## Watch & ListenThe week's best media, ranked, with summaries
## Editorial700–1,000 words by the week's byline (ISO week number mod 3)
## Winners & LosersExplicit calls, tech / business / finance
## ThreadsUpdate the threads table in data/threads.md; which moved?
## LedgerResolve what came due. Run predictions.py score. Log new calls
## Next WeekWhat to watch, with dates
## SourcesEvery URL, tiered; contested figures preserved

Log new predictions every week. A weekly issue with no new falsifiable calls has failed at its main job. Predictions are cumulative and mostly resolve months out, a call does not need to resolve within the week unless it was explicitly a one-week call.

Read the table honestly. If Actual keeps beating Predicted, the calls are too safe: say so in the editorial and take more risk.

Feed the libraries with what the week turned up (§3b). The dailies do the bulk of this; the weekly adds what only became visible with seven days of context, and is the right moment to notice that three entries are really one story.

Dating. The file is named for the Sunday it ships, and the site renders that as the week it covers ("Week of 10–16 August 2026"). Do not put a date in the H1: the kicker carries it, and a headline that repeats it will disagree with it eventually.


3. Monthly wrap

Runs on the 1st. Output: reports/monthly/YYYY-MM/ · Budget: ~15–25 searches

The monthly is the light one. The weekly is the main event and carries the deep read, so do not rebuild it here.

Deliberately light. The weeklies did the work; this is the retrospective that only makes sense at a month's distance.

python3 tools/new_issue.py monthly YYYY-MM
FileContents
00-executive-summary.mdThe month in 1–2 pages. What a reader who missed everything needs
02-full-report.mdThe month's arc: which threads moved, which stalled, what surprised
09-winners-and-losers.mdMonth-scale calls, with last month's revisited
sources.mdAnything new; mostly links back to the weeklies

The issue README carries the coverage window, and the site reads it to label the issue. **Coverage window:** 1 – 31 August 2026. A span of eight days or less renders as "Week of X"; anything longer states its range. Get this line right and the dating takes care of itself. Component files do not carry dates in their H1s.

Prune the libraries (§3b). A month is the right interval to check whether anything in tools.jsonl has been superseded, abandoned or shut down, and to resolve what actually happened to each filing in ventures.jsonl. A directory nobody prunes becomes a list of dead links, which is worse than no directory.

Plus: the reckoning. Score everything that resolved, publish the and calibration, and open the summary with what the month got right and wrong. Never quietly edit a past issue, corrections append to the old issue under "Corrections". Update the Issues table in the root README.md.


3b. The three libraries

Fed by every cadence. The daily does the bulk of it; the weekly adds what the week turned up; the monthly prunes what has died. Validate with python3 tools/watch.py and python3 tools/catalog.py.

Watch. One JSON object per line:

{"id":"latent-space-218-databricks","added":"2026-08-10","published":"2026-08-03",
 "kind":"podcast","title":"…","show":"Latent Space","people":["Matei Zaharia"],
 "tags":["enterprise","agents"],"length":"~1h20","url":"https://…",
 "url_status":"verified","tier":1,"note":"Why it is worth the time…",
 "issues":["reports/daily/2026-08-10.md"]}
  • tags come from the controlled vocabulary in tools/watch.py. Adding a tag means adding it there first: a free-text field becomes twelve spellings of "open weights" inside a month and then the filter is worse than none.
  • url_status is verified or unconfirmed. Never fabricate a URL.
  • If an episode already in the library comes up again, append the new issue to its issues array rather than adding a second record.
  • Rank by information density per minute. A three-hour interview with someone actually deciding things outranks a twenty-minute recap by a commentator.

Tools. Every scale, and the small end is the point. A GitHub repo with four hundred stars that does one thing properly, an MCP server somebody shipped this week, a Claude skill, a browser extension, a , a weekend project that works. The big platform launches will find their own audience; this section earns its place on the things a reader would not otherwise have seen.

  • category is what it is: model agent devtool repo mcp extension app infra cloud data security robotics.
  • scale is how big: project tool product platform. This is a filter axis, so a reader hunting a weekend project is not wading through hyperscaler announcements. It is also the thing catalog.py brief checks: three of the four every day, always including something small and something at platform scale.
  • Two reasons to list something, and a day needs both. reason records which:
    • new: you would not have found this. The repo with four hundred stars, the MCP server shipped on Tuesday, the proof assistant nobody outside mathematics has heard of. This is what a discovery surface is for.
    • consequential: you have to act on this. A price, a license, a capability that unblocks a use, a frontier release that moves what is possible.

An entry is often both; file it under the stronger one. The reason this is a field and not a sentence of advice is that each half collapses without the other. Only-new is a curiosity cabinet. Only-consequential is a press-release feed with better prose. catalog.py brief requires both in a day, and the site filters on it.

  • Where to look, beyond the news: GitHub trending and new releases in the AI topics, spaces and models, the MCP server registries, , Product Hunt, the release notes of tools you already track.

Ventures. Not just IPOs. The incubator half is half the section.

  • Go through the directories directly, and go through more than one. Y Combinator's company list filtered to the current and previous batch, then Techstars, Entrepreneur First, South Park Commons, AI House, Neo, Antler, a16z Speedrun. YC is the easiest to read and the hardest to stop reading, which is the trap.
  • How a spotlight gets picked, in priority order:
    1. Could this have been built two years ago? If yes it is a company, not a signal. The section is about what just became possible.
    2. Do the founders know something non-obvious? Someone who worked on deployment inside a frontier lab is making a claim about what is actually breaking in there. A strong résumé is not the same thing.
    3. Can you state the strongest case against? If not, you are writing a directory entry with better typography. The objection goes in the note.
    4. Never pick on traction. Revenue at week six is noise, and selecting on it means selecting whoever ran the best launch.
  • Two companies doing the same thing do not both get spotlighted in the same week.
  • The IPO half is not a selection problem. The AI listing pipeline is small enough to enumerate, so log all of it rather than picking favorites. The one threshold that matters: rumored requires a named outlet citing its sourcing. A well-followed post is not a rumor of record.
  • kind is ipo, incubator or company. status is rumored filed priced listed cohort raised, and it is load-bearing: a rumor is not a filing and a filing is not a listing. Never blur them.
  • batch records the cohort: "YC S26", "Techstars NYC 2026". On an incubator record it labels the cohort. On a company record it makes that record a spotlight, and a spotlight has to earn the name:
{"id":"decawork-yc-s26","added":"2026-08-12","name":"Decawork","kind":"company",
 "status":"raised","batch":"YC S26","what":"One line on what it does.",
 "founders":["Sarthak Aggarwal (NVIDIA AI systems; Ema)","Aman Raj (Barclays)"],
 "deal":"YC standard: $500K, as $125K post-money for 7% plus $375K uncapped MFN.",
 "site":"https://decawork.ai/","url":"https://www.ycombinator.com/companies/decawork",
 "url_status":"verified","note":"Why it is worth watching…","sources":["https://…"]}
  • founders, deal and site are required on a spotlight, and the note has to run past 180 characters, because the failure this prevents is a company reduced to its tagline. Founders because a two-person team out of one lab is the whole story in half these companies; the deal because "raised" without terms is a press release.
  • site is the company's own website, and it is what the card title links to. Clicking a company name and landing on its entry in an accelerator's directory is a small betrayal: the directory is where we found it, not what it is. url stays the profile page, and both render as labeled rows so a reader can see where each goes. Take the site from the profile page's own link-out rather than guessing a domain.
  • accelerator is who ran the batch, from the controlled vocabulary in tools/catalog.py. Adding one means adding it there first, or the breadth rule counts spellings instead of accelerators.
  • At least two spotlights a day, from at least two accelerators. Do not invent a founder name, a domain or a term: if the page does not say, the field says what is known and nothing more.
  • The cohort record stays, but it now carries the cohort-level read only. What is interesting about the individual companies belongs on the individual companies.

Validate all three with python3 tools/watch.py and python3 tools/catalog.py.

3c. The glossary

data/glossary.json, validated by python3 tools/glossary.py, rendered into every article at build time and browsable at /glossary.

The rule: if you had to look it up to write the sentence, define it. Then apply it again, harder, because the writer's sense of what is obvious is calibrated to the writer. , , Hugging Face and agentic all sat undefined for a week on that basis.

The archive runs dense: open-weight appears 66 times, capex 47, 38. A reader who does not know what a is loses the argument, not just a word. Currently 79 terms, and the number should keep going up.

{"term": "run-rate", "aliases": ["run rate"],
 "definition": "Current revenue projected forward a full year. A company earning $4B this month has a $48B run-rate, which flatters fast growth.",
 "url": "https://en.wikipedia.org/wiki/Run_rate"}
  • One or two sentences, under 260 characters, enforced. The job is to unblock the sentence being read, without trying to teach the subject. The url carries anyone who wants more.
  • Definitions are prose and get voice-checked like everything else. voice.py reads this file now, so the tells apply: no em dashes, no closing epigram, no "which is why" where "so" does the work.
  • aliases catch the spellings you did not write. "open weights" and "open-weight" are one entry.
  • Terms are marked once per page, on first appearance, at most three per paragraph, and never inside a heading, a link, code or a citation title. You do not mark anything by hand; adding the entry is the whole job, and every article ever published picks it up on the next build. The per-paragraph ceiling exists because this file grows every day and a dense summary line would otherwise end up underlined end to end.
  • Adding a term nobody uses is harmless. Missing one costs a reader the paragraph.

4. Prediction ledger hygiene

The ledger is why this is a repo. Append one JSON object per line:

{"id":"YYYY-MM-DD-T1","made":"YYYY-MM-DD","category":"tech",
 "title":"Anthropic holds the Sonnet 5 price increase",
 "claim":"Anthropic does not reverse or re-discount the Claude Sonnet 5 price increase within 90 days …",
 "why":"The cleanest natural experiment available on frontier pricing power. If a lab can raise …",
 "confidence":0.75,"resolves":"YYYY-MM-DD",
 "plain":"Wrong if list pricing drops below $3/$15 per million tokens before 30 November. Targeted enterprise discounts do not count.",
 "criterion":"RESOLVES WRONG if … RESOLVES CORRECT otherwise.",
 "status":"open","source":"08-editorial-finance.md"}
  • id prefix: T tech, B business, F finance.
  • confidence 0.50–0.95. Below 0.50, state the negation instead.
  • title states the call in one line, under 78 characters, no hedge clauses. The conditions live in plain and criterion, a title needing a comma is a claim wearing a headline's clothes, and the validator rejects it.
  • why is the reasoning: why this call, what would have to be true. It is the first thing a reader sees under the headline, so write it for them, not as a footnote.
  • plain is what counts, in plain English. No RESOLVES CORRECT language, the validator rejects that too, because having both fields is the whole point.
  • criterion must name an observable event a third party could check against a public source. predictions.py check rejects vague ones and gates the site build.
  • Referring to another call by its suffix ("that is what T2 tests") auto-links on the site. Use it; the calls are only fully legible against each other.

Resolving: edit in place, status to correct/wrong/partial/void, add resolved and resolution_note with a source. Never delete. Never soften a claim after the fact. void is only for predictions made unresolvable by outside events, with the reason recorded.

python3 tools/predictions.py check && python3 tools/predictions.py render

5. Commit and push

Run all six before pushing. Each guards a different data file, and each one also runs in CI, catching it here costs a minute, catching it there costs the run.

python3 tools/predictions.py check      # ledger structure, titles, plain-language split
python3 tools/predictions.py render     # PREDICTIONS.md is generated, never hand-edited
python3 tools/watch.py                  # episode tags, link status
python3 tools/timeline.py               # event tags, entity names
python3 tools/voice.py                  # prose that reads as generated
python3 tools/fonts.py check            # every declared face resolves
python3 tools/build_site.py             # and it has to build

git add -A && git commit -m "Daily brief YYYY-MM-DD"
git push origin "$BRANCH"

Pushing to main triggers a Cloudflare Pages build and .github/workflows/ci.yml, which validates the ledger, rebuilds, and fails on any broken internal link or a stale PREDICTIONS.md. If either goes red, fix it in the same run. See DEPLOY.md.

Retry a failed push up to 4 times with exponential backoff.


6. Google Drive, retired

Deliverables were mirrored to Google Drive while the site was being built and there was nowhere else to read them. The site now does that job, so runs no longer publish to Drive: it is a second copy that goes stale the moment a correction lands in the repo, and a mirror nobody re-reads is worse than no mirror.

The existing folders are left alone. Nothing new goes into them.


7. Standing rules

  • Never fabricate a URL. If it can't be confirmed, mark it unconfirmed and the site will offer a search instead. A search link is not a claim about where something lives; a plausible-looking invented URL is.
  • Everything on the site links out. Every timeline event, every episode, every item carries a way to reach the original. Where the archive has no citation, a search link is the floor. A dead end is not acceptable, and neither is a guess. In prose this means the tier marker carries the URL: [A](https://...). The first two daily briefs obeyed the rule everywhere except their own copy, listing every URL at the foot of the page and leaving the reader to work out which one backed which story. §1 has the convention.
  • Do not publish the same thing twice. A story that stays in the news is not a duplicate and the timeline should show it recurring, but the same event logged again under a reworded headline is, and it doubles the chronology silently. Before logging, read the last week of entries. If a story genuinely moved, the headline must say what changed; if it did not, it does not get a new entry. Same for media: an episode is recommended once. If it becomes relevant again, its argument is now being tested, someone has answered it, append the new issue to that record's issues and rewrite its note. Never add a second record. timeline.py and watch.py flag near-duplicates and fail the build.
  • Never average contested figures. Show the disagreement, pick the best-sourced value, give the reasoning.
  • Tier every number. A primary, B established outlet, C secondary, ? contested.
  • Dated issues are immutable. Corrections append.
  • Actively cover Chinese labs. English coverage under-weights them structurally.
  • Editorials argue, reports describe. Do not blur them.
  • US spelling and US dates. behavior, center, organization, and August 10th 2026, never 10 August 2026. voice.py reports both. A quotation keeps its source's spelling; a citation title is never edited.
  • No em dashes. No hedging that avoids a claim. Every sentence states a sourced fact, makes an arguable claim, or connects the two. See VOICE.md, tools/voice.py enforces the mechanical half and fails the build.
  • Personas change the argument, never the facts. Nobody gets their own numbers.
  • Charts wherever a number is worth seeing. A table of four values is usually a chart.

8. Schedule

RunCron (UTC)Local (US/Pacific)
Daily brief0 13 * * *6:00 AM daily
Weekly issue0 16 * * 09:00 AM Sunday
Monthly wrap0 15 1 * *8:00 AM on the 1st

Managed as Routines at claude.ai/code/routines, see