# Contract: engine_filename_schema

**Component**: shared_helpers / `helpers.engine_filename_schema` (cross-cutting concern owned by E-CC-HELPERS / AZ-264)
**Producer task**: AZ-281 — `_docs/02_tasks/todo/AZ-281_engine_filename_schema.md`
**Consumer tasks**: every C7 task that writes / reads `.engine` files via the inference runtime; every C10 task that compiles engines through C7 and writes them to the cache root
**Version**: 1.0.0
**Status**: draft
**Last Updated**: 2026-05-10

## Purpose

Self-describing `.engine` filename schema per 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) so refusing-to-deserialize-on-mismatch becomes trivial. Per `_docs/02_document/common-helpers/06_helper_engine_filename_schema.md`.

## Shape

### For function / method APIs

```python
class EngineFilenameSchema:
    @staticmethod
    def build(model_name: str, sm: int, jetpack: str, trt: str, precision: str) -> str: ...
    @staticmethod
    def parse(filename: str) -> EngineCacheKey: ...
    @staticmethod
    def matches_host(filename: str, host_capabilities: HostCapabilities) -> bool: ...
```

| Name | Signature | Throws / Errors | Blocking? |
|------|-----------|-----------------|-----------|
| `build` | `(model_name, sm, jetpack, trt, precision) -> str` | `EngineFilenameSchemaError` if any input fails validation (see Invariants) | sync, pure |
| `parse` | `(filename) -> EngineCacheKey` | `EngineFilenameSchemaError` if filename does not match the format | sync, pure |
| `matches_host` | `(filename, host_capabilities) -> bool` | `EngineFilenameSchemaError` only if the filename itself is malformed (returns False on tuple mismatch — that's the expected "not a match" path) | sync, pure |

`EngineCacheKey` and `HostCapabilities` are imported from `gps_denied_onboard._types.manifests`. The `EngineCacheKey` Protocol exposes: `model_name: str`, `sm: int`, `jetpack: str`, `trt: str`, `precision: str` (where `precision in {"fp16", "int8", "mixed"}`).

### Filename format

```
{model}__sm{SM}_jp{JP_dotted}_trt{TRT_dotted}_{precision}.engine
```

Example: `ultravpr__sm87_jp6.2_trt10.3_fp16.engine`

## Invariants

- **Stateless**: no module-level state; static methods only. The static-only design satisfies the coderule.mdc constraint ("only use static methods for pure self-contained computations") because filename parsing is a pure mathematical function of its arguments.
- **Format strictness**: filenames MUST follow `{model}__sm{SM}_jp{JP}_trt{TRT}_{precision}.engine` exactly. The double underscore (`__`) after `model` is intentional — it is the field separator that lets `model` itself contain single underscores (e.g., `ultra_vpr__sm87_...`).
- **Field validation**:
  - `model_name`: non-empty, only `[a-z0-9_]` characters (no double underscores), max 64 chars.
  - `sm`: positive integer (e.g., 87 for Jetson Orin Nano Super; 86 for Orin AGX; 72 for Xavier).
  - `jetpack`: dotted version string `<major>.<minor>` (e.g., `6.2`); each segment is a non-negative integer.
  - `trt`: dotted version string `<major>.<minor>` (e.g., `10.3`); same rules as `jetpack`.
  - `precision`: strictly one of `"fp16"`, `"int8"`, `"mixed"`.
  - The dotted-version format must round-trip cleanly through filesystems — no `/` or `\` in `model_name` or version segments.
- **`matches_host` is exact-match**: returns True iff every tuple element matches exactly (`sm == current_sm`, `jetpack == current_jetpack`, `trt == current_trt`). Precision and model_name do not affect host-matching but ARE preserved in the parsed key.
- **Round-trip identity**: `parse(build(*args)) == EngineCacheKey(*args)` for any valid args. `build(parse(filename)._asdict())` returns the same filename for any valid filename.
- **No upward imports** (Layer 1): the module imports ONLY from `_types`, `re`, and stdlib. No `gps_denied_onboard.components.*` imports.

## Non-Goals

- Versioning of the schema itself — there is no `schema_version` field. Adding a new tuple dimension is a Plan-phase carryforward (see Caveats in `_docs/02_document/common-helpers/06_helper_engine_filename_schema.md`).
- Engine compilation / compatibility resolution — owned by C7.
- Hot-loading engines / lazy materialisation — owned by C7.
- Filename collision detection across cache roots — owned by C10's Manifest.

## Versioning Rules

- **Breaking changes** (filename format changed, separator changed, new mandatory field added, precision enum reduced) require a new major version + a re-write pass over every existing `.engine` filename in the cache root.
- **Non-breaking additions** (new accessor function, new optional kwarg with safe default, new `precision` enum value appended) require a minor version bump.

## Test Cases

| Case | Input | Expected | Notes |
|------|-------|----------|-------|
| valid-build-ultravpr | `("ultravpr", 87, "6.2", "10.3", "fp16")` | `"ultravpr__sm87_jp6.2_trt10.3_fp16.engine"` | Reference example from helper doc |
| valid-roundtrip | `parse(build(*args))` for 10 random valid tuples | each round-trip returns deep-equal `EngineCacheKey` | Round-trip invariant |
| valid-matches-host-true | filename built for `(sm=87, jp=6.2, trt=10.3)`, host with same | `matches_host` returns True | Exact match |
| valid-matches-host-false-sm | filename built for `sm=87`, host with `sm=72` | `matches_host` returns False (no exception) | Tuple mismatch |
| valid-matches-host-false-trt | filename built for `trt=10.3`, host with `trt=10.4` | `matches_host` returns False | Patch-version mismatch is still a mismatch |
| invalid-precision-enum | `build(..., precision="bf16")` | `EngineFilenameSchemaError` mentions allowed enum | Precision strictness |
| invalid-model-uppercase | `build("UltraVPR", ...)` | `EngineFilenameSchemaError` mentions `[a-z0-9_]` | Model-name strictness |
| invalid-model-double-underscore | `build("ultra__vpr", ...)` | `EngineFilenameSchemaError` mentions reserved separator | Separator collision guard |
| invalid-jetpack-format | `jetpack="6.2.1"` | `EngineFilenameSchemaError` mentions dotted `<major>.<minor>` format | Version strictness |
| invalid-parse-malformed | `parse("not_an_engine_file.bin")` | `EngineFilenameSchemaError` raised | Parse strictness |
| invalid-parse-missing-suffix | `parse("ultravpr__sm87_jp6.2_trt10.3_fp16")` (no `.engine`) | `EngineFilenameSchemaError` raised | Suffix required |
| no-upward-imports | static import scan | only `_types`, `re`, stdlib | Layer 1 invariant |

## Change Log

| Version | Date | Change | Author |
|---------|------|--------|--------|
| 1.0.0 | 2026-05-10 | Initial contract derived from `_docs/02_document/common-helpers/06_helper_engine_filename_schema.md` | autodev decompose Step 2 |
