## 1. Think Before Coding

**Don't assume. Don't hide confusion. Surface tradeoffs.**

Before implementing:
- State your assumptions explicitly. If uncertain, ask.
- If multiple interpretations exist, present them - don't pick silently.
- If a simpler approach exists, say so. Push back when warranted.
- If something is unclear, stop. Name what's confusing. Ask.

## 2. Simplicity First

**Minimum code that solves the problem. Nothing speculative.**

- No features beyond what was asked.
- No abstractions for single-use code.
- No "flexibility" or "configurability" that wasn't requested.
- No error handling for impossible scenarios.
- If you write 200 lines and it could be 50, rewrite it.

Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.

## 3. Surgical Changes

**Touch only what you must. Clean up only your own mess.**

When editing existing code:
- Don't "improve" adjacent code, comments, or formatting.
- Don't refactor things that aren't broken.
- Match existing style, even if you'd do it differently.
- If you notice unrelated dead code, mention it - don't delete it.

When your changes create orphans:
- Remove imports/variables/functions that YOUR changes made unused.
- Don't remove pre-existing dead code unless asked.

The test: Every changed line should trace directly to the user's request.

## 4. Goal-Driven Execution

**Define success criteria. Loop until verified.**

Transform tasks into verifiable goals:
- "Add validation" → "Write tests for invalid inputs, then make them pass"
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
- "Refactor X" → "Ensure tests pass before and after"

For multi-step tasks, state a brief plan:
```
1. [Step] → verify: [check]
2. [Step] → verify: [check]
3. [Step] → verify: [check]
```

Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.

---

**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.

## 5. Repository Context

**VDL is a local-first media workflow toolkit, not just a downloader wrapper.**

Treat the current package under `src/vdl` as the active implementation.

Core product boundaries:
- `vdl` is the Python package and shared library.
- `vdl` is also the primary CLI command.
- `vdl-mcp` is an MCP server command exposed by the same package.
- `vdl` and `vdl-mcp` are commands/interfaces, not separate libraries.
- Shared business logic belongs in the library/core layer, not in CLI-only or MCP-only code.
- CLI, headless mode, Python API, and MCP should be adapters over the same core workflows.

Current release model:
- PyPI package name: `vdl`.
- Release tags: `vdl-vX.Y.Z`.
- PyPI publishing happens in GitLab CI using Trusted Publishing where possible.
- macOS arm64 standalone builds are local-first via `scripts/build-macos.sh`.
- Linux and Windows standalone builds are optional CI paths behind release variables.
- Do not commit generated binaries, wheels, sdists, archives, or release assets.

## 6. Development Commands

Prefer these commands for local validation:

```bash
uv sync --frozen --all-extras --dev
PYTHONPATH=src uv run pytest -q
uv build --no-sources
```

Useful Taskfile commands, when available:

```bash
task --list
task test
task build
task release:validate
```

Before changing release behavior, inspect:
- `.gitlab-ci.yml`
- `ci/release-vdl.yml`
- `ci/release-linux.yml`
- `ci/release-windows.yml`
- `scripts/build-macos.sh`
- `scripts/install.sh`
- `docs/RELEASE_PLAYBOOK.md`

## 7. Python Style and Docstrings

**Public code needs useful docstrings. Private implementation details need clarity, not noise.**

Add or update docstrings when creating or materially changing:
- public modules
- public classes
- public functions
- public methods
- dataclasses or models exposed to users/tests
- CLI/MCP entry points whose behavior is not obvious

Use concise Google-style docstrings by default:

```python
def resolve_playlist(url: str, limit: int | None = None) -> PlaylistResolution:
    """Resolve a playlist URL into selectable media items.

    Args:
        url: Playlist or page URL to inspect.
        limit: Optional maximum number of items to return.

    Returns:
        A playlist resolution containing discovered media items.

    Raises:
        VdlError: If the URL cannot be resolved.
    """
```

Docstring rules:
- Document intent and externally relevant behavior, not line-by-line mechanics.
- Include `Args`, `Returns`, and `Raises` only when they add useful information.
- Do not add verbose docstrings to trivial private helpers.
- Do not write misleading docstrings that claim behavior not covered by code or tests.
- Update stale docstrings when behavior changes.
- Prefer precise domain language: `download plan`, `playlist resolution`, `selection policy`, `local state`, `MCP tool`.

## 8. Tests and Verification

Every behavior change should be verified. Prefer the smallest meaningful test.

Testing expectations:
- Unit tests for pure logic and parsing.
- Contract tests for downloader/playlist interfaces.
- Integration tests for SQLite state and filesystem behavior.
- Smoke checks for CLI entry points, release scripts, and installer behavior.
- Regression tests for every bug fix when practical.

When changing CLI behavior:
- Verify command help still works.
- Verify error messages are actionable.
- Avoid breaking existing scripts unless the change is intentional and documented.

When changing MCP behavior:
- Keep MCP as an adapter over core functionality.
- Do not make MCP depend on the interactive CLI.
- If the optional `mcp` dependency is missing, `vdl-mcp` should fail gracefully with an install hint such as `pip install "vdl[mcp]"`.

## 9. Release and Packaging Guardrails

Be conservative with release code. A broken release pipeline wastes time and can publish bad artifacts.

Packaging rules:
- Keep `pyproject.toml` as the source of package metadata.
- Keep the PyPI package name aligned with `[project].name`.
- Use `uv build --no-sources` for release package builds.
- Standalone binary builds should include both `vdl` and `vdl-mcp` when intended.
- Do not include Windows in installer-facing `release.json` until there is a native Windows install path or explicit manual-download semantics.
- Linux/Windows CI artifacts must be attached to the GitLab Release before the Pages manifest advertises them.
- Avoid checksum filename collisions across platforms.

Release validation should check:
- package metadata
- console scripts
- included package data such as `vdl/data/websites.yaml`
- YAML validity for GitLab CI files
- shell syntax/linting for release scripts
- artifact naming conventions
- `release.json` URLs and SHA256 values

## 10. Documentation and Branding

Keep documentation professional, concise, and product-oriented.

Preferred positioning:
> VDL is a local-first media workflow toolkit for downloads, playlists, and automation through CLI, library, and MCP interfaces.

Avoid top-level branding like:
- “yt-dlp wrapper”
- “thin wrapper”
- “lightweight wrapper around yt-dlp”
- “powered by yt-dlp” in the headline

It is fine to mention later that VDL uses `yt-dlp` under the hood for media extraction and download support.

Documentation rules:
- Keep `README.md` as a professional landing page, not a full manual.
- Put deep release details in `docs/RELEASE_PLAYBOOK.md`.
- Keep release documentation focused on the live playbook in `docs/RELEASE_PLAYBOOK.md`.
- Do not claim features that are not implemented.
- Prefer short examples that can be copied and run.

## 11. Final Response Expectations

When finishing a task:
- Summarize what changed.
- List verification commands run and their results.
- Mention anything not run and why.
- Mention follow-up manual steps only when they are genuinely required.
- If a patch was created, keep the explanation concise and tie it directly to the user request.
