STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_layerx_wire.py
Go to the documentation of this file.
1"""Layer X records the whole feed network on every burn, and a vessel trip ends the burn.
2
3Two lib/feedtwin features wired into ``engine/layerx/analysis.py`` (DATA-CONTRACT 2 and 4):
4
5* **The network recorder** (``Probes(network=True)``, ``network_dict``). Recording only: a GN2 burn
6 with it and one without give the same series and summary to the last bit, and the block it writes
7 telescopes -- each side's rungs add up, step by step, to its first node minus the chamber.
8* **The vessel trip** (``BurnEnd.tripped``, ``trip_record``). The AUDIT's case is a tank whose MAWP
9 is restated below the pressure the burn reaches (AUDIT section 5, #1: Layer X then integrated the
10 frozen frame to the 14 s horizon, 99,478 N s for a ~24,240 N s load). Here TK-FUEL is restated to
11 566.3 psi on the helium drawing, which trips 0.575 s after Fire: the result must stop at the trip
12 (series, burn time, impulse), say so (``tripped``, a ``fail`` event keyed ``trip``, ``converged``
13 false, ``vessel_trip`` graded bad), and every tool that grades burns must count it as failing.
14 The same with the AUDIT's own 600 psi, through the replay and the diagnostics, is in
15 tests/test_layerx_integration_le4.py (LAYERX_GOLDEN=1).
16
17Trips in the settle and in the lead-in cannot be reached from a drawing that passes preflight (the
18T-0 lockup is checked against the MAWP), so those two paths are driven by tripping the session
19directly, the way ``Session._check_limits`` does.
20"""
21
22from __future__ import annotations
23
24import dataclasses
25import math
26import os
27import sys
28
29import pytest
30
31
32#: The study drawings' lockup these tests were written at [psia] (scripts/layerx_baseline.py).
33STUDY_LOCKUP_PSIA = 564.7
34
35sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
36
37feedtwin = pytest.importorskip("feedtwin", reason="lib/feedtwin is not installed")
38
39from engine.layerx import DrawingStore, LayerXSettings, StandTripped, prepare, run_prepared # noqa: E402
40from engine.layerx.measurements import Override # noqa: E402
41from engine.layerx.sources import shipped_drawings_dir # noqa: E402
42from engine.pipeline.io import load_config # noqa: E402
43
44ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
45CFG = os.path.join(ROOT, "configs", "ethalox_6800N.yaml")
46PSI = 6894.757293168361
47ATM_PSI = 101325.0 / PSI
48#: TK-FUEL restated just above the T-0 lockup's 564.4 psi across the wall, so preflight passes and the
49#: helium burn's supply-effect climb trips it early (0.575 s), keeping the test short. Chosen so the trip
50#: lands inside a 50 ms burn step (on its first 25 ms live step): 566.0 trips on a step boundary.
51LOW_MAWP_PSI = 566.3
52
53pytestmark = pytest.mark.skipif(
54 not (shipped_drawings_dir() / "copv_study_he.json").is_file()
55 or not (shipped_drawings_dir() / "copv_study_gn2.json").is_file(),
56 reason="feed-twin's shipped drawings are not next to this checkout")
57
58
59def _drawing(name):
60 return {d.name: d for d in DrawingStore(None).list()}[name]
61
62
63def _low_mawp(psi: float = LOW_MAWP_PSI) -> Override:
64 return Override(target="node:FUT", parameter="MAWP", value=psi, unit="psi",
65 source="test what-if (not a measurement)")
66
67
68@pytest.fixture(scope="module")
69def cfg():
70 return load_config(CFG)
71
72
73@pytest.fixture(scope="module")
74def he():
75 return _drawing("copv_study_he")
76
77
78@pytest.fixture(scope="module")
79def gn2_pair(cfg):
80 """One GN2 burn as Layer X runs it (network recorded) and the same burn with the recorder off."""
81 import feedtwin.session.burn as fb
82
83 drawing = _drawing("copv_study_gn2")
84 settings = LayerXSettings(drawing_id=drawing.id, tank_pressure_psia=STUDY_LOCKUP_PSIA, ack_gn2_condensation=True, replay=False)
85 prep = prepare(cfg, None, drawing, settings, [])
86 assert prep.ok
87 on = run_prepared(prep, replay=False)
88 original = fb.BurnTrace.recorder
89
90 def without_network(self, session):
91 self.probes = dataclasses.replace(self.probes, network=False)
92 return original(self, session)
93
94 with pytest.MonkeyPatch.context() as mp:
95 mp.setattr(fb.BurnTrace, "recorder", without_network)
96 off = run_prepared(prepare(cfg, None, drawing, settings, []), replay=False)
97 return {"on": on, "off": off, "prep": prep}
98
99
100@pytest.fixture(scope="module")
101def tripped(cfg, he):
102 """The early trip as the router runs a burn: erosion replay, flight asked for, diagnostics on.
103 The flight is a stub that counts its calls: a tripped burn must not be flown."""
104 from engine.core.runner import PintleEngineRunner
105 from engine.layerx import flight as flt
106
107 runner = PintleEngineRunner(cfg)
108 prep = prepare(cfg, runner, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA, flight=True), [_low_mawp()])
109 assert prep.ok, [c.detail for c in prep.checks if c.status == "fail"]
110 calls = []
111 with pytest.MonkeyPatch.context() as mp:
112 mp.setattr(flt, "fly", lambda *a, **k: calls.append(1) or {"ok": False, "error": "flown"})
113 result = run_prepared(prep, runner=runner, config=cfg, diagnostics=True)
114 return {"prep": prep, "result": result, "fly_calls": len(calls)}
115
116
117@pytest.fixture(scope="module")
118def tripped_bare(cfg, he):
119 """The same trip as the sweep burns it: no replay, no flight, so no passes decide ``converged``."""
120 prep = prepare(cfg, None, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA, replay=False), [_low_mawp()])
121 return run_prepared(prep, replay=False)
122
123
124# ---------------------------------------------------------------- the network recorder
125
126
128 on, off = gn2_pair["on"], gn2_pair["off"]
129 assert "network" in on and "network" not in off
130 # Exact, not approximate: the recorder reads the sample a step already produced.
131 assert on["series"] == off["series"]
132 assert on["summary"] == off["summary"]
133 assert [(e["t"], e["key"]) for e in on["events"]] == [(e["t"], e["key"]) for e in off["events"]]
134
135
137 r = gn2_pair["on"]
138 net, series = r["network"], r["series"]
139 n = len(series["t"])
140 assert net["t"] == series["t"]
141 kinds = {nd["kind"] for nd in net["nodes"].values()}
142 assert {"bottle", "tank", "tank_outlet", "chamber", "injector_inlet"} <= kinds
143 for nid, nd in net["nodes"].items():
144 assert {"label", "kind", "side", "phase", "p_psia", "T_K"} <= set(nd), nid
145 assert len(nd["p_psia"]) == n and len(nd["T_K"]) == n
146 for bid, br in net["branches"].items():
147 assert {"label", "kind", "from", "to", "side", "mdot", "dp_psi"} <= set(br), bid
148 assert br["from"] in net["nodes"] and br["to"] in net["nodes"]
149 assert len(br["mdot"]) == n and len(br["dp_psi"]) == n
150 chamber = next(k for k, nd in net["nodes"].items() if nd["kind"] == "chamber")
151 for side, key in (("ox", "ox"), ("fuel", "fuel")):
152 path = net["paths"][side]
153 first = net["branches"][path[0]]
154 assert net["nodes"][first["from"]]["kind"] == "bottle"
155 assert net["branches"][path[-1]]["kind"] == "injector" and net["branches"][path[-1]]["to"] == chamber
156 assert any(net["branches"][b]["kind"] == "tank_head" for b in path)
157 for i in range(n):
158 rungs = sum(net["branches"][b]["dp_psi"][i] for b in path)
159 whole = net["nodes"][first["from"]]["p_psia"][i] - net["nodes"][chamber]["p_psia"][i]
160 assert rungs == pytest.approx(whole, abs=1e-6), (side, i)
161 # The injector branch carries the chamber's own flow on every firing step.
162 inj = net["branches"][path[-1]]["mdot"]
163 for i, on in enumerate(series["firing"]):
164 if on:
165 assert inj[i] == pytest.approx(series[key]["mdot"][i], rel=1e-9, abs=1e-12)
166
167
169 from engine.layerx.analysis import diagnostics_of
170
171 r, prep = gn2_pair["on"], gn2_pair["prep"]
172 d, _ = diagnostics_of(prep, r, cfg, None)
173 for name in ("ladder", "regulator", "saturation"):
174 assert d[name].get("available", True) is not False, (name, d[name].get("error"))
175 assert d["ladder"]["ox"]["closes"] and d["ladder"]["fuel"]["closes"]
176 assert isinstance(d["solenoids"], list) and d["solenoids"]
177 assert all(row.get("available", True) is not False for row in d["solenoids"])
178 # The bottle's floor needs the regulator's capacity, which reads the recorded network.
179 assert math.isfinite(d["pressurant"]["required_kg"]) and math.isfinite(d["pressurant"]["margin_kg"])
180 assert "network record" in d["vv"]["mass"]["ox"]["basis"]
181 # And without the record they say so rather than guess.
182 bare = {k: v for k, v in r.items() if k != "network"}
183 d0, _ = diagnostics_of(prep, bare, cfg, None)
184 for name in ("ladder", "regulator", "saturation"):
185 assert d0[name].get("available") is False and "network" in d0[name]["error"], name
186
187
188# ---------------------------------------------------------------- a trip ends the burn
189
190
192 r, prep = tripped["result"], tripped["prep"]
193 trip = r["tripped"]
194 assert trip["vessel"] == "FUT" and trip["kind"] == "tank"
195 assert trip["mawp_psia"] == pytest.approx(LOW_MAWP_PSI + ATM_PSI, abs=1e-6)
196 assert trip["p_psia"] > trip["mawp_psia"]
197 s, series = r["summary"], r["series"]
198 assert 0.0 < trip["t"] < 2.0 # early: the full burn is ~3.5 s
199 # The burn's clock, burn time and totals end at the trip -- not a step later, not at the horizon.
200 assert series["t"][-1] == pytest.approx(trip["t"], abs=1e-12) and series["firing"][-1]
201 assert s["burn_time_s"] == pytest.approx(trip["t"], abs=1e-12)
202 # The trip landed inside the last 50 ms step and the session stopped there: that step ends at
203 # the trip and is no longer than one. (It used to assert the step was *short* -- true only while
204 # the crossing fell in the step's first half; correct oxygen-vapour properties moved it 0.3 psi
205 # and 25 ms later, onto the step's end, 2026-10-12.)
206 assert series["t"][-2] < trip["t"] <= series["t"][-2] + prep.plan.dt + 1e-9
207 assert series["dt"][-1] == pytest.approx(series["t"][-1] - series["t"][-2], abs=1e-12)
208 impulse = sum(f * dt for f, dt, on in zip(series["chamber"]["thrust_N"], series["dt"], series["firing"]) if on)
209 assert s["total_impulse_Ns"] == pytest.approx(impulse, rel=1e-12)
210 assert s["total_impulse_Ns"] < 1.1 * s["peak_thrust_N"] * trip["t"]
211 assert s["depleted_side"] == "" and s["impulse_to_depletion_Ns"] is None
212 assert r["converged"] is False
213 assert len(r["network"]["t"]) == len(series["t"])
214 assert any("Burn stopped at t =" in note for note in r["provenance"]["notes"])
215 # Replayed once for its delivered figures, which end at the trip too; never iterated, never flown.
216 assert len(r["passes"]) == 1 and r["passes"][0]["tripped"]
217 dv = r["delivered"]
218 assert dv["t"][-1] == pytest.approx(trip["t"], abs=1e-12)
219 assert 0.0 < dv["summary"]["total_impulse_Ns"] < 1.1 * s["peak_thrust_N"] * trip["t"]
220 assert tripped["fly_calls"] == 0
221 assert r["flight"]["ok"] is False and "vessel trip" in r["flight"]["error"]
222
223
225 r = tripped_bare
226 assert "passes" not in r and r["converged"] is False
227 assert r["tripped"]["t"] == pytest.approx(tripped["result"]["tripped"]["t"], abs=1e-12)
228 assert r["series"]["t"][-1] == pytest.approx(r["tripped"]["t"], abs=1e-12)
229
230
232 d = tripped["result"]["diagnostics"]
233 for name, block in d.items():
234 rows = block if isinstance(block, list) else [block]
235 assert isinstance(block, list) or block.get("available", True) is not False, (name, block.get("error"))
236 assert all(row.get("available", True) is not False for row in rows), name
237 # No tank ran dry: the tail-off is a cutoff at the trip, both tanks wet.
238 sd = d["shutdown"]
239 assert "vessel trip" in sd["first_dry_basis"]
240 assert sd["valve_command_s"] == pytest.approx(tripped["result"]["tripped"]["t"])
241
242
244 r = tripped["result"]
245 trip = r["tripped"]
246 ev = {e["key"]: e for e in r["events"]}
247 assert ev["trip"]["kind"] == "fail" and ev["trip"]["t"] == pytest.approx(trip["t"])
248 assert "TK-FUEL" in ev["trip"]["label"]
249 assert not any(e["label"] == "Horizon reached" for e in r["events"])
250 assert "dry_ox" not in ev and "dry_fuel" not in ev
251 assert ev["burnout"]["t"] == pytest.approx(trip["t"]) and "trip" in ev["burnout"]["detail"]
252 keys = [e["key"] for e in r["events"]]
253 assert len(keys) == len(set(keys))
254 g = {e["key"]: e for e in r["limits"]}
255 assert g["vessel_trip"]["grade"] == "bad" and g["vessel_trip"]["t_worst"] == pytest.approx(trip["t"])
256 assert "vessel trip" in g["depletion"]["hint"]
257
258
260 from backend.routers.layerx import _listing_summary
261
262 out = _listing_summary(tripped["result"])
263 assert out["tripped"]["vessel"] == "FUT" and out["tripped"]["t"] == tripped["result"]["tripped"]["t"]
264 assert "tripped" not in _listing_summary({k: v for k, v in tripped["result"].items() if k != "tripped"})
265
266
267# ---------------------------------------------------------------- every tool counts it as failing
268
269
271 import engine.layerx.analysis as A
272 from engine.layerx import setpoint as sp
273
274 monkeypatch.setattr(A, "run_prepared", lambda prep, **kw: tripped["result"])
275 p = sp.burn_point({"config": cfg, "drawing": he, "settings": LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA),
276 "overrides": [_low_mawp()], "replay": False})
277 assert p["ok"] and p["tripped"]["vessel"] == "FUT"
278 assert not sp.usable(p) and not sp.feasible(p)
279 assert next(r for r in p["limits"] if r["key"] == "vessel_trip")["grade"] == "bad"
280
281
283 import engine.layerx.analysis as A
284 from engine.layerx import uncertainty as U
285
286 monkeypatch.setattr(A, "run_prepared", lambda prep, **kw: tripped["result"])
287 case = U._burn_case((cfg, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA), [], {"id": "x|high"}))
288 assert case["ok"] is False and case["tripped"]["vessel"] == "FUT"
289 assert case["error"].startswith("vessel trip: TK-FUEL")
290
291 # The sweep itself: a nominal that burns and one case that trips.
292 nominal = {"ok": True, "case": "nominal", "metrics": {k: 1.0 for k in U.METRICS}, "thrust": [], "depleted": "oxidiser",
293 "lockup_psia": 578.0}
294
295 def fake_case(args):
296 cid = args[4]["id"]
297 if cid == "nominal":
298 return nominal
299 if cid.endswith("|high"):
300 return {"ok": False, "case": cid, "tripped": tripped["result"]["tripped"],
301 "error": U._trip_words(tripped["result"]["tripped"])}
302 return {**nominal, "case": cid}
303
304 monkeypatch.setattr(U, "_burn_case", fake_case)
305 out = U.run_sweep(cfg, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA), [], workers=1)
306 trips = [c for c in out["crossings"] if c.get("tripped")]
307 assert trips and all(c["side"] == "high" for c in trips)
308 assert all(c["breaks"][0].startswith("vessel trip") for c in trips)
309 for f in out["factors"]:
310 for side, cs in f["cases"].items():
311 assert cs["ok"] is (side != "high")
312 if side == "high":
313 assert cs["tripped"]["vessel"] == "FUT" and "delta" not in cs
314 assert any("tripped the stand" in n for n in out["notes"])
315 assert not any("failed:" in n for n in out["notes"])
316
317 monkeypatch.setattr(U, "_burn_case", lambda args: {"ok": False, "case": args[4]["id"],
318 "tripped": tripped["result"]["tripped"],
319 "error": U._trip_words(tripped["result"]["tripped"])})
320 with pytest.raises(RuntimeError, match="vessel trip"):
321 U.run_sweep(cfg, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA), [], workers=1)
322
323
325 """Sweep 20261102-122930-2c5489 on LE4 (3): the nominal emptied LOX first, two Cd cases emptied fuel
326 first with 0.003 kg of LOX left, and the page said '2 inputs break a limit: measure these first'. A
327 run grades which tank empties first as information and the propellant left over at 0.2 kg (limits.py);
328 the sweep grades a flip by the same residual."""
329 from engine.layerx import uncertainty as U
330
331 # Stiff injectors and a bottle well above lockup: the depletion order is the only thing in question.
332 metrics = {**{k: 1.0 for k in U.METRICS}, "ox_stiffness_min": 0.3, "fuel_stiffness_min": 0.3, "copv_end_psia": 1200.0}
333 nominal = {"ok": True, "case": "nominal", "metrics": metrics, "thrust": [], "depleted": "oxidiser",
334 "lockup_psia": 578.0, "residual_kg": 0.004}
335
336 def fake_case(args):
337 cid = args[4]["id"]
338 if cid == "nominal":
339 return nominal
340 # Every low end flips by grams; every other case flips and strands 0.35 kg of LOX.
341 return {**nominal, "case": cid, "depleted": "fuel", "residual_kg": 0.003 if cid.endswith("|low") else 0.35}
342
343 monkeypatch.setattr(U, "_burn_case", fake_case)
344 out = U.run_sweep(cfg, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA), [], workers=1)
345 assert out["crossings"], "a flip that strands 0.35 kg is a crossing"
346 assert not [c for c in out["crossings"] if c["side"] == "low"]
347 assert {tuple(c["breaks"]) for c in out["crossings"]} == {("LOX-first becomes fuel-first, 0.35 kg of LOX left > 0.2 kg",)}
348 lows = [f["cases"]["low"] for f in out["factors"] if "low" in f["cases"]]
349 assert lows and all(cs["breaks"] == [] for cs in lows)
350
351
353 import engine.layerx.analysis as A
354 from engine.layerx import optimize as opt
355 from engine.layerx import reconcile as R
356
357 f = opt._figures(tripped["result"])
358 assert f["tripped"]["vessel"] == "FUT"
359 g = opt.grade({"ok": True, "preflight": [], "figures": f, "x": {"lockup_psia": 578.0}},
360 opt.OptimizeRequest(), {}, None)
361 keys = {c["key"]: c for c in g["constraints"]}
362 assert not keys["vessel_trip"]["ok"] and "depletion" not in keys # not read as a regulator dropout
363 assert g["violation"] >= 1.0
364
365 monkeypatch.setattr(A, "run_prepared", lambda prep, **kw: tripped["result"])
366 with pytest.raises(ValueError, match="tripped"):
367 R.run_reconcile(cfg, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA, replay=False), [], R.ReconcileRequest(max_passes=1))
368
369
370# ---------------------------------------------------------------- trips before Fire
371
372
373def _trip_now(session, vessel="FUT"):
374 from feedtwin.session.core import Trip
375
376 sim = session.tanks[vessel]
377 session.trip = Trip(vessel, sim.label, "tank", session.t, sim.pressure, sim.pressure * 0.99)
378 session.tripped = f"{sim.label} over its MAWP (test)."
379
380
382 import feedtwin.session.burn as fb
383 from engine.layerx import setpoint as sp
384 from engine.layerx import uncertainty as U
385
386 original = fb.prime_at_t0
387
388 def prime(session, plan):
389 settled = original(session, plan)
390 _trip_now(session)
391 return settled
392
393 monkeypatch.setattr(fb, "prime_at_t0", prime)
394 prep = prepare(cfg, None, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA, replay=False), [])
395 with pytest.raises(StandTripped) as caught:
396 run_prepared(prep, replay=False)
397 assert caught.value.record["vessel"] == "FUT" and "settle" in str(caught.value)
398 p = sp.burn_point({"config": cfg, "drawing": he, "settings": LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA), "overrides": [],
399 "replay": False})
400 assert p["ok"] is False and p["tripped"]["vessel"] == "FUT" and not sp.usable(p)
401 case = U._burn_case((cfg, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA), [], {"id": "nominal"}))
402 assert case["ok"] is False and case["tripped"]["vessel"] == "FUT"
403
404
406 import feedtwin.session.burn as fb
407 from engine.core.runner import PintleEngineRunner
408
409 original = fb.prime_at_t0
410
411 def prime(session, plan):
412 settled = original(session, plan)
413 step = session.step
414 calls = {"n": 0}
415
416 def stepped(dt):
417 sample = step(dt)
418 calls["n"] += 1
419 if calls["n"] == 3:
420 _trip_now(session)
421 return sample
422
423 session.step = stepped
424 return settled
425
426 monkeypatch.setattr(fb, "prime_at_t0", prime)
427 runner = PintleEngineRunner(cfg)
428 prep = prepare(cfg, runner, he, LayerXSettings(drawing_id=he.id, tank_pressure_psia=STUDY_LOCKUP_PSIA), [])
429 assert prep.link is not None and prep.link.sampler is not None # the replay loop is armed
430 r = run_prepared(prep, runner=runner, config=cfg)
431 trip = r["tripped"]
432 assert trip["t"] < 0.0 and not any(r["series"]["firing"])
433 assert r["summary"]["total_impulse_Ns"] == 0.0 and r["summary"]["burn_time_s"] == 0.0
434 assert r["converged"] is False and len(r["passes"]) == 1 and r["passes"][0]["tripped"]
435 assert r["replay"]["available"] is False and "before Fire" in r["replay"]["error"]
436 labels = [e["label"] for e in r["events"]]
437 assert "Erosion replay failed" not in labels and "Burn did not settle" not in labels
438 assert next(e for e in r["events"] if e["key"] == "trip")["kind"] == "fail"
439 assert "burnout" not in {e["key"] for e in r["events"]} # nothing burned, nothing burned out
test_a_trip_is_unconverged_even_with_nothing_to_iterate(tripped_bare, tripped)
test_the_legacy_optimiser_and_reconcile_refuse_a_tripped_burn(tripped, cfg, he, monkeypatch)
test_recording_the_network_moves_no_number(gn2_pair)
_trip_now(session, vessel="FUT")
test_a_trip_in_the_lead_in_fires_nothing_and_is_not_replayed(cfg, he, monkeypatch)
test_a_trip_in_the_settle_raises_with_its_record(cfg, he, monkeypatch)
test_the_set_point_and_hardware_tools_do_not_use_a_tripped_burn(tripped, cfg, he, monkeypatch)
test_the_sweep_leaves_a_tripped_case_out_of_the_swings_and_lists_it(tripped, cfg, he, monkeypatch)
test_a_trip_is_a_fail_event_and_a_bad_limit_not_a_horizon(tripped)
test_the_sweep_counts_a_flip_of_the_tank_that_runs_dry_first_only_when_it_strands_propellant(cfg, he, monkeypatch)
test_the_feed_diagnostics_build_from_the_recorded_network(gn2_pair, cfg)
test_the_diagnostics_read_a_tripped_burn(tripped)
test_the_network_block_is_the_contracts_and_its_rungs_telescope(gn2_pair)
test_the_listing_marks_a_tripped_run(tripped)
test_a_trip_ends_the_burn_where_it_happened(tripped)
Override _low_mawp(float psi=LOW_MAWP_PSI)