feat(scada): add calibrated monitoring and incident recovery

This commit is contained in:
2026-11-07 19:44:58 +08:00
parent 26fa5d1909
commit ff8aba4964
109 changed files with 9165 additions and 629 deletions
+114
View File
@@ -0,0 +1,114 @@
#!/usr/bin/env python3
"""Create a private, read-only preflight report for the tjwater_v2 burst suite."""
from __future__ import annotations
import argparse
import asyncio
import json
import os
import sys
import traceback
from datetime import datetime, timezone
from pathlib import Path
from uuid import uuid4
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--suite",
type=Path,
default=Path("resources/benchmarks/tjwater-v2-burst.json"),
help="versioned burst suite manifest",
)
parser.add_argument("--case", action="append", default=[], help="case ID to inspect; repeatable")
parser.add_argument(
"--output-root",
type=Path,
default=Path("data/benchmark/preflight"),
help="private local artifact directory (default: ignored data/benchmark/preflight)",
)
args = parser.parse_args()
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from scripts.benchmark.contracts import fingerprint, load_suite
from scripts.benchmark.source import inspect_case, read_model, resolve_sources, source_identity, readonly_source
try:
suite = load_suite(args.suite)
cases = suite.select(args.case)
identity, routes = asyncio.run(resolve_sources(suite))
with readonly_source(routes["biz_data"]) as biz_connection:
biz_source = source_identity(biz_connection, routes["biz_data"])
model = read_model(biz_connection, cases)
with readonly_source(routes["iot_data"]) as iot_connection:
iot_source = source_identity(iot_connection, routes["iot_data"])
case_results = [inspect_case(iot_connection, suite, case, model) for case in cases]
content_fingerprint = fingerprint({
"suite": suite.model_dump(mode="json"),
"source_routes": {
"biz_data": biz_source["route_sha256"],
"iot_data": iot_source["route_sha256"],
},
"model": model,
"cases": [{
"case_id": result["case_id"],
"window_sha256": result["window_sha256"],
"topology_reference": result["topology_reference"],
"data_candidate_available": result["data_candidate_available"],
"blockers": result["blockers"],
} for result in case_results],
})
report = {
"report_version": "burst-preflight@1",
"status": "preflight_complete",
"readiness": "preflight_only; isolated runtime and Agent execution are not verified",
"created_at": datetime.now(timezone.utc),
"project": identity,
"sources": {"biz_data": biz_source, "iot_data": iot_source},
"suite_id": suite.suite_id,
"suite_version": suite.version,
"content_fingerprint_sha256": content_fingerprint,
"source_effect": "read-only transactions; no source database writes requested",
"cases": case_results,
"limitations": [
"preflight does not execute Agent, work-order, SCADA replay worker, or MCP tools",
"SCADA event data requiring generation remains blocked until produced in an isolated dataset",
"this report is not a frozen evaluation database snapshot",
"numeric reference outputs and approved equivalent candidate groups still require review",
],
}
stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%SZ")
output_dir = args.output_root / f"{suite.suite_id}-{stamp}-{uuid4().hex[:8]}"
output_dir.mkdir(parents=True, mode=0o700)
os.chmod(output_dir, 0o700)
output_file = output_dir / "preflight.json"
output_file.write_text(
json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True, default=str) + "\n",
encoding="utf-8",
)
os.chmod(output_file, 0o600)
except Exception as exc:
# Driver exceptions can include connection details; never echo them into CI logs.
frames = traceback.extract_tb(exc.__traceback__)
location = frames[-1] if frames else None
suffix = f" at {location.filename}:{location.lineno}" if location else ""
print(f"benchmark preflight failed ({type(exc).__name__}){suffix}", file=sys.stderr)
return 1
work_order_candidates = sum(bool(case["variants"][0]["data_candidate_available"])
for case in case_results)
scada_candidates = sum(bool(case["variants"][1]["data_candidate_available"])
for case in case_results)
print(
f"preflight complete: {work_order_candidates}/{len(case_results)} WO and "
f"{scada_candidates}/{len(case_results)} SCADA data candidates; report: {output_file}"
)
return 0
if __name__ == "__main__":
raise SystemExit(main())