A minor release that changes how the compose demo's figures are produced and quoted. The services, the wire format in common/, the migrations, the service manifests and the load generator's command line are untouched; make demo keeps its name and its stack, the generator's summary JSON keeps all 31 fields 5.1.0 wrote and adds eight, and each new environment variable has a default.
The load generator's summary now opens with a provenance object: the commit and machine passed in as RUN_COMMIT and RUN_MACHINE (unspecified when absent), the container's platform and JDK, the load window in UTC to the second, and its kernel's load average at either end of the load. It stores every figure its text prints, renders the text from those fields alone, stores it as summaryText, sets complete last, and prints the text and a SUMMARY_JSON line carrying the same map. The text gains commit, window, machine and load average lines, and the matching counters line now shows retried and dropped. LoadGenTest asserts, against a stub server, that the stored fields render the stored text exactly, that complete comes last and that the printed line equals the file.
make demo now runs scripts/compose-demo.sh, which starts the same stack, then runs the generator with --no-deps so that run --build no longer rebuilds and recreates the three services just before the load. It saves the SUMMARY_JSON line as demo-out/loadgen-summary.json, since the generator's own file is removed with its container, and writes demo-out/demo-run.json with the commit (suffixed -dirty on a modified tree), the host and Docker VM, the start and finish times, the host load average before and after, the stack's memory halfway through the load and the generator's exit code. A failed attempt keeps the last completed pair. The script needs git and a checkout, which the old compose commands did not. scripts/k8s-e2e.sh passes a commit and machine into the loadgen Job and refuses values outside a small character set.
scripts/patch-demo-summary.py writes the README block from those two files or refuses: an incomplete run or a nonzero generator exit, files that disagree on the commit or machine, a measured window outside the run's span, a modified tree, a commit other than HEAD, a missing or placeholder field, or a text line its fields do not render to. The README says what it cannot catch: a field edited together with its line, and the caption's load averages and memory, copied unchecked. With --check DIR it writes nothing and fails unless the README's block is, to the character, what the run committed in DIR renders to, under the same rules except that the run's commit need only be an ancestor of HEAD; the build job in CI runs it. scripts/test_demo_summary.py drives the patcher with 21 cases. scripts/demo-load-gate.sh, run before make demo, waits up to 45 minutes for a host load average below 8 and a Docker VM load average below 3 on two consecutive readings 30 seconds apart.
The README demo block captured at ae5dba8 on 2026-09-03 is gone; the 5.1.0 README already said the printed summary carried fields it lacked, and it named no clock window or load average. The block now comes from one make demo run at 1bc404c, 18:12:37 to 18:14:17 UTC on 2026-09-28, whose summary, run record and gate readings are committed in docs/demo-runs/1bc404c/; the readings end with two consecutive passes under those limits, and none of the code the run exercised has changed since. On Darwin arm64 with 10 CPUs and a 6 CPU, 7.7 GiB Docker VM, with host load 5.62 before and 4.68 after and container kernel load 2.18 at the start of the load and 5.75 at the end, it submitted 603 rides with no errors, retries or skips, decided and matched 603 of 603 trip rows, and measured p50 15 ms, p95 56 ms and p99 221 ms, with 1496 MiB in use across eight containers halfway through. The 5.1.0 claim that the stack fits a 2 GiB Docker VM is gone too.
Tests at the release commit, in CI run 36472860778: lint, 36 script cases, the demo block check, 63 Surefire unit tests and 14 Testcontainers integration tests, all passing, and the kind rolling update under load, whose rollout gate printed COVERAGE: PASS and RESULT: PASS.