Randy Olson

Weekly blog link maintenance

The iMac’s user crontab runs the check on Tuesday at 8:10 a.m. Pacific. The scan runs in the background without iTerm. The iMac needs to be awake for cron and logged in to open a repair session.

Install on the iMac

Use the main checkout of this repository and the local Python, GitHub CLI, GNU timeout, and iTerm launcher. Keep the existing ITERM_SKILL_RUNNER setting in the crontab. Create ~/.local/state/blog-link-check with mode 0700 before adding the job so cron can open its log.

10 8 * * 2 umask 077; /usr/bin/env PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin GIT_TERMINAL_PROMPT=0 GH_PROMPT_DISABLED=1 /usr/local/bin/timeout --kill-after=15s 50m /usr/local/bin/python3.14 -B /Users/rolson/Documents/GitHub/rhiever.github.io/scripts/link_maintenance.py >>/Users/rolson/.local/state/blog-link-check/cron.log 2>&1 # blog-link-check

What happens on Tuesday

  1. The checker reads the published sitemap, pages, and links. It saves the full report to latest-scan.json. Keep the historical access holds in denied.json, a local JSON array of URLs. The checker skips those URLs as direct requests and redirect destinations.
  2. Only a complete scan can trigger a repair. A URL must return 404 or 410 again on a separate request. Denials, verification gates, and timeouts stay in the report. The wrapper sends up to 5 confirmed targets and rotates through the list.
  3. The wrapper opens iTerm with the repair prompt and the path to a local report. It creates a separate Git worktree from current GitHub main. The agent verifies the newest usable Wayback capture, changes only the affected URLs, runs the repo checks, and opens a draft PR.
  4. A file lock prevents concurrent scans. A handoff reservation suppresses retries for 6 days, including ambiguous launcher failures. An open PR from the previous handoff blocks another session. Review cron.log, handoff.json, and the corresponding worktree if a handoff fails. Keep repair worktrees until their PRs and any local edits are resolved.

The scanner, wrapper, and prompt are private repository files under scripts/ and docs/. Reports, logs, and repair worktrees live outside the repository. GitHub’s PR workflow runs synthetic tests.

python3 -m unittest discover -s scripts/tests