docs: expand CONTRIBUTING with practical contributor workflow

Replace the minimal semver stub with setup steps, module map, safety
invariants, artifact guidance, PR checklist, and CI expectations.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
windyboy
2026-06-01 16:55:55 +08:00
co-authored by Cursor
parent 6f0df5a774
commit c7a55190d7
+137 -16
View File
@@ -1,33 +1,154 @@
# Contributing # Contributing to Video Library Manager (VLM)
## Versioning Thanks for helping improve VLM. This guide is for humans patching the CLI and library code—not for running the tool on your own media collection (see [README.md](README.md) for that).
This project follows [Semantic Versioning](https://semver.org/): ## What fits here
- **PATCH** — bug fixes, documentation-only changes Good contributions:
- **MINOR** — backward-compatible features (new commands, options, schema fields)
- **MAJOR** — breaking changes to CLI contracts, config keys, or artifact schemas
Release notes and test baselines are recorded in [`CHANGELOG.md`](CHANGELOG.md). - Bug fixes and regressions in `src/vlm/`
- CLI UX, validation messages, and safer defaults
- Tests and docs that match current behavior
- Performance or correctness in scan/parse/plan/execute paths
Out of scope unless discussed first:
- Breaking changes to artifact JSON schemas or default CLI behavior without a migration note in the PR
- Features that permanently delete files (use quarantine; see safety rules below)
- Committing generated workflow output or personal library data
## Prerequisites
- **Python 3.10+** (CI also runs 3.11 and 3.12)
- **[uv](https://github.com/astral-sh/uv)** for installs and `uv run …`
- **Git**
- Optional for manual end-to-end checks: `ffprobe` on `PATH` (metadata extraction degrades without it)
## Development setup ## Development setup
```bash ```bash
git clone <your-fork-url>
cd dl-organizer
# Editable install + dev tools (pytest, hypothesis, ruff, pytest-cov)
uv pip install -e ".[dev]" uv pip install -e ".[dev]"
# Optional: Textual UI for `vlm review-plan --tui` only
uv pip install -e ".[tui]"
```
Verify the environment:
```bash
uv run vlm --help
uv run ruff check src tests
uv run pytest -q uv run pytest -q
``` ```
Optional Textual UI: `uv pip install -e ".[tui]"`. Expect **517** tests to pass on the current baseline (`uv run pytest -q``517 passed`). If you change behavior, update or add tests—do not weaken assertions to green the suite.
## Pull requests During iteration, run a narrow file instead of the full suite:
1. Write or extend tests for behavior changes. ```bash
2. Run `uv run pytest -q` locally (CI runs the same). uv run pytest tests/test_planner.py -q
3. Keep commits focused; use imperative subject lines. uv run pytest tests/test_cli_scan.py::test_scan_writes_inventory -q
4. Do not commit personal library paths, workflow artifacts (`artifacts/`, root CSV/JSON), or API keys from `~/.vlm/config.yaml`. ```
## Where to change things
| Area | Location | Tests often in |
|------|----------|----------------|
| CLI registration | `src/vlm/cli.py` | `tests/test_cli_*.py` |
| Command implementation | `src/vlm/commands/` | matching `tests/test_cli_*.py` |
| Scan / inventory | `scanner.py` | `test_scanner.py`, `test_cli_scan.py` |
| Parse / identities | `parser.py`, `io.py` | `test_parser.py`, `test_io.py` |
| Enrich / TMDB | `enrichment.py`, `providers/` | `test_enrichment.py` |
| Analysis / duplicates | `analysis.py`, `duplicate_resolve.py` | `test_analysis*.py`, `test_duplicate_*.py` |
| Plan / review | `planner.py`, `plan_review.py`, `review_tui.py` | `test_planner.py`, `test_plan_review.py` |
| Execute / rollback | `executor.py`, `transaction.py` | `test_executor.py`, `test_cli_rollback.py` |
| Config | `config.py` | `test_config.py` |
| Shared models | `models.py` | domain tests that construct fixtures |
Agent-oriented repo notes live in [AGENTS.md](AGENTS.md). Architecture and workflow stages are summarized in [CLAUDE.md](CLAUDE.md).
## Safety rules (do not regress)
VLM is built around reversible, reviewed file operations:
1. **No permanent deletes** in normal workflows—duplicates go to quarantine.
2. **`vlm execute` is dry-run by default**; real moves need `--confirm` and rollback logging.
3. **Paths must stay under `library_root`** for move/rename execution.
4. **Default pipeline is read-first**: scan → parse → (enrich) → analyze → plan → review → execute. Do not hide destructive steps behind implicit flags.
If your change touches `executor.py`, `planner.py`, or `quarantine.py`, add or extend tests for failure paths and library-root checks.
## Artifacts and schemas
Generated files belong under `artifacts/` (or `workspace_dir` in config)—**never commit** them, root-level `inventory.csv` / `identities.json` / `plan.json`, or copies of `~/.vlm/config.yaml`.
| Artifact | Notes for contributors |
|----------|-------------------------|
| `identities.json` | v1 without `--inventory`; v2 embeds video metadata for quality-aware duplicates |
| `analysis.json` | Output of analyze; input to `vlm plan --analysis` |
| `plan.json` | Validated typed `ExecutionPlan`; review CSV syncs via `apply-review` |
Loading/saving goes through `io.py` with schema validation. If you add or rename JSON fields, update loaders, tests, and call out **backward compatibility** in the PR (v1 identities must still load).
## Code style ## Code style
- Python 3.10+, 4-space indentation, type hints on public APIs. - Python 3.10+, 4 spaces, PEP 8 naming (`snake_case` / `PascalCase`).
- Use absolute imports in package code: `from vlm.module import ...` (not relative imports in new code). - Type hints on public functions and non-trivial internal APIs.
- `uv run ruff check src tests` when Ruff is installed via `[dev]`. - Absolute imports in package code: `from vlm.module import …` (no new relative imports in `src/vlm/`).
- Ruff: `E`, `F`, `I` (see `pyproject.toml`). CI runs `uv run ruff check src tests`.
- Prefer small, focused modules; put CLI wiring in `commands/`, not bloated `cli.py`.
## Testing expectations
| Change type | Minimum bar |
|-------------|-------------|
| Pure helper / module logic | Unit test in `tests/test_<module>.py` |
| CLI flag or error message | `CliRunner` test in `tests/test_cli_*.py` |
| Invariants across inputs | Consider `hypothesis` (existing pattern in `test_*_properties.py`) |
| Config key or default | `test_config.py` + note in PR if users must edit `config.yaml` |
Property tests use Hypothesis with `max_examples = 100` in `pyproject.toml`.
Coverage is optional locally: `uv run pytest --cov=vlm --cov-report=term-missing` (requires `[dev]`).
## Pull request checklist
Before opening a PR:
- [ ] Branch is up to date with `main` (or target branch)
- [ ] `uv run ruff check src tests` passes
- [ ] `uv run pytest -q` passes (full suite)
- [ ] New/changed behavior has tests; CLI changes have at least one failure-path test if applicable
- [ ] No secrets, personal paths, or generated artifacts in the diff
- [ ] PR description: **what**, **why**, and **how you tested** (paste `pytest` summary or targeted command)
- [ ] Breaking CLI, config, or schema changes: migration steps and suggested `CHANGELOG.md` entry (maintainers may edit release notes)
Commit messages: short imperative subject (`fix planner conflict when destination exists`). Keep commits focused; split refactors from behavior changes when possible.
## CI
GitHub Actions (`.github/workflows/test.yml`) on push/PR to `main` / `master`:
1. `uv pip install -e ".[dev]"`
2. `uv run ruff check src tests`
3. `uv run pytest -q` on Python **3.10, 3.11, 3.12**
Match CI locally before requesting review.
## Versioning and releases
[Semantic Versioning](https://semver.org/):
- **PATCH** — bug fixes, docs-only
- **MINOR** — backward-compatible features (commands, options, new optional JSON fields)
- **MAJOR** — breaking CLI contracts, config keys, or artifact schemas
Release history: [CHANGELOG.md](CHANGELOG.md). Package version: `pyproject.toml``[project].version`.
## Questions
Open an issue for bugs or design questions. For large features, describe the safety impact (especially execute/quarantine) before a big PR so review stays tractable.