- Created QueueRepository adapter in src/server/services/queue_repository.py
- Refactored DownloadService to use repository pattern instead of JSON
- Updated application startup to initialize download service from database
- Updated all test fixtures to use MockQueueRepository
- All 1104 tests passing
- Added db_session parameter to SeriesApp.__init__()
- Added db_session property and set_db_session() method
- Added init_from_db_async() for async database initialization
- Pass db_session to SerieList and SerieScanner during construction
- Added get_series_app_with_db() dependency for FastAPI endpoints
- All 815 unit tests and 55 API tests pass
Task 6: Update Anime API endpoints to use database
- Modified add_series endpoint to save series to database when available
- Added get_optional_database_session dependency for graceful fallback
- Falls back to file-based storage when database unavailable
- All 55 API tests and 809 unit tests pass
- Enhanced infrastructure.md with identifier convention table, format requirements, migration notes
- Updated docs/README.md with series identifier convention section
- Updated docs/api_reference.md with key-based API examples and notes
- Added deprecation warnings to SerieList.get_by_folder()
- Added deprecation warnings to anime.py folder fallback lookup
- Added deprecation warnings to validate_series_key_or_folder()
- All warnings include v3.0.0 removal timeline
- All 1006 tests pass
- Updated AnimeSeries model docstring to clarify key is primary identifier
- Updated folder field to indicate metadata-only usage
- Updated AnimeSeriesService docstring and get_by_key method
- Updated infrastructure.md with database identifier documentation
- All 996 tests passing
- Updated app.js to use 'key' as primary series identifier
- selectedSeries Set now uses key instead of folder
- createSerieCard() uses data-key attribute for identification
- toggleSerieSelection() uses key for lookups
- downloadSelected() iterates with key values
- updateSelectionUI() and toggleSelectAll() use key
- Updated WebSocket service tests
- Tests now include key and folder in broadcast data
- Verified both fields are included in messages
- No changes needed for queue.js and other JS files
- They use download item IDs correctly, not series identifiers
- No template changes needed
- Series cards rendered dynamically in app.js
All 996 tests passing
- Add series context helpers: prepare_series_context, get_series_by_key, filter_series_by_missing_episodes
- Update module docstring with identifier convention documentation
- Add unit tests for new series context helper functions
- Update infrastructure.md with template helpers documentation
- Mark Phase 4 (API Layer) as complete
- Add validate_series_key() function that validates URL-safe, lowercase,
hyphen-separated series keys (e.g., 'attack-on-titan')
- Add validate_series_key_or_folder() for backward compatibility during
transition from folder-based to key-based identification
- Create comprehensive test suite with 99 test cases for all validators
- Update infrastructure.md with validation utilities documentation
- Mark Task 4.6 as complete in instructions.md
Test: conda run -n AniWorld python -m pytest tests/unit/test_validators.py -v
All 99 validator tests pass, 718 total unit tests pass
- Updated AnimeSeriesResponse and SearchResult models in anime.py:
- Changed 'id' field to 'key' as the primary series identifier
- Added 'folder' as optional metadata field
- Added field validator to normalize key to lowercase and strip whitespace
- Added comprehensive docstrings explaining identifier usage
- Updated DownloadItem and DownloadRequest models in download.py:
- Added field validator for serie_id normalization (lowercase, stripped)
- Improved documentation for serie_id (primary identifier) vs serie_folder (metadata)
- Updated test_anime_models.py with comprehensive tests:
- Tests for key normalization and whitespace stripping
- Tests for folder as optional metadata
- Reorganized tests into proper class structure
- Updated test_download_models.py with validator tests:
- Tests for serie_id normalization in DownloadItem
- Tests for serie_id normalization in DownloadRequest
All 885 tests pass.
- Updated src/server/api/websocket.py docstrings to document key as primary series identifier
- Updated src/server/models/websocket.py with detailed docstrings explaining key and folder fields in message payloads
- Updated src/server/services/websocket_service.py broadcast method docstrings to document key field usage
- Added WebSocket message example with key in infrastructure.md
- All 83 WebSocket tests pass
- Task 4.4 marked as complete in instructions.md
- Updated DownloadRequest and DownloadItem models with comprehensive
docstrings explaining serie_id (key as primary identifier) vs
serie_folder (filesystem metadata)
- Updated add_to_queue() endpoint docstring to document request parameters
- Updated all test files to include required serie_folder field:
- tests/api/test_download_endpoints.py
- tests/api/test_queue_features.py
- tests/frontend/test_existing_ui_integration.py
- tests/integration/test_download_flow.py
- Updated infrastructure.md with Download Queue request/response models
- All 869 tests pass
This is part of the Series Identifier Standardization effort (Phase 4.2)
to ensure key is used as the primary identifier throughout the codebase.
- Updated AnimeSummary model with enhanced documentation:
- key as primary identifier (unique series identifier)
- folder as metadata only (not used for lookups)
- Added Field descriptions for all attributes
- Updated AnimeDetail model:
- Replaced 'id' field with 'key' field
- Added 'folder' field as metadata
- Enhanced documentation and JSON schema example
- Updated get_anime() endpoint:
- Primary lookup by 'key' (preferred)
- Fallback lookup by 'folder' (backward compatibility)
- Updated docstring to clarify identifier usage
- Updated add_series() endpoint:
- Extracts key from link URL (/anime/stream/{key})
- Returns both key and folder in response
- Enhanced docstring with parameter descriptions
- Updated _perform_search():
- Uses key as primary identifier
- Extracts key from link URL if not present
- Enhanced docstring with return value details
- Updated list_anime() and search endpoint docstrings:
- Clarified key as primary identifier
- Documented folder as metadata only
- Updated instructions.md:
- Marked Task 4.1 as completed
- Updated task tracking section
- Updated infrastructure.md:
- Updated API endpoints documentation
- Added response model details
All anime API tests passing (11/11)
All unit tests passing (604/604)
- Create ScanService class (src/server/services/scan_service.py)
- Use 'key' as primary series identifier throughout
- Include 'folder' as metadata only for display purposes
- Implement scan progress tracking via ProgressService
- Add callback classes for progress, error, and completion
- Support scan event subscription and broadcasting
- Maintain scan history with configurable limit
- Provide cancellation support for in-progress scans
- Create comprehensive unit tests (tests/unit/test_scan_service.py)
- 38 tests covering all functionality
- Test ScanProgress dataclass serialization
- Test callback classes (progress, error, completion)
- Test service lifecycle (start, cancel, status)
- Test event subscription and broadcasting
- Test key-based identification throughout
- Test singleton pattern
- Update infrastructure.md with ScanService documentation
- Document service overview and key features
- Document components and event types
- Document integration points
- Include usage example
- Update instructions.md
- Mark Task 3.4 as complete
- Mark Phase 3 as fully complete
- Remove finished task definition
Task: Phase 3, Task 3.4 - Update ScanService to Use Key
Completion Date: November 27, 2025
- Added optional 'key' and 'folder' fields to ProgressUpdate dataclass
- key: Primary series identifier (provider key, e.g., 'attack-on-titan')
- folder: Optional series folder name for display (e.g., 'Attack on Titan (2013)')
- Updated start_progress() and update_progress() methods to accept key/folder parameters
- Enhanced to_dict() serialization to include key/folder when present
- Updated all docstrings to clarify identifier usage
- Added 5 new comprehensive unit tests for key/folder functionality
- All 25 ProgressService tests passing
- Updated infrastructure.md with series identifier documentation
- Maintains backward compatibility - fields are optional
- Completed Phase 3, Task 3.3 of identifier standardization initiative
- Enhanced class and method docstrings to clarify 'key' as primary identifier
- Documented that 'folder' is metadata only (display and filesystem operations)
- Updated event handler documentation to show both key and folder are received
- Modernized type hints to Python 3.9+ style (list[dict] vs List[dict])
- Fixed PEP 8 line length violations
- All 18 anime service tests passing
Implementation follows identifier standardization initiative:
- key: Primary series identifier (provider-assigned, URL-safe)
- folder: Metadata for display and filesystem paths only
Task 3.2 completed November 23, 2025
Documented in infrastructure.md and instructions.md
- Updated DownloadService to use 'serie_id' (provider key) for identification
- Changed 'serie_folder' from Optional to required in models (DownloadItem, DownloadRequest)
- Removed incorrect fallback logic that used serie_id as folder name
- Enhanced docstrings to clarify purpose of each identifier field:
* serie_id: Provider key (e.g., 'attack-on-titan') for lookups
* serie_folder: Filesystem folder name (e.g., 'Attack on Titan (2013)') for file operations
- Updated logging to reference 'serie_key' for clarity
- Fixed all unit tests to include required serie_folder field
- All 25 download service tests passing
- All 47 download model tests passing
- Updated infrastructure.md with detailed documentation
- Marked Task 3.1 as completed in instructions.md
Benefits:
- Clear separation between provider identifier and filesystem path
- Prevents confusion from mixing different identifier types
- Consistent with broader series identifier standardization effort
- Better error messages when required fields are missing