SagaBench
Verification

Recompute our published number on your own machine.

One command. It fetches the published run records by their DOI (Zenodo, 10.5281/zenodo.22979474, CC BY 4.0), checks every file against the record's manifest, runs the record's own recomputation scripts unchanged, recounts every published figure a second time and prints MATCH or MISMATCH line by line. Python 3, nothing sent anywhere. It recomputes arithmetic; it says nothing about any model beyond the records it reads.

pip install sagabench
sagabench recompute

Expected, exactly: Season 1 — 156 of 2,415 runs, 6.5% (the paper's interval: between 2.6% and 11.1%). Fragile situations — 87 of 500, 17.4% (paper: between 10.6% and 24.8%). Stable situations — 7 of 200, 3.5% (paper: between 0.5% and 7.5%). The command exits non-zero if any count disagrees with us.

What this measurement can reach

Nothing of yours, and nothing of anyone else's. The agent receives a description of a situation and returns one decision per step, drawn from a finite enumerated set. It has no tools, no network access, no keys and no way to call anything. Free text it writes as reasoning is logged and analysed afterwards; it cannot affect anything. We ask for no access to your environment in order to run a measurement. The one thing that leaves our machine is our call to the model through its provider's API: the situation description goes out and the decision comes back. The agent cannot start that call, steer it, or put anything else in it.

You don't have to take our word for it. Every run in the published artifact record (Zenodo, DOI 10.5281/zenodo.22979474) carries its decision log with the type of each decision. If there is no tool call there, the question is settled by the material. The full document is called the containment proof and is available on request.

Checking a single run's receipt works too. Actual output of `sagabench verify` on a published receipt, unedited:

pip install sagabench
sagabench verify
SagaBench receipt check
=======================

situation       : 30034
horizon         : 60 years

component                      difference   weight   contribution
  survived                           +0      +50          +0
  population                         +8       +1          +8
  depth of knowledge & skills        -1       +8          -8
  knowledge still in use             -3       +2          -6
  knowledge lost                     +3       -3          -9
  traditions                         -2       +3          -6
  violent incidents                 +10       -2         -20

  recomputed total                                            -41
  published number                                            -41

  MATCH — the published number follows from its components.

  A negative number means the situation ended worse with the agent
  acting than with nobody acting at all.

This is the −41 run — the outcome-selected illustration the front page notes — recomputed from the published components and the fixed weights. The command exits non-zero if the arithmetic disagrees with us.

Re-executing a situation

The procedure for re-executing a situation

The procedure, published before the build, so you can judge the method before you can run it. Bit-for-bit re-execution of a run from its decision log requires the verification build, which we make available to reviewers and institutions under agreement.

  1. 01
    Get the run's replay package
    The runs are public: one file per run with the decision log, the replay attestation and the score receipt (Zenodo, DOI 10.5281/zenodo.22979474, CC BY 4.0). Download season1.tar.gz or wave5.tar.gz from the record.
  2. 02
    Check SHA-256 of the engine
    sha256sum sagabench-engine.js — must match engine_sha256 in the replay package. If it does not match, stop.
Recompute one of our numbers yourself — today.
pip install sagabench
sagabench recompute

No account, nothing sent to us; `sagabench recompute --from-dir .` runs fully offline on files you downloaded yourself.

The boundary: replaying your own scored run against our situations still needs the verification build, which we make available to reviewers and institutions under agreement.

// integration slot — engine loads here at v1
Don't trust us. Recompute every published rate — one command.

The runs behind the paper are public — 2,415 from the first study and 960 from the second; every decision, every score, one file per run (Zenodo, DOI 10.5281/zenodo.22979474, CC BY 4.0). One command recomputes every published rate from them — or two plain-Python scripts, by hand. No engine. No account. Nothing sent to us.

sagabench recompute --keep ./record
# by hand, with nothing but Python 3:
python3 record/scripts/recompute_season1.py record/season1/
python3 record/scripts/recompute_classes.py record/wave5/

Expected, exactly: Season 1 — 156 of 2,415 runs, 6.5% (the paper's interval: between 2.6% and 11.1%). Fragile situations — 87 of 500, 17.4% (paper: between 10.6% and 24.8%). Stable situations — 7 of 200, 3.5% (paper: between 0.5% and 7.5%).

Counts and rates reproduce to the digit. The record's README says which intervals reproduce exactly, and where the recomputation lands a few tenths off — and why. If your machine says something else, tell us — that is the whole point.

The certificate that wraps these replays:

See a sample certificate →

The situations are generated, not modelled on any real business — here’s why that measures more, not less. →

Run record · shape (season1/)
{
  "run_id": "<16 hex>",
  "wave": "A2.4-GA1.2",
  "model": "<dated model id>",
  "provider": "<provider>",
  "seed": 3767144912,
  "rep": 0,
  "years": 60,
  "engineSha": "4f237acffa0c…",
  "replay": { "seed": 3767144912, "engineSha": "4f237acffa0c…", "ticks": 60,
              "edicts": [ { "year": 5, "type": "<edict type>", "args": { "delta": 1 } } /* … */ ] },
  "score": { "baseline": { /* 9 components */ }, "steward": { /* 9 components */ },
             "delta": { /* steward − baseline */ }, "weights": { /* 7 preregistered */ },
             "composite": -41.0 },
  "transcript": [ { "year": 5, "reportBytes": 4821,
                    "parsed": { "type": "<edict type>", "args": { "delta": 1 }, "reasoning": "<model's stated rationale>" } } /* … */ ]
}

Records from the second study (wave5/) carry the same shape without model, provider, seed or reasoning, plus a class label and a keyed situation id — the preregistration for that study commits us never to publish per-model rates for it.

What stays guarded — and why results are still verifiable

We do not disclose the situation-generator, the knife-edge screening pipeline, or the hidden holdout seeds. They are what keeps future evaluations unspoiled. Verification does not need them. Published and public-situation results will replay directly. For held-out situations the record carries the sealed starting state of the run as data — never the generator, its salt, or any seed — and bit-for-bit re-execution requires the verification build, which we make available to reviewers and institutions under agreement — it is planned, not yet available. If a published number doesn't replay, we retract it. That is the standard.