# Initial Project Structure

**Task**: 01_initial_structure
**Name**: Initial Structure
**Description**: Scaffold the project skeleton — folders, shared models, interfaces, stubs, Docker, CI/CD, test structure
**Complexity**: 5 points
**Dependencies**: None
**Component**: Bootstrap
**Jira**: TBD
**Epic**: Bootstrap & Initial Structure

## Project Folder Layout

```
detections-semantic/
├── src/
│   ├── __init__.py
│   ├── main.py
│   ├── config/
│   │   ├── __init__.py
│   │   ├── loader.py
│   │   └── schema.py
│   ├── types/
│   │   ├── __init__.py
│   │   ├── detection.py
│   │   ├── frame.py
│   │   ├── gimbal.py
│   │   ├── poi.py
│   │   ├── scenario.py
│   │   ├── spatial.py
│   │   └── vlm.py
│   ├── scan_controller/
│   │   ├── __init__.py
│   │   ├── tree.py
│   │   ├── behaviors/
│   │   │   └── __init__.py
│   │   └── subtrees/
│   │       └── __init__.py
│   ├── tier1_detector/
│   │   ├── __init__.py
│   │   └── detector.py
│   ├── tier2_spatial_analyzer/
│   │   ├── __init__.py
│   │   ├── mask_tracer.py
│   │   ├── cluster_tracer.py
│   │   └── roi_classifier.py
│   ├── vlm_client/
│   │   ├── __init__.py
│   │   └── client.py
│   ├── gimbal_driver/
│   │   ├── __init__.py
│   │   ├── driver.py
│   │   ├── protocol.py
│   │   └── pid.py
│   └── output_manager/
│       ├── __init__.py
│       └── manager.py
├── tests/
│   ├── unit/
│   │   ├── test_config.py
│   │   ├── test_types.py
│   │   ├── test_tier1.py
│   │   ├── test_tier2.py
│   │   ├── test_vlm.py
│   │   ├── test_gimbal.py
│   │   ├── test_output.py
│   │   └── test_scan_controller.py
│   ├── integration/
│   │   ├── conftest.py
│   │   └── test_data/
│   └── conftest.py
├── config/
│   ├── config.dev.yaml
│   ├── config.prod.yaml
│   └── config.test.yaml
├── docker/
│   ├── Dockerfile
│   ├── Dockerfile.dev
│   ├── mock-gimbal/
│   │   └── Dockerfile
│   └── .dockerignore
├── docker-compose.yml
├── docker-compose.test.yml
├── pyproject.toml
├── .env.example
├── .gitignore
└── azure-pipelines.yml
```

### Layout Rationale

Python package structure following standard conventions. Components as subpackages under `src/`. Config and types are helpers used by all components. Tests mirror the source layout. Docker files separated into `docker/` directory. Two compose files: one for dev (all services + mock gimbal), one for integration testing (black-box runner).

## DTOs and Interfaces

### Shared DTOs

| DTO Name | Used By Components | Fields Summary |
|----------|-------------------|---------------|
| FrameContext | All | frame_id, timestamp, image, scan_level, quality_score, pan, tilt, zoom |
| Detection | Tier1→ScanController | centerX, centerY, width, height, classNum, label, confidence, mask |
| SemanticDetection | OutputManager | extends Detection with tier, freshness, tier2/3 results |
| POI | ScanController | poi_id, frame_id, trigger_class, scenario_name, investigation_type, confidence, bbox, priority, status |
| GimbalState | GimbalDriver→ScanController | pan, tilt, zoom, target_pan/tilt/zoom, last_heartbeat |
| CapabilityFlags | ScanController | vlm_available, gimbal_available, semantic_available |
| SpatialAnalysisResult | Tier2→ScanController | pattern_type, waypoints, trajectory, overall_direction, skeleton, cluster_bbox |
| Waypoint | Tier2→ScanController | x, y, dx, dy, label, confidence, freshness_tag, roi_thumbnail |
| VLMResponse | VLMClient→ScanController | text, confidence, latency_ms |
| SearchScenario | Config→ScanController | name, enabled, trigger/investigation params |

### Component Interfaces

| Component | Interface | Methods | Exposed To |
|-----------|-----------|---------|-----------|
| Tier1Detector | Tier1Detector | load, detect, is_ready | ScanController |
| Tier2SpatialAnalyzer | Tier2SpatialAnalyzer | trace_mask, trace_cluster, analyze_roi | ScanController |
| VLMClient | VLMClient | connect, disconnect, is_available, analyze, load_model, unload_model | ScanController |
| GimbalDriver | GimbalDriver | connect, disconnect, is_alive, set_angles, get_state, set_sweep_target, zoom_to_poi, follow_path, return_to_sweep | ScanController |
| OutputManager | OutputManager | init, log_detection, record_frame, log_health, log_gimbal_command, report_to_operator, get_storage_status | ScanController |

## CI/CD Pipeline

| Stage | Purpose | Trigger |
|-------|---------|---------|
| Lint | ruff + mypy | Every push |
| Unit Tests | pytest tests/unit/ | Every push |
| Integration Tests | docker compose test | PR to dev |
| Security Scan | pip-audit + bandit | Every push |
| Build Docker | Build production image | Merge to dev |

### Pipeline Configuration Notes

Azure Pipelines (azure-pipelines.yml). Python 3.11 base. pip cache for dependencies. Unit tests run natively (no Docker needed). Integration tests spin up docker-compose.test.yml. Security scan includes pip-audit for known CVEs and bandit for SAST.

## Environment Strategy

| Environment | Purpose | Configuration Notes |
|-------------|---------|-------------------|
| Development | Local development on x86 workstation | ONNX Runtime fallback, mock gimbal TCP, console logging, local NVMe path |
| Production | Jetson Orin Nano Super on UAV | TensorRT FP16, real UART gimbal, JSON-lines to NVMe, tegrastats health |

### Environment Variables

| Variable | Dev | Production | Description |
|----------|-----|------------|-------------|
| CONFIG_PATH | config/config.dev.yaml | config/config.prod.yaml | Config file path |
| LOG_LEVEL | DEBUG | INFO | Logging verbosity |
| GIMBAL_MODE | mock_tcp | real_uart | Gimbal connection mode |
| VLM_SOCKET | /tmp/vlm.sock | /tmp/vlm.sock | VLM IPC socket path |
| OUTPUT_DIR | ./output | /data/output | NVMe output directory |

## Database Migration Approach

Not applicable — no database. Data model uses runtime structs (in-memory) and append-only flat files (NVMe). Config changes handled by YAML `version` field with backward-compatible defaults.

## Test Structure

```
tests/
├── unit/
│   ├── test_config.py          → Config loader + validation
│   ├── test_types.py           → Dataclass creation and field types
│   ├── test_tier1.py           → Detection output format, error handling
│   ├── test_tier2.py           → Mask tracing, cluster tracing, ROI classify
│   ├── test_vlm.py             → IPC protocol, timeout, availability
│   ├── test_gimbal.py          → Command format, PID, retry logic
│   ├── test_output.py          → Log format, storage status, write errors
│   └── test_scan_controller.py → POI queue, BT behavior, scenario matching
├── integration/
│   ├── conftest.py             → Docker compose fixtures
│   ├── test_data/              → Test images, masks, configs
│   ├── test_pipeline.py        → End-to-end L1→L2→L1 cycle
│   └── test_degradation.py     → Health degradation scenarios
└── conftest.py                 → Shared fixtures, mock factories
```

### Test Configuration Notes

pytest with pytest-timeout for latency tests. Mock factories for all component interfaces (returns fixture data). Integration tests use docker-compose.test.yml with mock gimbal and mock VLM services. Test data stored in tests/integration/test_data/ (not committed to git if > 10MB — download script instead).

## Implementation Order

| Order | Component | Reason |
|-------|-----------|--------|
| 1 | Config helper | All components depend on config |
| 2 | Types helper | All components depend on shared types |
| 3 | Tier1Detector | Core inference, blocks ScanController |
| 3 | Tier2SpatialAnalyzer | Parallel with Tier1 |
| 3 | VLMClient | Parallel with Tier1 |
| 3 | GimbalDriver | Parallel with Tier1 |
| 3 | OutputManager | Parallel with Tier1 |
| 4 | ScanController | Integrates all components (last) |
| 5 | Integration Tests | Validates complete system |

## Acceptance Criteria

**AC-1: Project scaffolded**
Given the structure plan above
When the implementer executes this task
Then all folders, stubs, and configuration files exist

**AC-2: Tests runnable**
Given the scaffolded project
When `pytest tests/unit/` is executed
Then all stub tests pass

**AC-3: Docker dev environment boots**
Given docker-compose.yml
When `docker compose up -d` is executed
Then all services start and health endpoint returns 200

**AC-4: CI pipeline configured**
Given azure-pipelines.yml
When pipeline is triggered
Then lint, test, and build stages complete successfully
