mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 19:41:14 +00:00
Decompose Step 6 snapshot: 140 task specs + contract docs
Closes out greenfield Step 6 (Decompose) for all 14 components (C1-C13 + cross-cutting helpers/replay). Covers tasks AZ-266..AZ-446 plus the _dependencies_table.md and component contract documents. State file updated to greenfield Step 7 (Implement), not_started. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user