RMHLadder — Operations Runbook¶
Operating the job-discovery pipeline (server/ladder-worker) and the resume
subsystem in production. Companion to the design spec
docs/superpowers/specs/2026-07-15-rmhladder-productionization-design.md.
Is it actually running? (prod truth)¶
The worker is the Docker Compose service ladder-worker
(command: node dist-server/server/ladder-worker/index.cjs). It runs the
pipeline on LADDER_CRON_SCHEDULE (default every 12h) and self-bootstraps
an empty database on startup.
Checklist:
Worker process:
docker compose ps ladder-worker→ should beUp.Worker logs:
docker compose logs --tail=100 ladder-worker→ look for[ladder-worker] Started, a resume-readiness line, and periodic[ladder-worker] Run complete [...] discovered=... created=....One-shot status report: run inside the worker (or web) container:
pnpm ladder:statusPrints last completed run + age (flagged
[STALE]if older than the 12h window), active/expired job counts, sources by status (active/unconfigured/blocked/error/disabled), and resume-subsystem readiness.Admin dashboard:
/rmhladder/healthshows the resume subsystem, silent sources, and the scrape-run ledger.
If there is no completed run and no Run complete log line, the worker is not
running or is crash-looping — check docker compose logs ladder-worker for the
stack trace (commonly a missing DATABASE_URL).
Scrape schedule¶
Default: every 12 hours (
0 */12 * * *).Override without a rebuild: set
LADDER_CRON_SCHEDULE(standard 5-field cron, UTC) in the production env file and restartladder-worker. An invalid value fails fast at startup withInvalid LADDER_CRON_SCHEDULE.
Force a run now¶
The web tier never scrapes. Trigger a manual run from the worker/web container:
pnpm ladder:run # full pipeline, trigger=manual
pnpm ladder:run --limit 20 # cap sources (smoke test)
pnpm ladder:run --platform greenhouse
Each run writes a LadderScrapeRun row visible on /rmhladder/health.
(An in-dashboard “Run now” button that signals the worker is planned for a later phase; until then use the CLI.)
Reading review tasks & a tripped circuit breaker¶
/rmhladder/reviewlists open review tasks. Amass_expiry_suspectedtask with the source set toerrormeans the mass-expiry circuit breaker tripped (a source’s board looked empty for many active jobs at once — usually a fetch problem, not real mass-expiry). Investigate the source before clearing./rmhladder/health“silent sources” lists sources with a stalelastSuccessAt— the earliest signal of a quietly-failing board.
Alerts¶
pnpm ladder:status prints an ALERTS section at the bottom, and the
ladder-worker logs a [ladder-worker] HEALTH ALERT [severity] code: message
line to stderr after each tick for every active alert. The four codes:
Code |
Severity |
Meaning |
Operator response |
|---|---|---|---|
|
high |
No completed scrape run within the stale window (default 24h). |
Check |
|
high |
Open |
Investigate the flagged source at |
|
high |
Resume subsystem blocked — object storage or encryption key unconfigured. |
Provision |
|
medium |
The latest scrape run’s error rate exceeded the threshold (default 50%). |
Check the failing sources on |
Tunable thresholds¶
Override the defaults with env vars (set in the production env file):
Var |
Default |
Meaning |
|---|---|---|
|
|
Age threshold (ms) before |
|
|
error rate threshold, >0 and ≤1 (default 0.5); above which |
|
|
Minimum |
Env var reference (ladder)¶
See .env.example (search LADDER_): LADDER_CRON_SCHEDULE,
LADDER_USER_AGENT, LADDER_DOMAIN_RATE_LIMIT_MS, LADDER_PROBE_BATCH_SIZE,
LADDER_RESUME_ENCRYPTION_KEY, LADDER_AI_*, LADDER_LEASE_*.