Files
gps-denied-onboard/_docs/02_tasks/done/AZ-281_engine_filename_schema.md
T
Oleksandr Bezdieniezhnykh 3acc7f33dd [AZ-270] [AZ-272] [AZ-279] [AZ-281] [AZ-283] Compose root + FDR schema + 3 Layer-1 helpers
AZ-270: composition root with strategy registry, tier-gated lookup,
topo-order construction, all-or-nothing teardown, StrategyNotLinkedError
payload.
AZ-272: orjson-backed FdrRecord serialise/parse with forward-compat for
unknown payload + top-level fields and canonical overrun-record shape.
AZ-279: pyproj-backed WGS84/ECEF/ENU + OSM slippy-map tile math with
WgsConversionError for shape/range/zoom guards.
AZ-281: strict EngineFilenameSchema build/parse/matches_host with
anchored regex + enum validation; round-trip identity by construction.
AZ-283: dtype-preserving (fp16/fp32) single + batch L2 normaliser with
zero-norm safety and descriptor_metric() source-of-truth.
pyproject.toml pins pyproj>=3.6 and orjson>=3.9 (named-backend deps per
the AZ-272 / AZ-279 contracts). New DTOs LatLonAlt + BoundingBox and
EngineCacheKey + HostCapabilities land in _types/ to back the helper
contracts.
203 unit tests pass (64 new). Review verdict: PASS_WITH_WARNINGS;
findings are perf-NFR deferrals + dep amendment + minor docstring polish.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 02:03:36 +03:00

9.0 KiB

EngineFilenameSchema Helper Module

Task: AZ-281_engine_filename_schema Name: EngineFilenameSchema Helper Description: Implement the shared EngineFilenameSchema helper for the self-describing .engine filename schema (D-C10-7). TensorRT engines are NOT portable across (SM, JetPack, TRT, precision) tuples; encoding the tuple in the filename makes mismatch instantly visible at takeoff load (F2). Used by C7 (writes engines on compile, reads on deserialize_engine) and C10 (compiles engines via C7 and writes them to the cache root). Stateless static-only design. Complexity: 2 points Dependencies: AZ-263_initial_structure Component: shared.helpers.engine_filename_schema (cross-cutting; epic AZ-264 / E-CC-HELPERS) Tracker: AZ-281 Epic: AZ-264 (E-CC-HELPERS)

Document Dependencies

  • _docs/02_document/contracts/shared_helpers/engine_filename_schema.md — frozen public interface this task produces.
  • _docs/02_document/common-helpers/06_helper_engine_filename_schema.md — design rationale (D-C10-7).

Problem

TensorRT engines are not portable. An engine compiled for SM 87 / JetPack 6.2 / TRT 10.3 / FP16 will fail to deserialize — or, worse, deserialize and silently produce wrong output — on a host with a different (sm, jp, trt, precision) tuple. Without a self-describing filename:

  • C7's deserialize_engine cannot tell whether an engine in the cache root matches the host capabilities until it tries to load it (an expensive, non-cheap, partially-side-effecting operation).
  • C10 has to maintain an out-of-band sidecar mapping filenames to tuples; that sidecar drifts.
  • An operator who copies an engine from a different deployment by mistake gets opaque "deserialize failed" errors at takeoff instead of a clear "engine was built for sm87, host is sm72".

Outcome

  • A single helpers.engine_filename_schema module is the only path through which any onboard process composes or parses .engine filenames.
  • The schema makes (model_name, sm, jetpack, trt, precision) part of the filename: {model}__sm{SM}_jp{JP}_trt{TRT}_{precision}.engine. F2 takeoff load uses matches_host to decide which engines to deserialize and which to refuse before paying the deserialise cost.
  • The schema is strict — invalid model names, non-dotted version strings, unknown precisions are rejected at build time; malformed filenames are rejected at parse time. Both raise EngineFilenameSchemaError with messages that name the offending field.
  • Round-trip identity: parse(build(*args)) == EngineCacheKey(*args) for any valid args. Round-trip is the contract test that catches any future format drift.

Scope

Included

  • EngineFilenameSchema static methods: build, parse, matches_host.
  • EngineFilenameSchemaError exception type.
  • Public interface contract published at _docs/02_document/contracts/shared_helpers/engine_filename_schema.md.

Excluded

  • Schema versioning (no schema_version field) — adding a new tuple dimension is a Plan-phase carryforward.
  • Engine compilation / compatibility resolution — C7.
  • Hot-loading / lazy materialisation — C7.
  • Filename collision detection across cache roots — C10's Manifest.
  • The EngineCacheKey / HostCapabilities types themselves — owned by _types/manifests.py (AZ-263).

Acceptance Criteria

AC-1: Reference example builds correctly Given ("ultravpr", 87, "6.2", "10.3", "fp16") When build runs Then the result is exactly "ultravpr__sm87_jp6.2_trt10.3_fp16.engine"

AC-2: Round-trip identity Given 10 random valid tuples When each round-trips through parse(build(*args)) Then each produces deep-equal EngineCacheKey outputs

AC-3: Host-match exact Given a filename built for (sm=87, jp=6.2, trt=10.3) and a HostCapabilities(sm=87, jp=6.2, trt=10.3) When matches_host runs Then the result is True

AC-4: Host-mismatch on any tuple element returns False (no exception) Given a filename built for (sm=87, jp=6.2, trt=10.3) and a host with sm=72 When matches_host runs Then the result is False (NOT an exception — tuple mismatch is the expected "not a match" path)

AC-5: Precision enum strictness Given build(..., precision="bf16") When the call runs Then EngineFilenameSchemaError is raised mentioning the allowed enum {fp16, int8, mixed}

AC-6: Model-name character set Given build("UltraVPR", ...) (uppercase letters) When the call runs Then EngineFilenameSchemaError is raised mentioning the allowed [a-z0-9_] set

AC-7: Reserved separator collision Given build("ultra__vpr", ...) (double underscore in model name) When the call runs Then EngineFilenameSchemaError is raised mentioning the reserved __ separator

AC-8: Version format strictness Given build(..., jetpack="6.2.1", ...) (three-segment version) When the call runs Then EngineFilenameSchemaError is raised mentioning the dotted <major>.<minor> format

AC-9: Parse rejects malformed filenames Given parse("not_an_engine_file.bin") When the call runs Then EngineFilenameSchemaError is raised

AC-10: Parse requires .engine suffix Given parse("ultravpr__sm87_jp6.2_trt10.3_fp16") (missing .engine) When the call runs Then EngineFilenameSchemaError is raised mentioning the required suffix

AC-11: No upward imports (Layer 1 invariant) Given the helper module When a static-import check runs Then it imports ONLY from _types, re, and stdlib — no gps_denied_onboard.components.* imports anywhere

Non-Functional Requirements

Performance

  • No specific latency budget per _docs/02_document/common-helpers/06_helper_engine_filename_schema.md (consumers are pre-flight / takeoff-load). Sanity bound: each helper call ≤ 50 µs on Tier-2.

Reliability

  • Pure deterministic; same input → byte-equal output.
  • EngineFilenameSchemaError is the ONLY exception type the public surface raises on validation / parse errors.

Unit Tests

AC Ref What to Test Required Outcome
AC-1 reference example exact filename match
AC-2 round-trip 10 random valid tuples deep-equal EngineCacheKey outputs
AC-3 matching host True
AC-4 mismatched sm False; no exception
AC-5 precision="bf16" EngineFilenameSchemaError; mentions enum
AC-6 uppercase model name EngineFilenameSchemaError; mentions [a-z0-9_]
AC-7 double-underscore model name EngineFilenameSchemaError; mentions reserved separator
AC-8 three-segment version EngineFilenameSchemaError; mentions dotted format
AC-9 malformed filename EngineFilenameSchemaError
AC-10 missing .engine suffix EngineFilenameSchemaError; mentions suffix
AC-11 importlinter / grep gate no components.* imports
NFR-perf microbench each helper (10k iterations on Tier-2 fixture) p99 ≤ 50 µs each

Constraints

  • Public surface frozen by _docs/02_document/contracts/shared_helpers/engine_filename_schema.md v1.0.0.
  • Layer 1 Foundation only.
  • Static-only design satisfies coderule.mdc.
  • No new dependency beyond what AZ-263 / E-BOOT pinned (only re and stdlib are needed).
  • The EngineCacheKey / HostCapabilities types live in _types/manifests.py (AZ-263 responsibility).

Risks & Mitigation

Risk 1: A future format change breaks existing cache roots

  • Risk: Adding a tuple dimension (e.g., BUILD_* flag combination) requires re-writing every existing .engine filename; deployments with stale cache roots fail silently.
  • Mitigation: The contract Versioning Rules mandate a major-version bump for any format change. C7's deserialize_engine should also reject unrecognised filename patterns rather than guess; that is C7's responsibility to wire on top of this helper's parse.

Risk 2: matches_host returns False without explanation

  • Risk: An operator copies an engine from a different deployment; takeoff-load skips it; the operator sees "no engine matches host" without knowing which tuple element mismatched.
  • Mitigation: This helper is just the predicate. The error-surfacing UX is C7's / C10's responsibility — they call parse to extract the engine's tuple AND read host_capabilities, then format an actionable error. The contract documents the predicate's "True iff all tuple elements match" semantics so consumers can produce that message themselves.

Runtime Completeness

  • Named capability: self-describing engine filename schema (D-C10-7 / 06_helper_engine_filename_schema.md).
  • Production code that must exist: real format builder + parser + host-match predicate; real strict validation for all five tuple elements.
  • Allowed external stubs: none — pure string parsing on stdlib.
  • Unacceptable substitutes: f"{model}_{sm}_{jp}_{trt}_{precision}.engine" (single underscore separators ambiguate model from sm); silently truncating jetpack="6.2.1" to 6.2; matching host with substring instead of exact-equality.

Contract

This task produces the contract at _docs/02_document/contracts/shared_helpers/engine_filename_schema.md. Consumers MUST read that file — not this task spec — to discover the interface.