# The Sandbox

The sandbox is a one-command, real-scenario tour of the entire forge lifecycle. It builds the actual `forge` binary, stages a realistic sample project, and drives it through import, scoring, every [enforced gate](/harness/overview), and the [dashboard](/features/dashboard) build — asserting at each step that the gates fire exactly the way they do in production. It is both the fastest way to *see* forge work end to end and the repository's end-to-end safety net.

::: info Runs from a source checkout
The sandbox lives in the forge source tree (`scripts/sandbox/`, wired to `make` targets), not in an installed project. Clone the repository to run it. Installed users get the same behavior through the individual commands documented across this site — the sandbox just wires them into one realistic run.
:::

## Two entry points

Both drive the **same 9-step scenario** against the **same fixtures**, so they never drift:

| Command | What it is |
| --- | --- |
| `make sandbox` | Human-drivable. Builds the binary, runs the full lifecycle, and **leaves the artifacts** under `scripts/sandbox/out/work/` for you to open and inspect. |
| `make sandbox-clean` | The same run with a wiped output directory first (`run.sh --clean`). Use it when a previous run left stale state. |
| `make e2e` | The hermetic, CI-gated form: a tag-gated Go test (`go test -tags e2e ./e2e/...`) that runs the identical scenario in a temp directory with hard assertions and no persisted artifacts. |

The script runs every step even if an earlier one failed, prints one `PASS`/`FAIL` line per assertion, and exits non-zero if any assertion failed — so a single run reports every problem rather than stopping at the first.

## The 9-step lifecycle

```mermaid
flowchart LR
  B[build] --> S[stage] --> I[import] --> A[analyze]
  A --> SC[secscan BLOCK] --> W[waive] --> BU[budget EXCEEDED]
  BU --> V[verify breaker] --> D[trace + docs]
```

Each step asserts a specific, observable outcome. The gate steps are the point: they deliberately expect a **non-zero exit** to prove the gate blocks.

1. **build** — compile the `forge` binary to `out/bin/forge`.
2. **stage** — copy the `acme-shop` fixture into a fresh work directory.
3. **import** — map the `.specify/` project into `.forge/` and assert the change directories were created. See [Migration Importer](/features/migration).
4. **analyze** — run the portfolio health rollup and a single-spec score, asserting the [quality score](/features/quality) is non-trivial.
5. **secscan** — scan the planted secret and assert the [guardrails gate](/harness/guardrails) **BLOCKS** (exit non-zero).
6. **secscan waive + rescan** — waive the finding as a human would, and assert the rescan is now clean.
7. **budget** — accumulate spend, then cross the ceiling and assert the [spend budget](/harness/budget) reports `BUDGET EXCEEDED` (exit non-zero).
8. **verify breaker** — force a verify failure so the [circuit-breaker](/harness/circuit-breaker) opens (exit non-zero), then `--reset-breaker` and assert it clears.
9. **trace + docs** — assert the [session timeline](/harness/timeline) aggregated the gate events, then build the offline [dashboard](/features/dashboard) and assert `index.html` was written.

::: tip The gates are supposed to fail
Steps 5, 7, and 8 assert a **non-zero** exit. That is the sandbox proving the enforced gates actually stop the line — a secret is blocked, a budget ceiling is enforced, a failing verify escalates. A sandbox where every step returns `0` would mean the gates are asleep.
:::

## The sample project

The fixture is a small but realistic `.specify/` project, `acme-shop`, committed under `scripts/sandbox/fixtures/`:

```text
acme-shop/
  .specify/
    memory/constitution.md            # a few real principles
    specs/001-checkout/{spec,plan,tasks}.md
    specs/002-auth/{spec,plan,tasks}.md
  src/
    checkout.js                       # secret-free
    config.js                         # a planted, clearly-fake AWS key
```

`src/config.js` contains an intentionally-fake AWS-style key. It is the trigger for step 5 — the thing the [guardrails gate](/harness/guardrails) must catch. Everything else is authored so `analyze` produces a real, non-trivial [quality score](/features/quality).

## Inspecting the artifacts

`make sandbox` leaves a fully-populated `.forge/` behind so you can explore the exact state the gates produced:

```text
scripts/sandbox/out/work/
  .forge/
    changes/001-checkout/
      budget.yaml            # the spend ledger
      secscan.yaml           # the waiver from step 6
      session-log.jsonl      # the attributed timeline
      verify-attempts.yaml   # the circuit-breaker state
    site/index.html          # the generated dashboard
```

The run prints the path to the generated dashboard at the end — open it in a browser to see the same [spec-viewer](/features/dashboard) a real project produces.

## Sandbox, selftest, and e2e

Forge ships three overlapping checks. They are complementary, not redundant:

| Check | Command | Scope |
| --- | --- | --- |
| **Selftest** | `forge doctor --selftest` | Fast **in-process** smoke test that the core commands are wired, using tiny synthetic stubs. |
| **Sandbox** | `make sandbox` | Drives the **real binary** through the full lifecycle against a realistic project, asserting each gate. Leaves artifacts to inspect. |
| **e2e** | `make e2e` | The sandbox scenario as a **hermetic, CI-gated** Go test — same assertions, no persisted state. |

Reach for the selftest to check the plumbing, the sandbox to see and inspect the experience, and `make e2e` in CI.

## Extending it

The fixture and the driver are plain, versioned files:

- Add a spec or feature under `scripts/sandbox/fixtures/acme-shop/.specify/`.
- Add or adjust a step in `scripts/sandbox/run.sh` (each step asserts an exit code and records `PASS`/`FAIL`).
- Mirror any new assertion in `e2e/sandbox_test.go` so CI covers it too.

Keep the two entry points in lockstep: whatever the human sandbox demonstrates, the hermetic e2e test should assert.

## Next steps

- [The enforcement doctrine](/harness/overview) — the enforced gates the sandbox exercises.
- [The forge CLI](/reference/cli) — the real commands each step drives.
- [Migration Importer](/features/migration) — the import step the sandbox runs first.
- [Spec-Viewer Dashboard](/features/dashboard) — the dashboard the final step builds.
- [Getting the Most out of Forge](/guide/best-practices) — apply the workflow to your own repo.
