存档求解器回归基线与当前改动

纳管 AMESim 对齐基线、发布锁、回归测试及当前物理门禁调整。

更新日志仅记录已完成成果,并注明当前 HEAD 尚待真实 production 复跑与远端 workflow 验证。
This commit is contained in:
lujingze committed 2026-08-18 15:20:42 +00:00
1 parent 53f8601fec
commit a8c733883c
32 files changed
+47241 -108

No files matched your search

+329 -2
View File
@@ -31,6 +31,14 @@ from time import monotonic, perf_counter, process_time
from typing import Any
import xml.etree.ElementTree as ET
from app.simulation.physical_state_v21 import (
PhysicalStateV21Error,
evaluate_physical_state_v21,
load_approved_golden as load_physical_state_v21_golden,
physical_state_v21_applicable,
project_physical_state_v21,
)
try: # resource is unavailable on native Windows Python.
import resource
except ImportError: # pragma: no cover - Windows regression job
@@ -456,6 +464,50 @@ def load_regression_manifest(path: Path | str) -> dict[str, object]:
"Authoritative XML byte count does not match manifest source.bytes."
)
reference_archive = source.get("referenceArchive")
reference_archive_path: Path | None = None
reference_archive_sha256: str | None = None
if reference_archive is not None:
if not isinstance(reference_archive, Mapping):
raise RegressionManifestError(
"Manifest source.referenceArchive must be an object when declared."
)
archive_path_value = reference_archive.get("path")
archive_sha256 = reference_archive.get("sha256")
archive_bytes = reference_archive.get("bytes")
if (
not isinstance(archive_path_value, str)
or not archive_path_value
or not _valid_sha256(archive_sha256)
or not isinstance(archive_bytes, int)
or archive_bytes <= 0
or reference_archive.get("role") != "authoritativePhysicalBaseline"
):
raise RegressionManifestError(
"Manifest AMESim reference archive identity or role is incomplete."
)
reference_archive_path = (repository_root / archive_path_value).resolve()
if not reference_archive_path.is_relative_to(repository_root):
raise RegressionManifestError(
"AMESim reference archive must remain inside the repository."
)
try:
archive_payload = reference_archive_path.read_bytes()
except OSError as exc:
raise RegressionManifestError(
f"Could not read AMESim reference archive {reference_archive_path}: {exc}"
) from exc
if len(archive_payload) != archive_bytes:
raise RegressionManifestError(
"AMESim reference archive byte count mismatch."
)
actual_archive_sha256 = _sha256(archive_payload)
if actual_archive_sha256 != archive_sha256:
raise RegressionManifestError(
"AMESim reference archive hash mismatch."
)
reference_archive_sha256 = str(archive_sha256)
companion = source.get("companionProject")
companion_path: Path | None = None
if companion is not None:
@@ -627,6 +679,28 @@ def load_regression_manifest(path: Path | str) -> dict[str, object]:
correctness = manifest.get("correctness")
if not isinstance(correctness, dict):
raise RegressionManifestError("Manifest correctness must be an object.")
python_golden_role = correctness.get("pythonGoldenRole", "acceptanceGate")
if python_golden_role not in {
"acceptanceGate",
"determinismDiagnosticOnly",
}:
raise RegressionManifestError(
"correctness.pythonGoldenRole must be acceptanceGate or "
"determinismDiagnosticOnly."
)
physical_baseline_authority = correctness.get("physicalBaselineAuthority")
compare_amesim_on_every_run = correctness.get(
"compareAmesimOnEveryRun", False
)
if physical_baseline_authority is not None and (
physical_baseline_authority != "amesim"
or compare_amesim_on_every_run is not True
or reference_archive_path is None
):
raise RegressionManifestError(
"AMESim physical authority requires a validated reference archive "
"and compareAmesimOnEveryRun=true."
)
state_relative_tolerance = _finite_nonnegative(
correctness.get("stateRelativeTolerance"),
field="correctness.stateRelativeTolerance",
@@ -641,6 +715,9 @@ def load_regression_manifest(path: Path | str) -> dict[str, object]:
)
loaded_goldens: dict[str, dict[str, dict[str, object]]] = {}
loaded_physical_state_v21_goldens: dict[
str, dict[str, dict[str, object]]
] = {}
for case_id in sequence:
variant = variants[case_id]
assert isinstance(variant, dict)
@@ -654,6 +731,14 @@ def load_regression_manifest(path: Path | str) -> dict[str, object]:
raise RegressionManifestError(
f"Variant {case_id!r} has an invalid golden lane reference."
)
if python_golden_role == "determinismDiagnosticOnly" and (
reference.get("role") != "pythonDeterminismRegression"
or reference.get("affectsPhysicalCorrectness") is not False
):
raise RegressionManifestError(
f"Variant {case_id!r} Python golden must be marked as a "
"non-physical determinism regression."
)
golden_path_value = reference.get("path")
golden_sha256 = reference.get("sha256")
if (
@@ -704,6 +789,95 @@ def load_regression_manifest(path: Path | str) -> dict[str, object]:
)
loaded_goldens.setdefault(case_id, {})[lane_name] = golden
raw_physical_state_v21_goldens = variant.get(
"physicalStateV21Goldens", {}
)
if not isinstance(raw_physical_state_v21_goldens, dict):
raise RegressionManifestError(
f"Variant {case_id!r} physicalStateV21Goldens must be an object "
"keyed by lane."
)
for lane_name, reference in raw_physical_state_v21_goldens.items():
if lane_name not in lanes or not isinstance(reference, Mapping):
raise RegressionManifestError(
f"Variant {case_id!r} has an invalid physical-state-v2.1 "
"golden lane reference."
)
if physical_baseline_authority == "amesim" and (
reference.get("role") != "amesimPhysicalBaseline"
or reference.get("compareOnEveryRun") is not True
):
raise RegressionManifestError(
f"Variant {case_id!r} physical-state reference must be marked "
"as the per-run AMESim physical baseline."
)
golden_path_value = reference.get("path")
golden_sha256 = reference.get("sha256")
if (
not isinstance(golden_path_value, str)
or not golden_path_value
or not _valid_sha256(golden_sha256)
):
raise RegressionManifestError(
f"Variant {case_id!r} physical-state-v2.1 golden reference "
"is incomplete."
)
golden_path = (repository_root / golden_path_value).resolve()
if not golden_path.is_relative_to(repository_root):
raise RegressionManifestError(
"Physical-state-v2.1 golden must remain inside the repository."
)
try:
physical_state_golden = load_physical_state_v21_golden(golden_path)
except (OSError, PhysicalStateV21Error) as exc:
raise RegressionManifestError(
f"Could not load physical-state-v2.1 golden {golden_path}: {exc}"
) from exc
if physical_state_golden.get("_sha256") != golden_sha256:
raise RegressionManifestError(
f"Variant {case_id!r} physical-state-v2.1 golden hash mismatch."
)
if (
physical_state_golden.get("caseId") != case_id
or physical_state_golden.get("lane") != lane_name
or physical_state_golden.get("sourceXmlSha256") != expected_sha256
):
raise RegressionManifestError(
f"Variant {case_id!r} physical-state-v2.1 golden identity "
"does not match the manifest."
)
physical_provenance = physical_state_golden.get("provenance")
physical_amesim = (
physical_provenance.get("amesim")
if isinstance(physical_provenance, Mapping)
else None
)
if physical_baseline_authority == "amesim" and (
not isinstance(physical_amesim, Mapping)
or physical_amesim.get("archiveSha256")
!= reference_archive_sha256
):
raise RegressionManifestError(
f"Variant {case_id!r} AMESim baseline provenance does not "
"match source.referenceArchive."
)
expected_times = [float(value) for value in variant["checkpointTimes"]]
physical_state_checkpoints = physical_state_golden.get("checkpoints")
assert isinstance(physical_state_checkpoints, list)
golden_times = [
float(checkpoint["requestedTime"])
for checkpoint in physical_state_checkpoints
if isinstance(checkpoint, Mapping)
]
if expected_times != golden_times:
raise RegressionManifestError(
f"Variant {case_id!r} physical-state-v2.1 golden checkpoint "
"times differ from manifest."
)
loaded_physical_state_v21_goldens.setdefault(case_id, {})[
lane_name
] = physical_state_golden
_finite_positive(
execution.get("predictionSafetyFactor", 1.0),
field="execution.predictionSafetyFactor",
@@ -720,10 +894,14 @@ def load_regression_manifest(path: Path | str) -> dict[str, object]:
manifest["_manifestPath"] = str(manifest_path)
manifest["_repositoryRoot"] = str(repository_root)
manifest["_sourcePath"] = str(source_path)
manifest["_referenceArchivePath"] = (
str(reference_archive_path) if reference_archive_path is not None else None
)
manifest["_companionPath"] = (
str(companion_path) if companion_path is not None else None
)
manifest["_goldens"] = loaded_goldens
manifest["_physicalStateV21Goldens"] = loaded_physical_state_v21_goldens
return manifest
@@ -1105,7 +1283,7 @@ def summarize_simulation_result(
"eventTrace": event_trace,
"comparisonMode": "numericTolerance",
}
return {
summary = {
"success": bool(result.get("success")),
"status": result.get("status"),
"partial": bool(result.get("partial")),
@@ -1126,6 +1304,13 @@ def summarize_simulation_result(
"diagnostics": dict(diagnostic_mapping),
"eventTrace": event_trace,
}
if physical_state_v21_applicable(result):
summary["physicalStateV21"] = project_physical_state_v21(
result,
checkpoint_times=checkpoint_times,
sample_step=sample_step,
)
return summary
def _worker_control_listener(cancel_event: threading.Event) -> None:
@@ -1666,6 +1851,77 @@ def evaluate_regression_golden(
return audit
def evaluate_physical_state_v21_golden(
summary: Mapping[str, object] | None,
golden: Mapping[str, object] | None,
) -> dict[str, object]:
"""Evaluate the algebraic/discrete v2.1 contract when a manifest pins it."""
if golden is None:
return {
"configured": False,
"evaluated": False,
"passed": None,
"issues": [],
}
provenance = golden.get("provenance")
amesim_provenance = (
provenance.get("amesim") if isinstance(provenance, Mapping) else None
)
alignment = golden.get("amesimAlignmentAtGeneration")
audit: dict[str, object] = {
"configured": True,
"evaluated": False,
"passed": False,
"goldenId": golden.get("id"),
"goldenPath": golden.get("_path"),
"goldenSha256": golden.get("_sha256"),
"amesimArchiveSha256": (
amesim_provenance.get("archiveSha256")
if isinstance(amesim_provenance, Mapping)
else None
),
"amesimAlignmentAtGenerationPassed": (
alignment.get("passed") if isinstance(alignment, Mapping) else None
),
"issues": [],
"metrics": [],
}
if summary is None:
audit["issues"] = ["missingSummaryForPhysicalStateV21Golden"]
return audit
contract = summary.get("physicalStateV21")
if not isinstance(contract, Mapping):
audit["issues"] = ["missingPhysicalStateV21Contract"]
return audit
audit["evaluated"] = True
try:
evaluation = evaluate_physical_state_v21(contract, golden)
except PhysicalStateV21Error as exc:
audit["issues"] = ["invalidPhysicalStateV21Contract"]
audit["error"] = str(exc)
return audit
audit.update(evaluation)
audit.update(
{
"configured": True,
"evaluated": True,
"goldenId": golden.get("id"),
"goldenPath": golden.get("_path"),
"goldenSha256": golden.get("_sha256"),
"amesimArchiveSha256": (
amesim_provenance.get("archiveSha256")
if isinstance(amesim_provenance, Mapping)
else None
),
"amesimAlignmentAtGenerationPassed": (
alignment.get("passed") if isinstance(alignment, Mapping) else None
),
}
)
return audit
def _case_correctness_issues(
result: Mapping[str, object],
*,
@@ -1827,8 +2083,20 @@ def _case_correctness_issues(
if isinstance(golden_evaluation, Mapping):
raw_golden_issues = golden_evaluation.get("issues")
if isinstance(raw_golden_issues, list):
python_golden_role = correctness.get(
"pythonGoldenRole", "acceptanceGate"
)
accepted_issues = (
raw_golden_issues
if python_golden_role == "acceptanceGate"
else [
issue
for issue in raw_golden_issues
if issue in {"missingOutputContract", "outputContractMismatch"}
]
)
issues.extend(
str(issue) for issue in raw_golden_issues if isinstance(issue, str)
str(issue) for issue in accepted_issues if isinstance(issue, str)
)
return tuple(dict.fromkeys(issues))
@@ -1912,6 +2180,10 @@ def run_regression_suite(
assert isinstance(correctness, dict)
loaded_goldens = manifest.get("_goldens", {})
assert isinstance(loaded_goldens, dict)
loaded_physical_state_v21_goldens = manifest.get(
"_physicalStateV21Goldens", {}
)
assert isinstance(loaded_physical_state_v21_goldens, dict)
case_reports: list[dict[str, object]] = []
predecessor_completed = True
@@ -1988,6 +2260,45 @@ def run_regression_suite(
summary if isinstance(summary, Mapping) else None,
golden if isinstance(golden, Mapping) else None,
)
golden_evaluation["role"] = correctness.get(
"pythonGoldenRole", "acceptanceGate"
)
golden_evaluation["affectsPhysicalCorrectness"] = (
correctness.get("pythonGoldenRole", "acceptanceGate")
== "acceptanceGate"
)
raw_python_golden_issues = golden_evaluation.get("issues")
golden_evaluation["acceptanceIssues"] = (
list(raw_python_golden_issues)
if correctness.get("pythonGoldenRole", "acceptanceGate")
== "acceptanceGate"
and isinstance(raw_python_golden_issues, list)
else [
issue
for issue in (
raw_python_golden_issues
if isinstance(raw_python_golden_issues, list)
else []
)
if issue in {"missingOutputContract", "outputContractMismatch"}
]
)
case_physical_state_v21_goldens = loaded_physical_state_v21_goldens.get(
case_id, {}
)
physical_state_v21_golden = (
case_physical_state_v21_goldens.get(lane)
if isinstance(case_physical_state_v21_goldens, Mapping)
else None
)
physical_state_v21_evaluation = evaluate_physical_state_v21_golden(
summary if isinstance(summary, Mapping) else None,
(
physical_state_v21_golden
if isinstance(physical_state_v21_golden, Mapping)
else None
),
)
correctness_issues = (
_case_correctness_issues(
result,
@@ -1998,6 +2309,21 @@ def run_regression_suite(
if solver_completed
else ()
)
if solver_completed:
raw_v21_issues = physical_state_v21_evaluation.get("issues")
if isinstance(raw_v21_issues, list):
correctness_issues = tuple(
dict.fromkeys(
(
*correctness_issues,
*(
str(issue)
for issue in raw_v21_issues
if isinstance(issue, str)
),
)
)
)
report = {
"caseId": case_id,
"stopTime": stop_time,
@@ -2016,6 +2342,7 @@ def run_regression_suite(
"passed": solver_completed and not correctness_issues,
"issues": list(correctness_issues),
"regressionGolden": golden_evaluation,
"physicalStateV21Golden": physical_state_v21_evaluation,
},
}
if solver_completed and correctness_issues: