flight-recorder
Record what the outside world told your code — every database answer, HTTP response, clock read and random draw — as one small JSONL file per request: a tape. Replay that file against your real code later: same inputs, same execution, bit for bit, with every internal variable observable. When a replay diverges, the report names the first difference instead of leaving you to guess.
A program's execution is fully determined by its code plus its nondeterministic inputs. Record just those, per call — one cheap line — and that line is the execution, compressed. Feed the answers back and the real code re-runs the original execution exactly: no network, no database, no waiting for the bug to happen again.
The cardinal rule: instrument, never duplicate. Nothing here evaluates a query, reimplements a client, or knows what any value means. Recording is a transparent proxy; replay feeds the recorded answers back and verifies the questions still match.
→ Read the guide
The full walkthrough — declare the boundary, record, replay, edit the tape to visit worlds that never happened, invariants, semantic spans — in Python, Node, .NET, Go, Java and PHP, one tab away. Slides — Testing as Simulation.
What a pile of tapes says that one tape cannot
A tape is one execution. A directory of them is a record of how the software is actually used — and flight_recorder.episodes reads that: the recurring act-sequences, mined from each tape's call envelopes. Turn each tape into a story with story(), hand the stories to mine() with the acts you know to be plumbing as noise, and each episode comes back as its acts with the number of tapes that walked them; successors() reads the same stories for the branches mining throws away. The module's own docstrings are the walkthrough until the guide grows its episodes chapter.
Counting what each call touched answers what did this do; it destroys the order, which is usually the part worth having. open → act → open → read is a conversation; {open: 2, act: 1, read: 1} is not. Deliberately pre-semantic — it reads each envelope's fn and nothing else, no spans and no model — because a workflow is visible before anyone has drawn a model of it, and a mined workflow is often what reveals a model missing an act.
Three shaping rules, each a bug before it was a rule. Consecutive repeats collapse: twelve of the same act in a row are one act, and left alone they flood the n-grams with eleven identical pairs. Stopwords are named by the caller, never inferred: a session handshake preceding nearly every call appears in every window and distinguishes nothing, and a frequency threshold would silently eat the busiest real act in a heavy week. And one line per ritual: a→b, b→a and a→b→a are one conversation told three ways, and dealing all three makes a deck nobody reads.
merge(scripted, live) keeps rehearsal and performance apart. Recordings driven by an authored scenario mine correctly and are not fake, but their counts mean something else — and a reader who cannot tell them apart reads a script's repetitions as usage.
The tape is a standard
The recording format is a frozen, documented wire contract: spec/tape-v1.md. Implementations are welcome — only record and replay must be native to a runtime; everything that analyzes a tape works on any tape. Conformance is not the prose: it is spec/fixtures/ plus the checker in spec/validate.py (mirrored in JS, .NET, Go, Java, and PHP). Every implementation must validate every fixture, and every fixture must have been produced by an implementation. This repo ships six implementations — Python, Node, .NET, Go, Java, and PHP — reading and writing the same tapes.
Why
flight-recorder pushes the heavy lifting from human to AI, and from AI to code. As AI takes on most of the development, scenario testing and debugging become the bottleneck, and the work left to the human is the tedious kind. Recording at the nondeterminism boundary gives the agent the missing instruments: it re-runs the exact request against the real code and watches any variable as the bug happens — root cause by lookup, not by guess; fixes proven by replay; regressions caught by a directory of files. What is left to the human is the decisions.
License
Apache-2.0 — see LICENSE and NOTICE. Relicensed from MIT deliberately, before any outside contribution existed: the tape spec is meant to be implemented by others, and Apache-2.0's explicit patent grant is what makes "implement this freely" a promise rather than a mood.
© 2026 Xavier Grehant
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file xag_flight_recorder-0.9.0.tar.gz.
File metadata
- Download URL: xag_flight_recorder-0.9.0.tar.gz
- Upload date:
- Size: 147.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
570c9f6d70452cca88a40649360748c23625cb5baaca7abea7ed6c0365dd2e3f
|
|
| MD5 |
211c814f7402e6103e85583e6acd5a83
|
|
| BLAKE2b-256 |
c4c660c56cab4b61a16703a54814d3e76b2f233593cb0986c8790a204aadcba6
|
File details
Details for the file xag_flight_recorder-0.9.0-py3-none-any.whl.
File metadata
- Download URL: xag_flight_recorder-0.9.0-py3-none-any.whl
- Upload date:
- Size: 86.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cff1d46eaa76a8a4b4ebfc9f486ca25b9e6883023acc8d5eb276bb2ce15788d6
|
|
| MD5 |
81206a806223ec95a12a502247f32f23
|
|
| BLAKE2b-256 |
a619303eb9ebc533c271e6fa63621298334a94d75c64695a9b641a0189529fba
|