mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 06:31:12 +00:00
[AZ-507] [AZ-323] [AZ-324] C10 Manifest build + verify + AZ-270 hygiene
AZ-507: codify cross-component import rule. Added _types/inference_errors.py shim re-exporting EngineBuildError + CalibrationCacheError from c7_inference; narrowed C10 EngineCompiler's except Exception to the two typed errors so unknown exceptions propagate (AC-3). Rewrote module-layout.md "Imports from" sections for 9 components + added Rule 9; appended an architecture.md ADR-009 note explaining why components must go through _types/*. AZ-323: ManifestBuilder + Ed25519ManifestSigner. Canonical JSON via orjson OPT_SORT_KEYS+OPT_INDENT_2, atomic-write Manifest.json + sha sidecar + .sig via AZ-280, operator-key fingerprint allowlist gate (C10-ST-01), ADR-010 takeoff_origin + flight_id baked into Manifest AND manifest_hash so re-planned routes change the cache identity (AC-15/AC-16). 20 unit tests cover all 16 ACs. AZ-324: ManifestVerifierImpl. Fail-closed Steps A-D: Manifest.json sidecar self-hash, Ed25519 trust-key set, schema parse with absolute/.. path rejection + takeoff_origin in-bbox check, stream SHA-256 per artifact with multi-failure accumulation. Operator mode re-derives tiles_coverage_sha256 from C6; airborne mode trusts the signed aggregate. 19 unit tests cover all 17 ACs. Composition root: c10_factory.build_manifest_builder + build_manifest_verifier + c6_tile_metadata_store_to_tiles_query adapter (the one place that legitimately imports both C6 and C10 without violating the AZ-270 lint). Dependency: pinned cryptography>=43.0,<46.0 in pyproject.toml. Tests: 1300 passed, 80 skipped (env-only), ruff clean for all AZ-323/324 files. AZ-306 (FAISS) intentionally deferred to batch 35 — needs C++ pybind11 toolchain not present in this environment. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -597,6 +597,72 @@ def test_missing_sidecar_treated_as_cache_miss(
|
||||
)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# AZ-507 AC-3: non-typed exceptions propagate without the compile.error log
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
|
||||
def test_az507_ac3_non_typed_exception_propagates_without_structured_log(
|
||||
cache_root: Path,
|
||||
backbones: tuple[BackboneSpec, ...],
|
||||
logger: logging.Logger,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
# Arrange — the runtime raises a stdlib RuntimeError, which is NOT
|
||||
# in the C7 typed-error envelope. AZ-507 narrows the catch to
|
||||
# `(EngineBuildError, CalibrationCacheError)` so the unknown error
|
||||
# must propagate unchanged and the c10.engine.compile.error log
|
||||
# must NOT fire (the structured log is the typed-failure contract,
|
||||
# not a catch-all).
|
||||
runtime = _FakeRuntime(
|
||||
cache_root=cache_root,
|
||||
raise_on={"dinov2_vpr": RuntimeError("unexpected programmer error")},
|
||||
)
|
||||
compiler = EngineCompiler(inference_runtime=runtime, logger=logger)
|
||||
request = _request(backbones, cache_root)
|
||||
|
||||
# Act + Assert — propagation
|
||||
with caplog.at_level(logging.ERROR, logger=logger.name):
|
||||
with pytest.raises(RuntimeError, match="unexpected programmer error"):
|
||||
compiler.compile_engines_for_corpus(request)
|
||||
|
||||
# Assert — no structured compile.error log for the unknown type
|
||||
error_kinds = [
|
||||
rec for rec in caplog.records
|
||||
if rec.__dict__.get("kind") == "c10.engine.compile.error"
|
||||
]
|
||||
assert error_kinds == []
|
||||
|
||||
|
||||
def test_az507_ac3_typed_exception_still_logs_structured_diagnostic(
|
||||
cache_root: Path,
|
||||
backbones: tuple[BackboneSpec, ...],
|
||||
logger: logging.Logger,
|
||||
caplog: pytest.LogCaptureFixture,
|
||||
) -> None:
|
||||
# Arrange — typed C7 error MUST still produce the structured log
|
||||
# and re-raise (regression guard for AZ-321's diagnostic contract
|
||||
# that AZ-507 must not break).
|
||||
runtime = _FakeRuntime(
|
||||
cache_root=cache_root,
|
||||
raise_on={"dinov2_vpr": EngineBuildError("typed failure")},
|
||||
)
|
||||
compiler = EngineCompiler(inference_runtime=runtime, logger=logger)
|
||||
request = _request(backbones, cache_root)
|
||||
|
||||
# Act + Assert
|
||||
with caplog.at_level(logging.ERROR, logger=logger.name):
|
||||
with pytest.raises(EngineBuildError, match="typed failure"):
|
||||
compiler.compile_engines_for_corpus(request)
|
||||
|
||||
error_kinds = [
|
||||
rec for rec in caplog.records
|
||||
if rec.__dict__.get("kind") == "c10.engine.compile.error"
|
||||
]
|
||||
assert len(error_kinds) == 1
|
||||
assert error_kinds[0].__dict__["kv"]["error_class"] == "EngineBuildError"
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# NFR placeholders (Tier-2 microbench harness owns these on Jetson)
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user