Incident response — the Radon playbook

SkillWeb & browsing

The exact Radon triage playbook for a production incident - reproduce locally, write a FAILING regression test first, fix, run the full test gate, commit a focused single-purpose commit, push once, wait for CI green, verify live in the browser. Use whenever an incident JSON from data/incidents/ or a production bug report is being worked; /incident orchestrates the parallel-analysis phase on top of this playbook.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Incident response — the Radon playbook skill

What this skill tells your AI

The instructions your AI receives, as published by joemccann/radon in .claude/skills/incident-response/SKILL.md and read by ahel’s review.

The sequence is fixed. Skipping a step is how the 2026-07-08 outage happened (rapid pushes) and how the destroy storm shipped green (regression test that could not express the failing topology). Every step names its verification evidence; paste that evidence before claiming the step done.

0. Read the incident + runbook case first

  • Parse the incident JSON (data/incidents/incident-*.json): case_id, severity, evidence, fingerprint.
  • Read the matching case in docs/incident-runbook.md. If the case documents a discriminating check (e.g. the Python Turso canary for turso-destroy-storm), RUN IT before touching code — the same symptom has more than one cause, and the wrong branch wastes the whole response (restart-flapping an upstream Turso outage makes it worse).
  • Confirm blast radius from live evidence, not assumption: curl -s localhost:3000/api/service-health | jq (judge the BODY), curl -s localhost:8321/health/lite, gh run list --workflow=ci.yml --limit 3.
  • If this is a NEW failure mode, you will add a runbook case in step 6.

1. Reproduce locally

  • Reproduce the failure on your machine before writing the fix. For data bugs, reproduce against the artifact the user/production actually sees, never a synthetic fixture (feedback lesson: confirm against the user-visible artifact). Verify against live Turso, not data/*.json fallbacks.
  • Confirm pwd is the repo root before any test run — cwd drift produces bogus failures.
  • If the failure cannot be reproduced locally (VPS-topology-only), reproduce the MECHANISM in a test harness (the destroy-storm fix reproduced agent.destroy() mid-flight aborting 10/10 concurrent requests).

2. Write the FAILING regression test FIRST (red)

  • Vitest for web/lib, pytest for scripts/api. The test must fail for the same REASON production failed, not merely fail. Encode the failing topology: the destroy storm shipped because db-timeout-self-heal.test.ts was single-caller while the incident was concurrent-caller.
  • Derive expected values, never arithmetic in your head.
  • Run it, paste the red output. No red, no fix.

3. Fix

  • Root cause, not symptom. Surgical diff — touch only what the fix requires; no adjacent "improvements".
  • Respect the standing invariants for the subsystem (runbook case lists them): e.g. never destroy the shared undici Agent on isolated evidence; all persistence through Turso; heartbeats on skip paths; bounded IB awaits.

4. Full test gate (green)

  • Run the regression test file in isolation first, then the full gates from the repo root, mirroring CI:
    • bunx vitest run --config vitest.config.ts (root config, NOT bun run test)
    • python3.13 -m pytest scripts/tests scripts/api/tests scripts/trade_blotter
  • If a test flakes, re-run the suspect file in isolation before concluding your change caused it (test-ordering pollution is common here).
  • All green, pasted, before any commit.

5. Commit — focused, single-purpose

  • git status FIRST. Stage ONLY the files you edited, by path (git add path/to/file). NEVER git add -A / git add . — untracked WIP (journals, scratch scripts, notebooks) must not be swept in.
  • One logical change per commit; docs/runbook updates for THIS incident belong in the same commit. No secrets/PII. Claim in the message only what was actually verified.

6. Update the runbook + lessons

  • New failure mode → new case section in docs/incident-runbook.md (mechanism, detection signals, discriminating checks, fix commits, regression tests). Known mode → append the new commit SHA to its case.
  • If the incident came from a correction or a wrong first diagnosis, add the pattern to tasks/lessons.md.

7. Push ONCE and wait for CI green

  • Check nothing is mid-deploy: gh run list --workflow=ci.yml --limit 1. If a run is in progress, WAIT — rapid-fire pushes cancelled an in-flight deploy and corrupted the production build (2026-07-08).
  • git push origin main (main, never beta), then watch to completion: gh run watch or poll gh run list --workflow=ci.yml --limit 1 until completed/success. The deploy job is gated on the full test matrix and holds a non-canceling production lock.

8. Verify live

  • UI-visible fixes: verify in the real browser via chrome-cdp (fallback Playwright) and capture a screenshot as evidence. Tests alone do not close a UI incident.
  • Data/API fixes: curl the production route (authenticated where needed) and verify the BODY; for persistence fixes confirm the row in live Turso.
  • Confirm the incident watchdog resolves the artifact on its next cycle (python3.13 -m scripts.incident_watchdog --once, then check the incident file's status flipped to resolved), or resolve-and-note manually if the probe surface cannot see the fix.
  • Only now report done, with the evidence inline.

Stand-down criteria (do NOT ship a fix)

  • Upstream/platform outage (Turso-side wedge, IB farm down): remediation is operational, not code. Follow the runbook case, alert, stand down.
  • Off-hours staleness on RTH writers, anonymous 401/404 on protected routes, unknown probe states: not incidents. Close the artifact with a note.
  • Deploy in a transitional state (CI in_progress): wait; do not "fix" a marker mismatch that a running deploy is about to close.

Signals

GitHub stars
30
Forks
6
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
incident-response-joemccann
Source
github.com/joemccann/radon