Migrating to 0.9¶
Wind Tunnel 0.9 makes scenario intent decide the verdict. It also separates agent robustness from test-harness integrity and versions the native artifacts that carry those decisions. Runtime SPI method signatures are unchanged.
Declared expectations now gate by default¶
In 0.8, only outcome decided the aggregate verdict. Trajectory and constraint
failures were diagnostic even when the scenario explicitly declared
must_call, forbidden_calls, a custom TrajectoryCheck, or a Policy.
In 0.9, Scenario.resolved_gate_layers() infers:
outcomefor every scenario;trajectorywhen any trajectory expectation is declared; andconstraintwhen any policy is declared.
This means a scenario cannot report PASS while violating one of its authored
expectations. If a check is intentionally diagnostic during exploration, say so
explicitly:
Scenario(
name="observe_lookup_path",
prompt="Find the account.",
target_facts=[["ACC-123"]],
must_call=["account_lookup"],
gate_layers=["outcome"],
)
Remove the explicit gate_layers once the trajectory assertion is ready to
gate. gate_layers=[] creates a diagnostic-only scenario, but experiment
integrity is still mandatory.
Integrity and robustness now mean different things¶
Score.integrity answers: did the declared experiment condition actually
happen? For perturbations, it checks the evidence markers recorded on the
trace. A failed integrity check makes the aggregate INVALID; it does not
count as an agent pass or failure.
Robustness answers: did the agent satisfy its gate under a valid adverse
condition? Reports calculate robustness from gate performance on scenarios
that declare perturbations. A suite without perturbation scenarios reports
robustness as N/A.
For source compatibility, 0.9 still accepts Score(..., robustness=...),
exposes score.robustness, and exports evaluate_robustness(). These are 0.8
compatibility spellings for integrity; new code should use integrity and
evaluate_integrity().
Failure cost is operational¶
FailureCost now has a deterministic risk_weight:
| Input | Weight |
|---|---|
severity low / medium / high / critical |
1 / 4 / 16 / 64 |
| customer visible | +2 |
| irreversible | +4 |
| side effect performed | +8 |
Aggregates expose failure_risk = risk_weight × (1 - pass_rate). Reports,
ledger rows, and wt compare surface this value and rank regressions by it.
Risk does not relax the gate: every gated regression still fails.
Scenario authoring is less duplicative¶
promptmay be omitted whenuser_turnsis present.target_factsdefaults to[], so anoutcome_fnneeds no placeholder.scenario.scored_promptreturns the finaluser_turnsentry or the single-turnpromptand is used by reports and triage.- Empty names, missing both prompt forms, empty user turns, duplicate or
unknown gates, and
order_matters=Truewithoutmust_callfail at authoring time.
Persisted artifacts have explicit versions¶
New native traces carry "windtunnel_trace": 1, score sidecars carry
"windtunnel_score": 2, and ledger records carry "windtunnel_ledger": 1.
The v2 score stores integrity instead of the old robustness marker field.
Readers migrate unversioned 0.8 traces and scores in memory. They reject unknown future versions instead of guessing at their meaning. Contract A interchange and Contract B universe files remain version 1: additive unknown fields within v1 are tolerated, while unknown version numbers are rejected.
Upgrade checklist¶
- Run the suite and inspect scenarios whose trajectory or constraint layer had been failing diagnostically; those failures now affect the verdict.
- Use explicit
gate_layers=["outcome"]only where diagnostic behavior is intentional and documented. - Rename direct
score.robustnessreads toscore.integrityandevaluate_robustnesscalls toevaluate_integrity. - Treat
INVALIDas a bench/setup problem that requires rerunning after the condition is repaired, not as an agent regression. - Confirm artifact consumers tolerate the new version keys and
integrityfield. Preferscore_from_dict()over parsing score dictionaries directly. - Review
FailureCostannotations so risk-ranked comparisons reflect the operational consequence of each scenario.