Phase 1 data layer: calc/fmt/alarms + 31 CPython tests + live gateway P1 smoke

pytest 31/31. In-gateway end-to-end: 559 activations correlated (uuid mode), 3 chatterers,
34 fleeting, 1 flood, health F(22) on the deliberately-bad sim plant. Gate G1 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 13:08:02 -05:00
parent c82a2fa6df
commit ecb10b9b7b
12 changed files with 1971 additions and 3 deletions

View File

@@ -11,7 +11,60 @@
import json
OUT_DIR = "/usr/local/bin/ignition/data/projects/.probe"
PROBE_NAME = "P0"
PROBE_NAME = "P1"
def _p1():
"""Exec PrimeBAT's real PrimeControls modules (calc/fmt/alarms) in this scope
and run getDashboardBundle against the live journal - end-to-end data-layer
smoke with zero dev footprint inside PrimeBAT."""
import imp
base = "/usr/local/bin/ignition/data/projects/PrimeBAT/ignition/script-python/PrimeControls/"
pkg = imp.new_module("PrimeControls")
pkg.__path__ = [base]
sys_modules = __import__("sys").modules
sys_modules["PrimeControls"] = pkg
for name in ("calc", "fmt", "alarms"):
m = imp.new_module("PrimeControls." + name)
m.__dict__["system"] = system
code = open(base + name + "/code.py").read()
compiled = compile(code, name, "exec")
# py2 qualified-exec statement form: required because _p1 contains
# closures, which forbid the unqualified exec(...) call form in Jython.
exec compiled in m.__dict__
sys_modules["PrimeControls." + name] = m
setattr(pkg, name, m)
al = pkg.alarms
end = system.date.toMillis(system.date.now())
start = end - 4 * 3600 * 1000
b = al.getDashboardBundle(start, end, None)
page = al.getJournalPage(start, end, None, 0, 5)
shift = al.getShiftReportText()
return {
"meta": {"event_count": b["meta"]["event_count"],
"activation_count": b["meta"]["activation_count"],
"areas": b["meta"]["areas"],
"correlation_mode": b["meta"]["correlation_mode"],
"standing_mode": b["meta"]["standing_mode"],
"error": b["meta"]["error"],
"dropped": b["meta"]["dropped_rows"]},
"health": {"grade": b["health"]["grade"], "score": b["health"]["score"],
"subs": [(s["key"], s["score"]) for s in b["health"]["subs"]]},
"kpis": dict((k, b["kpis"][k]["value"]) for k in b["kpis"]),
"counts": {"chattering": len(b["chattering"]),
"standing": b["standing"]["count"],
"fleeting": b["fleeting"]["total"],
"floods": len(b["floods"]["episodes"]),
"pareto_rows": len(b["pareto"]["rows"]),
"bins": len(b["rate"]["bins"]),
"active_now": len(b["active_now"])},
"insights": [i["text"] for i in b["insights"]],
"journal_page": {"total": page["total"], "rows": len(page["rows"]),
"error": page["error"],
"first": page["rows"][0] if page["rows"] else None},
"shift_label": shift["label"],
"shift_text_head": shift["text"][:400],
}
def _safe(fn):
@@ -174,6 +227,6 @@ def _p0():
def run():
result = {"probe": PROBE_NAME,
"ranAt": str(system.date.now())}
result["payload"] = _safe(_p0)
result["payload"] = _safe(_p1)
_write(result)
system.util.getLogger("probe").info("probe %s written to %s" % (PROBE_NAME, OUT_DIR))

View File

@@ -12,4 +12,4 @@
"fixedDelay": true,
"enabled": false
}
}
}