{
 "format": "SIMULATION.md",
 "version": 1,
 "note": "Inputs and exact outputs from the published engine. node simulation.mjs selftest vectors.json checks them. Every world here is a made-up example.",
 "vectors": [
  {
   "name": "sha256 of abc",
   "fn": "sha256",
   "input": "abc",
   "expect": "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
  },
  {
   "name": "sha256 of non-ASCII text",
   "fn": "sha256",
   "input": "José 日本語",
   "expect": "2010305a012d846e4d8a85c8b775bd3a637291ab5145a981d78999dac5563b94"
  },
  {
   "name": "canonical JSON sorts keys and normalizes -0",
   "fn": "canon",
   "input": {
    "b": [
     1,
     2.5,
     0
    ],
    "a": {
     "z": null,
     "y": "é"
    }
   },
   "expect": "{\"a\":{\"y\":\"é\",\"z\":null},\"b\":[1,2.5,0]}"
  },
  {
   "name": "the engine's own ln",
   "fn": "ln",
   "input": [
    1,
    2,
    0.5,
    1e-300,
    1e+300,
    123456.789,
    0.1
   ],
   "expect": [
    0,
    0.6931471805599453,
    -0.6931471805599453,
    -690.7755278982137,
    690.7755278982137,
    11.723646487185881,
    -2.3025850929940455
   ]
  },
  {
   "name": "the engine's own exp",
   "fn": "exp",
   "input": [
    0,
    1,
    -1,
    0.5,
    100,
    -100,
    700
   ],
   "expect": [
    1,
    2.7182818284590455,
    0.36787944117144233,
    1.6487212707001282,
    2.6881171418161356e+43,
    3.720075976020836e-44,
    1.0142320547350045e+304
   ]
  },
  {
   "name": "a named random stream",
   "fn": "rng",
   "seed": 42,
   "stream": "tool/refund",
   "count": 8,
   "expect": [
    3664801445,
    1882491594,
    2248361707,
    2234648660,
    4092963342,
    2178392394,
    824411274,
    4148831739
   ]
  },
  {
   "name": "a child stream per call",
   "fn": "fork",
   "seed": 42,
   "stream": "tool/refund",
   "index": 3,
   "count": 8,
   "expect": [
    1826491517,
    2608728714,
    3939500581,
    3691615724,
    626025404,
    986958496,
    446470788,
    3061279681
   ]
  },
  {
   "name": "one run, refund world",
   "fn": "run",
   "world": {
    "simulation": 1,
    "name": "refund-plain-retry",
    "horizon": 3600,
    "state": {
     "refunded": 0,
     "owed": 40,
     "receipts": 0
    },
    "tools": {
     "payments.refund": {
      "branches": [
       {
        "label": "timed out, but the money moved",
        "p": 0.06,
        "latency": 30,
        "error": "timeout",
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       },
       {
        "label": "timed out, nothing moved",
        "p": 0.04,
        "latency": 30,
        "error": "timeout"
       },
       {
        "label": "rate limited",
        "p": 0.05,
        "latency": {
         "dist": "uniform",
         "min": 0.1,
         "max": 0.5
        },
        "error": "rate_limited"
       },
       {
        "label": "refunded",
        "latency": {
         "dist": "lognormal",
         "mean": 0.8,
         "sd": 0.4
        },
        "returns": {
         "status": "refunded"
        },
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       }
      ]
     },
     "email.receipt": {
      "branches": [
       {
        "label": "sent",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 1
        },
        "returns": "sent",
        "set": {
         "receipts": "=state.receipts + 1"
        }
       }
      ]
     }
    },
    "processes": {
     "plan": {
      "steps": [
       {
        "repeat": {
         "max": 4,
         "until": "last.ok",
         "steps": [
          {
           "call": "payments.refund",
           "args": {
            "amount": 40
           }
          },
          {
           "if": "!last.ok",
           "then": [
            {
             "delay": "2 * (attempt + 1)"
            }
           ]
          }
         ]
        }
       },
       {
        "if": "last.ok",
        "then": [
         {
          "call": "email.receipt"
         }
        ]
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed",
      "says": "Refunded more than was owed."
     },
     {
      "id": "customer_told",
      "final": true,
      "holds": "state.refunded == 0 || state.receipts > 0",
      "says": "Money moved and the customer never heard."
     }
    ],
    "metrics": {
     "refunded": "state.refunded",
     "finished_at_s": "now"
    }
   },
   "seed": 18,
   "expect": {
    "hash": "sr_e76f5357379033c307716668db267368",
    "stopped": "done",
    "events": 5,
    "broken": [
     "no_double_refund"
    ],
    "metrics": {
     "finished_at_s": 33.34532922505138,
     "refunded": 80
    }
   }
  },
  {
   "name": "one forced path",
   "fn": "run",
   "world": {
    "simulation": 1,
    "name": "refund-plain-retry",
    "horizon": 3600,
    "state": {
     "refunded": 0,
     "owed": 40,
     "receipts": 0
    },
    "tools": {
     "payments.refund": {
      "branches": [
       {
        "label": "timed out, but the money moved",
        "p": 0.06,
        "latency": 30,
        "error": "timeout",
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       },
       {
        "label": "timed out, nothing moved",
        "p": 0.04,
        "latency": 30,
        "error": "timeout"
       },
       {
        "label": "rate limited",
        "p": 0.05,
        "latency": {
         "dist": "uniform",
         "min": 0.1,
         "max": 0.5
        },
        "error": "rate_limited"
       },
       {
        "label": "refunded",
        "latency": {
         "dist": "lognormal",
         "mean": 0.8,
         "sd": 0.4
        },
        "returns": {
         "status": "refunded"
        },
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       }
      ]
     },
     "email.receipt": {
      "branches": [
       {
        "label": "sent",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 1
        },
        "returns": "sent",
        "set": {
         "receipts": "=state.receipts + 1"
        }
       }
      ]
     }
    },
    "processes": {
     "plan": {
      "steps": [
       {
        "repeat": {
         "max": 4,
         "until": "last.ok",
         "steps": [
          {
           "call": "payments.refund",
           "args": {
            "amount": 40
           }
          },
          {
           "if": "!last.ok",
           "then": [
            {
             "delay": "2 * (attempt + 1)"
            }
           ]
          }
         ]
        }
       },
       {
        "if": "last.ok",
        "then": [
         {
          "call": "email.receipt"
         }
        ]
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed",
      "says": "Refunded more than was owed."
     },
     {
      "id": "customer_told",
      "final": true,
      "holds": "state.refunded == 0 || state.receipts > 0",
      "says": "Money moved and the customer never heard."
     }
    ],
    "metrics": {
     "refunded": "state.refunded",
     "finished_at_s": "now"
    }
   },
   "seed": 1,
   "options": {
    "force": [
     0,
     3,
     0
    ]
   },
   "expect": {
    "hash": "sr_201e25142f1ee34d441f6789b90371aa",
    "stopped": "done",
    "events": 5,
    "broken": [
     "no_double_refund"
    ],
    "metrics": {
     "finished_at_s": 33.288798699762786,
     "refunded": 80
    }
   }
  },
  {
   "name": "one run, docks",
   "fn": "run",
   "world": {
    "simulation": 1,
    "name": "warehouse-docks",
    "horizon": 28800,
    "state": {
     "served": 0
    },
    "resources": {
     "dock": {
      "capacity": 4
     }
    },
    "processes": {
     "truck": {
      "count": 400,
      "every": {
       "dist": "exp",
       "mean": 90
      },
      "steps": [
       {
        "seize": "dock"
       },
       {
        "delay": {
         "dist": "lognormal",
         "mean": 320,
         "sd": 110
        }
       },
       {
        "release": "dock"
       },
       {
        "set": {
         "served": "=state.served + 1"
        }
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "wait_under_10_min",
      "final": true,
      "holds": "res.dock.mean_wait <= 600",
      "says": "Trucks waited more than 10 minutes on average."
     }
    ],
    "metrics": {
     "served": "state.served",
     "mean_wait_s": "res.dock.mean_wait",
     "dock_utilization": "res.dock.utilization",
     "in_queue_at_close": "res.dock.queue"
    }
   },
   "seed": 7,
   "expect": {
    "hash": "sr_cfee27a657bc880f9619c8983680de4c",
    "stopped": "horizon",
    "events": 781,
    "broken": [],
    "metrics": {
     "dock_utilization": 0.8297090331867376,
     "in_queue_at_close": 0,
     "mean_wait_s": 257.246835614652,
     "served": 297
    }
   }
  },
  {
   "name": "one run, fan-out",
   "fn": "run",
   "world": {
    "simulation": 1,
    "name": "fanout-under-a-rate-limit",
    "horizon": 7200,
    "state": {
     "done": 0,
     "gave_up": 0,
     "spend": 0,
     "inflight": 0
    },
    "resources": {
     "slot": {
      "capacity": 8
     }
    },
    "tools": {
     "model.call": {
      "branches": [
       {
        "label": "over the rate limit",
        "if": "state.inflight > 12",
        "p": 0.8,
        "latency": {
         "dist": "uniform",
         "min": 0.05,
         "max": 0.2
        },
        "error": "rate_limited"
       },
       {
        "label": "timed out, still billed",
        "p": 0.02,
        "latency": 60,
        "error": "timeout",
        "set": {
         "spend": {
          "add": {
           "dist": "lognormal",
           "mean": 0.07,
           "sd": 0.05
          }
         }
        }
       },
       {
        "label": "finished",
        "latency": {
         "dist": "lognormal",
         "mean": 14,
         "sd": 9
        },
        "returns": "ok",
        "set": {
         "spend": {
          "add": {
           "dist": "lognormal",
           "mean": 0.07,
           "sd": 0.05
          }
         }
        }
       }
      ]
     }
    },
    "processes": {
     "worker": {
      "count": 200,
      "every": 0.25,
      "steps": [
       {
        "seize": "slot"
       },
       {
        "repeat": {
         "max": 6,
         "until": "last.ok",
         "steps": [
          {
           "set": {
            "inflight": "=state.inflight + 1"
           }
          },
          {
           "call": "model.call"
          },
          {
           "set": {
            "inflight": "=state.inflight - 1"
           }
          },
          {
           "if": "!last.ok",
           "then": [
            {
             "delay": {
              "dist": "uniform",
              "min": 1,
              "max": "4 * (attempt + 1)"
             }
            }
           ]
          }
         ]
        }
       },
       {
        "release": "slot"
       },
       {
        "if": "last.ok",
        "then": [
         {
          "set": {
           "done": "=state.done + 1"
          }
         }
        ],
        "else": [
         {
          "set": {
           "gave_up": "=state.gave_up + 1"
          }
         }
        ]
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "spend_under_cap",
      "holds": "state.spend <= 15.5",
      "says": "Spend crossed the cap."
     },
     {
      "id": "done_by_deadline",
      "final": true,
      "holds": "now <= 600",
      "says": "Still running at the deadline."
     },
     {
      "id": "nothing_gave_up",
      "final": true,
      "holds": "state.gave_up == 0",
      "says": "A task gave up after six tries."
     }
    ],
    "metrics": {
     "finished_at_s": "now",
     "spend": "state.spend",
     "completed": "state.done",
     "gave_up": "state.gave_up",
     "cost_per_completed": "state.spend / max(1, state.done)"
    }
   },
   "seed": 3,
   "expect": {
    "hash": "sr_7247bc82dfca72cff51be0cee1165860",
    "stopped": "done",
    "events": 610,
    "broken": [
     "spend_under_cap"
    ],
    "metrics": {
     "completed": 200,
     "cost_per_completed": 0.07761671839562191,
     "finished_at_s": 461.2415549256555,
     "gave_up": 0,
     "spend": 15.523343679124382
    }
   }
  },
  {
   "name": "one run, booking race",
   "fn": "run",
   "world": {
    "simulation": 1,
    "name": "agents-booking-one-slot-check_then_book",
    "horizon": 600,
    "state": {
     "booked": 0,
     "refused": 0
    },
    "resources": {},
    "tools": {
     "calendar.check": {
      "branches": [
       {
        "label": "read",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 1.2
        },
        "returns": "=state.booked == 0"
       }
      ]
     },
     "calendar.book": {
      "branches": [
       {
        "label": "booked",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 1.2
        },
        "returns": "booked",
        "set": {
         "booked": "=state.booked + 1"
        }
       }
      ]
     }
    },
    "processes": {
     "agent": {
      "count": 3,
      "every": {
       "dist": "uniform",
       "min": 0,
       "max": 2
      },
      "steps": [
       {
        "call": "calendar.check"
       },
       {
        "if": "last.value",
        "then": [
         {
          "call": "calendar.book"
         }
        ]
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "one_booking_only",
      "holds": "state.booked <= 1",
      "says": "The same slot was booked twice."
     }
    ],
    "metrics": {
     "bookings": "state.booked",
     "finished_at_s": "now"
    }
   },
   "seed": 1,
   "expect": {
    "hash": "sr_19707b2e237874d19511f9b03833ad98",
    "stopped": "done",
    "events": 8,
    "broken": [
     "one_booking_only"
    ],
    "metrics": {
     "bookings": 2,
     "finished_at_s": 3.132446953440402
    }
   }
  },
  {
   "name": "a run stops at its fuel limit",
   "fn": "run",
   "world": {
    "simulation": 1,
    "name": "fanout-under-a-rate-limit",
    "horizon": 7200,
    "state": {
     "done": 0,
     "gave_up": 0,
     "spend": 0,
     "inflight": 0
    },
    "resources": {
     "slot": {
      "capacity": 8
     }
    },
    "tools": {
     "model.call": {
      "branches": [
       {
        "label": "over the rate limit",
        "if": "state.inflight > 12",
        "p": 0.8,
        "latency": {
         "dist": "uniform",
         "min": 0.05,
         "max": 0.2
        },
        "error": "rate_limited"
       },
       {
        "label": "timed out, still billed",
        "p": 0.02,
        "latency": 60,
        "error": "timeout",
        "set": {
         "spend": {
          "add": {
           "dist": "lognormal",
           "mean": 0.07,
           "sd": 0.05
          }
         }
        }
       },
       {
        "label": "finished",
        "latency": {
         "dist": "lognormal",
         "mean": 14,
         "sd": 9
        },
        "returns": "ok",
        "set": {
         "spend": {
          "add": {
           "dist": "lognormal",
           "mean": 0.07,
           "sd": 0.05
          }
         }
        }
       }
      ]
     }
    },
    "processes": {
     "worker": {
      "count": 200,
      "every": 0.25,
      "steps": [
       {
        "seize": "slot"
       },
       {
        "repeat": {
         "max": 6,
         "until": "last.ok",
         "steps": [
          {
           "set": {
            "inflight": "=state.inflight + 1"
           }
          },
          {
           "call": "model.call"
          },
          {
           "set": {
            "inflight": "=state.inflight - 1"
           }
          },
          {
           "if": "!last.ok",
           "then": [
            {
             "delay": {
              "dist": "uniform",
              "min": 1,
              "max": "4 * (attempt + 1)"
             }
            }
           ]
          }
         ]
        }
       },
       {
        "release": "slot"
       },
       {
        "if": "last.ok",
        "then": [
         {
          "set": {
           "done": "=state.done + 1"
          }
         }
        ],
        "else": [
         {
          "set": {
           "gave_up": "=state.gave_up + 1"
          }
         }
        ]
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "spend_under_cap",
      "holds": "state.spend <= 15.5",
      "says": "Spend crossed the cap."
     },
     {
      "id": "done_by_deadline",
      "final": true,
      "holds": "now <= 600",
      "says": "Still running at the deadline."
     },
     {
      "id": "nothing_gave_up",
      "final": true,
      "holds": "state.gave_up == 0",
      "says": "A task gave up after six tries."
     }
    ],
    "metrics": {
     "finished_at_s": "now",
     "spend": "state.spend",
     "completed": "state.done",
     "gave_up": "state.gave_up",
     "cost_per_completed": "state.spend / max(1, state.done)"
    }
   },
   "seed": 3,
   "options": {
    "fuel": 500
   },
   "expect": {
    "hash": "sr_66ea9aa8ad11b4c4d2819da3e0e078d1",
    "stopped": "fuel",
    "events": 87,
    "broken": [],
    "metrics": {
     "completed": 7,
     "cost_per_completed": 0.06576573508181868,
     "finished_at_s": 17.80506570300691,
     "gave_up": 0,
     "spend": 0.46036014557273075
    }
   }
  },
  {
   "name": "many seeds",
   "fn": "sweep",
   "world": {
    "simulation": 1,
    "name": "refund-plain-retry",
    "horizon": 3600,
    "state": {
     "refunded": 0,
     "owed": 40,
     "receipts": 0
    },
    "tools": {
     "payments.refund": {
      "branches": [
       {
        "label": "timed out, but the money moved",
        "p": 0.06,
        "latency": 30,
        "error": "timeout",
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       },
       {
        "label": "timed out, nothing moved",
        "p": 0.04,
        "latency": 30,
        "error": "timeout"
       },
       {
        "label": "rate limited",
        "p": 0.05,
        "latency": {
         "dist": "uniform",
         "min": 0.1,
         "max": 0.5
        },
        "error": "rate_limited"
       },
       {
        "label": "refunded",
        "latency": {
         "dist": "lognormal",
         "mean": 0.8,
         "sd": 0.4
        },
        "returns": {
         "status": "refunded"
        },
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       }
      ]
     },
     "email.receipt": {
      "branches": [
       {
        "label": "sent",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 1
        },
        "returns": "sent",
        "set": {
         "receipts": "=state.receipts + 1"
        }
       }
      ]
     }
    },
    "processes": {
     "plan": {
      "steps": [
       {
        "repeat": {
         "max": 4,
         "until": "last.ok",
         "steps": [
          {
           "call": "payments.refund",
           "args": {
            "amount": 40
           }
          },
          {
           "if": "!last.ok",
           "then": [
            {
             "delay": "2 * (attempt + 1)"
            }
           ]
          }
         ]
        }
       },
       {
        "if": "last.ok",
        "then": [
         {
          "call": "email.receipt"
         }
        ]
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed",
      "says": "Refunded more than was owed."
     },
     {
      "id": "customer_told",
      "final": true,
      "holds": "state.refunded == 0 || state.receipts > 0",
      "says": "Money moved and the customer never heard."
     }
    ],
    "metrics": {
     "refunded": "state.refunded",
     "finished_at_s": "now"
    }
   },
   "options": {
    "runs": 300
   },
   "expect": {
    "hash": "ss_2e35d937a2a3dbfac980bb6107d08673",
    "runs": 300,
    "rules": {
     "no_double_refund": {
      "broke_in": 20,
      "of": 300,
      "rate": 0.066667,
      "ci95": [
       0.043568,
       0.100723
      ],
      "first_seed": 18
     },
     "customer_told": {
      "broke_in": 0,
      "of": 300,
      "rate": 0,
      "ci95": [
       0,
       0.012643
      ],
      "first_seed": null
     }
    }
   }
  },
  {
   "name": "every branch",
   "fn": "explore",
   "world": {
    "simulation": 1,
    "name": "refund-plain-retry",
    "horizon": 3600,
    "state": {
     "refunded": 0,
     "owed": 40,
     "receipts": 0
    },
    "tools": {
     "payments.refund": {
      "branches": [
       {
        "label": "timed out, but the money moved",
        "p": 0.06,
        "latency": 30,
        "error": "timeout",
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       },
       {
        "label": "timed out, nothing moved",
        "p": 0.04,
        "latency": 30,
        "error": "timeout"
       },
       {
        "label": "rate limited",
        "p": 0.05,
        "latency": {
         "dist": "uniform",
         "min": 0.1,
         "max": 0.5
        },
        "error": "rate_limited"
       },
       {
        "label": "refunded",
        "latency": {
         "dist": "lognormal",
         "mean": 0.8,
         "sd": 0.4
        },
        "returns": {
         "status": "refunded"
        },
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       }
      ]
     },
     "email.receipt": {
      "branches": [
       {
        "label": "sent",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 1
        },
        "returns": "sent",
        "set": {
         "receipts": "=state.receipts + 1"
        }
       }
      ]
     }
    },
    "processes": {
     "plan": {
      "steps": [
       {
        "repeat": {
         "max": 4,
         "until": "last.ok",
         "steps": [
          {
           "call": "payments.refund",
           "args": {
            "amount": 40
           }
          },
          {
           "if": "!last.ok",
           "then": [
            {
             "delay": "2 * (attempt + 1)"
            }
           ]
          }
         ]
        }
       },
       {
        "if": "last.ok",
        "then": [
         {
          "call": "email.receipt"
         }
        ]
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed",
      "says": "Refunded more than was owed."
     },
     {
      "id": "customer_told",
      "final": true,
      "holds": "state.refunded == 0 || state.receipts > 0",
      "says": "Money moved and the customer never heard."
     }
    ],
    "metrics": {
     "refunded": "state.refunded",
     "finished_at_s": "now"
    }
   },
   "expect": {
    "paths": 121,
    "complete": true,
    "timing_dependent": false,
    "covered": 1,
    "by_stated_chances": {
     "no_double_refund": 0.06575478,
     "customer_told": 0.00044064
    }
   }
  },
  {
   "name": "every branch says when timing matters",
   "fn": "explore",
   "world": {
    "simulation": 1,
    "name": "agents-booking-one-slot-check_then_book",
    "horizon": 600,
    "state": {
     "booked": 0,
     "refused": 0
    },
    "resources": {},
    "tools": {
     "calendar.check": {
      "branches": [
       {
        "label": "read",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 1.2
        },
        "returns": "=state.booked == 0"
       }
      ]
     },
     "calendar.book": {
      "branches": [
       {
        "label": "booked",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 1.2
        },
        "returns": "booked",
        "set": {
         "booked": "=state.booked + 1"
        }
       }
      ]
     }
    },
    "processes": {
     "agent": {
      "count": 2,
      "every": {
       "dist": "uniform",
       "min": 0,
       "max": 2
      },
      "steps": [
       {
        "call": "calendar.check"
       },
       {
        "if": "last.value",
        "then": [
         {
          "call": "calendar.book"
         }
        ]
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "one_booking_only",
      "holds": "state.booked <= 1",
      "says": "The same slot was booked twice."
     }
    ],
    "metrics": {
     "bookings": "state.booked",
     "finished_at_s": "now"
    }
   },
   "expect": {
    "paths": 1,
    "complete": true,
    "timing_dependent": true,
    "covered": 1,
    "by_stated_chances": null
   }
  },
  {
   "name": "A against B on the same draws",
   "fn": "compare",
   "a": {
    "simulation": 1,
    "name": "refund-retry-blind",
    "horizon": 7200,
    "state": {
     "refunded": 0,
     "owed": 40,
     "settled": 0
    },
    "tools": {
     "payments.refund": {
      "branches": [
       {
        "label": "timed out, but the money moved",
        "p": 0.06,
        "latency": 30,
        "error": "timeout",
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       },
       {
        "label": "timed out, nothing moved",
        "p": 0.04,
        "latency": 30,
        "error": "timeout"
       },
       {
        "label": "rate limited",
        "p": 0.05,
        "latency": {
         "dist": "uniform",
         "min": 0.1,
         "max": 0.5
        },
        "error": "rate_limited"
       },
       {
        "label": "refunded",
        "latency": {
         "dist": "lognormal",
         "mean": 0.8,
         "sd": 0.4
        },
        "returns": {
         "status": "refunded"
        },
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       }
      ]
     },
     "payments.status": {
      "branches": [
       {
        "label": "stale read, shows nothing yet",
        "p": 0.1,
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 0.6
        },
        "returns": {
         "refunded": 0
        }
       },
       {
        "label": "current read",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 0.6
        },
        "returns": {
         "refunded": "=state.refunded"
        }
       }
      ]
     }
    },
    "processes": {
     "plan": {
      "steps": [
       {
        "repeat": {
         "max": 4,
         "until": "state.settled == 1",
         "steps": [
          {
           "call": "payments.refund",
           "args": {
            "amount": 40
           }
          },
          {
           "if": "last.ok",
           "then": [
            {
             "set": {
              "settled": 1
             }
            }
           ],
           "else": [
            {
             "delay": "2 * (attempt + 1)"
            }
           ]
          }
         ]
        }
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed",
      "says": "Refunded more than was owed."
     }
    ],
    "metrics": {
     "overpaid": "max(0, state.refunded - state.owed)",
     "finished_at_s": "now",
     "cost": "max(0, state.refunded - state.owed) + now * 0.02"
    }
   },
   "b": {
    "simulation": 1,
    "name": "refund-check-status-before-retrying",
    "horizon": 7200,
    "state": {
     "refunded": 0,
     "owed": 40,
     "settled": 0
    },
    "tools": {
     "payments.refund": {
      "branches": [
       {
        "label": "timed out, but the money moved",
        "p": 0.06,
        "latency": 30,
        "error": "timeout",
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       },
       {
        "label": "timed out, nothing moved",
        "p": 0.04,
        "latency": 30,
        "error": "timeout"
       },
       {
        "label": "rate limited",
        "p": 0.05,
        "latency": {
         "dist": "uniform",
         "min": 0.1,
         "max": 0.5
        },
        "error": "rate_limited"
       },
       {
        "label": "refunded",
        "latency": {
         "dist": "lognormal",
         "mean": 0.8,
         "sd": 0.4
        },
        "returns": {
         "status": "refunded"
        },
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       }
      ]
     },
     "payments.status": {
      "branches": [
       {
        "label": "stale read, shows nothing yet",
        "p": 0.1,
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 0.6
        },
        "returns": {
         "refunded": 0
        }
       },
       {
        "label": "current read",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 0.6
        },
        "returns": {
         "refunded": "=state.refunded"
        }
       }
      ]
     }
    },
    "processes": {
     "plan": {
      "steps": [
       {
        "repeat": {
         "max": 4,
         "until": "state.settled == 1",
         "steps": [
          {
           "call": "payments.refund",
           "args": {
            "amount": 40
           }
          },
          {
           "if": "last.ok",
           "then": [
            {
             "set": {
              "settled": 1
             }
            }
           ],
           "else": [
            {
             "delay": 20
            },
            {
             "call": "payments.status"
            },
            {
             "if": "last.value.refunded > 0",
             "then": [
              {
               "set": {
                "settled": 1
               }
              }
             ]
            }
           ]
          }
         ]
        }
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed",
      "says": "Refunded more than was owed."
     }
    ],
    "metrics": {
     "overpaid": "max(0, state.refunded - state.owed)",
     "finished_at_s": "now",
     "cost": "max(0, state.refunded - state.owed) + now * 0.02"
    }
   },
   "options": {
    "runs": 200
   },
   "expect": {
    "runs": 200,
    "rules": {
     "no_double_refund": {
      "a_only": 11,
      "b_only": 0,
      "both": 5,
      "neither": 184
     }
    },
    "metrics": {
     "cost": {
      "a": 3.702249,
      "b": 1.152211,
      "b_minus_a": -2.550038,
      "ci95": [
       -4.021609,
       -1.078467
      ],
      "b_higher": 17,
      "same": 171
     },
     "finished_at_s": {
      "a": 5.11245,
      "b": 7.610553,
      "b_minus_a": 2.498103,
      "ci95": [
       1.539821,
       3.456384
      ],
      "b_higher": 27,
      "same": 171
     },
     "overpaid": {
      "a": 3.6,
      "b": 1,
      "b_minus_a": -2.6,
      "ci95": [
       -4.078528,
       -1.121472
      ],
      "b_higher": 0,
      "same": 188
     }
    }
   }
  },
  {
   "name": "which plan wins and what flips it",
   "fn": "decide",
   "a": {
    "simulation": 1,
    "name": "refund-retry-blind",
    "horizon": 7200,
    "state": {
     "refunded": 0,
     "owed": 40,
     "settled": 0
    },
    "tools": {
     "payments.refund": {
      "branches": [
       {
        "label": "timed out, but the money moved",
        "p": 0.06,
        "latency": 30,
        "error": "timeout",
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       },
       {
        "label": "timed out, nothing moved",
        "p": 0.04,
        "latency": 30,
        "error": "timeout"
       },
       {
        "label": "rate limited",
        "p": 0.05,
        "latency": {
         "dist": "uniform",
         "min": 0.1,
         "max": 0.5
        },
        "error": "rate_limited"
       },
       {
        "label": "refunded",
        "latency": {
         "dist": "lognormal",
         "mean": 0.8,
         "sd": 0.4
        },
        "returns": {
         "status": "refunded"
        },
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       }
      ]
     },
     "payments.status": {
      "branches": [
       {
        "label": "stale read, shows nothing yet",
        "p": 0.1,
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 0.6
        },
        "returns": {
         "refunded": 0
        }
       },
       {
        "label": "current read",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 0.6
        },
        "returns": {
         "refunded": "=state.refunded"
        }
       }
      ]
     }
    },
    "processes": {
     "plan": {
      "steps": [
       {
        "repeat": {
         "max": 4,
         "until": "state.settled == 1",
         "steps": [
          {
           "call": "payments.refund",
           "args": {
            "amount": 40
           }
          },
          {
           "if": "last.ok",
           "then": [
            {
             "set": {
              "settled": 1
             }
            }
           ],
           "else": [
            {
             "delay": "2 * (attempt + 1)"
            }
           ]
          }
         ]
        }
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed",
      "says": "Refunded more than was owed."
     }
    ],
    "metrics": {
     "overpaid": "max(0, state.refunded - state.owed)",
     "finished_at_s": "now",
     "cost": "max(0, state.refunded - state.owed) + now * 0.02"
    }
   },
   "b": {
    "simulation": 1,
    "name": "refund-check-status-before-retrying",
    "horizon": 7200,
    "state": {
     "refunded": 0,
     "owed": 40,
     "settled": 0
    },
    "tools": {
     "payments.refund": {
      "branches": [
       {
        "label": "timed out, but the money moved",
        "p": 0.06,
        "latency": 30,
        "error": "timeout",
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       },
       {
        "label": "timed out, nothing moved",
        "p": 0.04,
        "latency": 30,
        "error": "timeout"
       },
       {
        "label": "rate limited",
        "p": 0.05,
        "latency": {
         "dist": "uniform",
         "min": 0.1,
         "max": 0.5
        },
        "error": "rate_limited"
       },
       {
        "label": "refunded",
        "latency": {
         "dist": "lognormal",
         "mean": 0.8,
         "sd": 0.4
        },
        "returns": {
         "status": "refunded"
        },
        "set": {
         "refunded": "=state.refunded + args.amount"
        }
       }
      ]
     },
     "payments.status": {
      "branches": [
       {
        "label": "stale read, shows nothing yet",
        "p": 0.1,
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 0.6
        },
        "returns": {
         "refunded": 0
        }
       },
       {
        "label": "current read",
        "latency": {
         "dist": "uniform",
         "min": 0.2,
         "max": 0.6
        },
        "returns": {
         "refunded": "=state.refunded"
        }
       }
      ]
     }
    },
    "processes": {
     "plan": {
      "steps": [
       {
        "repeat": {
         "max": 4,
         "until": "state.settled == 1",
         "steps": [
          {
           "call": "payments.refund",
           "args": {
            "amount": 40
           }
          },
          {
           "if": "last.ok",
           "then": [
            {
             "set": {
              "settled": 1
             }
            }
           ],
           "else": [
            {
             "delay": 20
            },
            {
             "call": "payments.status"
            },
            {
             "if": "last.value.refunded > 0",
             "then": [
              {
               "set": {
                "settled": 1
               }
              }
             ]
            }
           ]
          }
         ]
        }
       }
      ]
     }
    },
    "invariants": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed",
      "says": "Refunded more than was owed."
     }
    ],
    "metrics": {
     "overpaid": "max(0, state.refunded - state.owed)",
     "finished_at_s": "now",
     "cost": "max(0, state.refunded - state.owed) + now * 0.02"
    }
   },
   "options": {
    "metric": "cost",
    "vary": [
     {
      "id": "stale",
      "name": "stale",
      "path": [
       "tools",
       "payments.status",
       "branches",
       0,
       "p"
      ],
      "values": [
       0,
       0.25,
       0.5,
       0.75,
       0.9,
       0.95,
       0.98,
       1
      ]
     }
    ]
   },
   "expect": {
    "method": "every_branch",
    "winner": "b",
    "a": 2.910276,
    "b": 0.402906,
    "flips": [
     0.980585
    ]
   }
  },
  {
   "name": "retry-blind",
   "fn": "plan",
   "plan": {
    "state": {
     "refunded": 0,
     "owed": 40
    },
    "tools": {
     "refund": {
      "kind": "write",
      "pack": "money",
      "chances": {
       "ghost_success": 0.06,
       "timeout": 0.04,
       "rate_limited": 0.05,
       "duplicate_delivery": 0,
       "server_error": 0
      },
      "effect": {
       "refunded": "+args.amount"
      },
      "latency": {
       "dist": "lognormal",
       "mean": 0.8,
       "sd": 0.4
      },
      "returns": {
       "status": "refunded"
      }
     },
     "status": {
      "kind": "read",
      "faults": [
       "stale_read"
      ],
      "chances": {
       "stale_read": 0.1
      },
      "latency": {
       "dist": "uniform",
       "min": 0.2,
       "max": 0.6
      },
      "returns": {
       "refunded": "=state.refunded"
      },
      "stale": {
       "refunded": 0
      }
     }
    },
    "a": {
     "name": "retry-blind",
     "steps": [
      {
       "call": "refund",
       "args": {
        "amount": 40
       },
       "retry": {
        "max": 4,
        "wait": "2 * (attempt + 1)"
       }
      }
     ]
    },
    "b": {
     "name": "check-first",
     "steps": [
      {
       "call": "refund",
       "args": {
        "amount": 40
       },
       "retry": {
        "max": 4,
        "wait": 20,
        "after_fail": [
         {
          "call": "status"
         },
         {
          "stop_if": "last.value.refunded > 0"
         }
        ]
       }
      }
     ]
    },
    "rules": [
     {
      "id": "no_double_refund",
      "holds": "state.refunded <= state.owed"
     },
     {
      "id": "customer_refunded",
      "final": true,
      "holds": "state.refunded >= state.owed"
     }
    ],
    "measure": {
     "overpaid": "max(0, state.refunded - state.owed)",
     "cost": "max(0, state.refunded - state.owed) + now * 0.02"
    }
   },
   "steps": [
    {
     "call": "refund",
     "args": {
      "amount": 40
     },
     "retry": {
      "max": 4,
      "wait": "2 * (attempt + 1)"
     }
    }
   ],
   "expect": {
    "file_id": "sm_d1c4dfada50ee947",
    "assumptions": [
     "refund.ghost_success",
     "refund.timeout",
     "refund.rate_limited",
     "refund.duplicate_delivery",
     "refund.server_error",
     "status.stale_read",
     "state.refunded",
     "state.owed"
    ]
   }
  },
  {
   "name": "a session token holds non-ASCII",
   "fn": "token",
   "input": {
    "c": "sm_0",
    "seed": 1,
    "a": [
     {
      "tool": "x",
      "args": {
       "note": "José"
      }
     }
    ]
   },
   "expect": "eyJhIjpbeyJhcmdzIjp7Im5vdGUiOiJKb3PDqSJ9LCJ0b29sIjoieCJ9XSwiYyI6InNtXzAiLCJzZWVkIjoxfQ"
  },
  {
   "name": "a good file",
   "fn": "check",
   "text": "---\nsimulation: 1\nkind: plan\nname: refund-retry\n---\n\n# refund-retry\n\nTwo ways to handle a refund that times out. Plan A retries after a short wait. Plan B waits for things to settle, checks the status, and retries only if nothing moved.\n\nMock world only. Nothing here touches a real system, and every chance below is an assumption, not a measurement. A result describes this file, not reality. It is not a test, a safety assessment or advice. Terms: https://simulation.md/terms\n\n```json simulation\n{\n  \"state\": {\n    \"refunded\": 0,\n    \"owed\": 40\n  },\n  \"tools\": {\n    \"refund\": {\n      \"kind\": \"write\",\n      \"pack\": \"money\",\n      \"chances\": {\n        \"ghost_success\": 0.06,\n        \"timeout\": 0.04,\n        \"rate_limited\": 0.05,\n        \"duplicate_delivery\": 0,\n        \"server_error\": 0\n      },\n      \"effect\": {\n        \"refunded\": \"+args.amount\"\n      },\n      \"latency\": {\n        \"dist\": \"lognormal\",\n        \"mean\": 0.8,\n        \"sd\": 0.4\n      },\n      \"returns\": {\n        \"status\": \"refunded\"\n      }\n    },\n    \"status\": {\n      \"kind\": \"read\",\n      \"faults\": [\n        \"stale_read\"\n      ],\n      \"chances\": {\n        \"stale_read\": 0.1\n      },\n      \"latency\": {\n        \"dist\": \"uniform\",\n        \"min\": 0.2,\n        \"max\": 0.6\n      },\n      \"returns\": {\n        \"refunded\": \"=state.refunded\"\n      },\n      \"stale\": {\n        \"refunded\": 0\n      }\n    }\n  },\n  \"a\": {\n    \"name\": \"retry-blind\",\n    \"steps\": [\n      {\n        \"call\": \"refund\",\n        \"args\": {\n          \"amount\": 40\n        },\n        \"retry\": {\n          \"max\": 4,\n          \"wait\": \"2 * (attempt + 1)\"\n        }\n      }\n    ]\n  },\n  \"b\": {\n    \"name\": \"check-first\",\n    \"steps\": [\n      {\n        \"call\": \"refund\",\n        \"args\": {\n          \"amount\": 40\n        },\n        \"retry\": {\n          \"max\": 4,\n          \"wait\": 20,\n          \"after_fail\": [\n            {\n              \"call\": \"status\"\n            },\n            {\n              \"stop_if\": \"last.value.refunded > 0\"\n            }\n          ]\n        }\n      }\n    ]\n  },\n  \"rules\": [\n    {\n      \"id\": \"no_double_refund\",\n      \"holds\": \"state.refunded <= state.owed\"\n    },\n    {\n      \"id\": \"customer_refunded\",\n      \"final\": true,\n      \"holds\": \"state.refunded >= state.owed\"\n    }\n  ],\n  \"measure\": {\n    \"overpaid\": \"max(0, state.refunded - state.owed)\",\n    \"cost\": \"max(0, state.refunded - state.owed) + now * 0.02\"\n  }\n}\n```\n",
   "expect": {
    "valid": true,
    "errors": [],
    "warnings": []
   }
  },
  {
   "name": "no frontmatter",
   "fn": "check",
   "text": "# nothing here\n",
   "expect": {
    "valid": false,
    "errors": [
     "E01"
    ],
    "warnings": []
   }
  },
  {
   "name": "a typo in a rule is an error",
   "fn": "check",
   "text": "---\nsimulation: 1\nkind: world\nname: bad\n---\n\n```json simulation\n{\"simulation\":1,\"state\":{\"x\":5},\"invariants\":[{\"id\":\"r\",\"holds\":\"state.y <= 5\"}]}\n```\n",
   "expect": {
    "valid": false,
    "errors": [
     "E07"
    ],
    "warnings": []
   }
  },
  {
   "name": "a stray character in a rule is an error",
   "fn": "check",
   "text": "---\nsimulation: 1\nkind: world\nname: bad\n---\n\n```json simulation\n{\"simulation\":1,\"state\":{\"x\":5},\"invariants\":[{\"id\":\"r\",\"holds\":\"state.x > 1 @ state.x < 3\"}]}\n```\n",
   "expect": {
    "valid": false,
    "errors": [
     "E07"
    ],
    "warnings": []
   }
  },
  {
   "name": "a bad chance is an error",
   "fn": "check",
   "text": "---\nsimulation: 1\nkind: world\nname: bad\n---\n\n```json simulation\n{\"simulation\":1,\"tools\":{\"t\":{\"branches\":[{\"p\":-0.5},{}]}}}\n```\n",
   "expect": {
    "valid": false,
    "errors": [
     "E07"
    ],
    "warnings": []
   }
  },
  {
   "name": "a secret is refused",
   "fn": "check",
   "text": "---\nsimulation: 1\nkind: world\nname: bad\n---\n\n```json simulation\n{\"simulation\":1,\"state\":{\"x\":\"sk_live_abcdefghijkl\"}}\n```\n",
   "expect": {
    "valid": false,
    "errors": [
     "E06"
    ],
    "warnings": []
   }
  },
  {
   "name": "a file with no rules gets a warning",
   "fn": "check",
   "text": "---\nsimulation: 1\nkind: world\nname: bad\n---\n\n```json simulation\n{\"simulation\":1,\"state\":{\"x\":1}}\n```\n",
   "expect": {
    "valid": true,
    "errors": [],
    "warnings": [
     "W01",
     "W05"
    ]
   }
  },
  {
   "name": "chances from counts",
   "fn": "calibrate",
   "input": {
    "outcomes": {
     "ok": 97,
     "timeout": 3
    },
    "latencies": [
     0.5,
     0.7,
     0.9,
     1.2,
     3
    ]
   },
   "expect": {
    "chances": {
     "ok": {
      "chance": 0.97,
      "count": 97,
      "of": 100,
      "range95": [
       0.915481,
       0.989745
      ],
      "source": "measured"
     },
     "timeout": {
      "chance": 0.03,
      "count": 3,
      "of": 100,
      "range95": [
       0.010255,
       0.084519
      ],
      "source": "measured"
     }
    },
    "ok_share": null,
    "latency": {
     "n": 5,
     "mean": 1.26,
     "sd": 1.006479,
     "p50": 0.9,
     "p95": 3,
     "max": 3,
     "use_this": {
      "dist": "lognormal",
      "mean": 1.293207,
      "sd": 0.99362
     },
     "source": "measured"
    },
    "notes": [
     "Under 30 latencies: p95 and the fit are rough."
    ]
   }
  }
 ]
}
