- usePolling gains a pauseWhenHidden option (default true): the timer
pauses while the document is hidden (background tab / minimised) and
resumes with an immediate reload on returning to visible. Callers keep
owning their initial fetch, so no duplicate first request.
- CronPoolMonitor now delegates its 5s poll to the shared usePolling hook
(initial load stays in its own useEffect); removes the bespoke
setInterval + manual visibility gap.
- CronPoolMonitor.test: visibility guard now passes (3/3), removing the
previous it.fails. Frontend suite: 18/18; tsc clean; backend 878.
Resolves scan §6.3.
- .scratch/v111-architecture-scan.md: mark §6.1, §6.2, §6.4
as RESOLVED (commits 38e3817, f85eca1, 6d32653); add §6.5
for T8 decision-log dedupe (commit 4bcab06).
- docs/release-notes-v1.1.0.md: add section ten listing the
four post-release fixes shipped to main after v1.1.1 was deployed,
so the release page documents what v1.1.1 production actually
contains (and what the v1.1.1 image does NOT contain).
T2 frontend CronPoolMonitor: polls every 5s, unmount clears interval,
plus it.fails guard for missing visibilitychange listener (S6).
T3 router ORM contract: heartbeat updates fields + 404, decision-logs
POST persists + 404, GET lists inserted (guards S2 — must continue to
pass after router handlers move into a service in P3).
T8 decision-log immutability: append-only on context change passes;
dedupe of identical (decision_type, context) is xfail (real gap).
T7 alert→auto-scale: task_backlog alert recorded on first call (passes);
check_alerts never invokes auto_scale is xfail (real gap, §6.4).
All real gaps are logged in .scratch/v111-architecture-scan.md §6.