Recovery Watch (gsc-watch)
Recovery Watch
scripts/gsc-watch.sh is the daily read of the re-evaluation window. It wraps
go run . gsc-report (see the Site Generator docs for what the report itself
prints) so the watch loop is one operator action instead of a remembered
command.
The doctrine
- Week-over-week is the primary signal. Day-over-day is noise on a
collapsed estate. The first recovery signal is
/estado/impressions in the WoW block, then the family impression share holding ≥90%. gsc-reportexit 1 is expected for the whole window. The exit code is the alarm, not the diagnosis. The wrapper therefore exits 0 for the steady alert state — a timer that is permanently red gets ignored — and exits 1 only when a page is warranted.- Exit 0 can also mean a truncated export. When the report turns clean, check the day count in the header before believing it.
The operator’s part (cannot be automated)
There are no Search Console or AdSense API credentials on the build host, so the exports are downloaded by hand, once a day:
- GSC → Performance → export (keep a consistent filter, e.g. last 3 months — the WoW windows are the export’s last 14 days).
- AdSense → Reports → export the daily CSV.
- Drop both into
site/cache/gsc/inbox/:- the GSC export as its
.zipor the extracted folder (anything named*Performance-on-Search*), - the AdSense CSV as any loose
*.csv(recognized by itsEstimated earningsheader — the browser’sreport (1).csvname is fine).
- the GSC export as its
The timer (13:00 daily) or a manual scripts/gsc-watch.sh picks the newest of
each, runs the report, and archives what it consumed to
inbox/processed/<runstamp>/. Snapshots under site/cache/gsc/ are idempotent
— re-running the same export changes nothing.
What pages (webhook) vs what only logs
Paging uses the same channels as the build freshness check
(NOTIFY_WEBHOOK_URL / NOTIFY_DESKTOP from .env) and only for actionable
events:
| Event | Meaning |
|---|---|
| broken input | the export fails to load — the file stays in the inbox and the next run retries |
| starving inbox | no export covering the last ~4 days, or no AdSense CSV dropped in 3 days — the dead-man’s switch on the manual download loop |
DEINDEXED SCOPE LEAK | a de-indexed scope family appeared in the GSC top 1,000 — the X-Robots-Tag noindex is not reaching some path; investigate before anything else |
| alerts re-firing after a clean read | a collapse transition, not a steady state |
Everything else — including the steady alert state of the window and the
“alerts cleared” transition — is log-only. Logs: per-run
logs/gsc-watch-YYYYMMDD-HHMMSS.log, append-only
logs/gsc-watch-alerts.log, state in site/cache/gsc/watch-state.
Installation
cp scripts/systemd-units/redecasas-gsc-watch.{service,timer} ~/.config/systemd/user/systemctl --user daemon-reloadsystemctl --user enable --now redecasas-gsc-watch.timerRuns daily at 13:00, Persistent=true.
Relation to the estate freeze
The watch timer is deliberately not freeze-gated and is not in
estate-freeze.sh’s timer lists: watching is the one activity that must
continue through the freeze. The script analyses local CSVs and writes only to
the gitignored site/cache/gsc/ and logs/ — it never generates pages and
never deploys. Lifting the freeze does not touch it.