Sizing: the HP check can only RAISE a figure (R-1009, operator ruling A) — build_sizing.py

The second machine's figures (sizing-check-2026-10-14/hp-figures.json, HP t740, used basis): each
typical/peak becomes the higher of the two; nothing goes down; every raised figure is named in
raised_by_hp. The patch from sizing-check-2026-10-14/raise-only-source.patch, unchanged. Data rebuilt
in the next commit.

Claude-Session: https://claude.ai/code/session_012qRErfCoiTkvDK9N5XHbzb
This commit is contained in:
2026-10-14 15:24:07 +02:00
parent 65493fc481
commit 3f7f26a7d3
@@ -10,6 +10,10 @@ Sources, per app, in the spec's order of preference (sizing-2026-10-13 TASK §7
(evidence/onboarding-peaks.json, collected 2026-10-13; per run, containers summed)
3 measured — this run's bench on the N100 (evidence/<batch>/summary.json)
4 unmeasured — the catalog's own mem_request / mem_limit
+ hp-check — RAISE ONLY (operator ruling 2026-10-14, R-1009): the second machine's figures
(../sizing-check-2026-10-14/hp-figures.json, HP t740, `used` basis). For each app there,
each figure (typical, peak) becomes the higher of the figure above and the HP figure; nothing
goes down. The record names every raised figure in `raised_by_hp`.
Rules: telemetry under 7 days counts only when nothing better exists (`short-telemetry`). When two
sources' peaks differ by more than 50 %, both are reported and the HIGHER is used for mem_peak_mb.
mem_typical_mb is the chosen source's typical figure. CPU always comes from the N100 bench when it
@@ -136,8 +140,28 @@ def floor():
)
HP = os.path.join(os.path.dirname(AUDIT), "sizing-check-2026-10-14", "hp-figures.json")
def hp_check():
return json.load(open(HP))["apps"] if os.path.exists(HP) else {}
def raise_only(typ, peak, h):
"""The second machine can only RAISE a figure. Returns (typical, peak, raised) — raised = [(field, old, new)]."""
raised = []
if h:
if h.get("typical_mb") is not None and (typ is None or h["typical_mb"] > typ):
raised.append(("typical", typ, h["typical_mb"])); typ = h["typical_mb"]
if h.get("peak_mb") is not None and (peak is None or h["peak_mb"] > peak):
raised.append(("peak", peak, h["peak_mb"])); peak = h["peak_mb"]
if typ is not None and peak is not None and peak < typ:
raised.append(("peak", peak, typ)); peak = typ
return typ, peak, raised
def main():
cat, tel, onb, ben = catalog(), telemetry(), onboarding(), bench()
cat, tel, onb, ben, hpc = catalog(), telemetry(), onboarding(), bench(), hp_check()
apps, table = [], []
for slug, c in cat.items():
t, o, b = tel.get(slug), onb.get(slug), ben.get(slug)
@@ -162,6 +186,7 @@ def main():
peak = typ # a peak below the typical figure is two sources' noise, never a real peak
else:
src, typ, peak, when, box, disagree = "unmeasured", mb(c["mem_request"]), mb(c["mem_limit"]), None, None, False
typ, peak, raised = raise_only(typ, peak, hpc.get(slug))
cpu_rest = b["cpu_rest_avg_pct"] if b else (round(t["cpu_avg_dockerpct"] / 4, 2) if t else None)
cpu_pk = b["cpu_peak_1m_pct"] if b else (round(t["cpu_max_15min"] / 4, 1) if t else None)
rec = dict(
@@ -170,11 +195,13 @@ def main():
cpu_class=cpu_class(cpu_rest, cpu_pk), cpu_note=CPU_NOTES.get(slug, ""),
source=src, measured_on=box, date=when,
)
if raised:
rec["raised_by_hp"] = [dict(field=f, was=o, now=n) for f, o, n in raised]
if c["lifecycle"] != "active":
rec["lifecycle"] = c["lifecycle"]
apps.append(rec)
table.append(dict(rec, catalog_request_mb=mb(c["mem_request"]), catalog_limit_mb=mb(c["mem_limit"]),
sources_disagree=disagree, cpu_rest_pct=cpu_rest, cpu_peak_1m_pct=cpu_pk,
sources_disagree=disagree, cpu_rest_pct=cpu_rest, cpu_peak_1m_pct=cpu_pk, hp=hpc.get(slug),
telemetry=t, onboarding=o, bench=b))
power = json.load(open(os.path.join(EV, "power.json"))) if os.path.exists(os.path.join(EV, "power.json")) else None
out = dict(