Skip to main content
guard run is fully deterministic: it builds the repo via the recipe, executes every committed scenario (including the ones that were already failing at birth), and writes the run to .truecourse/guard/. A test that was red at birth simply comes back green once the code catches up. It exits non-zero on any drift, so it drops straight into CI. No LLM, no API key, no claude binary.
For api-driver scenarios the runner boots one fresh server per scenario in an isolated sandbox, runs api.services.up and the seed once per run, and points provided external services through their fault-scriptable proxies.

Not every red test is drift

A scenario walks a flow: some steps assert a spec claim (they carry a milestone), others only prepare the world (the seeding request at the head of a flow, a login). When the step that fails is one of the preparation steps, the run annotates the result blocked precondition: the scenario still fails, but the documented behavior was never actually exercised, so the fix is the setup (seed the row, declare the fixture, supply the credential), not the code. The CLI prints it on its own line under the failure and the dashboard marks the test “setup failed”, distinctly from a real expectation mismatch. It’s an annotation only; it never changes an outcome and never softens a CI gate.

Reading the results

A failing scenario means the bound spec section and the code disagree: a drift or a bug, the developer’s call. Each failure carries an evidence transcript under .truecourse/guard/evidence/<runId>/ showing exactly what the scenario ran and what came back (credential and external-service values are masked). The dashboard’s Guard → Runs view shows each run’s drifts with the per-failure evidence inline.

The run store

.truecourse/guard/ mirrors the analyze store:

In CI

The exit code is the gate: 0 when every scenario passes, non-zero on any drift. Scenarios, recipe, and manifest are committed, so CI needs no LLM configuration at all.
TRUECOURSE_MAX_CONCURRENCY caps the runner’s parallel scenario sandboxes, and TRUECOURSE_MAX_API_CONCURRENCY separately bounds how many api-driver servers are resident at once; see Models & environment.

Next steps

Dashboard

Review runs, drifts, and per-failure evidence visually.

Storage

What the guard store holds, and which files to commit.