diff --git a/documentation/audits/sizing-2026-10-13/tools/build_sizing.py b/documentation/audits/sizing-2026-10-13/tools/build_sizing.py index f198bcb4..4e3caf6a 100644 --- a/documentation/audits/sizing-2026-10-13/tools/build_sizing.py +++ b/documentation/audits/sizing-2026-10-13/tools/build_sizing.py @@ -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//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(