Architecture
One Next.js 16 (App Router) application. Pure decision logic is separated from I/O so the rules that matter — what counts as proven, what counts as a recurrence — are small, readable and unit-tested.
┌──────────── Next.js app (Vercel) ────────────┐
GitHub ──────► │ /api/webhooks/github ─┐ │
Alerts ──────► │ /api/webhooks/<source> ├─► lib/workflows ───┼──► Runner (Vercel Sandbox / Docker)
(9 sources) │ lib/integrations ┘ │ │ one VM per run, no secrets
CLI / CI ────► │ /api/v1/* ▼ │
Browser ─────► │ app/(app) pages ──► lib/db ──► Postgres │──► Model (Muse / AI Gateway / custom)
└──────────────────────────────────────────────┘Flows
Time travel (lib/workflows/timeTravel.ts)
- Resolve the fix commit and its parent (
lib/git/source.ts: the GitHub REST API for GitHub repositories, the git CLI for local paths). A root commit or unknown SHA leaves the incident in Awaiting fix with a reason. - Read context: the fix diff, the changed files at the parent, test setup files, the nearest tests.
- Draft a test (
lib/model/draft.ts). Output is validated: one file, under the test folder, the right framework, a real test, balanced code. Model timeouts and rate limits are retried with back-off (lib/model/retry.ts). - Run it three times on the parent. Anything but three failures stops here: passing means rejected and feeds back into the next draft; errors mean unproven and end the run.
- Run it three times on the fix.
lib/domain/admission.tsdecides. - On proven: store the memory test, open a bot PR, then start Epicenter and the retro-check.
Pull request check (lib/workflows/prCheck.ts)
- Select memory tests: every test whose watched files the PR changes, plus any the model triage adds (
lib/domain/relevance.ts). - Pick the runner (
lib/runner/select.ts): sandbox, the team's GitHub Actions, or unavailable when the sandbox allowance is spent. - Run each test three times on GitHub's test merge commit (the PR merged into its base, as CI does), or on the head when the PR conflicts;
lib/domain/verdict.tsdecides per test and overall. - Update the GitHub check run and the single PR comment.
Epicenter (lib/workflows/epicenter.ts) gallops back through first-parent history until the test passes, or until the code it tests does not exist yet, then binary-searches the boundary (lib/domain/epicenter.ts, capped at 12 runs). It can be re-run from the incident page.
Daily (lib/workflows/daily.ts, started by the daily cron) re-checks each memory test once on the default branch as its own step (lib/workflows/nightly.ts) and keeps 14 nights of health.
Each workflow is a deterministic "use workflow" function calling "use step" functions. On Vercel the Workflow SDK makes them durable; locally and in tests the same code runs in-process (lib/workflows/start.ts).
Code layout
app/(site)/ public site: home, pricing, security, docs, sign in
app/(app)/ product: overview, incidents, time travel, memory, pull requests,
repositories, integrations, settings, onboarding; server actions
app/api/auth/ GitHub OAuth, demo sign-in, workspace switch, sign out
app/api/webhooks/ GitHub and every alert source (signature- or token-verified, rate-limited)
app/api/v1/ HTTP API (token or session)
app/api/cron/ nightly re-check
components/ui/ Pill, Card, Button, Field, Strip, Logo
components/app/ sidebar, top bar, shared rows
components/site/ marketing header/footer, hero, pricing
lib/domain/ verdicts, admission, relevance, fault lines, epicenter, lessons, ids
lib/db/ Drizzle schema, client (Neon or PGlite), workspace-scoped queries, demo seed
lib/auth/ sessions (jose), GitHub OAuth, roles, API tokens
lib/runner/ Runner interface; Docker and Vercel Sandbox; JUnit parsing; framework adapters
lib/git/ commit resolution, file reads and history via the GitHub API or git CLI
lib/model/ provider config, fencing of untrusted text, prompts, validation, drafting, triage
lib/github/ App client, REST calls, webhook routing, comments, bot PRs, suggestions
lib/integrations/ source registry (sources.ts), signatures, receive() and intake
lib/workflows/ time travel, PR check, suggested fix, epicenter, retro-check, nightly
lib/http/ absolute URLs, rate limiting
cli/ aftershock CLI (bundled with esbuild)
drizzle/ SQL migrations
tests/unit, tests/integration, e2e/Security model
- Isolation: every run is a fresh microVM (or container locally). Dependencies install with network; the network is cut before tests run. No secrets enter a run.
- Least privilege: runners clone with read-only, single-repository tokens. The app writes only
aftershock/*branches. - Untrusted input: incident text, postmortems, code and diffs reach the model inside random-nonce fences; model output is validated and only ever written to the test path.
- Tenancy: every query goes through
scoped(workspaceId); API tokens are stored as SHA-256 hashes; model keys and webhook secrets are encrypted with AES-256-GCM. - Webhooks: HMAC signatures are verified in constant time before anything is parsed or stored.
- Abuse: per-caller rate limits on webhook and API routes; custom model endpoints must be public
https://hosts.