Every faultbox test run emits a single .fb archive capturing
everything needed to re-run it later: the trace, the environment,
per-service logs, a copy of the .star source tree, and a one-liner
that reproduces the run. Bundles exist so a failure found on Monday
can be re-run by a colleague on Tuesday — without reconstructing the
environment from conversation history.
Introduced in v0.9.7 (RFC-025). The bundle is the input contract for
faultbox replay (v0.10.0) and faultbox report (v0.11.0) — every
downstream tool reads one .fb and nothing else.
Quick start
# Run tests → bundle is emitted automatically in the cwd.
faultbox test faultbox.star
# → Bundle: run-2026-04-22T15-03-11-42.fb
# Inspect what's inside.
faultbox inspect run-2026-04-22T15-03-11-42.fb
# Dump one file to stdout (pipe to jq, less, etc.).
faultbox inspect run-*.fb manifest.json | jq '.summary'
# Extract everything into a directory.
faultbox inspect run-*.fb --extract ./unpacked/
Flags on faultbox test
| Flag | Effect |
|---|---|
| (default) | Emit run-<ts>-<seed>.fb in cwd |
--bundle=<path> | Write the bundle to a specific path |
--no-bundle | Skip bundle emission entirely (rare; CI opt-out) |
$FAULTBOX_BUNDLE_DIR | Environment override — bundles go in this dir |
Precedence: --bundle > $FAULTBOX_BUNDLE_DIR > cwd.
Archive layout
A .fb file is a tar.gz. The writer emits files in a predictable
order so tar -tf run.fb users see the important ones up front.
run-2026-04-22T15-03-11-42.fb (tar.gz)
├── manifest.json # schema version + run summary
├── env.json # host fingerprint (OS, kernel, Docker, …)
├── trace.json # full event log — same shape as --output
├── replay.sh # one-liner; `faultbox replay <this-bundle>`
└── spec/ # user .star tree snapshot
├── faultbox.star
└── helpers/…
manifest.json
Top-level summary. Consumers should read this first.
{
"schema_version": 1,
"faultbox_version": "0.9.7",
"run_id": "8ebbad2351b0c7accb6aa1ee8ce1aca8",
"created_at": "2026-04-22T15:03:11Z",
"seed": 42,
"spec_root": "faultbox.star",
"tests": [
{"name": "test_happy", "outcome": "passed", "duration_ms": 12},
{"name": "test_fault", "outcome": "failed", "duration_ms": 204}
],
"summary": {"total": 2, "passed": 1, "failed": 1, "errored": 0}
}
schema_version evolution rules:
- Additive field changes (new optional keys) do not bump it.
- Layout changes (new top-level files, renames) do bump.
- Tools refuse bundles with an unknown
schema_versionrather than silently mis-parse.
env.json
Everything the runtime could determine about the host. Every field is best-effort; fields it couldn’t resolve are omitted, not nulled.
{
"faultbox_version": "0.9.7",
"host_os": "linux",
"host_arch": "arm64",
"kernel": "6.8.0-49-generic",
"go_toolchain": "go1.26.1",
"docker_version": "27.3.1",
"runtime_hints": ["lima"]
}
trace.json
Identical to today’s --output trace.json — the full event log with
vector clocks, per-test syscall summaries, and diagnostics. Embedded
in the bundle so everything needed for a report lives in one file.
replay.sh
A tiny POSIX script that re-runs the bundle:
#!/usr/bin/env sh
# Generated by faultbox 0.9.7 at 2026-04-22T15:03:11Z
DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
exec faultbox replay "$DIR/run-2026-04-22T15-03-11-42.fb" "$@"
Pass --test <name> to re-run a single test.
spec/
A snapshot of every local .star file the Starlark runtime loaded:
the root spec plus every file pulled in via load("./helpers/…").
Paths preserve the tree structure relative to the root’s directory,
so faultbox replay can rehydrate the run against the exact source
that produced it.
@faultbox/… stdlib loads are NOT captured — they’re part of the
consuming binary already, so re-archiving them would bloat bundles
without adding reproducibility value.
Version compatibility
manifest.faultbox_version records which Faultbox binary produced
the bundle. Different consumers apply the field differently:
| Consumer | Same X.Y.Z | Minor/patch drift | Major drift |
|---|---|---|---|
faultbox inspect | silent | warn, proceed | warn, proceed |
faultbox replay (v0.10.0) | silent | warn, proceed | refuse |
faultbox report (v0.11.0) | silent | warn in header, render | warn in header, render |
Rationale: major bumps are deliberate breaking changes; re-running a pre-1.0 bundle on 1.x would silently change semantics. Minor/patch drifts are tolerated because Faultbox doesn’t yet ship a version-switcher — users would otherwise be stranded if they lacked the exact producing version.
The warning message names the exact version needed for byte-identical replay so, when a version-switcher does ship, the guidance turns from informational into actionable.
Observability paired with bundles
Every failed test prints a replay hint at the end of the terminal session:
Replay: faultbox replay run-2026-04-22T15-03-11-42.fb --test test_fault --seed 42
Every fault_zero_traffic event (rule installed but matched no
syscalls) also surfaces at session end:
Zero-traffic faults (1): rule installed, matched no syscalls
test_fault — db.connect (deny)
Hint: the scenario may not be exercising the upstream during the fault window.
Both were previously visible only inside trace.json. Users writing
fault_matrix tests now see them directly.
Checking bundles into git
Bundles are useful as regression evidence — “here’s the failure I found, check if v0.9.8 still reproduces it.” A common pattern:
# .gitignore
*.fb
!regressions/*.fb
This ignores everyday bundles while allowing a curated
regressions/ directory with named golden bundles to ride in the
repo.
Security note
Bundles contain:
- Resolved
.starsource underspec/ - Captured stdout/stderr of every service (Phase 1.5)
- Environment-variable values the test passed in
Treat bundles with the same care as service logs — they carry whatever secrets were in the test environment. The bundle emitter has no redaction logic; that’s the caller’s responsibility when running against production-like configs.
See also
- RFC-025 — full specification
- RFC-030 —
faultbox.lockfor image-digest pinning (v0.10.0) - RFC-029 —
faultbox reportHTML rendering (v0.11.0) faultbox replayin CLI reference — the bundle’s primary consumer; v0.10.0+faultbox lockin CLI reference — digest pinning that pairs with the bundle’s env.json snapshot