Aug 2's weekly review died on a network outage that plan-day is already hardened against — because the Jul 26 hardening went into one wrapper instead of a shared runner. Fixing the instance isn't fixing the class.
This one failure cascaded for a week: no Aug 2 card meant no curriculum authored for Aug 3–8 (your lesson page has been frozen on 'Aug 1: wind-down playbook' all week) and no release scan. One unhardened wrapper, six days of stalled downstream.
On Jul 26 you shipped network-wait + retry into run_plan_day.sh (commit a727e1b) after plan-day kept dying on pre-dawn network flaps. It works: every plan-day log this week shows 'network ready' before each attempt. On Aug 2 at 18:08, run_weekly_review.sh hit the same class of failure — ENOTFOUND, DNS unreachable — and died in 70 minutes with no wait, no retry, exit 1.
This is the instance-vs-class trap, and every codebase falls into it: a failure gets fixed where it was observed, not where it lives. You have at least three cron wrappers (plan-day, weekly-review, jobhunt-sweep) that all do the same dance — wait for network, prefetch, run claude -p under a watchdog, verify the side-effect, alert on failure. Each one currently has a different, hand-copied subset of that dance.
The class-level fix is a shared runner: one script (or sourced shell library) that owns network-wait, retry, watchdog, fallback-model, and the verify-and-alert leg — with each job supplying only its prompt, its artifact check, and its timeout. Then hardening lands once and every cadence inherits it.
Measure the drift between your two Sunday-critical wrappers:
for f in run_plan_day.sh run_weekly_review.sh; do
echo "== $f =="
grep -cE 'network|retry|attempt' /Users/tom/Claude/PDB/scripts/$f
done
When you fix a failure, ask 'where else does this exact failure live?' — the answer is the difference between a patch and a fix.