docs: consolidate CLAUDE.md into AGENTS.md and simplify
Merge detailed content from CLAUDE.md into AGENTS.md, then condense to essential information. Removes Claude-specific documentation in favor of tool-agnostic guidelines. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.5
parent
0f0636bf19
commit
8a60aaf9a9
@@ -1,46 +1,88 @@
|
||||
# Repository Guidelines
|
||||
|
||||
## Project Structure & Module Organization
|
||||
- Core package lives in `src/vlm/`.
|
||||
- CLI entrypoint is `src/vlm/cli.py` (`vlm` console script). Shared CLI helpers live in `cli_helpers.py`. Command logic is in `commands/` (scan, parse, enrich, analyze, plan, execute, review_plan, report, quarantine_cmd, state_cmd, config_cmd).
|
||||
- Functional modules by concern: scanning (`scanner.py`), parsing (`parser.py`), enrichment (`enrichment.py`, `cache.py`, `providers/`), analysis/planning/execution (`analysis.py`, `planner.py`, `executor.py`), I/O helpers (`io.py`), utilities (`utils.py`), state/reporting/logging (`state.py`, `reports.py`, `logging_config.py`), config (`config.py`), models (`models.py`).
|
||||
- Tests live in `tests/` and mirror feature areas (e.g. `tests/test_scanner.py`, `tests/test_cli_state.py`, `tests/test_enrichment.py`).
|
||||
- Project metadata and tool config are in `pyproject.toml`.
|
||||
## Project Overview
|
||||
Video Library Manager (VLM) - Python CLI for managing personal video collections. Safety-first, human-in-the-loop approach. All operations reversible.
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
- `uv pip install -e .` installs the package in editable mode.
|
||||
- `uv pip install -e ".[dev]"` installs dev dependencies (`pytest`, `hypothesis`, `pytest-cov`, `ruff`).
|
||||
- `uv run pytest -q` runs the full test suite.
|
||||
- `uv run pytest tests/test_logging.py` runs a targeted test file during iteration.
|
||||
- `uv run ruff check src tests` runs the linter (also in CI).
|
||||
- `vlm --help` verifies CLI startup and available commands.
|
||||
## Quick Start
|
||||
```bash
|
||||
uv pip install -e ".[dev]" # Install with dev deps
|
||||
uv run pytest -q # Run tests
|
||||
uv run vlm --help # Verify CLI
|
||||
```
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
- Use Python 3.10+ idioms, 4-space indentation, and PEP 8 naming.
|
||||
- Modules/functions/variables: `snake_case`; classes: `PascalCase`; constants: `UPPER_SNAKE_CASE`.
|
||||
- Keep modules focused on a single responsibility; prefer small pure helpers in domain modules.
|
||||
- Add type hints for public functions and non-trivial internal APIs.
|
||||
- Use absolute imports in `src/vlm/`: `from vlm.module import ...` (avoid new relative imports).
|
||||
- Ruff (`E`, `F`, `I`) is configured in `pyproject.toml`; CI runs `ruff check src tests`.
|
||||
## Core Workflow
|
||||
1. `vlm scan` → discover files → `artifacts/inventory.csv`
|
||||
2. `vlm parse` → extract identities → `artifacts/identities.json`
|
||||
3. `vlm enrich` → (optional) add TMDB metadata
|
||||
4. `vlm analyze` → detect gaps/duplicates → `artifacts/analysis.json`
|
||||
5. `vlm plan` → generate execution plan → `artifacts/plan.json`
|
||||
6. `vlm review-plan` → preview high-risk operations
|
||||
7. `vlm execute` → dry-run by default, `--confirm` to execute
|
||||
8. `vlm rollback` → undo executed operations
|
||||
|
||||
## Testing Guidelines
|
||||
- Framework: `pytest`; property-based tests use `hypothesis`.
|
||||
- Naming (enforced in config): files `test_*.py`, functions `test_*`, classes `Test*`.
|
||||
- Add/extend tests with each behavior change, including CLI error paths and edge cases.
|
||||
- Prefer narrow unit tests for module logic plus targeted CLI integration tests via `CliRunner`.
|
||||
## Project Structure
|
||||
- `src/vlm/cli.py` - CLI entrypoint
|
||||
- `src/vlm/commands/` - Command implementations (scan, parse, enrich, analyze, plan, execute, review_plan, report, quarantine_cmd, state_cmd, config_cmd)
|
||||
- `src/vlm/scanner.py` - File discovery + ffprobe metadata
|
||||
- `src/vlm/parser.py` - Filename parsing (movies: title+year, series: SxxExx)
|
||||
- `src/vlm/enrichment.py` - TMDB enrichment pipeline
|
||||
- `src/vlm/planner.py` - Execution plan generation
|
||||
- `src/vlm/executor.py` - File operations with rollback
|
||||
- `src/vlm/models.py` - Data structures (VideoFile, MovieIdentity, SeriesIdentity, etc.)
|
||||
- `tests/` - Test suite mirroring source modules
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
- Current history is minimal; use clear, imperative commit subjects (example: `fix logging fallback for unwritable log dir`).
|
||||
- Keep commits focused; avoid mixing refactors and behavior changes unless tightly coupled.
|
||||
- PRs should include: summary, rationale, test evidence (`pytest` output), and any CLI-visible output changes.
|
||||
- Link related issues/tasks when applicable and call out config or migration impacts.
|
||||
## Key Concepts
|
||||
|
||||
## Security & Configuration Tips
|
||||
- Do not commit local paths, personal media metadata, or generated state/log artifacts.
|
||||
- Validate config changes against `vlm --help` and at least one end-to-end CLI flow before merging.
|
||||
### Safety Protocol
|
||||
- NEVER delete files permanently - use quarantine
|
||||
- All operations create rollback logs with `--confirm`
|
||||
- Default mode is dry-run
|
||||
|
||||
### File Categorization
|
||||
Based on top-level directory matching `categories` config (case-insensitive). Default: `movie`, `series`, `anime`.
|
||||
|
||||
## Documentation baseline
|
||||
- Updated to reflect release 0.2.0 baseline as of 2026-06-01.
|
||||
- Canonical release notes are tracked in `CHANGELOG.md`.
|
||||
- Default workflow artifacts: `artifacts/` (do not commit generated CSV/JSON).
|
||||
### Schema Versions
|
||||
- **v1** (default): Lightweight, no embedded metadata
|
||||
- **v2** (with `--inventory`): Includes video metadata for quality-aware duplicate resolution
|
||||
|
||||
### Parsing Patterns (Hardcoded)
|
||||
- Movies: `{title} ({year})` or `{title}.{year}`
|
||||
- Series: `S{season:02d}E{episode:02d}` or `{season}x{episode}`
|
||||
|
||||
## Development Commands
|
||||
```bash
|
||||
uv run pytest # All tests
|
||||
uv run pytest tests/test_scanner.py # Specific file
|
||||
uv run ruff check src tests # Lint
|
||||
uv run vlm scan # Discover files
|
||||
uv run vlm parse --inventory artifacts/inventory.csv # Parse with metadata
|
||||
uv run vlm plan --analysis artifacts/analysis.json # Plan with duplicates
|
||||
uv run vlm review-plan --tui # Interactive review (requires [tui])
|
||||
```
|
||||
|
||||
## Code Style
|
||||
- Python 3.10+, 4-space indent, PEP 8
|
||||
- `snake_case` functions/vars, `PascalCase` classes, `UPPER_SNAKE_CASE` constants
|
||||
- Type hints for public APIs
|
||||
- Absolute imports: `from vlm.module import ...`
|
||||
- Ruff (`E`, `F`, `I`) enforced in CI
|
||||
|
||||
## Testing
|
||||
- pytest + hypothesis for property-based tests
|
||||
- Naming: `test_*.py`, `test_*()`, `Test*`
|
||||
- Add tests with behavior changes
|
||||
- Prefer unit tests + targeted CLI integration via `CliRunner`
|
||||
|
||||
## Commit Guidelines
|
||||
- Imperative subjects: `fix logging fallback for unwritable log dir`
|
||||
- Keep commits focused (no mixed refactors + behavior changes)
|
||||
- Include: `Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>`
|
||||
- PRs: summary, rationale, test evidence, CLI output changes
|
||||
|
||||
## Important Notes
|
||||
- Anime: discovered but not parsed in v1
|
||||
- State tracking: optional, persisted to `~/.vlm/state.json`
|
||||
- Quarantine: only movie/series (not anime/other)
|
||||
- Timestamps: UTC ISO 8601 format
|
||||
- Logging: `~/.vlm/vlm.log`, falls back to console if unwritable
|
||||
- Config: `~/.vlm/config.yaml`
|
||||
|
||||
@@ -1,279 +0,0 @@
|
||||
# CLAUDE.md
|
||||
|
||||
## Documentation Status
|
||||
- Synchronized with release 0.2.0 baseline on 2026-06-01 (see `CHANGELOG.md`).
|
||||
- Default workflow outputs: `artifacts/` — do not commit generated CSV/JSON at repo root.
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Video Library Manager (VLM) is a Python CLI tool for managing personal video collections with a safety-first, human-in-the-loop approach. All file operations are reversible, require explicit confirmation, and generate reviewable execution plans before making changes.
|
||||
|
||||
## Development Commands
|
||||
|
||||
**Important:** This project uses `uv` for Python package management. All commands should be run with `uv run` to ensure they execute in the correct project environment with proper dependencies.
|
||||
|
||||
### Installation
|
||||
```bash
|
||||
# Install package in editable mode
|
||||
uv pip install -e .
|
||||
|
||||
# Install with dev dependencies (pytest, hypothesis)
|
||||
uv pip install -e ".[dev]"
|
||||
|
||||
# Optional Textual UI for `vlm review-plan --tui`
|
||||
uv pip install -e ".[tui]"
|
||||
```
|
||||
|
||||
The default CLI path does not require Textual; it is imported only when `uv run vlm review-plan --tui` is used.
|
||||
|
||||
### Testing
|
||||
```bash
|
||||
# Run all tests (use uv run to execute in the project environment)
|
||||
uv run pytest
|
||||
|
||||
# Run specific test file
|
||||
uv run pytest tests/test_scanner.py
|
||||
|
||||
# Run with verbose output
|
||||
uv run pytest -v
|
||||
|
||||
# Run with quiet output (summary only)
|
||||
uv run pytest -q
|
||||
|
||||
# Count total test cases
|
||||
uv run pytest --collect-only -q
|
||||
```
|
||||
|
||||
### Running the CLI
|
||||
```bash
|
||||
# Verify CLI works (use uv run for proper environment)
|
||||
uv run vlm --help
|
||||
|
||||
# Initialize config
|
||||
uv run vlm config init
|
||||
|
||||
# Common workflow
|
||||
uv run vlm scan # Discover files
|
||||
uv run vlm parse # Extract identities (v1 schema)
|
||||
uv run vlm parse --inventory artifacts/inventory.csv # Embed metadata for quality-aware duplicate handling
|
||||
uv run vlm enrich # (Optional) Enrich titles/reputation via TMDB
|
||||
uv run vlm enrich --refresh-all # Force full refresh (ignore cache)
|
||||
uv run vlm analyze # Detect gaps/duplicates
|
||||
uv run vlm plan # Generate execution plan
|
||||
uv run vlm plan --analysis artifacts/analysis.json # Generate plan with duplicate resolution
|
||||
uv run vlm review-plan # Export CSV + terminal review preview
|
||||
uv run vlm review-plan --tui # Optional full-screen review UI
|
||||
uv run vlm apply-review # Sync edited CSV decisions back into the plan
|
||||
uv run vlm execute # Dry-run (default)
|
||||
uv run vlm execute --confirm # Actually execute
|
||||
uv run vlm rollback # Undo executed operations
|
||||
|
||||
# Reporting
|
||||
uv run vlm report summary # Overview statistics
|
||||
uv run vlm report inventory # File inventory
|
||||
uv run vlm report completeness # Series with missing episodes
|
||||
uv run vlm report duplicates # Duplicate files with quality comparison
|
||||
|
||||
# Quarantine management
|
||||
uv run vlm quarantine list # List quarantined files
|
||||
uv run vlm quarantine add <file> --reason "duplicate"
|
||||
uv run vlm quarantine restore <file>
|
||||
|
||||
# State management
|
||||
uv run vlm state show <file>
|
||||
uv run vlm state set <file> --status reviewed
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Workflow
|
||||
VLM follows a read-first, multi-stage pipeline:
|
||||
1. **Scan** → discovers video files, extracts metadata via ffprobe (optional), saves to `artifacts/inventory.csv`
|
||||
2. **Parse** → extracts titles/years/seasons/episodes from filenames, saves to `artifacts/identities.json`
|
||||
- Use `--inventory artifacts/inventory.csv` to embed video metadata (v2 schema) for accurate duplicate resolution by quality
|
||||
- Without `--inventory`, produces v1 schema (lightweight, no embedded metadata)
|
||||
3. **Enrich** (optional) → adds bilingual titles and reputation (TMDB); updates `artifacts/identities.json` in place; uses SQLite cache for incremental runs
|
||||
4. **Analyze** → detects episode gaps and duplicates, saves to `artifacts/analysis.json`
|
||||
5. **Plan** → generates reviewable execution plan (`artifacts/plan.json`) with file operations
|
||||
6. **Review / Apply Review** → previews high-risk operations in terminal or optional TUI, then syncs edited CSV decisions back into the plan when needed
|
||||
7. **Execute** → performs file operations (dry-run by default, `--confirm` to execute)
|
||||
8. **Rollback** → reverses executed operations (best-effort)
|
||||
|
||||
### Module Organization
|
||||
- `cli.py` - Thin Click registrar with global options; command definitions live in `commands/`
|
||||
- `cli_helpers.py` - Shared CLI helpers (context init, command runner, report emission)
|
||||
- `context.py` - CLIContext (config, paths) and pass_context for commands
|
||||
- `commands/` - Command modules (scan, parse, enrich, analyze, plan, execute/rollback, review_plan, report, quarantine_cmd, state_cmd, config_cmd)
|
||||
- `plan_render.py` - Shared rendering of plan summaries in CLI output
|
||||
- `plan_review.py` - High-risk operation flagging and manual-review export
|
||||
- `plan_structure_preview.py` - Target library tree preview for review-plan
|
||||
- `review_display.py` - Human-readable plan review rendering shared by CLI preview and TUI
|
||||
- `review_tui.py` - Optional Textual review UI (lazy import)
|
||||
- `transaction.py` - Transaction/rollback logging for executed operations
|
||||
- `scanner.py` - File discovery using system `find` command, metadata extraction via ffprobe
|
||||
- `parser.py` - Filename parsing using regex patterns (movies: title + year, series: SxxExx)
|
||||
- `enrichment.py` - Enrichment pipeline; `cache.py` - SQLite cache; `providers/` - TMDB etc.
|
||||
- `io.py` - Unified JSON/CSV I/O helpers, including validated typed plan loading/saving
|
||||
- `utils.py` - UTC time, format_size, shared helpers
|
||||
- `analysis.py` - Completeness checking (episode gaps) and duplicate detection
|
||||
- `duplicate_resolve.py` - Duplicate group resolution with explicit failures for unresolved strategies/data
|
||||
- `planner.py` - Execution plan generation with conflict detection and manual-review duplicate fallback
|
||||
- `executor.py` - File operations (move/rename/quarantine) with rollback logging and library-root safety checks
|
||||
- `quarantine.py` - Quarantine management with manifest tracking
|
||||
- `state.py` - File state tracking across workflow stages
|
||||
- `reports.py` - Report generation (inventory, completeness, duplicates, summary)
|
||||
- `config.py` - YAML configuration loading and validation
|
||||
- `models.py` - Dataclass definitions for all data structures
|
||||
- `logging_config.py` - Logging setup with fallback to console if file logging fails
|
||||
|
||||
### Key Data Structures
|
||||
All defined in `models.py`:
|
||||
- `VideoFile` - represents discovered video file with metadata
|
||||
- `MovieIdentity` / `SeriesIdentity` - parsed identity with confidence score
|
||||
- `ExecutionPlan` - collection of file operations with summary
|
||||
- `FileOperation` - single operation (move/rename/quarantine/no-op) with conflict detection
|
||||
- `RollbackLog` - log of executed operations for reversal
|
||||
- `QuarantineEntry` - quarantined file with original location
|
||||
- `FileState` - workflow state (reviewed/ignored/planned/executed/quarantined)
|
||||
|
||||
### File Categorization
|
||||
Based on top-level directory within library root, matched against configured category mappings (case-insensitive).
|
||||
|
||||
Files in unmapped directories are categorized as "other" and skipped by planner/quarantine operations.
|
||||
|
||||
### Parsing Patterns (Hardcoded)
|
||||
**Movies** (high confidence):
|
||||
- `{title} ({year})`
|
||||
- `{title}.{year}`
|
||||
|
||||
**Series** (high confidence):
|
||||
- `S{season:02d}E{episode:02d}`
|
||||
- `{season}x{episode}`
|
||||
|
||||
Patterns are hardcoded in parser.py, not user-configurable.
|
||||
|
||||
### Configuration
|
||||
Default location: `~/.vlm/config.yaml`
|
||||
|
||||
Key settings:
|
||||
- `library_root` - root directory to scan (required)
|
||||
- `video_extensions` - list of extensions to recognize
|
||||
- `templates.movie_dir` / `templates.series_dir` - directory structure templates
|
||||
- `templates.movie_filename` / `templates.series_filename` - filename templates
|
||||
- `quarantine_dir` - name of quarantine directory (default: `.quarantine`)
|
||||
- `log_level` - logging verbosity
|
||||
- `categories` - mapping of category names to directory name lists
|
||||
- `enrichment` (or `enrich`) - TMDB/api_keys, cache_db, translation, reputation; see README for full schema
|
||||
- `plan.duplicate_keep` - when using `vlm plan --analysis`: `by_quality`, `by_reputation` (default), `by_reputation_quality_time`, `first_seen`, or `manual`
|
||||
|
||||
### Category Mappings
|
||||
|
||||
Categories are determined by matching the top-level directory name against configured mappings:
|
||||
|
||||
**Default mappings:**
|
||||
```yaml
|
||||
categories:
|
||||
movie: [movie]
|
||||
series: [series]
|
||||
anime: [anime]
|
||||
```
|
||||
|
||||
**Custom mappings** support multiple directory names per category:
|
||||
```yaml
|
||||
categories:
|
||||
movie: [movie, movies, films]
|
||||
series: [series, tv, shows, television]
|
||||
anime: [anime]
|
||||
```
|
||||
|
||||
This allows files in `/library/movies/` or `/library/films/` to be recognized as the "movie" category. Directory matching is case-insensitive.
|
||||
|
||||
**Migration Note:** If you have existing directories with non-standard names (like "movies" or "tv"), update your config.yaml and re-run `vlm scan` to fix categorization. No files will be moved.
|
||||
|
||||
### Schema Versioning
|
||||
|
||||
**identities.json Schema Versions:**
|
||||
|
||||
- **v1** (default without `--inventory`): Lightweight schema without embedded metadata
|
||||
- Records contain: path, filename, category, title, year/season/episodes, confidence, needs_review
|
||||
- VideoFile objects reconstructed with defaults: size_bytes=0, resolution=None, codec=None
|
||||
- Suitable for basic organization workflows
|
||||
|
||||
- **v2** (with `--inventory`): Enhanced schema with embedded video metadata
|
||||
- All v1 fields plus `video_metadata` object containing:
|
||||
- size_bytes, modified_timestamp, resolution, codec, duration_seconds, bitrate_kbps
|
||||
- Enables accurate duplicate resolution by quality (compare resolution, codec, file size)
|
||||
- Required for `by_quality` duplicate resolution strategy
|
||||
- Backward compatible: v1 files load without errors
|
||||
|
||||
**Implementation Details:**
|
||||
- `_video_file_from_record()` in io.py extracts embedded metadata if present
|
||||
- Parse command with `--inventory` flag loads inventory.csv and embeds metadata in output
|
||||
- Schema version stored in `vlm_schema_version` field at root level of identities.json
|
||||
|
||||
### File Discovery
|
||||
Uses system `find` command for speed, falls back to Python recursion if unavailable. Hidden paths (starting with `.`) are skipped automatically.
|
||||
|
||||
### Timestamp Handling
|
||||
All timestamps stored in UTC using ISO 8601 format (`YYYY-MM-DDTHH:MM:SS`). The scanner normalizes naive timestamps to UTC using system timezone.
|
||||
|
||||
### Logging
|
||||
Logs to `~/.vlm/vlm.log` by default. If log directory is unwritable, falls back to console-only logging and continues execution (does not fail).
|
||||
|
||||
### Error Handling
|
||||
- Configuration errors: display helpful message, create default config, continue
|
||||
- Missing ffprobe: skip metadata extraction, log debug message, continue
|
||||
- File access errors: log error, skip file, continue scanning
|
||||
- Invalid YAML: display error, use default config
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
- Framework: pytest with hypothesis for property-based tests
|
||||
- Test file naming: `test_*.py`
|
||||
- Test function naming: `test_*`
|
||||
- Test class naming: `Test*`
|
||||
- Use `CliRunner` for CLI integration tests
|
||||
- Prefer narrow unit tests for module logic plus targeted CLI integration tests
|
||||
- Add tests with each behavior change, including error paths and edge cases
|
||||
|
||||
## Important Implementation Notes
|
||||
|
||||
### Safety Protocol
|
||||
- NEVER permanently delete files - use quarantine instead
|
||||
- All file operations create rollback logs when executed with --confirm
|
||||
- Execution plans detect destination conflicts and mark operations
|
||||
- Default mode is dry-run; --confirm required for actual execution
|
||||
- Quarantine is reversible via restore command
|
||||
|
||||
### Anime Handling
|
||||
Anime files are discovered and categorized but NOT parsed in v1 (deferred for future implementation).
|
||||
|
||||
### State Management
|
||||
State tracking is optional and allows marking files as reviewed/ignored/planned/executed/quarantined. State is persisted to `~/.vlm/state.json`.
|
||||
|
||||
### Quarantine Constraints
|
||||
Only movie and series files can be quarantined in v1 (anime and other categories rejected).
|
||||
|
||||
### Template Variables
|
||||
Available for path/filename templates:
|
||||
- Movies: `{title}`, `{year}`, `{ext}`
|
||||
- Series: `{title}`, `{season}`, `{episode}`, `{ext}`
|
||||
|
||||
Format specifiers like `{season:02d}` are supported.
|
||||
|
||||
## Code Style
|
||||
|
||||
- Python 3.10+ idioms
|
||||
- 4-space indentation
|
||||
- PEP 8 naming: `snake_case` for functions/variables, `PascalCase` for classes, `UPPER_SNAKE_CASE` for constants
|
||||
- Type hints for public functions and non-trivial internal APIs
|
||||
- Modules focused on single responsibility
|
||||
- No formatter/linter enforced - maintain consistency with existing files
|
||||
|
||||
## Commit Guidelines
|
||||
|
||||
- Clear, imperative commit subjects (e.g., "fix logging fallback for unwritable log dir")
|
||||
- Keep commits focused - avoid mixing refactors and behavior changes
|
||||
- Include co-author tag: `Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>`
|
||||
Reference in New Issue
Block a user