[AZ-219] Scaffold onboard runtime project

Add the initial source, test, infrastructure, CI, configuration, and evidence-path scaffold so dependent implementation tasks have stable package and runtime boundaries.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-03 12:04:22 +03:00
parent dd9afe2797
commit 79997e39ac
97 changed files with 753 additions and 3 deletions
+27
View File
@@ -0,0 +1,27 @@
.git
.github
.cursor
_docs
.venv
__pycache__
.pytest_cache
.ruff_cache
.mypy_cache
.env
.env.*
*.pem
*.key
*.secret
data/input/*
data/cache/*
data/fdr/*
data/test-results/*
*.tlog
*.ulg
*.bag
*.mcap
*.cbor
*.parquet
*.mp4
*.mov
*.avi
+10
View File
@@ -0,0 +1,10 @@
GPSD_ENV=development
GPSD_CONFIG_DIR=./config/development
GPSD_CACHE_DIR=./data/cache
GPSD_FDR_DIR=./data/fdr
GPSD_DATABASE_URL=postgresql://gpsd:gpsd@localhost:5432/gpsd
GPSD_MAVLINK_URL=udp:127.0.0.1:14550
GPSD_CAMERA_SOURCE=./data/input
GPSD_SIGNING_KEY_REF=test-key-ref
GPSD_MAX_FDR_BYTES=104857600
GPSD_LOG_LEVEL=info
+43
View File
@@ -0,0 +1,43 @@
name: CI
on:
pull_request:
push:
branches:
- dev
jobs:
python-quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
- name: Format check
run: python -m black --check src tests
- name: Lint
run: python -m ruff check src tests
- name: Unit tests
run: python -m pytest tests/unit
replay-compose-smoke:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate compose files
run: |
docker compose -f docker-compose.yml config
docker compose -f docker-compose.test.yml config
- name: Collect artifact placeholders
run: mkdir -p data/test-results e2e/reports
- uses: actions/upload-artifact@v4
with:
name: replay-evidence-placeholders
path: |
data/test-results
e2e/reports
+41
View File
@@ -1 +1,42 @@
.DS_Store
.venv/
__pycache__/
*.py[cod]
.pytest_cache/
.ruff_cache/
.mypy_cache/
.coverage
htmlcov/
*.egg-info/
.env
.env.*
!.env.example
*.pem
*.key
*.secret
data/input/*
data/cache/*
data/fdr/*
data/test-results/*
data/expected/*
!data/input/.gitkeep
!data/cache/.gitkeep
!data/fdr/.gitkeep
!data/test-results/.gitkeep
!data/expected/.gitkeep
*.tlog
*.ulg
*.bag
*.mcap
*.cbor
*.parquet
*.mp4
*.mov
*.avi
*.jpg
*.jpeg
*.png
!_docs/00_problem/input_data/**
+21
View File
@@ -0,0 +1,21 @@
# GPS-Denied Onboard Runtime
Scaffold for the Jetson-hosted GPS-denied localization runtime, replay harness, and
deployment evidence paths.
The project uses a Python `src/` layout for orchestration code, with native bridge
directories reserved for BASALT, feature matching, and TensorRT integrations.
Generated mission data, FDR payloads, cache payloads, and raw frame dumps are kept
out of git unless they are explicitly curated test fixtures.
## Local Development
```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -e ".[dev]"
python -m pytest
```
Local replay infrastructure is described in `docker-compose.yml`; CI and black-box
test infrastructure are described in `docker-compose.test.yml`.
@@ -0,0 +1,41 @@
# Batch Report
**Batch**: 1
**Tasks**: AZ-219_initial_structure
**Date**: 2026-05-03
## Task Results
| Task | Status | Files Modified | Tests | AC Coverage | Issues |
|------|--------|----------------|-------|-------------|--------|
| AZ-219_initial_structure | Done | 98 files | Pass | 7/7 ACs covered | None |
## AC Test Coverage: All covered
| AC Ref | Coverage |
|--------|----------|
| AC-1 | `test_scaffold_paths_cover_runtime_test_and_evidence_layout` verifies source, tests, migrations, deployment, configuration, data, CI, and compose scaffold paths. |
| AC-2 | `test_runtime_component_public_modules_are_importable` and `test_shared_contract_locations_are_importable` verify public component and shared contract namespaces. |
| AC-3 | `test_scaffold_paths_cover_runtime_test_and_evidence_layout` verifies compose, env template, and migration paths; compose config validation passed. |
| AC-4 | `test_scaffold_paths_cover_runtime_test_and_evidence_layout` verifies `.github/workflows/ci.yml`; the workflow defines format, lint, unit test, compose config, and artifact placeholder jobs. |
| AC-5 | `test_scaffold_paths_cover_runtime_test_and_evidence_layout` verifies unit, integration, black-box, fixture, SITL, and e2e runner paths. |
| AC-6 | `test_scaffold_paths_cover_runtime_test_and_evidence_layout` verifies deployment scripts and evidence report paths. |
| AC-7 | `test_ignore_rules_exclude_runtime_payloads_and_secrets` verifies secrets, raw frames, cache/FDR payloads, and test result artifacts are ignored. |
## Code Review Verdict: PASS
Review report: `_docs/03_implementation/reviews/batch_01_review.md`
## Auto-Fix Attempts: 0
## Stuck Agents: None
## Verification
- `.venv/bin/python -m black --check src tests e2e/replay` passed.
- `.venv/bin/python -m ruff check src tests e2e/replay` passed.
- `.venv/bin/python -m pytest` passed: 5 tests.
- `docker compose -f docker-compose.yml config` passed.
- `docker compose -f docker-compose.test.yml config` passed.
## Next Batch: AZ-220_shared_runtime_contracts
@@ -0,0 +1,29 @@
# Code Review Report
**Batch**: AZ-219_initial_structure
**Date**: 2026-05-03
**Verdict**: PASS
## Findings
| # | Severity | Category | File:Line | Title |
|---|----------|----------|-----------|-------|
| - | - | - | - | No findings |
## Review Notes
- AC-1 is satisfied by the `src/`, `migrations/`, `tests/`, `e2e/`, `deployment/`, `config/`, and `data/` scaffold plus tracked placeholders.
- AC-2 is satisfied by importable component and shared package namespaces under `src/`.
- AC-3 is satisfied by `docker-compose.yml`, `docker-compose.test.yml`, `.env.example`, and the initial PostGIS migration.
- AC-4 is satisfied by `.github/workflows/ci.yml` with format, lint, unit-test, compose-config, and artifact placeholder stages.
- AC-5 is satisfied by pytest unit scaffold coverage and black-box/SITL/e2e fixture entry-point directories.
- AC-6 is satisfied by deployment Dockerfiles, Jetson/deployment placeholders, `e2e/reports/`, and `deployment/scripts/collect_evidence.sh`.
- AC-7 is satisfied by `.gitignore`, `.dockerignore`, and non-secret environment templates excluding generated runtime payloads and credentials.
## Verification
- `.venv/bin/python -m black --check src tests e2e/replay` passed.
- `.venv/bin/python -m ruff check src tests e2e/replay` passed.
- `.venv/bin/python -m pytest` passed: 5 tests.
- `docker compose -f docker-compose.yml config` passed.
- `docker compose -f docker-compose.test.yml config` passed.
+3 -3
View File
@@ -7,8 +7,8 @@ name: Implement
status: in_progress
tracker: jira
sub_step:
phase: 0
name: awaiting-invocation
detail: ""
phase: 1
name: batch-loop
detail: "batch 1: AZ-219_initial_structure"
retry_count: 0
cycle: 1
+6
View File
@@ -0,0 +1,6 @@
GPSD_ENV=ci
GPSD_LOG_LEVEL=info
GPSD_CONFIG_DIR=./config/ci
GPSD_CACHE_DIR=./data/cache
GPSD_FDR_DIR=./data/fdr
GPSD_CAMERA_SOURCE=./tests/fixtures
+6
View File
@@ -0,0 +1,6 @@
GPSD_ENV=development
GPSD_LOG_LEVEL=debug
GPSD_CONFIG_DIR=./config/development
GPSD_CACHE_DIR=./data/cache
GPSD_FDR_DIR=./data/fdr
GPSD_CAMERA_SOURCE=./data/input
+6
View File
@@ -0,0 +1,6 @@
GPSD_ENV=jetson
GPSD_LOG_LEVEL=info
GPSD_CONFIG_DIR=/etc/gps-denied-onboard
GPSD_CACHE_DIR=/var/lib/gps-denied/cache
GPSD_FDR_DIR=/var/lib/gps-denied/fdr
GPSD_CAMERA_SOURCE=hardware
+10
View File
@@ -0,0 +1,10 @@
GPSD_ENV=production
GPSD_LOG_LEVEL=info
GPSD_CONFIG_DIR=/etc/gps-denied-onboard
GPSD_CACHE_DIR=/var/lib/gps-denied/cache
GPSD_FDR_DIR=/var/lib/gps-denied/fdr
GPSD_DATABASE_URL=postgresql://user:password@localhost:5432/gpsd
GPSD_MAVLINK_URL=serial:/dev/ttyTHS1:921600
GPSD_CAMERA_SOURCE=hardware
GPSD_SIGNING_KEY_REF=replace-with-secret-manager-reference
GPSD_MAX_FDR_BYTES=68719476736
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+4
View File
@@ -0,0 +1,4 @@
# Compose Configuration
Runtime compose files live at the repository root so local and CI commands can
use Docker defaults without extra path arguments.
+19
View File
@@ -0,0 +1,19 @@
FROM python:3.12-slim-bookworm
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
RUN groupadd --system gpsd && useradd --system --gid gpsd --home-dir /app gpsd
COPY pyproject.toml README.md ./
COPY src ./src
COPY tests ./tests
RUN python -m pip install --no-cache-dir --upgrade pip \
&& python -m pip install --no-cache-dir ".[dev]"
USER gpsd
CMD ["python", "-m", "pytest"]
+18
View File
@@ -0,0 +1,18 @@
FROM python:3.12-slim-bookworm
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
RUN groupadd --system gpsd && useradd --system --gid gpsd --home-dir /app gpsd
COPY pyproject.toml README.md ./
COPY src ./src
RUN python -m pip install --no-cache-dir --upgrade pip \
&& python -m pip install --no-cache-dir .
USER gpsd
CMD ["python", "-c", "import shared.contracts; print('gps-denied runtime scaffold ready')"]
+4
View File
@@ -0,0 +1,4 @@
# Jetson Deployment Notes
Reserved for Jetson provisioning, thermal/resource evidence, and hardware-runner
qualification procedures.
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
mkdir -p e2e/reports data/test-results
printf 'Evidence collection placeholder. Wire runtime reports in deploy phase.\n'
+27
View File
@@ -0,0 +1,27 @@
services:
postgis:
image: postgis/postgis:16-3.4
environment:
POSTGRES_DB: gpsd_test
POSTGRES_USER: gpsd
POSTGRES_PASSWORD: gpsd
volumes:
- ./migrations/postgresql:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U gpsd -d gpsd_test"]
interval: 10s
timeout: 5s
retries: 5
replay-tests:
build:
context: .
dockerfile: deployment/docker/Dockerfile.replay
env_file:
- config/ci/runtime.env
depends_on:
postgis:
condition: service_healthy
volumes:
- ./tests/fixtures:/app/tests/fixtures:ro
- ./data/test-results:/app/data/test-results
+34
View File
@@ -0,0 +1,34 @@
services:
postgis:
image: postgis/postgis:16-3.4
environment:
POSTGRES_DB: gpsd
POSTGRES_USER: gpsd
POSTGRES_PASSWORD: gpsd
ports:
- "5432:5432"
volumes:
- postgis-data:/var/lib/postgresql/data
- ./migrations/postgresql:/docker-entrypoint-initdb.d:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U gpsd -d gpsd"]
interval: 10s
timeout: 5s
retries: 5
runtime:
build:
context: .
dockerfile: deployment/docker/Dockerfile.runtime
env_file:
- .env.example
depends_on:
postgis:
condition: service_healthy
volumes:
- ./data/cache:/app/data/cache
- ./data/fdr:/app/data/fdr
- ./data/input:/app/data/input:ro
volumes:
postgis-data:
+4
View File
@@ -0,0 +1,4 @@
# Replay Harness
Reserved for suite-level replay entry points that drive the runtime only through
public files, MAVLink/cache/FDR interfaces, and published reports.
+14
View File
@@ -0,0 +1,14 @@
"""Replay runner entry point."""
from pathlib import Path
def main() -> int:
report_path = Path("e2e/reports/replay_smoke.txt")
report_path.parent.mkdir(parents=True, exist_ok=True)
report_path.write_text("replay scaffold ready\n", encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+1
View File
@@ -0,0 +1 @@
@@ -0,0 +1 @@
CREATE EXTENSION IF NOT EXISTS postgis;
+4
View File
@@ -0,0 +1,4 @@
# Seed Data
Place deterministic development and CI seed data here. Do not add production
mission payloads, signing material, or raw frame dumps.
+32
View File
@@ -0,0 +1,32 @@
[build-system]
requires = ["setuptools>=69", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "gps-denied-onboard"
version = "0.1.0"
description = "Jetson-hosted GPS-denied localization runtime scaffold."
requires-python = ">=3.10"
dependencies = []
[project.optional-dependencies]
dev = [
"black>=24.0",
"pytest>=8.0",
"ruff>=0.5",
]
[tool.setuptools.packages.find]
where = ["src"]
[tool.pytest.ini_options]
pythonpath = ["src"]
testpaths = ["tests"]
[tool.ruff]
line-length = 100
src = ["src", "tests"]
[tool.black]
line-length = 100
target-version = ["py310"]
+1
View File
@@ -0,0 +1 @@
"""Source-root package marker for editable installs."""
+1
View File
@@ -0,0 +1 @@
"""Anchor verification component."""
+10
View File
@@ -0,0 +1,10 @@
"""Public anchor verification interfaces."""
from typing import Any, Protocol
class AnchorVerifier(Protocol):
"""Verifies retrieved candidates against camera observations."""
def verify(self, frame: Any, candidate: Any) -> Any:
"""Return an anchor decision for one candidate."""
+5
View File
@@ -0,0 +1,5 @@
"""Public anchor verification type aliases."""
from typing import Any
AnchorDecisionLike = Any
+1
View File
@@ -0,0 +1 @@
"""BASALT VIO adapter component."""
+13
View File
@@ -0,0 +1,13 @@
"""Public BASALT VIO adapter interfaces."""
from typing import Any, Protocol
class VioAdapter(Protocol):
"""Processes frame and telemetry inputs into relative VIO state."""
def initialize(self) -> None:
"""Initialize adapter resources."""
def process(self, frame: Any, telemetry: Any) -> Any:
"""Process one synchronized frame/telemetry pair."""
+5
View File
@@ -0,0 +1,5 @@
"""Public BASALT VIO type aliases."""
from typing import Any
VioStatePacketLike = Any
@@ -0,0 +1 @@
"""Camera ingest and calibration component."""
@@ -0,0 +1,10 @@
"""Public camera ingest interfaces."""
from typing import Any, Protocol
class FrameProvider(Protocol):
"""Source of navigation frames for downstream localization components."""
def next_frame(self) -> Any:
"""Return the next frame packet."""
+5
View File
@@ -0,0 +1,5 @@
"""Public camera ingest type aliases."""
from typing import Any
FramePacketLike = Any
+1
View File
@@ -0,0 +1 @@
"""Flight data recorder and observability component."""
+13
View File
@@ -0,0 +1,13 @@
"""Public flight recorder interfaces."""
from typing import Any, Protocol
class FlightRecorder(Protocol):
"""Append-only event recorder for runtime evidence."""
def append_event(self, event: Any) -> None:
"""Persist one FDR event."""
def export(self) -> Any:
"""Export recorded evidence for post-flight analysis."""
+5
View File
@@ -0,0 +1,5 @@
"""Public FDR type aliases."""
from typing import Any
FdrEventLike = Any
+1
View File
@@ -0,0 +1 @@
"""MAVLink and GCS integration component."""
+13
View File
@@ -0,0 +1,13 @@
"""Public MAVLink gateway interfaces."""
from typing import Any, Protocol
class MavlinkGateway(Protocol):
"""Bridges FC telemetry inputs and localization GPS_INPUT outputs."""
def subscribe_telemetry(self) -> Any:
"""Subscribe to flight-controller telemetry."""
def emit_gps_input(self, estimate: Any) -> None:
"""Emit one localization estimate to the flight controller."""
+5
View File
@@ -0,0 +1,5 @@
"""Public MAVLink/GCS type aliases."""
from typing import Any
TelemetrySampleLike = Any
+3
View File
@@ -0,0 +1,3 @@
# BASALT Bridge
Reserved for native BASALT integration code wrapped by `basalt_vio_adapter`.
+3
View File
@@ -0,0 +1,3 @@
# Feature Matching Bridge
Reserved for native feature extraction, matching, and RANSAC acceleration code.
+3
View File
@@ -0,0 +1,3 @@
# TensorRT Bridge
Reserved for Jetson/TensorRT descriptor inference integrations.
+1
View File
@@ -0,0 +1 @@
"""Safety and anchor wrapper component."""
+13
View File
@@ -0,0 +1,13 @@
"""Public localization state-machine interfaces."""
from typing import Any, Protocol
class LocalizationStateMachine(Protocol):
"""Coordinates VIO propagation and anchor promotion decisions."""
def update_vio(self, vio_state: Any) -> Any:
"""Update the state machine with a VIO state packet."""
def consider_anchor(self, anchor_decision: Any) -> Any:
"""Evaluate a verified anchor decision."""
+5
View File
@@ -0,0 +1,5 @@
"""Public safety wrapper type aliases."""
from typing import Any
PositionEstimateLike = Any
+1
View File
@@ -0,0 +1 @@
"""Offline satellite retrieval and synchronization component."""
+13
View File
@@ -0,0 +1,13 @@
"""Public satellite service interfaces."""
from typing import Any, Protocol
class SatelliteService(Protocol):
"""Retrieves offline VPR candidates from mission cache data."""
def load_index(self) -> None:
"""Load the local descriptor index."""
def retrieve(self, frame: Any) -> list[Any]:
"""Return candidate anchor records for one frame."""
+5
View File
@@ -0,0 +1,5 @@
"""Public satellite service type aliases."""
from typing import Any
VprCandidateLike = Any
+1
View File
@@ -0,0 +1 @@
"""Shared runtime foundation packages."""
+1
View File
@@ -0,0 +1 @@
"""Runtime configuration helper namespace."""
+3
View File
@@ -0,0 +1,3 @@
"""Shared DTO and interface contract namespace."""
CONTRACT_VERSION = "0.1.0"
+1
View File
@@ -0,0 +1 @@
"""Shared error envelope namespace."""
+1
View File
@@ -0,0 +1 @@
"""Geospatial geometry helper namespace."""
+1
View File
@@ -0,0 +1 @@
"""Structured telemetry and health metadata namespace."""
+1
View File
@@ -0,0 +1 @@
"""Clock-domain and timestamp helper namespace."""
+1
View File
@@ -0,0 +1 @@
"""Tile cache and generated tile lifecycle component."""
+13
View File
@@ -0,0 +1,13 @@
"""Public tile manager interfaces."""
from typing import Any, Protocol
class TileManager(Protocol):
"""Validates and serves local cache tile records."""
def validate_cache(self) -> None:
"""Validate local cache metadata and signatures."""
def get_tile_window(self, footprint: Any) -> list[Any]:
"""Return tiles intersecting a requested footprint."""
+5
View File
@@ -0,0 +1,5 @@
"""Public tile manager type aliases."""
from typing import Any
CacheTileRecordLike = Any
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+18
View File
@@ -0,0 +1,18 @@
"""Black-box runner entry point.
Future scenarios should call only public runtime inputs and outputs: replay frames,
telemetry, offline cache, MAVLink output, status events, and FDR artifacts.
"""
from pathlib import Path
def main() -> int:
reports_dir = Path("data/test-results")
reports_dir.mkdir(parents=True, exist_ok=True)
(reports_dir / "blackbox_smoke.txt").write_text("blackbox scaffold ready\n", encoding="utf-8")
return 0
if __name__ == "__main__":
raise SystemExit(main())
+1
View File
@@ -0,0 +1 @@
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+1
View File
@@ -0,0 +1 @@
+126
View File
@@ -0,0 +1,126 @@
from importlib import import_module
from pathlib import Path
COMPONENT_PACKAGES = [
"camera_ingest_calibration",
"basalt_vio_adapter",
"safety_anchor_wrapper",
"satellite_service",
"anchor_verification",
"tile_manager",
"mavlink_gcs_integration",
"fdr_observability",
]
SHARED_PACKAGES = [
"shared.contracts",
"shared.geo_geometry",
"shared.time_sync",
"shared.config",
"shared.errors",
"shared.telemetry",
]
REQUIRED_PATHS = [
"src",
"migrations/postgresql/0001_enable_postgis.sql",
"migrations/seed/README.md",
"tests/unit/test_scaffold.py",
"tests/unit/shared/.gitkeep",
"tests/unit/camera_ingest_calibration/.gitkeep",
"tests/unit/basalt_vio_adapter/.gitkeep",
"tests/unit/safety_anchor_wrapper/.gitkeep",
"tests/unit/satellite_service/.gitkeep",
"tests/unit/anchor_verification/.gitkeep",
"tests/unit/tile_manager/.gitkeep",
"tests/unit/mavlink_gcs_integration/.gitkeep",
"tests/unit/fdr_observability/.gitkeep",
"tests/integration/contracts/.gitkeep",
"tests/blackbox/still_image_geolocation/.gitkeep",
"tests/fixtures/project_60_images/.gitkeep",
"tests/sitl/plane_gps_input/.gitkeep",
"tests/e2e/replay/.gitkeep",
"e2e/replay/run_replay.py",
"e2e/reports/.gitkeep",
"deployment/docker/Dockerfile.runtime",
"deployment/docker/Dockerfile.replay",
"deployment/scripts/collect_evidence.sh",
"config/development/runtime.env",
"config/ci/runtime.env",
"config/jetson/runtime.env",
"config/production/runtime.env.example",
"docker-compose.yml",
"docker-compose.test.yml",
".github/workflows/ci.yml",
".env.example",
".dockerignore",
]
def test_runtime_component_public_modules_are_importable() -> None:
# Act
imported_modules = [
import_module(module_name)
for package_name in COMPONENT_PACKAGES
for module_name in (package_name, f"{package_name}.interfaces", f"{package_name}.types")
]
# Assert
assert len(imported_modules) == len(COMPONENT_PACKAGES) * 3
def test_shared_contract_locations_are_importable() -> None:
# Act
imported_modules = [import_module(package_name) for package_name in SHARED_PACKAGES]
# Assert
assert len(imported_modules) == len(SHARED_PACKAGES)
def test_generated_runtime_data_paths_are_gitkeep_only() -> None:
# Arrange
data_dirs = ["input", "expected", "cache", "fdr", "test-results"]
# Act
missing = [
directory for directory in data_dirs if not Path("data", directory, ".gitkeep").is_file()
]
# Assert
assert missing == []
def test_scaffold_paths_cover_runtime_test_and_evidence_layout() -> None:
# Act
missing = [path for path in REQUIRED_PATHS if not Path(path).exists()]
# Assert
assert missing == []
def test_ignore_rules_exclude_runtime_payloads_and_secrets() -> None:
# Arrange
required_patterns = [
".env",
"*.pem",
"*.key",
"data/input/*",
"data/cache/*",
"data/fdr/*",
"data/test-results/*",
"*.tlog",
"*.cbor",
"*.mp4",
]
# Act
gitignore = Path(".gitignore").read_text(encoding="utf-8")
dockerignore = Path(".dockerignore").read_text(encoding="utf-8")
missing_from_gitignore = [pattern for pattern in required_patterns if pattern not in gitignore]
missing_from_dockerignore = [
pattern for pattern in required_patterns if pattern not in dockerignore
]
# Assert
assert missing_from_gitignore == []
assert missing_from_dockerignore == []
+1
View File
@@ -0,0 +1 @@