{ "project": { "name": "voice-server", "description": "Local HTTP service for text-to-speech playback", "version": "1.0.0", "created": "2025-12-18", "last_updated": "2025-12-18" }, "methodology": { "approach": "hybrid-tdd", "description": "TDD for API contracts, validation, and queue logic. Implementation-first for hardware integrations.", "tdd_components": [ "request_validation", "queue_behavior", "error_responses", "health_check_logic" ], "implementation_first_components": [ "piper_tts_integration", "sounddevice_playback", "end_to_end_flow" ] }, "phases": [ { "id": "phase_1", "name": "Core Infrastructure", "description": "Project setup, FastAPI skeleton, and configuration management", "estimated_days": "1-2" }, { "id": "phase_2", "name": "TTS Integration", "description": "Piper TTS setup, voice model management, and parameter support", "estimated_days": "1-2" }, { "id": "phase_3", "name": "Audio Playback", "description": "sounddevice integration and audio error handling", "estimated_days": "1" }, { "id": "phase_4", "name": "Queue Management", "description": "Async queue implementation and request processing pipeline", "estimated_days": "1" }, { "id": "phase_5", "name": "Error Handling", "description": "Exception handlers, logging infrastructure, and health monitoring", "estimated_days": "1" }, { "id": "phase_6", "name": "Testing", "description": "Unit tests, integration tests, performance tests, and system tests", "estimated_days": "1-2" }, { "id": "phase_7", "name": "Documentation & Deployment", "description": "README, systemd service, and production hardening", "estimated_days": "1" } ], "tasks": [ { "id": "1.1.1", "phase": "phase_1", "name": "Initialize project directory", "description": "Create project directory structure at /mnt/NV2/Development/voice-server with app/, tests/, models/ subdirectories", "dependencies": [], "completed": false, "tested": false, "test_approach": null, "notes": "Directory already exists from PRD creation" }, { "id": "1.1.2", "phase": "phase_1", "name": "Create Python virtual environment", "description": "Initialize virtual environment using uv (uv venv)", "dependencies": ["1.1.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Use uv as per user preference" }, { "id": "1.1.3", "phase": "phase_1", "name": "Install core dependencies", "description": "Install fastapi, uvicorn[standard], piper-tts, sounddevice, numpy, pydantic, python-dotenv", "dependencies": ["1.1.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Also install pytest, pytest-asyncio, httpx for testing" }, { "id": "1.1.4", "phase": "phase_1", "name": "Create pyproject.toml", "description": "Create pyproject.toml with pinned dependency versions and project metadata", "dependencies": ["1.1.3"], "completed": false, "tested": false, "test_approach": null, "notes": "Use uv's native pyproject.toml support instead of requirements.txt" }, { "id": "1.1.5", "phase": "phase_1", "name": "Create environment configuration", "description": "Create .env.example with all configurable environment variables", "dependencies": ["1.1.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Include HOST, PORT, QUEUE_SIZE, LOG_LEVEL, MODEL_DIR, DEFAULT_VOICE" }, { "id": "1.1.6", "phase": "phase_1", "name": "Initialize git repository", "description": "Initialize git repo with .gitignore for Python, IDEs, .env, voice models, __pycache__", "dependencies": ["1.1.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Add models/*.onnx and models/*.json to .gitignore (large files)" }, { "id": "1.2.1", "phase": "phase_1", "name": "Write tests for Pydantic request/response models", "description": "TDD: Write tests for NotifyRequest, NotifyResponse, HealthResponse, ErrorResponse models with validation rules", "dependencies": ["1.1.4"], "completed": false, "tested": false, "test_approach": "tdd", "notes": "Test message length limits (1-10000), rate range (50-400), voice pattern validation" }, { "id": "1.2.2", "phase": "phase_1", "name": "Implement Pydantic models", "description": "Create app/models.py with NotifyRequest, NotifyResponse, HealthResponse, ErrorResponse models", "dependencies": ["1.2.1"], "completed": false, "tested": true, "test_approach": "tdd", "notes": "Implementation to make tests from 1.2.1 pass" }, { "id": "1.2.3", "phase": "phase_1", "name": "Create FastAPI application skeleton", "description": "Create app/main.py with FastAPI app, lifespan handler, and CORS middleware", "dependencies": ["1.2.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Use lifespan context manager (not deprecated on_event)" }, { "id": "1.2.4", "phase": "phase_1", "name": "Write tests for /notify endpoint contract", "description": "TDD: Write tests for POST /notify - valid requests return 202, invalid return 422, missing fields return 400", "dependencies": ["1.2.3"], "completed": false, "tested": false, "test_approach": "tdd", "notes": "Use httpx.AsyncClient for async endpoint testing" }, { "id": "1.2.5", "phase": "phase_1", "name": "Implement /notify endpoint skeleton", "description": "Create POST /notify endpoint that validates request and returns 202 (queue integration later)", "dependencies": ["1.2.4"], "completed": false, "tested": true, "test_approach": "tdd", "notes": "Initially just validate and return success; queue integration in phase 4" }, { "id": "1.2.6", "phase": "phase_1", "name": "Write tests for /health endpoint", "description": "TDD: Write tests for GET /health - returns status, uptime, queue info structure", "dependencies": ["1.2.3"], "completed": false, "tested": false, "test_approach": "tdd", "notes": "Test both healthy and unhealthy response structures" }, { "id": "1.2.7", "phase": "phase_1", "name": "Implement /health endpoint skeleton", "description": "Create GET /health endpoint returning basic health status", "dependencies": ["1.2.6"], "completed": false, "tested": true, "test_approach": "tdd", "notes": "Full health checks (TTS, audio) added in phase 5" }, { "id": "1.2.8", "phase": "phase_1", "name": "Implement /voices endpoint skeleton", "description": "Create GET /voices endpoint returning list of available voice models", "dependencies": ["1.2.3"], "completed": false, "tested": false, "test_approach": null, "notes": "Initially return empty list; populate after TTS integration" }, { "id": "1.2.9", "phase": "phase_1", "name": "Configure JSON logging middleware", "description": "Add structured JSON logging for all requests with timestamp, request_id, path, status_code", "dependencies": ["1.2.3"], "completed": false, "tested": false, "test_approach": null, "notes": "Use Python's logging with JSON formatter" }, { "id": "1.2.10", "phase": "phase_1", "name": "Verify server startup", "description": "Test server starts successfully with uvicorn app.main:app --reload", "dependencies": ["1.2.5", "1.2.7", "1.2.8"], "completed": false, "tested": false, "test_approach": null, "notes": "Verify /docs (Swagger UI) is accessible" }, { "id": "1.3.1", "phase": "phase_1", "name": "Write tests for configuration loading", "description": "TDD: Write tests for config loading from env vars with defaults, validation of values", "dependencies": ["1.1.5"], "completed": false, "tested": false, "test_approach": "tdd", "notes": "Test default values, env var override, invalid value handling" }, { "id": "1.3.2", "phase": "phase_1", "name": "Implement configuration module", "description": "Create app/config.py with Settings class using pydantic-settings for env var loading", "dependencies": ["1.3.1"], "completed": false, "tested": true, "test_approach": "tdd", "notes": "Include host, port, queue_size, log_level, model_dir, default_voice settings" }, { "id": "1.3.3", "phase": "phase_1", "name": "Add CLI argument parsing", "description": "Add CLI argument support for --host, --port, --log-level to override env vars", "dependencies": ["1.3.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Use argparse or typer; CLI args take precedence over env vars" }, { "id": "2.1.1", "phase": "phase_2", "name": "Create TTS engine module structure", "description": "Create app/tts_engine.py with TTSEngine abstract base and PiperTTSEngine class skeleton", "dependencies": ["1.2.10"], "completed": false, "tested": false, "test_approach": null, "notes": "Abstract base allows for future TTS engine swapping" }, { "id": "2.1.2", "phase": "phase_2", "name": "Download default voice model", "description": "Download en_US-lessac-medium.onnx and .json to models/ directory", "dependencies": ["1.1.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Can use piper --download-dir or manual download from GitHub releases" }, { "id": "2.1.3", "phase": "phase_2", "name": "Implement Piper TTS voice loading", "description": "Implement PiperTTSEngine.load_voice() to load .onnx model with caching", "dependencies": ["2.1.1", "2.1.2"], "completed": false, "tested": false, "test_approach": "implementation_first", "notes": "Cache loaded models in memory to avoid reload on each request" }, { "id": "2.1.4", "phase": "phase_2", "name": "Implement text-to-audio synthesis", "description": "Implement PiperTTSEngine.synthesize() returning NumPy array of audio samples", "dependencies": ["2.1.3"], "completed": false, "tested": false, "test_approach": "implementation_first", "notes": "Return float32 NumPy array compatible with sounddevice" }, { "id": "2.1.5", "phase": "phase_2", "name": "Write integration tests for TTS synthesis", "description": "Write tests verifying TTS generates valid audio array for sample text", "dependencies": ["2.1.4"], "completed": false, "tested": false, "test_approach": "implementation_first", "notes": "Test output is non-empty NumPy array with expected sample rate" }, { "id": "2.1.6", "phase": "phase_2", "name": "Measure TTS latency benchmarks", "description": "Benchmark TTS generation time for various text lengths (10, 100, 500, 1000, 5000 chars)", "dependencies": ["2.1.5"], "completed": false, "tested": false, "test_approach": null, "notes": "Document results for performance baseline" }, { "id": "2.2.1", "phase": "phase_2", "name": "Create models directory structure", "description": "Create models/ directory for voice model storage with README explaining model installation", "dependencies": ["1.1.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Include instructions for downloading additional voices" }, { "id": "2.2.2", "phase": "phase_2", "name": "Implement voice model discovery", "description": "Implement function to scan models/ directory and return available voice models", "dependencies": ["2.2.1", "2.1.3"], "completed": false, "tested": false, "test_approach": null, "notes": "Parse .json config files for model metadata (language, quality)" }, { "id": "2.2.3", "phase": "phase_2", "name": "Implement /voices endpoint fully", "description": "Update /voices endpoint to return discovered models with metadata", "dependencies": ["2.2.2", "1.2.8"], "completed": false, "tested": false, "test_approach": null, "notes": "Include name, language, quality, size_mb, installed status" }, { "id": "2.2.4", "phase": "phase_2", "name": "Add voice validation to /notify", "description": "Validate requested voice exists before queuing; return 422 if not found", "dependencies": ["2.2.2", "1.2.5"], "completed": false, "tested": false, "test_approach": null, "notes": "Provide helpful error message listing available voices" }, { "id": "2.3.1", "phase": "phase_2", "name": "Implement speech rate adjustment", "description": "Add rate parameter support to TTS synthesis (50-400 WPM range)", "dependencies": ["2.1.4"], "completed": false, "tested": false, "test_approach": null, "notes": "Check if Piper supports rate adjustment natively or needs post-processing" }, { "id": "2.3.2", "phase": "phase_2", "name": "Test rate adjustment across range", "description": "Test TTS output at rate=50, 100, 170 (default), 300, 400 WPM", "dependencies": ["2.3.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Verify audio sounds correct at extremes" }, { "id": "2.3.3", "phase": "phase_2", "name": "Implement voice_enabled flag", "description": "Add voice_enabled parameter to skip TTS for debugging/testing", "dependencies": ["2.1.4"], "completed": false, "tested": false, "test_approach": null, "notes": "When false, skip TTS and audio playback but still process request" }, { "id": "3.1.1", "phase": "phase_3", "name": "Create audio player module", "description": "Create app/audio_player.py with AudioPlayer class skeleton", "dependencies": ["1.2.10"], "completed": false, "tested": false, "test_approach": null, "notes": "Use sounddevice for non-blocking playback" }, { "id": "3.1.2", "phase": "phase_3", "name": "Implement audio device verification", "description": "Implement verify_audio_devices() to check for available output devices at startup", "dependencies": ["3.1.1"], "completed": false, "tested": false, "test_approach": "implementation_first", "notes": "Use sd.query_devices() to enumerate devices" }, { "id": "3.1.3", "phase": "phase_3", "name": "Implement non-blocking playback", "description": "Implement AudioPlayer.play() using sd.play() for non-blocking audio output", "dependencies": ["3.1.2"], "completed": false, "tested": false, "test_approach": "implementation_first", "notes": "sd.play() returns immediately; audio plays in background thread" }, { "id": "3.1.4", "phase": "phase_3", "name": "Implement async wait method", "description": "Implement AudioPlayer.wait_async() for async-friendly waiting on playback completion", "dependencies": ["3.1.3"], "completed": false, "tested": false, "test_approach": "implementation_first", "notes": "Poll sd.get_stream().active with asyncio.sleep()" }, { "id": "3.1.5", "phase": "phase_3", "name": "Test audio playback with sample data", "description": "Test AudioPlayer with synthesized sine wave to verify audio output works", "dependencies": ["3.1.4"], "completed": false, "tested": false, "test_approach": "implementation_first", "notes": "Use numpy to generate test tone; verify sound is heard" }, { "id": "3.1.6", "phase": "phase_3", "name": "Verify non-blocking behavior", "description": "Test that play() returns immediately and server can handle requests during playback", "dependencies": ["3.1.5"], "completed": false, "tested": false, "test_approach": null, "notes": "Send request, verify 202 returned before audio finishes" }, { "id": "3.2.1", "phase": "phase_3", "name": "Implement retry logic for device failures", "description": "Implement RobustAudioPlayer with automatic retry on sd.PortAudioError", "dependencies": ["3.1.4"], "completed": false, "tested": false, "test_approach": null, "notes": "Retry up to 3 times with 0.5s delay between attempts" }, { "id": "3.2.2", "phase": "phase_3", "name": "Handle device disconnection", "description": "Gracefully handle audio device disconnection during playback", "dependencies": ["3.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Log error, skip playback, continue processing queue" }, { "id": "3.2.3", "phase": "phase_3", "name": "Implement audio diagnostics", "description": "Implement get_audio_diagnostics() for health check reporting", "dependencies": ["3.1.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Return device count, default output name, sample rate" }, { "id": "3.2.4", "phase": "phase_3", "name": "Add audio error logging", "description": "Add detailed logging for all audio errors with device context", "dependencies": ["3.2.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Include device name, error type, retry count in logs" }, { "id": "4.1.1", "phase": "phase_4", "name": "Write tests for queue behavior", "description": "TDD: Write tests for queue enqueue, dequeue, overflow, ordering (FIFO)", "dependencies": ["1.2.10"], "completed": false, "tested": false, "test_approach": "tdd", "notes": "Test max size enforcement, QueueFullError raising" }, { "id": "4.1.2", "phase": "phase_4", "name": "Create queue manager module", "description": "Create app/queue_manager.py with TTSQueue class using asyncio.Queue", "dependencies": ["4.1.1"], "completed": false, "tested": true, "test_approach": "tdd", "notes": "Implement to pass tests from 4.1.1" }, { "id": "4.1.3", "phase": "phase_4", "name": "Implement queue enqueue with timeout", "description": "Implement TTSQueue.enqueue() with 1s timeout, raising QueueFullError on timeout", "dependencies": ["4.1.2"], "completed": false, "tested": true, "test_approach": "tdd", "notes": "Return queue position on success" }, { "id": "4.1.4", "phase": "phase_4", "name": "Implement queue metrics", "description": "Add stats tracking: processed count, error count, current size", "dependencies": ["4.1.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Expose via TTSQueue.stats property" }, { "id": "4.1.5", "phase": "phase_4", "name": "Implement graceful queue shutdown", "description": "Implement TTSQueue.shutdown() to wait for current item, reject new items", "dependencies": ["4.1.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Called during application shutdown via lifespan" }, { "id": "4.2.1", "phase": "phase_4", "name": "Implement background queue processor", "description": "Create async background task to process queue items sequentially", "dependencies": ["4.1.2", "2.1.4", "3.1.4"], "completed": false, "tested": false, "test_approach": null, "notes": "Generate TTS, play audio, wait for completion, then next item" }, { "id": "4.2.2", "phase": "phase_4", "name": "Integrate queue with /notify endpoint", "description": "Update /notify to enqueue validated requests to TTSQueue", "dependencies": ["4.2.1", "1.2.5"], "completed": false, "tested": false, "test_approach": null, "notes": "Return queue_position in response" }, { "id": "4.2.3", "phase": "phase_4", "name": "Add request timeout handling", "description": "Add 60s timeout for individual request processing in queue worker", "dependencies": ["4.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Cancel TTS generation if exceeds timeout; log and continue" }, { "id": "4.2.4", "phase": "phase_4", "name": "Implement CPU-bound TTS in thread pool", "description": "Run TTS synthesis in thread pool executor to avoid blocking event loop", "dependencies": ["4.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Use loop.run_in_executor() for TTS generation" }, { "id": "4.2.5", "phase": "phase_4", "name": "Test queue with concurrent requests", "description": "Test sending 20+ concurrent requests and verify sequential playback", "dependencies": ["4.2.2"], "completed": false, "tested": false, "test_approach": null, "notes": "All requests should be processed in order received" }, { "id": "4.3.1", "phase": "phase_4", "name": "Add queue status to /health", "description": "Update /health to include queue size, capacity, utilization percentage", "dependencies": ["4.1.4", "1.2.7"], "completed": false, "tested": false, "test_approach": null, "notes": "Include processed and error counts" }, { "id": "4.3.2", "phase": "phase_4", "name": "Add queue event logging", "description": "Log queue events: enqueue, process start, process complete, errors", "dependencies": ["4.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Include request_id for correlation" }, { "id": "4.3.3", "phase": "phase_4", "name": "Test queue overflow scenarios", "description": "Test behavior when queue reaches max size; verify 503 returned", "dependencies": ["4.2.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Fill queue with slow requests, send additional request" }, { "id": "5.1.1", "phase": "phase_5", "name": "Write tests for error responses", "description": "TDD: Write tests for all error response formats (400, 422, 500, 503)", "dependencies": ["1.2.2"], "completed": false, "tested": false, "test_approach": "tdd", "notes": "Verify error response structure matches API spec" }, { "id": "5.1.2", "phase": "phase_5", "name": "Create custom exception classes", "description": "Create app/exceptions.py with QueueFullError, TTSEngineError, AudioPlaybackError", "dependencies": ["5.1.1"], "completed": false, "tested": true, "test_approach": "tdd", "notes": "Include error codes and details for each exception type" }, { "id": "5.1.3", "phase": "phase_5", "name": "Implement exception handlers", "description": "Add FastAPI exception handlers for each custom exception type", "dependencies": ["5.1.2"], "completed": false, "tested": true, "test_approach": "tdd", "notes": "Map exceptions to appropriate HTTP status codes" }, { "id": "5.1.4", "phase": "phase_5", "name": "Implement generic exception handler", "description": "Add catch-all exception handler for unexpected errors (500)", "dependencies": ["5.1.3"], "completed": false, "tested": false, "test_approach": null, "notes": "Log full traceback but return sanitized error to client" }, { "id": "5.2.1", "phase": "phase_5", "name": "Configure structured JSON logging", "description": "Set up logging with JSON formatter including timestamp, level, message, context", "dependencies": ["1.2.9"], "completed": false, "tested": false, "test_approach": null, "notes": "Use python-json-logger or custom formatter" }, { "id": "5.2.2", "phase": "phase_5", "name": "Implement rotating file handler", "description": "Configure RotatingFileHandler with 10MB max size, 5 backups", "dependencies": ["5.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Write to voice-server.log in project directory" }, { "id": "5.2.3", "phase": "phase_5", "name": "Add request ID tracking", "description": "Generate unique request_id for each request; include in all related logs", "dependencies": ["5.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Use UUID4; add to response headers for client correlation" }, { "id": "5.2.4", "phase": "phase_5", "name": "Test log rotation", "description": "Verify log files rotate correctly when size limit reached", "dependencies": ["5.2.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Generate enough log entries to trigger rotation" }, { "id": "5.3.1", "phase": "phase_5", "name": "Implement comprehensive /health endpoint", "description": "Update /health with TTS engine, audio system, queue, and system resource checks", "dependencies": ["4.3.1", "3.2.3"], "completed": false, "tested": false, "test_approach": null, "notes": "Return 200 if all healthy, 503 if any component unhealthy" }, { "id": "5.3.2", "phase": "phase_5", "name": "Add TTS engine health check", "description": "Test TTS engine can synthesize short test phrase", "dependencies": ["2.1.4"], "completed": false, "tested": false, "test_approach": null, "notes": "Use minimal text to minimize overhead" }, { "id": "5.3.3", "phase": "phase_5", "name": "Add system resource monitoring", "description": "Include CPU and memory usage in health check response", "dependencies": ["5.3.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Use psutil for system metrics" }, { "id": "5.3.4", "phase": "phase_5", "name": "Test health endpoint under load", "description": "Verify /health responds correctly while queue is processing", "dependencies": ["5.3.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Health check should not block or be blocked by TTS processing" }, { "id": "6.1.1", "phase": "phase_6", "name": "Set up pytest infrastructure", "description": "Create tests/ directory with conftest.py, pytest.ini, test fixtures", "dependencies": ["1.1.4"], "completed": false, "tested": false, "test_approach": null, "notes": "Include async fixtures for FastAPI testing" }, { "id": "6.1.2", "phase": "phase_6", "name": "Write remaining unit tests", "description": "Complete any missing unit tests to achieve 80%+ coverage", "dependencies": ["6.1.1", "5.1.3"], "completed": false, "tested": false, "test_approach": null, "notes": "Use pytest-cov for coverage reporting" }, { "id": "6.2.1", "phase": "phase_6", "name": "Write end-to-end integration tests", "description": "Test complete request flow from HTTP request to audio playback", "dependencies": ["4.2.5"], "completed": false, "tested": false, "test_approach": null, "notes": "May need to mock audio output for CI environments" }, { "id": "6.2.2", "phase": "phase_6", "name": "Write error scenario tests", "description": "Test TTS failure, audio failure, queue overflow scenarios end-to-end", "dependencies": ["6.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Use dependency injection to simulate failures" }, { "id": "6.3.1", "phase": "phase_6", "name": "Create load testing script", "description": "Create load test using locust or wrk for performance benchmarking", "dependencies": ["4.2.5"], "completed": false, "tested": false, "test_approach": null, "notes": "Target: 50+ req/s, <50ms API response time" }, { "id": "6.3.2", "phase": "phase_6", "name": "Measure performance benchmarks", "description": "Record p50, p95, p99 latency; TTS generation time; memory usage", "dependencies": ["6.3.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Document baseline performance for future comparison" }, { "id": "6.4.1", "phase": "phase_6", "name": "Test on target environment", "description": "Run full test suite on Nobara/Fedora 42 with real audio hardware", "dependencies": ["6.2.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Test with both PulseAudio and ALSA if possible" }, { "id": "6.4.2", "phase": "phase_6", "name": "Test long-running stability", "description": "Run server for 24+ hours with periodic requests; check for memory leaks", "dependencies": ["6.4.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Monitor memory usage over time" }, { "id": "7.1.1", "phase": "phase_7", "name": "Create comprehensive README", "description": "Write README.md with overview, installation, configuration, usage, API docs, troubleshooting", "dependencies": ["6.4.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Include example curl commands and Python client code" }, { "id": "7.1.2", "phase": "phase_7", "name": "Document voice model installation", "description": "Create guide for downloading and installing additional Piper voice models", "dependencies": ["2.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Link to Piper voice model repository" }, { "id": "7.1.3", "phase": "phase_7", "name": "Create example client scripts", "description": "Create examples/ directory with curl, Python, and JavaScript client examples", "dependencies": ["7.1.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Include async Python example using httpx" }, { "id": "7.2.1", "phase": "phase_7", "name": "Create systemd service file", "description": "Create voice-server.service for systemd deployment", "dependencies": ["6.4.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Include restart on failure, proper user/group, working directory" }, { "id": "7.2.2", "phase": "phase_7", "name": "Test systemd service", "description": "Test service installation, start, stop, restart, and auto-restart on failure", "dependencies": ["7.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Document installation steps in README" }, { "id": "7.2.3", "phase": "phase_7", "name": "Create deployment script", "description": "Create deploy.sh script for automated deployment", "dependencies": ["7.2.1"], "completed": false, "tested": false, "test_approach": null, "notes": "Include venv setup, dependency install, service restart" }, { "id": "7.3.1", "phase": "phase_7", "name": "Configure production logging", "description": "Set up production log levels (INFO default, DEBUG disabled)", "dependencies": ["5.2.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Configurable via LOG_LEVEL environment variable" }, { "id": "7.3.2", "phase": "phase_7", "name": "Implement graceful shutdown", "description": "Handle SIGTERM/SIGINT for graceful shutdown with queue draining", "dependencies": ["4.1.5"], "completed": false, "tested": false, "test_approach": null, "notes": "Wait for current playback to complete before exit" }, { "id": "7.3.3", "phase": "phase_7", "name": "Security audit", "description": "Review input sanitization, resource limits, error message exposure", "dependencies": ["6.2.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Verify no internal details leaked in error responses" }, { "id": "7.3.4", "phase": "phase_7", "name": "Performance tuning", "description": "Tune queue size, worker count, timeouts based on benchmark results", "dependencies": ["6.3.2"], "completed": false, "tested": false, "test_approach": null, "notes": "Document recommended settings for different use cases" } ], "summary": { "total_tasks": 78, "tdd_tasks": 12, "implementation_first_tasks": 8, "phases": 7, "estimated_days": "4-7" } }