Purpose: This guide covers local development setup, workflows, testing, and code style guidelines for contributing to Wingfix.
Last Updated: March 2026
For experienced developers who want to get started immediately:
# 1. Clone and setup backend
git clone https://github.com/wingfix/wingfix.git && cd wingfix
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
# 2. Setup frontend (includes rehype-raw for HTML-in-Markdown rendering)
cd frontend && npm install && cd ..
# 3. Drop your manuals and start everything
cp /path/to/your-manual.pdf data/incoming/
./wingfix-start
# 4. Web UI opens at http://localhost:5173 (dev) or http://localhost (production)
# Use the chat interface with streaming responses and visual citations
# Or run ./wingfix-start --cli for terminal-based interaction
# Type 'exit' or Ctrl+C to stop all services- Prerequisites
- Local Development Setup
- Quick Start with wingfix-start
- Docker Compose Infrastructure
- Running the Application
- Running Tests
- UI & CLI Testing
- Database Migrations
- Code Style Guidelines
- Development Workflow
- Common Tasks
- Troubleshooting
| Software | Version | Purpose |
|---|---|---|
| Python | 3.11+ | Primary development language |
| Node.js | 20+ | Frontend development (React PWA) |
| npm or pnpm | 10+ / 9+ | Package management for frontend |
| Docker | 24.0+ | Container runtime for infrastructure services |
| Docker Compose | 2.20+ | Multi-container orchestration |
| Git | 2.40+ | Version control |
| ffmpeg | 6.0+ | Audio format conversion (STT pipeline) |
| Software | Version | Purpose |
|---|---|---|
| NVIDIA Driver | 535+ | GPU support |
| CUDA | 12.1+ | GPU acceleration |
| NVIDIA Container Toolkit | Latest | Docker GPU support |
Minimum (CPU-only development):
- 16GB RAM
- 50GB disk space
- 4 CPU cores
Recommended (full system with GPU):
- 192GB RAM (for in-memory knowledge graph)
- Dual NVIDIA RTX A6000 (96GB VRAM total)
- Intel i9-14900K or equivalent
- NVMe SSD
git clone https://github.com/wingfix/wingfix.git
cd wingfix# Create virtual environment
python -m venv .venv
# Activate (Linux/macOS)
source .venv/bin/activate
# Activate (Windows)
.venv\Scripts\activate# Development installation (recommended)
pip install -e ".[dev]"
# Or use pinned versions for reproducibility
pip install -r requirements-dev.txt
# IMPORTANT: optimum[onnxruntime] is required for ONNX embedding backend
# Without it, embedding server silently falls back to PyTorch (130-226s load vs ~35s)
pip install 'optimum[onnxruntime]'# Copy example environment file
cp .env.example .env
# Edit with your local settings
nano .env # or your preferred editorKey environment variables:
# Application
WINGFIX_ENVIRONMENT=development
WINGFIX_DEBUG=true
# Database connections (defaults work with Docker Compose)
WINGFIX_DATABASE__POSTGRES_HOST=localhost
WINGFIX_DATABASE__POSTGRES_PORT=5432
WINGFIX_DATABASE__POSTGRES_PASSWORD=wingfix_dev_password
# Qdrant vector database
WINGFIX_DATABASE__QDRANT_HOST=localhost
WINGFIX_DATABASE__QDRANT_HTTP_PORT=6333
# MinIO object storage
WINGFIX_DATABASE__MINIO_HOST=localhost
WINGFIX_DATABASE__MINIO_PORT=9000
WINGFIX_DATABASE__MINIO_SECRET_KEY=wingfix_dev_password
# Redis cache
WINGFIX_DATABASE__REDIS_HOST=localhost
WINGFIX_DATABASE__REDIS_PORT=6379
# LLM configuration (optional for development)
WINGFIX_MODEL__LLM_BASE_URL=http://localhost:11435/v1# Install pre-commit hooks
pre-commit install
# Run on all files (first-time setup)
pre-commit run --all-filescd frontend
npm install # Includes rehype-raw for HTML-in-Markdown rendering
cd ..# Creates data/, logs/, and cache directories
python -c "from wingfix.config import ensure_directories; ensure_directories()"The startup configuration validator runs automatically during ./wingfix-start, but you can run it manually:
# Validate before launching
python -m wingfix.cli.config_validatorThis checks:
.envfile existence (warns if missing, uses defaults)- Required environment variables
- Port availability (5432, 6333, 9000, 6379)
- Data directory write permissions
- Docker daemon availability
- Ollama installation (warns if missing)
The easiest way to run Wingfix is using the unified start script that handles all setup automatically.
# Start everything with a single command (React dev server is default)
./wingfix-startThis script will:
- Validate configuration (
ConfigValidator— checks env, ports, directories) - Activate the virtual environment (detects
.venvor conda) - Start Docker infrastructure (PostgreSQL, Qdrant, MinIO, Redis)
- Run database migrations (
MigrationRunner— Alembic upgrade head) - Initialize Qdrant collections (
QdrantInitializer— idempotent) - Start Ollama LLM server (with Gemma 4 31B Instruct)
- Start WingFix API on port 8082
- Start React dev server on port 5173 (Vite HMR)
- Ingest documents from
data/incoming/ - Open browser to
http://localhost:5173
./wingfix-start # Full startup + React dev server (default)
./wingfix-start --cli # Use interactive CLI instead of Web UI
./wingfix-start --no-ingest # Skip document ingestion
./wingfix-start --no-browser # Don't auto-open browser
./wingfix-start --skip-migrations # Skip Alembic migrations (for dev)
./wingfix-start --help # Show all optionsOnce the React PWA is running at http://localhost:5173 (dev mode):
| Feature | Description |
|---|---|
| Chat Interface | Type questions in the chat input at the bottom |
| Streaming Responses | Watch answers appear token-by-token |
| Citation Viewer | Click [1], [2] links to see PDF source in split-screen |
| Session History | Left sidebar shows previous chats (click to restore) |
| File Upload | Drag PDFs into the chat area for ingestion |
| Theme Toggle | Switch between light/dark/system mode in header |
| Settings Panel | Gear icon or Ctrl+, — configure effectivity, voice, shortcuts |
| Effectivity Context | Set tail number, date, station, fleet (persisted across sessions) |
| Stock Panel | Inline inventory availability for part numbers in responses |
| Safety Blocks | Color-coded WARNING / CAUTION / NOTE indicators in responses |
| Voice Mode | Push-to-Talk microphone input + auto read-aloud TTS responses |
| Print View | Print button to produce clean work-card output |
| PWA Install | Install-to-home-screen prompt (tablets / desktops) |
| Offline Mode | Banner when offline; cached manuals remain accessible |
| Keyboard Shortcuts | Ctrl+N, Ctrl+/, Ctrl+K, Escape, Ctrl+M, Ctrl+. |
| Shortcut | Action |
|---|---|
Ctrl+N |
New chat session |
Ctrl+/ |
Focus chat input |
Ctrl+K |
Focus session search in sidebar |
Ctrl+, |
Open settings panel |
Ctrl+M |
Toggle voice mode on/off |
Ctrl+. |
Stop current TTS playback |
Escape |
Close PDF viewer panel |
When using ./wingfix-start --cli, you get a terminal interface:
[wingfix]> What is the torque value for IDG mounting bolts?
# (Streaming response with citations)
[wingfix]> status # Check service health
[wingfix]> ingest file.pdf # Manually ingest a document
[wingfix]> help # Show available commands
[wingfix]> exit # Graceful shutdown
./wingfix-stop # Graceful stop (preserve data)
./wingfix-stop --force # Force kill all processes
./wingfix-stop --clean # Stop and remove all data (DANGER!)
./wingfix-stop --api-only # Stop only API (keep infra running)Wingfix uses Docker Compose to manage infrastructure services locally.
| Service | Port | Purpose |
|---|---|---|
| PostgreSQL 16 | 5432 | Metadata store (documents, parts, policies, sessions) |
| Qdrant | 6333 (HTTP), 6334 (gRPC) | Vector database for embeddings |
| MinIO | 9000 (API), 9001 (Console) | S3-compatible object storage |
| Redis | 6379 | Caching and job queue |
# Start all services (recommended method)
./scripts/start-infra.sh
# Or use Docker Compose directly
docker compose up -d
# Start with log following
./scripts/start-infra.sh --logs
# Rebuild containers before starting
./scripts/start-infra.sh --build# Run health check script
./scripts/docker-health-check.sh
# Or check status manually
docker compose psExpected output:
==========================================
Wingfix Docker Infrastructure Health Check
==========================================
Checking services...
-------------------------------------------
PostgreSQL: ✓ Healthy
Qdrant: ✓ Healthy
MinIO: ✓ Healthy
Redis: ✓ Healthy
-------------------------------------------
All services are healthy!
# All services
docker compose logs -f
# Specific service
docker compose logs -f postgres
docker compose logs -f qdrant
docker compose logs -f minio
docker compose logs -f redis# Stop services (preserve data)
./scripts/stop-infra.sh
# Stop and remove volumes (DATA LOSS!)
./scripts/stop-infra.sh --clean
# Or use Docker Compose directly
docker compose down # Preserve data
docker compose down -v # Remove volumes- MinIO Console: http://localhost:9001 (user:
wingfix, pass:wingfix_dev_password) - Qdrant Dashboard: http://localhost:6333/dashboard
The recommended way to run Wingfix is using the unified start script:
./wingfix-startThis handles all service orchestration and provides an interactive CLI.
If you need to run components individually:
# Development mode with auto-reload
uvicorn wingfix.api.main:app --reload --port 8082
# Or using the entry point
wingfix
# Production mode
uvicorn wingfix.api.main:app --host 0.0.0.0 --port 8082 --workers 4API will be available at:
- API: http://localhost:8082
- OpenAPI Docs: http://localhost:8082/docs
- Health Check: http://localhost:8082/health
- Embedding Health: http://localhost:8082/api/v1/embed/health
To run only the React frontend (requires API to be running):
# Development mode with hot reload (Vite HMR)
cd frontend
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview
# Type-check without building
npm run type-check
# Lint
npm run lintFrontend will be available at:
- Dev server: http://localhost:5173
- Requires: API running on http://localhost:8082
React Development Tips:
- Changes to
frontend/src/auto-reload via Vite HMR - Use React DevTools browser extension for component inspection
- Use TanStack Query DevTools for API cache debugging
- Test SSE consumption with browser dev tools Network tab
- Theme changes apply immediately via Tailwind
dark:classes - Effectivity context persists to
localStorage— reset via Settings panel
# Print configuration summary
python -c "from wingfix.config import print_config_summary; print_config_summary()"# Check collection status
python -m wingfix.cli.qdrant_init status
# Initialize collections (idempotent — safe to run multiple times)
python -m wingfix.cli.qdrant_init init
# Check only (verify, no changes)
python -m wingfix.cli.qdrant_init init --check-only
# Recreate collections (DANGER — deletes all vectors!)
python -m wingfix.cli.qdrant_init init --recreateIf not using ./wingfix-start, start the Ollama server manually:
# Using the provided script (requires GPU)
./scripts/start_ollama.sh
# Check status
./scripts/start_ollama.sh status
# Stop Ollama
./scripts/start_ollama.sh stopNote:
./wingfix-startautomatically manages Ollama startup and shutdown.
src/tests/
├── conftest.py # Shared fixtures
├── test_*.py # Unit tests (~80+ test files)
│ ├── test_auth_middleware.py # JWT auth tests
│ ├── test_rbac.py # Role-based access control tests
│ ├── test_rate_limiter_redis.py # Redis-backed rate limiting tests
│ ├── test_connection_limits.py # SSE connection limiter tests
│ ├── test_security_headers.py # Security headers middleware tests
│ ├── test_prompt_injection_guardrail.py # Prompt injection detection tests
│ ├── test_subprocess_hardening.py # Subprocess safe execution tests
│ ├── test_temp_manager.py # Temp file management tests
│ ├── test_pdf_hardening.py # PDF validator (zip-bomb, malformed) tests
│ ├── test_image_sanitization.py # Image validator tests
│ ├── test_xxe_prevention.py # XML XXE prevention tests
│ ├── test_graph_cache_security.py # HMAC graph cache integrity tests
│ ├── test_keyboard_accessibility.py # Keyboard shortcut and ARIA accessibility tests
│ ├── test_production_config.py # Production config safety tests
│ └── ... (domain tests: parsers, retrievers, workflow, API endpoints, etc.)
├── integration/ # Integration tests
│ ├── conftest.py
│ ├── test_agent_workflow.py
│ ├── test_health_checks.py
│ ├── test_ingestion_pipeline.py
│ ├── test_knowledge_link.py
│ ├── test_retrieval_pipeline.py
│ └── test_startup_shutdown.py
├── e2e/ # Playwright browser end-to-end tests
│ ├── conftest.py
│ ├── test_chat_e2e.py
│ ├── test_citations_e2e.py
│ ├── test_upload_e2e.py
│ ├── test_voice_e2e.py # Voice / audio E2E (Task 14.x)
│ ├── test_voice_ui_e2e.py # Voice UI component tests
│ ├── test_theme_e2e.py
│ ├── test_responsive_e2e.py
│ └── visual/ # Visual regression baselines
│ └── test_visual_regression.py
├── cli/ # Pexpect interactive CLI tests
│ ├── conftest.py
│ ├── test_cli_interactive.py
│ └── test_cli_ingest.py
├── eval/ # Evaluation tests
│ ├── eval_dataset.json
│ ├── synthetic_eval_dataset.json
│ ├── run_eval.py
│ ├── test_eval.py
│ ├── models.py
│ └── synthetic_generator.py
└── benchmarks/ # Performance benchmarks
├── bench_embedding.py
├── bench_ingestion.py
└── bench_retrieval.py
# Run all tests
pytest
# Run with coverage
pytest --cov=wingfix --cov-report=html
# Run specific test file
pytest src/tests/test_pn_extractor.py
# Run specific test function
pytest src/tests/test_pn_extractor.py::test_boeing_pn_format
# Run tests with verbose output
pytest -v
# Run tests matching a pattern
pytest -k "pn_extract"# Run all security-related tests
pytest -k "security or injection or rbac or rate_limiter or hardening"
# Prompt injection guardrail tests
pytest src/tests/test_prompt_injection_guardrail.py -v
# JWT auth and RBAC tests
pytest src/tests/test_auth_middleware.py src/tests/test_rbac.py -v
# Redis-backed rate limiter tests
pytest src/tests/test_rate_limiter_redis.py -v
# SSE connection limiter tests
pytest src/tests/test_connection_limits.py -v
# Security headers tests
pytest src/tests/test_security_headers.py -v
# Subprocess hardening tests
pytest src/tests/test_subprocess_hardening.py -v
# Temp file management tests
pytest src/tests/test_temp_manager.py -v
# PDF/image validation tests
pytest src/tests/test_pdf_hardening.py src/tests/test_image_sanitization.py -v
# XML XXE prevention tests
pytest src/tests/test_xxe_prevention.py -v
# Graph cache integrity tests
pytest src/tests/test_graph_cache_security.py -v
# Keyboard accessibility tests
pytest src/tests/test_keyboard_accessibility.py -v
# Production config safety tests
pytest src/tests/test_production_config.py -v# Skip slow tests
pytest -m "not slow"
# Skip integration tests
pytest -m "not integration"
# Run only integration tests
pytest -m integration
# Run only GPU-required tests
pytest -m gpu
# Run benchmarks
pytest -m benchmark# Generate HTML coverage report
pytest --cov=wingfix --cov-report=html
# View report
xdg-open htmlcov/index.html # LinuxIntegration tests require Docker services to be running:
# Start infrastructure first
./scripts/start-infra.sh
# Run integration tests
pytest -m integration
# Run with specific database
WINGFIX_DATABASE__POSTGRES_DB=wingfix_test pytest -m integrationWingfix uses Playwright for browser E2E tests and Pexpect for interactive CLI tests. It also uses Vitest for React unit tests. These tests validate the visual and interactive components of the application.
# Install E2E testing dependencies
pip install -e ".[e2e]"
# Or manually install
pip install pytest-playwright pexpect
# Install Playwright browsers (one-time setup)
playwright install chromium
# Optionally install all browsers
playwright install # chromium, firefox, webkit
# Install frontend test dependencies (already included in package.json devDependencies)
cd frontend
npm installE2E tests require the full Wingfix stack to be running:
# Start Wingfix services (in background)
./wingfix-start --no-browser &
# Wait for services to be healthy
./scripts/wait_for_services.sh 180
# Run all E2E tests
pytest -m e2e tests/e2e/
# Run specific E2E test file
pytest tests/e2e/test_chat_e2e.py -v
# Run voice/audio E2E tests
pytest tests/e2e/test_voice_e2e.py -v
pytest tests/e2e/test_voice_ui_e2e.py -v
# Run with visible browser (headed mode for debugging)
pytest -m e2e --headed
# Run with slow motion for visual debugging
pytest -m e2e --headed --slowmo=500
# Run only visual regression tests
pytest tests/e2e/test_theme_e2e.py tests/e2e/test_responsive_e2e.py
# Generate test code interactively (opens browser)
playwright codegen http://localhost:5173E2E tests run in headless mode by default, which is suitable for CI/CD pipelines:
# CI-friendly command (no display required)
pytest -m e2e --browser chromium
# Run with Xvfb on Linux CI without display
xvfb-run pytest -m e2e
# Generate JUnit XML report for CI
pytest -m e2e --junitxml=test-results/e2e.xmlGitHub Actions Example:
- name: Install Playwright Browsers
run: playwright install chromium --with-deps
- name: Start Wingfix Services
run: |
./wingfix-start --no-browser --no-cli &
./scripts/wait_for_services.sh 180
- name: Run E2E Tests
run: pytest -m e2e --browser chromium
- name: Stop Services
if: always()
run: ./wingfix-stop --forceCLI tests spawn interactive terminal sessions and require TTY support:
# Run all CLI tests
pytest tests/cli/ -v
# Run specific CLI test
pytest tests/cli/test_cli_interactive.py::test_cli_query_with_streaming_response
# Run with extended timeout (for slow systems)
pytest tests/cli/ -v --timeout=180
# Skip CLI tests (useful in environments without TTY)
pytest -m "not cli"Note: CLI tests require a proper TTY and may not work in all CI environments. Use pytest -m "not cli" to skip them when necessary.
Playwright supports visual comparison testing for catching unintended UI changes:
# Generate baseline screenshots (first run or after intentional changes)
pytest tests/e2e/test_theme_e2e.py --update-snapshots
# Run visual regression tests (compares against baselines)
pytest tests/e2e/test_theme_e2e.py
# View visual diff report (if tests fail)
open test-results/visual-diff.htmlBaseline screenshots are stored in tests/e2e/visual/ and should be committed to version control.
# Run only E2E tests
pytest -m e2e
# Run only CLI tests
pytest -m cli
# Run everything except E2E (faster feedback)
pytest -m "not e2e"
# Run everything except CLI (for CI without TTY)
pytest -m "not cli"
# Run unit and integration tests only (skip all UI tests)
pytest -m "not e2e and not cli"Playwright Debugging:
# Enable Playwright debug mode (opens inspector)
PWDEBUG=1 pytest tests/e2e/test_chat_e2e.py -v -k test_chat_query
# Save screenshots on failure
pytest -m e2e --screenshot=on --output=test-results/
# Save video recordings of test runs
pytest -m e2e --video=retain-on-failure --output=test-results/
# Generate trace files for detailed debugging
pytest -m e2e --tracing=retain-on-failure
playwright show-trace test-results/trace.zipPexpect Debugging:
# In test code, enable logging to see CLI output
child.logfile = sys.stdout
# Increase timeout for debugging
child.timeout = 300Wingfix frontend uses Vitest (integrated into Vite) for React component unit tests:
# Run React unit tests
cd frontend
npm run test # Run once
npm run test -- --watch # Watch mode (alias: npm run test:watch)
npm run test -- --coverage # With coverage
# Run a specific test file
npm run test -- src/__tests__/AudioPlayer.test.tsx
npm run test -- src/__tests__/VoiceInput.test.tsxWhen adding new E2E tests, follow these patterns:
# tests/e2e/test_example_e2e.py
import pytest
from playwright.sync_api import Page, expect
@pytest.mark.e2e
def test_feature_works(wingfix_page: Page):
"""Test description explaining what's being validated."""
page = wingfix_page
# Arrange: Set up test state
# ...
# Act: Perform user actions
page.locator('[data-testid="chat-input"]').fill("What is the torque value?")
page.locator('[data-testid="send-button"]').click()
# Assert: Verify expected outcome
expect(page.locator('[data-testid="assistant-message"]')).to_be_visible()Best Practices:
- Use
data-testidattributes for reliable selectors (e.g.,data-testid="chat-input",data-testid="assistant-message") - Use Playwright's
expect()assertions for auto-waiting - Add
@pytest.mark.e2emarker to all E2E tests - Keep tests independent (no shared state between tests)
- Use fixtures for common setup/teardown
Wingfix uses Alembic for database migrations. The MigrationRunner class handles migrations programmatically during startup.
alembic current
# Or via MigrationRunner
python -m wingfix.cli.migration_runner statusalembic upgrade head
# Or via MigrationRunner (captures output, handles errors gracefully)
python -m wingfix.cli.migration_runner upgradealembic downgrade -1alembic downgrade 001_initial# Auto-generate from model changes
alembic revision --autogenerate -m "Add new column to parts table"
# Create empty migration
alembic revision -m "Custom migration description"alembic history- Always review auto-generated migrations before applying
- Test migrations on a copy of production data
- Include both upgrade and downgrade functions
- Use descriptive revision messages
- The startup
MigrationRunneruses--skipmode by default during development — pass./wingfix-startwithout--skip-migrationsfor a clean run
Wingfix uses Black for code formatting with a line length of 100 characters.
# Format all files
black src/
# Check formatting without changing
black --check src/
# Format specific file
black src/wingfix/config.pyWingfix uses Ruff for linting (replaces flake8, isort, pyupgrade).
# Run linter
ruff check src/
# Auto-fix issues
ruff check --fix src/
# Check specific file
ruff check src/wingfix/config.pyWingfix uses mypy for static type checking.
# Type check entire codebase
mypy src/wingfix/
# Type check specific module
mypy src/wingfix/retrieval/# Via pre-commit (recommended)
pre-commit run --all-files
# Manually
black src/
ruff check --fix src/
mypy src/wingfix/| Aspect | Standard |
|---|---|
| Line length | 100 characters |
| Quotes | Double quotes (") |
| Imports | Sorted by isort (via Ruff) |
| Type hints | Required for all public functions |
| Docstrings | Google style |
| Naming | snake_case for functions/variables, PascalCase for classes |
"""Module docstring describing purpose.
Extended description if needed.
"""
from __future__ import annotations
from typing import TYPE_CHECKING
from wingfix.config import get_settings
if TYPE_CHECKING:
from wingfix.models.llm_client import LLMClient
class PartExtractor:
"""Extract part numbers from aviation documents.
This class handles extraction of Boeing, NAS, AN, and MS part numbers
using both regex patterns and ML-based tagging.
Attributes:
confidence_threshold: Minimum confidence for extraction (0-1).
patterns: Compiled regex patterns for PN formats.
"""
def __init__(self, confidence_threshold: float = 0.8) -> None:
"""Initialize the part extractor.
Args:
confidence_threshold: Minimum confidence score to accept
an extracted part number. Defaults to 0.8.
"""
self.confidence_threshold = confidence_threshold
self._compile_patterns()
def extract(self, text: str) -> list[str]:
"""Extract part numbers from text.
Args:
text: Input text to scan for part numbers.
Returns:
List of extracted part numbers (normalized format).
Raises:
ValueError: If text is empty or None.
"""
if not text:
raise ValueError("Text cannot be empty")
results = []
# Implementation...
return resultsfeature/add-mel-parser
bugfix/fix-pn-extraction
refactor/optimize-retrieval
docs/update-api-docs
Follow Conventional Commits:
feat: add MEL deferral parser
fix: correct PN normalization for NAS format
docs: update API endpoint documentation
refactor: optimize vector search query
test: add integration tests for Knowledge Link
chore: update dependencies
- Create feature branch from
main - Make changes with tests
- Ensure all checks pass:
pre-commit run --all-files - Run test suite:
pytest - Run frontend tests:
cd frontend && npm run test - Push and create PR
- Address review feedback
- Squash and merge
- Create parser in
src/wingfix/ingestion/parsers/ - Add Pydantic models in
*_models.py - Register in
src/wingfix/ingestion/parsers/__init__.py - Add unit tests in
src/tests/test_*_parser.py - Update document type enum if needed
- Create route in
src/wingfix/api/routes/ - Add Pydantic request/response models
- Register router in
src/wingfix/api/main.py - Add tests in
src/tests/test_api.py - OpenAPI docs generate automatically at http://localhost:8082/docs
- Create node in
src/wingfix/agents/nodes/ - Define state updates and routing logic
- Register in
src/wingfix/agents/workflow.py - Add conditional edges for routing
- Update workflow diagram in docs
- Create component in
frontend/src/components/ - Add
data-testidattributes for E2E test selectors - Use existing contexts via hooks:
useTheme,useAuth,useEffectivity,useSession,useVoiceMode - Follow the existing pattern using Tailwind CSS +
dark:variants - Export from component file; import directly (Vite path aliases:
@/maps tosrc/) - Add Vitest unit tests in
frontend/src/__tests__/
- Create middleware in
src/wingfix/api/middleware/ - Follow the existing pattern (auth.py, rbac.py, rate_limiter.py)
- Register in
src/wingfix/api/main.pylifespan or middleware stack - Add tests in
src/tests/test_<middleware_name>.py - Update
configs/default.yamlif the middleware needs configuration - Document in the Architecture doc's Security Layer section
# Clear embedding cache
python -c "from wingfix.storage.object_store import ObjectStore; ObjectStore().clear_bucket('embeddings-cache')"
# Re-run indexing
python -m wingfix.indexing.text_embedder --reindexThe audio pipeline requires ffmpeg installed on the host. Test it manually:
# Check STT endpoint (requires Whisper model loaded)
curl -X POST http://localhost:8082/api/v1/audio/transcribe \
-F "audio=@data/test/test-audio.wav" | jq
# Check TTS endpoint (requires Kokoro ONNX models in data/models/kokoro-v1.0/)
curl -X POST http://localhost:8082/api/v1/audio/synthesize \
-H "Content-Type: application/json" \
-d '{"text": "Check oil filter torque value before installation.", "voice": "am_michael"}' \
--output output.wav
# Check audio service health
curl http://localhost:8082/health | jq '.services.audio'Available TTS voices: am_michael, af_sarah, bf_emma, bm_george
TTS speed range: 0.5x – 2.0x
# List all sessions
curl http://localhost:8082/api/v1/sessions | jq
# Get specific session with messages
curl http://localhost:8082/api/v1/sessions/{session_id} | jq
# Search sessions
curl "http://localhost:8082/api/v1/sessions/search?q=IDG+filter" | jq
# Delete session
curl -X DELETE http://localhost:8082/api/v1/sessions/{session_id}Services won't start:
# Check for port conflicts
lsof -i :5432 # PostgreSQL
lsof -i :6333 # Qdrant
lsof -i :9000 # MinIO
lsof -i :6379 # Redis
# Reset Docker environment
docker compose down -v
docker system prune -f
./scripts/start-infra.shConnection refused errors:
# Verify services are healthy
./scripts/docker-health-check.sh
# Check container logs
docker compose logs postgresMigration errors:
# Reset database (development only!)
docker compose down -v
./scripts/start-infra.sh
alembic upgrade headConnection pool exhausted:
# Increase pool size in config
WINGFIX_DATABASE__POSTGRES_POOL_SIZE=10
WINGFIX_DATABASE__POSTGRES_MAX_OVERFLOW=20Module not found:
# Ensure package is installed in editable mode
pip install -e ".[dev]"
# Check Python path
python -c "import wingfix; print(wingfix.__file__)"CUDA out of memory:
# Clear GPU memory
nvidia-smi --gpu-reset
# Check GPU utilization
nvidia-smi -l 1
# Reduce batch sizes in config
WINGFIX_MODEL__EMBEDDING_BATCH_SIZE=8ffmpeg not found:
# Install on Ubuntu/Debian
sudo apt install ffmpeg
# Verify
ffmpeg -versionSTT returns empty transcript:
# Check Whisper model is loaded
curl http://localhost:8082/health | jq '.services.audio.stt'
# Check audio format (must be WebM, WAV, MP3, OGG, FLAC, or M4A)
# Max file size: 25 MBTTS produces no audio:
# Verify Kokoro models exist
ls data/models/kokoro-v1.0/
# Expected: kokoro-v1.0.onnx voices-v1.0.bin
# Check TTS health
curl http://localhost:8082/health | jq '.services.audio.tts'Rate limiting errors (429):
- STT: 30 transcriptions/minute
- TTS: 60 syntheses/minute
- Wait 60 seconds and retry
Collection not found or wrong dimensions:
# Check collection status
python -m wingfix.cli.qdrant_init status
# Reinitialize (safe for existing data)
python -m wingfix.cli.qdrant_init init
# Force recreate (DANGER — destroys all vectors)
python -m wingfix.cli.qdrant_init init --recreate
alembic downgrade base && alembic upgrade head # also reset metadataPWA install prompt not showing:
- Requires HTTPS or localhost
- Browser must not have dismissed the prompt previously — use DevTools > Application > Manifest to reset
Effectivity context not persisting:
# Check localStorage in DevTools (Application > Local Storage > localhost:5173)
# Key: wingfix-effectivityTanStack Query not caching:
# Open React Query DevTools (gear icon in bottom-right corner during dev)
# Look for stale/refetching queriesFixture not found:
# Ensure conftest.py is in correct location
# Check test collection
pytest --collect-onlyAsync test issues:
# Ensure pytest-asyncio is installed
pip install pytest-asyncio
# Check asyncio mode in pyproject.toml
# asyncio_mode = "auto"Vitest failures:
cd frontend
npm run type-check # Check for TypeScript errors first
npm run test -- --reporter=verbose- Documentation: Check
docs/directory - Issues: Open a GitHub issue
- Code Questions: Review existing code for patterns
- OpenAPI Docs: http://localhost:8082/docs (when API is running)
Built for Aircraft Maintenance Engineers