# One fill, two deliveries

An executable local experiment accompanying the Eigenstate essay. The broker,
consumer processes, offset commits and SQLite writes are real. The fill,
account and instrument are constructed inputs. This is not a production trace.

## Run

Requirements: Python 3.9 or newer, Apache Kafka **4.0.2**, and Java 17 or newer.
Use a disposable local working directory on macOS or Linux. The script requires
SIGKILL and creates its own broker; it never connects to an existing cluster.

Download the Kafka binary distribution from the
[Apache archive](https://archive.apache.org/dist/kafka/4.0.2/) and check its
published SHA-512 before extracting it. Provide an existing Java installation
or unpack a suitable runtime separately. Neither runtime is included here.

```sh
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python reproduce.py run \
  --kafka-home /absolute/path/to/kafka_2.13-4.0.2 \
  --java-home /absolute/path/to/java-home \
  --output /absolute/path/to/a-new-results-directory
```

`--output` must not already exist. Kafka binds two ephemeral loopback ports.
Allow approximately 512 MB for the broker heap, additional process memory and
disk space for Kafka's internal logs. The command stops its broker when it
finishes or reports an exception. Interrupted machine sessions may require
stopping that isolated process manually. No database or cluster is reused.

## Read the result

`recorded.json` contains the input, runtime versions, consumer settings,
producer acknowledgments, each worker's received offsets and results, database
snapshots, and group offsets read back from Kafka. A committed offset is the
**next** record to read: offset 0 means F1 at offset 0 is still pending; offset 1
means that record has been passed. Each group is explicitly initialized to 0.

Each crash case gets a fresh topic, group and database. The worker reports a
named checkpoint and waits. The parent sends SIGKILL, waits for exit code -9,
reads the persisted database and broker offset, then starts a new consumer
using the same group. The restarted consumer subscribes normally; the harness
does not seek it backward or reproduce an exception in place of a process kill.

Cases and expected final holdings for the one-unit fill:

- `mark-first`: separately commit the deduplication marker, then die before the
  position update. Recovery skips the fill and leaves **0** units.
- `effect-first`: separately commit the position update, then die before its
  marker. Recovery applies it again and leaves **2** units.
- `atomic-before-commit`: write both inside one open SQLite transaction, then
  die before committing. The open transaction rolls back; recovery leaves **1**.
- `atomic-after-commit`: commit both in one transaction, then die before the
  Kafka offset commit. Recovery recognizes the fill and leaves **1**.
- `atomic-new-offset`: make two intentional producer calls with the same fill
  and producer idempotence enabled. Kafka stores offsets 0 and 1; the database
  recognizes the business identity and leaves **1** unit. No crash is injected.

The duplicate key is `(source, account, fill_id)`. A different payload under an
existing key raises an error rather than being silently treated as a duplicate.
The supplied duplicate uses exactly the same payload bytes. `BEGIN IMMEDIATE`
serializes SQLite writers; the key lookup, marker and effect share a transaction
in the atomic variants. The two split variants are intentionally incorrect.

Worker receipts and stderr logs are saved per case. `runtime/` contains broker
configuration, logs and storage for local inspection; it is excluded from the
download bundle. SQL exports in the bundle show the final databases from the
recorded run. The source hash in `recorded.json` identifies the executed script.
`SHA256SUMS` lists the published evidence files, including the source and SQL.

## Scope

One Kafka broker, one partition and one active consumer per case; one account,
instrument and business fill; an external SQLite database with rollback journal
and `synchronous=FULL`. This checks selected consumer-crash windows. It does not
exercise broker failure, disk loss, multiple partitions, concurrent consumers,
outbound orders, cross-database transactions, deduplication expiry or throughput.
There is no Kafka transaction spanning the external SQLite database.

Redis Streams is not run by this experiment. Browser playback of the original
trading model is independent of these processes and recorded files.
