## Scheduled execution — migrating from the VM to Claude Code web routines
The unattended runs are moving off the `sh-secrev` VM into **Claude Code web scheduled routines** (which
post ALARM-only to Slack `#repo-scanner`): one routine for the agentic two-tier sweep, and a second that
runs the deterministic `checker_coordinator.sh` (the script owns the findings + ALARM decision; the
routine relays its output verbatim, never re-judging). `nightly_sweep.sh` / `checker_coordinator.sh` and
the `systemd/` units below remain the source of truth and the VM-deployment path; the VM timers are being
retired once the routines are validated.
## Nightly sweep (Path B) — two-tier, clean-clone auto-discovery
`nightly_sweep.sh` runs on the `sh-secrev` Ubuntu VM (R720) and needs **no per-repo wiring**. It:
1.**Discovers** every non-archived Sea-Haven-Industries repo via the GitHub REST API (`curl` + a
read-only `GH_TOKEN`; no `gh` CLI dependency) and **mirrors** each as a shallow clean clone
(`git clone --depth=1`, default branch from the API) into `~/repo-mirrors`. Scanning server-side
clones — not developer working trees — structurally keeps local gitignored `.env` secrets out of scope.
2.**Tier 1 (every repo, every night, $0 Claude):**`review.sh --scanners-only` over every mirror —
complete deterministic baseline coverage.
3.**Tier 2 (bounded agentic):**`run_headless.py` over a deterministic **round-robin rotation** that
fits `TOTAL_BUDGET_USD`, with a persistent cycle pointer so every repo gets a deep pass within
`MAX_CYCLE_NIGHTS`. This bounds the draw on the shared Max limits (a clean night never deep-scans all
repos). A `COVERAGE ALARM` fires if the rotation falls behind.
It is **ALARM-only**: a clean night posts nothing. See memory `feedback_cloudwatch_alarms`.
### Skip / override
- A repo is skipped if it commits a `.security-review-skip` marker **or** is listed in the central skip
file (`~/.secrev-skip.txt`, one repo name per line). Repos skipped via their own committed marker are
**logged in the report** so a sensitive repo can't silently self-exclude.
-`TARGETS="/path/a /path/b"` overrides discovery entirely (scan explicit paths, no cloning).
- The canary corpus (`~/security-review-testbed`) is **always** scanned agentically first as the
anti-complacency check — independent of the skip filter.
### Anti-complacency + guards
- **Canary check:** the testbed MUST block AND surface ≥ `CANARY_FLOOR` (default 10) confirmed crit/high.
Otherwise → COMPLACENCY ALARM. The corpus now includes Node + .NET fixtures (see the testbed key);
re-tune the floor after the first VM canary run reports the expanded recall number.
- **Budget ceiling:** `TOTAL_BUDGET_USD` (default 120 — full deep-pass coverage of every repo per night) caps aggregate agentic spend; `PER_TARGET_BUDGET_USD`