Handoff: Meta ad fatigue watcher, merged build (20 Oct 2026)

Status: built, backtested, published. Cron and email still OFF. Nothing in any ad account was changed.

Live example (Pott): https://pott-fatigue-watch.pages.dev/ (19 Oct run) and https://pott-fatigue-watch.pages.dev/2026-08-31.html (the Ad 707 case). De-indexed but public.

What this is

One daily watcher, scripts/meta-fatigue-watch/, that judges every ad still taking real money and puts it on one of five stages, each tied to one action:

StageAction
FatiguedCut today
Close to fatiguingRefresh this week
Highly likelyBrief the replacement now
MonitorWatch (also: pulled back, over-scaled, check site, audience-not-creative)
NoneNothing

Too new and too small are labelled separately.

What changed today

Three fatigue systems existed. The June weekly scoring (raw week on week, age as a trigger), a September daily agent on an unmerged branch that was never recorded anywhere, and the October watcher. Today the best of September was folded into October:

Kept from October over September: breakeven line, material-only and spend-held gates, over-scaled and pulled-back as separate outcomes, own-best-week slow decay, signal families, five action-defined stages, account-wide guard, persistence against the ledger a week earlier (never yesterday's overlapping run).

Verification

The four hand-picked cases all land where they should:

CaseResult
Pott Ad 707, 31 AugFatigued (23% of spend, 1.79x against 2.46x, click rate down)
Pott 18 Jul (site dip)Account-wide guard fired (audience family 4 of 7), nothing cut
H&H Ad 260, 14 OctClose, with the no-breakeven note
Pairs Ad 446, 14 OctMonitor (was a misfire at Close); Ad 264 Highly likely on hook rate

Pott live run for 13 to 19 Oct: nothing above Monitor. Ad 940 is pulled back (Meta halved its spend), 11 Christmas ads become judgeable from about 21 Oct.

Next-14-day backtest. 113 judged ads across 30 Jul, 13 Aug, 27 Aug, 10 Sep and 24 Sep for Pott, H&H, Pairs and SHF. For each stage, the median of each ad's ROAS over the following 14 days as a share of its own baseline:

StageCallsNext 14 days vs baselineFell under 0.8x baseline
Fatigued10.60x100%
Close51.07x50%
Highly likely131.03x15%
Monitor590.86x44%
None351.18x30%

Read: Fatigued was right when it fired (Pott 707 on 10 Sep) and None ads kept earning. Highly likely ads kept earning too, which is what an early warning should do. Close is mixed and the sample is tiny. One thing worth watching: Monitor ads whose only signal was an unconfirmed best week went on to earn 0.76x of baseline (17 calls), so that signal has some predictive power even when the week looks fine. Only Pott has a breakeven set, so only Pott could reach Fatigued in this test. Full rows in scripts/meta-fatigue-watch/backtests/.

Decisions needed from Casey

  1. Breakeven ROAS for H&H, Pairs and SHF Set 20 Oct from Casey: H&H 4.0x (the floor of "4 or 5 minimum"; 5x is the target), Pairs 2.0x (new customer), SHF 3.0x (blended). These are targets, not margin-sheet breakevens; the KC dashboard's plan engine holds a computed break-even ROAS per client but its keys live only in Railway, so it was not cross-checked. With the real bars: H&H 260 on 14 Oct stays at Close (5.15x is above 4.0x), SHF on 19 Oct reads as an account-wide return dip (6 of 6 ads), Pairs on 19 Oct has Ad 465 at Close and 264 at Highly likely.
  2. Cron and email. Crontab line is in the header of run-daily.sh; Casey adds it himself. Keep per-client email false, the combined morning email reads state/last-result.json.
  3. Publishing. The daily run writes the report locally only. Say if the Pott page should republish each day.

Files

Later

Point the weekly optimizer's step 5 at this watcher's output instead of keeping a second scoring system. Pott's Christmas ads are the first live read of the merged rules.