I run four GitHub Actions cron routines that all need to know the same thing: which game subjects have live search demand right now. The YouTube Short generation routine picks matchup titles from it. The Bluesky post queue uses it to weight the gaming slot. The article generation routine uses it to anchor VoC topics. A market monitoring sweep updates it.
For the first month of this setup, each routine had its own baked-in assumptions. The YT script used a hardcoded list of "safe" matchup pairs. The Bluesky routine had a separate file with a different classification of "hot" subjects. The article routine ignored market signal entirely. Every system was drifting independently, and updating any one of them required touching multiple files.
The fix was one shared markdown file — docs/market-trends.md — with three design rules. To be honest about the timeline: I wrote all three rules into the file's first commit, because each one closes a failure mode I could already see in the scattered per-routine assumptions the file replaced.
Rule 1: counted numbers only, every claim traceable
The obvious way to write a file like this is impressionistic notes. "Underdog narratives seem to do well." "Players talk about price gaps." Useful to write down, useless to automate against. A routine reading notes like that has no way to prefer one subject over another when the file's evidence is impressionistic.
The TERUS method — every number is a count from a specific source, every source is saved raw — forces the file into something a routine can act on, so that's the discipline the file follows. "3.1M views, 'Indie Dev Beat AAA Studios With 0 Marketing'" is something a routine can compare against "5K views, most recent build-in-public short." An impression is not.
This also matters for the author. When you have to write a specific count, you have to actually count. You can't hand-wave "players care about X" when the claim has to be backed by "I read 43 comments and 11 mentioned X." The discipline of traceable numbers improved the file's accuracy more than any review process would have.
Rule 2: fail-closed freshness gate
A file like this has a built-in failure mode: it could be months old and none of the consumers would know. The YT script would anchor on "hot subjects" that went stale long ago, and the routine would behave as if the data were current. That's exactly the problem the old per-routine hardcoded lists already had — nothing ever told me they were out of date.
The guard is a updated: date field at the top of the file and a freshness rule that consumers must check before using the file's content:
updated: 2026-08-10
Freshness rule (fail-closed): if updated: is more than 14 days
old, consumers MUST ignore this file and fall back to their own defaults —
stale trends are worse than no trends.
Fail-closed here means: if the file is stale, the routine ignores the market-trends data and uses conservative defaults (established evergreen matchups, not trend-chasing). It doesn't silently use the stale data, and it doesn't crash. The 14-day window matches the social-listening sweep cadence — I update the file weekly when things are moving, less often when they're stable.
The key design choice is making freshness the consumer's responsibility rather than the publisher's. The consumer checks the updated: date on every run. This means a routine added six months from now will inherit the freshness check automatically if it follows the documented pattern — I don't need to update a registry or notify consumers when the file goes stale.
Rule 3: separate what's measured from what's prescribed
The rule that matters most day to day: splitting the file into an observations section (what I measured) and a prescriptions section (what consumers should do with it).
The tempting shortcut is to mix these together: "Underdog narratives get high views, so use them." That forces consumers to interpret the claim, and different routines interpret it differently. The Bluesky routine might take "use underdog narratives" to mean write underdog captions. The YT routine might take it to mean use underdog-narrative titles. Neither is wrong, but they diverge over time.
The current structure separates the measurement table from the action directive:
- Observations section: the raw data table — video format, measured view counts, evidence notes. This is what I actually found. Consumers can read this to understand the evidence.
- Hot subjects list: the prescriptions — specific matchup subjects, anchor candidates, and what-to-avoid notes. This is what the routine should act on. The YT script reads this section and picks from the "anchor OK" rows; the Bluesky routine reads it to weight game subjects for the 70% gaming slot.
The separation means I can update the observations without changing any consuming routine's behavior. If I notice something new in the measurement data, I can add it to the observations section without touching the prescriptions — the prescriptions only change when I've decided what action to take based on the evidence.
What I'd do differently
Honestly, not much yet — the file is young, and all three rules went in on day one, so I can't claim battle scars from leaving one out. What I would say is: build the freshness check first, before it feels necessary. The pre-hub month of scattered hardcoded assumptions, where nothing could ever flag that a "safe" list had gone stale, is what convinced me it isn't a future concern.
The other thing I'd keep: writing the consuming routine's expected behavior in the file itself. docs/market-trends.md has a "Who reads this (mandatory)" section that names each of the three consumers — the YT routine, the Bluesky routine, and the article routine — and what each should do with the file. All three were wired in from the first commit, and the section doubles as a template: any consumer added later has a clear pattern for how to plug in, plus a record of what the existing consumers are doing, so I can check for overlap or contradiction.
A shared markdown file with a freshness gate and a traced-evidence discipline is a long way from a config service, but for a four-system automation project running on a $25/month budget, it's the right level of infrastructure.
Part of an ongoing 6-month experiment running three AI-curated directory sites. The technical claims here are real; this article was AI-assisted.
Top comments (0)