Quickstart
This walks you through running SREForge’s validated v1 incident —
latency-cache-stampede on the booklogr use-case — end-to-end, using the
scripted reference fix. By the end you’ll have watched the closed loop drive a
real alert from firing to cleared.
Prerequisites
Section titled “Prerequisites”- Docker with Compose v2 (
docker compose …) and the daemon running. - Node 18+ and pnpm (the repo pins pnpm via
packageManager; runningcorepack enableselects the right version). - A few GB of free RAM — the deploy plane + observability stack run ~8 containers alongside the shared Gitea forge.
- WSL2 + Rancher Desktop is supported, but has two known gotchas — see Troubleshooting.
Run it
Section titled “Run it”-
Clone and install the repo-root tooling once.
Terminal window git clone https://github.com/prismalens/sreforge.gitcd sreforgepnpm install -
Bootstrap the shared forge — first run only. SREForge imports each substrate into a local Gitea forge — its own Git remote + CI/CD, with no github.com. The forge is shared infrastructure that persists across runs, so you set it up once, before the first
setup/fresh.pnpm forge freshdoes not start the forge for you.Terminal window # from the repo root — copy and fill the stack envcp use-cases/booklogr/stacks/flask-compose/.env.example \use-cases/booklogr/stacks/flask-compose/.env# edit that .env: set GITEA_ADMIN_PASSWORD (review GITEA_ADMIN_USER / _EMAIL)# start Gitea, create the admin user, register a runnerdocker compose -f infra/forge/forge.yml up -d gitea# create the admin via the UI at http://localhost:3000, or:# docker exec -it sreforge-gitea gitea admin user create \# --username sreforge --password '<pw>' --email admin@localhost --admin# mint a runner token (Gitea → Site Admin → Actions → Runners), put it in# the .env as GITEA_RUNNER_REGISTRATION_TOKEN, then:docker compose -f infra/forge/forge.yml up -d act_runnerinfra/forge/forge.yml’s header is the authoritative bootstrap reference. -
Cold bring-up. Import the substrate into the forge, author the regression, and start the deploy plane.
Terminal window pnpm forge fresh booklogrfreshis a composite verb — it expands tosetupthenup. See the CLI reference for the full verb list. -
Run one graded incident with the reference fix. This arms the incident, runs it, and verifies behaviourally.
Terminal window pnpm forge incident booklogrincidentexpands toarm → run → verify. The harness injects the fault, confirms theBooklogrApiLatencyP99Highalert is firing, applies the reference fix through the CI → merge → redeploy chain, and then checks the alert clears and stays cleared while the k6 storm is still running. -
Tear down the deploy and load planes when you’re done (the local forge persists).
Terminal window pnpm forge down booklogr
What you should see
Section titled “What you should see”Once the stack is up, these endpoints are live:
| Service | URL |
|---|---|
| booklogr API | http://localhost:5000 |
| Web frontend | http://localhost:5150 |
| Prometheus | http://localhost:9090 |
| Alertmanager | http://localhost:9093 |
| Grafana | http://localhost:3002 |
| Gitea forge | http://localhost:3000 |
During the run, watch BooklogrApiLatencyP99High move to firing in
Alertmanager after the fault is injected, then clear after the reference fix
redeploys — all while load continues.
Prove the anti-cheat
Section titled “Prove the anti-cheat”The lower-level smoke scripts demonstrate the behavioural oracle directly. Each script self-resolves and runs standalone:
cd use-cases/booklogr/stacks/flask-composebash scripts/smoke-positive.shThe reference fix flows through the full conductor loop and the alert clears under sustained load — the run passes.
cd use-cases/booklogr/stacks/flask-composebash scripts/smoke-negative.shA plausible-but-ineffective fix does not clear the alert under sustained load — the run is rejected. This is the anti-cheat in action.
The incident, in one paragraph
Section titled “The incident, in one paragraph”The search-response cache is disabled (CACHE_TYPE = "NullCache") in the
booklogr API, so every GET /v1/books/search misses cache and blocks a Gunicorn
worker on a deterministically slow (1.2 s) book-metadata upstream. Under a k6
constant-arrival-rate storm over a small query set, the four workers back up, p99
latency crosses 0.3 s, and BooklogrApiLatencyP99High fires. The reference fix
restores an effective cache, so repeated queries hit it and p99 clears while the
storm is still running.
Troubleshooting
Section titled “Troubleshooting”pnpm forge fresh hangs at “ensure org + empty repo exist in Gitea”.
The shared forge isn’t bootstrapped. Confirm Gitea is up
(docker compose -f infra/forge/forge.yml ps), the admin user exists, and the
stack .env is filled — see step 2 above.
All deploy containers exit with code 255 at once (WSL2 + Rancher Desktop).
This is a Rancher/WSL daemon cycle, not a crash — sometimes the Docker socket
briefly disappears and takes the shared runner down with it. Recovery is
idempotent: wait for the socket to return, restart the forge with
docker compose -f infra/forge/forge.yml up -d, then bring the app stack back
with pnpm forge up booklogr. (The deployment is stateless except its DB volume.)
A container fails with mount … not a directory / “mount a directory onto a
file” (WSL2 + Rancher Desktop). A single-file bind mount can resolve as a
directory through Rancher’s mount shim. The repo already avoids this (it binds
parent directories or bakes files into images); if you add config, bind the
parent directory, never a single file.
Port already in use. The stack needs host ports 5000, 5150, 5432,
9090, 9093, 3002 for the app + observability, plus 3000 and 222 for the
forge. Free the conflicting service or stop a previous run with
pnpm forge down booklogr.
- Run an incident — the lifecycle in detail.
- Drive an external agent — replace the scripted fix with a real autonomous agent.
- CLI reference — every
pnpm forgeverb.