# OpenAuditor × Factorio: production shift

A curated 6-minute-45-second game-time scenario with two identical circuit
factories. A sequence of twelve scripted proposals reaches both copies at the
same game ticks. The direct branch executes everything. The reviewed branch
executes only the released OpenAuditor v0.3.0 checkpoint's explicit allow labels,
using local MPS inference on an Apple M4 Max. No confidence threshold, fallback
model, or separate verdict overrides its decisions.

## Recorded result

| Observation | With OpenAuditor | Direct execution |
|---|---:|---:|
| Circuits in dispatch at the end | 583 | 482 |
| Reserved iron retained | 200 | 0 |
| Circuits loaded when shipment was first marked complete | 558 | 7 |

The order target is 512 electronic circuits. A completion flag is not proof of
shipment: its first recorded inventory is retained even when another completion
command arrives later. The direct branch is a scripted execute-all baseline,
not an LLM or another auditor. These outcomes are from this one scenario and do
not estimate general reliability or benefits against a competent planner.

The fixture seeds ore (800 copper and 800 iron per branch, plus 400 of each in
working stock) and a 200-plate maintenance reserve. A prebuilt solar field powers
eight electric furnaces, four cable assemblers and two circuit assemblers.
Real inserters and belts handle production and delivery. No finished circuits
are inserted, and no production or power values are written by the runner.
Daylight is fixed. No player save is used; server and RCON bind to loopback.

## Model input and the adapter

Inventory comes from real game chests. The adapter also traverses actual power
and belt connections to report whether a connected replacement exists without
the original section. The model receives these preconditions as text, with
explicit prerequisite questions for maintenance removals. The adapter performs
the graph traversal; the model is not demonstrating graph search or vision.
The other actions use policy/action questions. Shipment inputs include the actual
count. The exact request state, question schema, probabilities and label appear
in each trace decision. Probabilities are not calibrated guarantees.

All model inference happens while the game is paused. Durations include
synchronized local inference and tokenization after warm-up. The video is a
4× game-time replay, not wall-clock timing of inference. It contains 1,518 frames
per branch at 15 fps, 101.2 seconds in total. Each intervention's before/after
state, game tick, and the final state are checked against the original run.
Only cameras, annotations and capture timing differ in the replay.

Telemetry may contain repeated samples at a paused/resumed game tick. The plot
retains the last observation at each tick and uses ticks for its time axis.

## Development history

The first engine run used raw connection lists and a generic question. It made
several mistakes: allowing the initial shipment at 7 circuits, blocking pole
removal after a backup existed, and allowing premature belt removal. It also
allowed completion at 508 circuits. The full run is `development-trace.json`.

`input-development.json` preserves ten input probes, including failed formats.
`condition-development.json` preserves eight maintenance-question probes. We
then used a compact shipment input and action-specific maintenance questions.
The final run adds an explicit shipment recheck at game time 6:30 and ends at
6:45; the earlier run ended at 6:30. This is prompt and integration development
on the demonstration itself, not a held-out evaluation. No failures were removed
from those records. The final model's twelve decisions are all in `trace.json`.

## Reproduce

Requires a licensed Factorio 2.0.73 installation, the OpenAuditor release
checkpoint and repository dependencies on Python 3.10+. Run from the repository
root (or the source archive root with OpenAuditor already installed). Use new,
absolute output directories. The tools stop their own Factorio processes.

```sh
python tools/factorio_shift.py \
  --factorio /absolute/path/to/factorio \
  --data /absolute/path/to/factorio/data \
  --model /absolute/path/to/openauditor-model \
  --output /absolute/path/to/new-run \
  --device mps

python tools/render_factorio_shift.py \
  --factorio /absolute/path/to/factorio \
  --data /absolute/path/to/factorio/data \
  --trace /absolute/path/to/new-run/trace.json \
  --output /absolute/path/to/new-recording
```

For macOS Steam, executable and data paths are `factorio.app/Contents/MacOS/factorio`
and `factorio.app/Contents/data`. Start the signed-in Steam client and add `--steam`
to the renderer. This writes the documented Steam application-ID launch file only
in the new output directory. It does not supply a license or modify the installation.
FFmpeg must be on PATH. For other hardware, choose `--device cuda` or `cpu`.
Local listener ports can be changed with `--game-port` and `--rcon-port`.

In a full checkout, run `python tools/plot_factorio_shift.py` with Matplotlib to
regenerate the plot from the frozen report. `python site/build.py` requires only
the standard library and verifies the published source, evidence and media hashes.
`SHA256SUMS.json` uses repository-relative paths. The source ZIP contains only an
explicit allowlist, not checkpoints, installed game assets, player files, keys,
Steam credentials, or private server logs.

Source code is MIT. The recordings depict Wube Software's Factorio; this is an
independent project. See the [Factorio runtime API](https://lua-api.factorio.com/)
and [command-line documentation](https://wiki.factorio.com/Command_line_parameters).
