diff --git a/_docs/02_document/module-layout.md b/_docs/02_document/module-layout.md index 34588bd..b0e00f0 100644 --- a/_docs/02_document/module-layout.md +++ b/_docs/02_document/module-layout.md @@ -17,7 +17,7 @@ Bootstrap reference: `_docs/02_tasks/todo/AZ-263_initial_structure.md`. Architec 4. Native (C++) libraries live under `cpp/` (parallel to `src/`, NOT nested), built by CMake; per-component pybind11 wrappers live at `src/gps_denied_onboard/components//_native/.py` and import the resulting `.so` from a CMake-known path. 5. **Public API surface per component** = the files listed in each component's `Public API` list below. Anything not listed is internal and MUST NOT be imported from another component. 6. The composition root is `src/gps_denied_onboard/runtime_root.py`. It is the ONLY place that may import concrete strategy implementations across components — every other cross-component dependency is constructor-injected against an interface (ADR-009). -7. Tests mirror the component graph 1:1 at `tests/unit//`. Cross-component scenarios live in `tests/integration/`, `tests/e2e/`, `tests/perf/`, `tests/security/`, `tests/resilience/`. +7. Tests mirror the component graph 1:1 at `tests/unit//`. In-process cross-component scenarios that import SUT source live under `tests/integration/`. The **blackbox / e2e** test harness — which MUST NOT import SUT source and exercises the system only via public boundaries (MAVLink / MSP2 / HTTP / filesystem) — lives at the repo-root `e2e/` directory and is owned by the `blackbox_tests` cross-cutting entry (Shared section). Performance, resilience, security, and resource-limit scenarios that are also boundary-driven likewise live under `e2e/tests//`; only in-process performance/security micro-tests (if any) would live under `tests/perf/`, `tests/security/`, `tests/resilience/`. 8. Build-time exclusion (ADR-002): each `/_native/` and the corresponding `cpp//` carry a CMake `BUILD_` flag. The composition root validator refuses to wire a strategy whose flag is OFF. 9. **AZ-507 cross-component contract surface** — the only places a `components//*.py` file may import are: its own subpackage (`gps_denied_onboard.components..*`), `_types/*`, `_types.inference_errors`, `helpers/*`, `config`, `logging`, `fdr_client`, `clock`, `frame_source` (interface only). Cross-component contracts (Protocols + typed exceptions) reach consumers through `_types/*` modules — DTOs in the canonical `_types` files (e.g. `_types.inference.EngineCacheEntry`), typed-error envelopes in `_types.inference_errors`, and consumer-side structural `Protocol` cuts defined locally inside each consuming component (e.g. `c10_provisioning.engine_compiler.CompileEngineCallable`). NEVER `from gps_denied_onboard.components. import ...` — the AZ-270 `test_az270_compose_root.test_ac6_only_compose_root_imports_concrete_strategies` lint enforces this on every `components/**/*.py`. The composition root (`runtime_root/*`) is the single exception; it wires concrete strategies into duck-typed Protocol parameters via constructor injection. This rule is the architectural contract paired with the AZ-270 lint; see `architecture.md` § Cross-Component Contract Surface for the rationale. @@ -416,6 +416,17 @@ Bootstrap reference: `_docs/02_tasks/todo/AZ-263_initial_structure.md`. Architec - **Owned by**: AZ-263. - **Consumed by**: companion-tier1 Dockerfile, operator-orchestrator Dockerfile, CI smoke job. +### blackbox_tests (cross-cutting test harness) + +- **Directory**: `e2e/` (repo root, **NOT** under `tests/`) +- **Purpose**: Tier-1 Docker + Tier-2 Jetson blackbox test harness. The runner image is fully separated from the SUT and exercises the system through declared public boundaries only (frame source replay, FC inbound/outbound via SITL, tile-cache mount, MAVLink via mavproxy, FDR filesystem, mock Suite Sat Service). Owns the docker-compose test environment, Jetson Tier-2 runner scripts, fixture builders, runner image, conftest, pytest plugins (csv reporter, evidence bundler), helper modules, and per-category test trees (`positive/`, `negative/`, `performance/`, `resilience/`, `security/`, `resource_limit/`). +- **Owned by**: epic AZ-262 (E-BBT) — task specs AZ-406 (infrastructure bootstrap), AZ-407..AZ-446 (fixture builders + per-scenario tests + Tier-2 harness wrapper + CSV reporter). +- **Owns (exclusive write during implementation)**: `e2e/**` +- **Imports from**: nothing inside `src/gps_denied_onboard/**`. The runner image MUST NOT import any SUT module; the only legal interaction surfaces are MAVLink / MSP2 / HTTP / filesystem. Reads RO from `_docs/00_problem/input_data/**` (bind-mounted test data) and `_docs/02_document/tests/**` (test specs that drive AC mapping). May import standard ground-side libraries (`pymavlink`, `opencv-python`, `numpy`, `scipy`, `geopy`, `pytest`, etc.) and the `msp_gps_toy` Rust binary via subprocess. +- **FORBIDDEN**: `src/gps_denied_onboard/**` (any product source), `tests/unit/**`, `tests/integration/**`, `cpp/**` (native source trees), `db/migrations/**`. Product-side tests under `tests/unit//` remain owned by the respective component per its existing Per-Component Mapping entry. +- **Consumed by**: CI matrix (Tier-1 docker-compose entrypoint, Tier-2 Jetson runner harness); operator manual Tier-2 invocation via `./e2e/jetson/run-tier2.sh`. +- **Layering note**: blackbox_tests is an external observer of the SUT — it does not sit in the production layering table. Treat it as a separate harness outside Layers 1–5. The "no Layer-3 → Layer-4 imports" and "interface-at-producer" rules do not apply (no production code lives here). + ## Allowed Dependencies (Layering) Read top-to-bottom; an upper layer may import from a lower layer but NEVER the reverse. Cross-layer violations are **Architecture** findings in code-review (High severity). @@ -477,7 +488,7 @@ Build-time exclusion is enforced by: ## Self-Verification Checklist - [x] Every component in `_docs/02_document/components/` has a Per-Component Mapping entry (14 components: c1_vio, c2_vpr, c2_5_rerank, c3_matcher, c3_5_adhop, c4_pose, c5_state, c6_tile_cache, c7_inference, c8_fc_adapter, c10_provisioning, c11_tile_manager, c12_operator_orchestrator, c13_fdr). -- [x] Every shared / cross-cutting concern has a Shared section entry (_types, config, logging, fdr_client, frame_source, clock, replay_input, helpers/* × 8, runtime_root, cli/replay, healthcheck). +- [x] Every shared / cross-cutting concern has a Shared section entry (_types, config, logging, fdr_client, frame_source, clock, replay_input, helpers/* × 8, runtime_root, cli/replay, healthcheck, blackbox_tests). - [x] Layering table covers every component; foundation at Layer 1. - [x] No component's `Imports from` list points at a component in a higher layer (back-channel exception for C8 → C1/C5 documented as interface-at-producer pattern). - [x] Paths follow Python `src/`-layout convention with single top-level package `gps_denied_onboard/`. diff --git a/_docs/_autodev_state.md b/_docs/_autodev_state.md index deb230d..eb52a96 100644 --- a/_docs/_autodev_state.md +++ b/_docs/_autodev_state.md @@ -4,10 +4,10 @@ flow: greenfield step: 10 name: Implement Tests -status: not_started +status: in_progress sub_step: - phase: 0 - name: awaiting-invocation + phase: 1 + name: parse-and-detect-progress detail: "" retry_count: 0 cycle: 1