01Python only, supported and not frozen#
The surface is packvium.simulation, packvium.recommendations, packvium.outcomes and packvium.holdout. PHP, Rust and JavaScript do not export it, and it is held to no four-engine conformance: a scenario takes an evaluator callback as its central argument, and a callback cannot cross the JSON-over-subprocess harness every other contract is proved through. It is tested and will not be withdrawn inside 1.x, but it sits outside the frozen API, so a parameter may be renamed in a minor release. Pin the version if you depend on the exact shape.
02A scenario runs against a pin, never against current#
run_scenario folds your evaluator over a list of orders under a version pin: the exact catalog, tariff, policy and solver versions. How pricing, policy or packing happen is the evaluator's business, not the orchestration's. The result records which pin and which orders it ran, so a stored scenario replays the same however far the registries have moved since.
03A comparison is never one number#
compare_scenarios returns a Pareto report order by order rather than a blended delta, because a mean over a cohort can be carried entirely by a few large orders. It refuses to compare two scenarios that ran different sets of orders.
04A proposal cannot publish itself#
propose_recommendation returns nothing rather than a low-confidence proposal when too few orders succeeded in both arms, and its expected deltas use only orders both arms answered, so a failure on one side cannot manufacture an improvement. A proposal must state how to roll itself back, and it is handed no registry. Publishing goes only through approve_catalog or approve_policy into append-only registries, so undoing a change is publishing the previous version again.
05Replay on history the proposal did not see#
evaluate_on_history scores a recommendation against decisions held out by split_at, a required point in time: a decision whose earliest recorded event is at or after it is held out. The evaluation is refused if the proposal cites held-out orders as its own evidence. The answer is a count of held-out decisions improved, regressed, traded off, or that neither arm could pack.
06What history can and cannot prove#
Only what can be recomputed is scored: the carton chosen, its cost and the billed shipping price. Damage, returns, repacks and operator overrides happened under the carton that actually shipped, so they are reported against the baseline and never credited to the change. Every replayed packing goes through an independent validator before its metrics count, a packing it rejects is that arm's failure at any cost, and the validator never sees a score.