WolfSDKWolfXLWolfPPTWolfDocxWolfRender

Example · wolf transact

An agent's broken edit, refused before the file changes

Run wolf transact with the edit and the invariants it must keep. The edit is applied in memory and checked, and the workbook is written only when every check passes. In this run, an agent's Q3 close edit failed 3 of 3 declared checks, with exit code 7 and a byte-identical input file. A repaired request then committed with exit 0.

Synthetic workbook·Wolf 0.2.17·openpyxl 3.1.5·macOS arm64·Numbers from results.json

3 failed checks, exit 7, and the same file hash before and after

The workbook holds a Regions table with Q2 and Q3 revenue, a Q3 ledger control of 21,750, and a board summary sheet. The agent's task: Post the final Q3 actuals: Europe 6,240 and APAC 4,410. Then fill the Summary line Variance to ledger. Its request has two mistakes: APAC's 4,410 goes to the Q2 column, and the variance formula names a table column, Q3 Actual, that the table lacks. Each step below is read from the receipts.1

  1. 1. Request3 ops, 3 checks
  2. 2. Verdicts3 failed, exit 7
  3. 3. Diskhash unchanged
  4. 4. Repair2 ops changed
  5. 5. Commitexit 0, committed
  1. 1

    The agent's request

    bad-request.json

    Task: Post the final Q3 actuals: Europe 6,240 and APAC 4,410. Then fill the Summary line Variance to ledger.

    • table:Regions/row:Europe/col:Q36,240as asked
    • table:Regions/row:APAC/col:Q24,410mistake
    • sheet:Summary/cell:B7=SUM(Regions[Q3 Actual])-Regions!C10mistake

    Declared with it: scope, the 6 cells the task may change; no-errors, no new error values; and ledger, the Q3 column summing to the ledger control in Regions!C10.

  2. 2

    Verdicts: the edit is applied in memory and checked

    exit 7invariant-violatedcommitted: false
    • FAILscopeonly-changes

      sheet:#1/cell:B8, table:Regions/row:APAC/col:Q2, sheet:#2/cell:B4 changed but are not declared

      Cells: Regions!B8, Regions table, APAC row, Q2 column, Summary!B4

    • FAILno-errorsno-new-errors

      new errors at sheet:#2/cell:B7

      Cells: Summary!B7

    • FAILledgerreconcile

      21750 != 21440 (tolerance 0.005)

      Cells: Regions!C10

    • PASSaddress-resolutionaddress-resolution, implicit
    • PASSparts-preservedparts-preserved, implicit

      10 of 12 input parts byte-identical

    In the receipt, the diff the edit would have made: 7 cells modified and 1 added. Rows named by a failed verdict are marked.

    • sheet:#1/cell:B8Regions!B8modified, recalculated:19,400 →20,010
    • sheet:#1/cell:C8Regions!C8modified, recalculated:21,200 →21,440
    • table:Regions/row:Europe/col:Q3Regions table, Europe row, Q3 columnmodified, op 0:6,000 →6,240
    • table:Regions/row:APAC/col:Q2Regions table, APAC row, Q2 columnmodified, op 1:3,800 →4,410
    • sheet:#2/cell:B3Summary!B3modified, recalculated:21,200 →21,440
    • sheet:#2/cell:B4Summary!B4modified, recalculated:19,400 →20,010
    • sheet:#2/cell:B5Summary!B5modified, recalculated:9.3% →7.1%
    • sheet:#2/cell:B7Summary!B7added, op 2:formula written
  3. 3

    Disk: nothing written

    input unchanged
    sha256 before
    f4a778a56b0edb331e85d3193b2938ab5030e441c960fa453cecbae23839e240
    sha256 after
    f4a778a56b0edb331e85d3193b2938ab5030e441c960fa453cecbae23839e240 (identical)
    out/ folder
    not created
    receipt outputs
    []
    unwritten result
    bebdd7671be398d17e18cc98165a63ce21c7a4c8bcfb4a7e52bf30a97ac05928
  4. 4

    The repaired request

    fixed-request.json

    With the cell addresses from the failed verdicts, the repair is local: 2 ops change, and the invariants stay exactly as declared.

    • op 1

      table:Regions/row:APAC/col:Q2 4,410

      table:Regions/row:APAC/col:Q3 4,410

    • op 2

      sheet:Summary/cell:B7 =SUM(Regions[Q3 Actual])-Regions!C10

      sheet:Summary/cell:B7 =SUM(Regions[Q3])-Regions!C10

  5. 5

    Commit: every check passes

    exit 0committed: true
    • PASS scope
    • PASS no-errors
    • PASS ledger 21750 = sum 21750
    • PASS address-resolution
    • PASS parts-preserved 10 of 12 input parts byte-identical
    • sheet:#1/cell:C8Regions!C8modified, recalculated:21,200 →21,750
    • table:Regions/row:Europe/col:Q3Regions table, Europe row, Q3 columnmodified, op 0:6,000 →6,240
    • table:Regions/row:APAC/col:Q3Regions table, APAC row, Q3 columnmodified, op 1:4,100 →4,410
    • sheet:#2/cell:B3Summary!B3modified, recalculated:21,200 →21,750
    • sheet:#2/cell:B5Summary!B5modified, recalculated:9.3% →12.1%
    • sheet:#2/cell:B7Summary!B7added, op 2:formula written
    parts written
    xl/worksheets/sheet1.xml, xl/worksheets/sheet2.xml
    parts preserved
    10, byte for byte
    output sha256
    2ce514439fd7224f69063c03981ba084000496a2bcafab5aa614061d0acf6444
    input sha256
    f4a778a56b0edb331e85d3193b2938ab5030e441c960fa453cecbae23839e240 (unchanged)

    5 of 5 verdicts passed. The committed copy is written to out/ beside the input.

Watch both runs in a terminal

In the clip, both requests are run against the published workbook with the Wolf 0.2.17 release binary. The first run ends with exit 7 and an unchanged digest; the second ends with exit 0 and 5 passing checks.

33.3 seconds, recorded with VHS from refused-edit.tape. Open the GIF (406 KB).
terminal
wolf transact --request bad-request.json > bad-receipt.json; echo "exit $?"
jq -r -f verdicts.jq bad-receipt.json
shasum -a 256 q3-close.xlsx   # same digest as before the run

wolf transact --request fixed-request.json > fixed-receipt.json; echo "exit $?"
jq -r -f verdicts.jq fixed-receipt.json

Save the same faulty request with openpyxl and get no warning

Apply the same three edits with openpyxl 3.1.5 and the save exits 0 with 0 warnings. The saved copy has 6 of 6 formula cells with no cached value, so without recalculation they read as empty. After a LibreOffice recalculation, the Q3 total is 21,440 against a ledger control of 21,750, the Q2 total is 20,010, and the variance cell shows #NAME?.23

Faulty request, saved by openpyxl
Rendered workbook after the faulty edit saved with openpyxl and recalculated in LibreOffice: APAC 4,410 sits in the Q2 column, the totals read Q2 20,010 and Q3 21,440 against a ledger control of 21,750, and the variance cell shows #NAME?.
Repaired request, committed by Wolf
Rendered workbook after the repaired request committed by Wolf: APAC 4,410 in the Q3 column, a Q3 total of 21,750 matching the ledger control, and a variance of 0.
Workbook values before the edit, after the faulty request through openpyxl and a LibreOffice recalculation, and after the repaired request through Wolf
CellBeforeopenpyxl, faultyWolf, repaired
Q3 totalRegions!C821,20021,44021,750
Ledger controlRegions!C1021,75021,75021,750
Variance to ledgerSummary!B7empty#NAME?0
Q2 totalRegions!B819,40020,01019,400
Growth, Q2 to Q3Summary!B59.3%7.1%12.1%

Declare the rules beside the edit

Put invariants in the request, next to the ops. This run uses three kinds: only-changes for the cells the task may change, no-new-errors against new error values, and reconcile to compare a control cell with an aggregate of a table column.4 Every run also gets two implicit checks, address-resolution and parts-preserved. On commit, only the changed parts of the package are rewritten: here 2 worksheets, with 10 parts copied byte for byte.5

bad-request.json: invariants
[
  {
    "id": "scope",
    "kind": "only-changes",
    "addresses": [
      "table:Regions/row:Europe/col:Q3",
      "table:Regions/row:APAC/col:Q3",
      "sheet:Regions/cell:C8",
      "sheet:Summary/cell:B3",
      "sheet:Summary/cell:B5",
      "sheet:Summary/cell:B7"
    ]
  },
  {
    "id": "no-errors",
    "kind": "no-new-errors"
  },
  {
    "id": "ledger",
    "kind": "reconcile",
    "left": "sheet:Regions/cell:C10",
    "right": "table:Regions/col:Q3",
    "aggregate": "sum",
    "tolerance": 0.005
  }
]

Reproduce every number and image

Download run_demo.py, fixture.py, openpyxl_edit.py, card.py, verdicts.jq, and refused-edit.tape into an empty folder, point WOLF_BIN at the Wolf 0.2.17 binary, and install LibreOffice, Poppler, jq, VHS, and ffmpeg. Run run_demo.py to build the workbook, run both requests and the openpyxl comparison, render the sheets, record the clip, draw the share card, and write results.json and SHA256SUMS.6

terminal
export WOLF_BIN=/path/to/wolf   # wolf 0.2.17 (commit dbd2defe08a522e38bcaff9dfddb64876deca10d)
export DEMO_OUT="$PWD/out" CARD_FONT=/path/to/Archivo.ttf
uv run --no-project --python 3.13 --with openpyxl==3.1.5 \
  --with pillow==12.3.0 python run_demo.py