vdl 1.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. vdl-1.0.1/.env-template +24 -0
  2. vdl-1.0.1/.gitignore +23 -0
  3. vdl-1.0.1/.gitlab-ci.yml +62 -0
  4. vdl-1.0.1/AGENTS.md +59 -0
  5. vdl-1.0.1/CHANGELOG.md +50 -0
  6. vdl-1.0.1/CLAUDE.md +221 -0
  7. vdl-1.0.1/CODEX.md +221 -0
  8. vdl-1.0.1/PKG-INFO +421 -0
  9. vdl-1.0.1/README.md +385 -0
  10. vdl-1.0.1/Taskfile.yml +310 -0
  11. vdl-1.0.1/ci/release-linux.yml +85 -0
  12. vdl-1.0.1/ci/release-vdl.yml +227 -0
  13. vdl-1.0.1/ci/release-windows.yml +59 -0
  14. vdl-1.0.1/docs/RELEASE_PLAYBOOK.md +201 -0
  15. vdl-1.0.1/docs/RELEASE_SETUP_VERIFICATION.md +206 -0
  16. vdl-1.0.1/frozen/README.md +17 -0
  17. vdl-1.0.1/frozen/vdl-v0/.gitignore +20 -0
  18. vdl-1.0.1/frozen/vdl-v0/README.md +48 -0
  19. vdl-1.0.1/frozen/vdl-v0/docs/cli-usage.md +51 -0
  20. vdl-1.0.1/frozen/vdl-v0/docs/configuration.md +42 -0
  21. vdl-1.0.1/frozen/vdl-v0/docs/downloads-and-idempotency.md +28 -0
  22. vdl-1.0.1/frozen/vdl-v0/docs/install.md +57 -0
  23. vdl-1.0.1/frozen/vdl-v0/docs/release-builds.md +82 -0
  24. vdl-1.0.1/frozen/vdl-v0/docs/troubleshooting.md +52 -0
  25. vdl-1.0.1/frozen/vdl-v0/release/generate_release_json.py +89 -0
  26. vdl-1.0.1/frozen/vdl-v0/release/install-local.sh +26 -0
  27. vdl-1.0.1/frozen/vdl-v0/release/install.sh +139 -0
  28. vdl-1.0.1/frozen/vdl-v0/scripts/dev/export-code.sh +110 -0
  29. vdl-1.0.1/frozen/vdl-v0/vdl-core/README.md +6 -0
  30. vdl-1.0.1/frozen/vdl-v0/vdl-core/pyproject.toml +30 -0
  31. vdl-1.0.1/frozen/vdl-v0/vdl-core/tests/__init__.py +1 -0
  32. vdl-1.0.1/frozen/vdl-v0/vdl-core/tests/test_output_paths.py +75 -0
  33. vdl-1.0.1/frozen/vdl-v0/vdl-core/uv.lock +615 -0
  34. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/__init__.py +0 -0
  35. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/__main__.py +15 -0
  36. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/cli/__init__.py +0 -0
  37. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/cli/commands.py +782 -0
  38. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/cli/ui.py +833 -0
  39. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/config/__init__.py +0 -0
  40. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/config/app_paths.py +50 -0
  41. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/config/defaults.py +21 -0
  42. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/config/manager.py +103 -0
  43. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/config/paths.py +84 -0
  44. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/__init__.py +0 -0
  45. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/batch.py +219 -0
  46. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/crawler.py +697 -0
  47. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/downloader.py +1222 -0
  48. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/library_manager.py +9 -0
  49. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/metadata_extractor.py +8 -0
  50. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/models.py +34 -0
  51. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/playlist.py +254 -0
  52. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/processor.py +8 -0
  53. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/core/video_converter.py +204 -0
  54. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/release.py +164 -0
  55. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/state.py +141 -0
  56. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/__init__.py +0 -0
  57. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/console.py +11 -0
  58. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/errors.py +8 -0
  59. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/logging/__init__.py +5 -0
  60. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/logging/config.py +64 -0
  61. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/logging/context.py +25 -0
  62. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/logging/filters.py +14 -0
  63. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/logging/formatters.py +35 -0
  64. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/logging/logger.py +9 -0
  65. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/sanitizers.py +50 -0
  66. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/url_helpers.py +116 -0
  67. vdl-1.0.1/frozen/vdl-v0/vdl-core/vdl_core/utils/validators.py +8 -0
  68. vdl-1.0.1/frozen/vdl-v0/vdl.spec +73 -0
  69. vdl-1.0.1/pyproject.toml +82 -0
  70. vdl-1.0.1/scripts/build-macos.sh +74 -0
  71. vdl-1.0.1/scripts/install.sh +184 -0
  72. vdl-1.0.1/scripts/release.sh +423 -0
  73. vdl-1.0.1/src/README.md +12 -0
  74. vdl-1.0.1/src/vdl/__init__.py +35 -0
  75. vdl-1.0.1/src/vdl/acquisition.py +96 -0
  76. vdl-1.0.1/src/vdl/bootstrap.py +60 -0
  77. vdl-1.0.1/src/vdl/cancellation.py +109 -0
  78. vdl-1.0.1/src/vdl/cli.py +540 -0
  79. vdl-1.0.1/src/vdl/client.py +1014 -0
  80. vdl-1.0.1/src/vdl/config.py +255 -0
  81. vdl-1.0.1/src/vdl/crawler.py +627 -0
  82. vdl-1.0.1/src/vdl/data/websites.yaml +186 -0
  83. vdl-1.0.1/src/vdl/doctor.py +207 -0
  84. vdl-1.0.1/src/vdl/downloader.py +717 -0
  85. vdl-1.0.1/src/vdl/error_translation.py +139 -0
  86. vdl-1.0.1/src/vdl/errors.py +77 -0
  87. vdl-1.0.1/src/vdl/impersonation.py +56 -0
  88. vdl-1.0.1/src/vdl/input_parser.py +50 -0
  89. vdl-1.0.1/src/vdl/interactive.py +783 -0
  90. vdl-1.0.1/src/vdl/logging.py +95 -0
  91. vdl-1.0.1/src/vdl/mcp_server.py +118 -0
  92. vdl-1.0.1/src/vdl/mcp_setup.py +149 -0
  93. vdl-1.0.1/src/vdl/models.py +362 -0
  94. vdl-1.0.1/src/vdl/naming.py +170 -0
  95. vdl-1.0.1/src/vdl/paths.py +275 -0
  96. vdl-1.0.1/src/vdl/playlist.py +364 -0
  97. vdl-1.0.1/src/vdl/probe.py +46 -0
  98. vdl-1.0.1/src/vdl/progress.py +390 -0
  99. vdl-1.0.1/src/vdl/prompt_utils.py +216 -0
  100. vdl-1.0.1/src/vdl/selection.py +124 -0
  101. vdl-1.0.1/src/vdl/serialization.py +142 -0
  102. vdl-1.0.1/src/vdl/site_rules.py +100 -0
  103. vdl-1.0.1/src/vdl/state.py +411 -0
  104. vdl-1.0.1/src/vdl/tools.py +255 -0
  105. vdl-1.0.1/src/vdl/urls.py +331 -0
  106. vdl-1.0.1/tests/README.md +5 -0
  107. vdl-1.0.1/tests/conftest.py +18 -0
  108. vdl-1.0.1/tests/contract/__init__.py +0 -0
  109. vdl-1.0.1/tests/contract/test_downloader_contract.py +90 -0
  110. vdl-1.0.1/tests/contract/test_playlist_contract.py +153 -0
  111. vdl-1.0.1/tests/integration/__init__.py +0 -0
  112. vdl-1.0.1/tests/integration/test_sqlite_state.py +220 -0
  113. vdl-1.0.1/tests/smoke/__init__.py +0 -0
  114. vdl-1.0.1/tests/support/__init__.py +0 -0
  115. vdl-1.0.1/tests/support/fake_downloader.py +41 -0
  116. vdl-1.0.1/tests/support/fake_playlist_resolver.py +44 -0
  117. vdl-1.0.1/tests/support/fake_state_store.py +157 -0
  118. vdl-1.0.1/tests/unit/__init__.py +0 -0
  119. vdl-1.0.1/tests/unit/test_acquisition.py +107 -0
  120. vdl-1.0.1/tests/unit/test_bootstrap.py +108 -0
  121. vdl-1.0.1/tests/unit/test_cancellation.py +200 -0
  122. vdl-1.0.1/tests/unit/test_cli.py +264 -0
  123. vdl-1.0.1/tests/unit/test_client.py +971 -0
  124. vdl-1.0.1/tests/unit/test_config.py +197 -0
  125. vdl-1.0.1/tests/unit/test_crawler.py +140 -0
  126. vdl-1.0.1/tests/unit/test_doctor.py +171 -0
  127. vdl-1.0.1/tests/unit/test_error_translation.py +107 -0
  128. vdl-1.0.1/tests/unit/test_errors.py +79 -0
  129. vdl-1.0.1/tests/unit/test_impersonation.py +67 -0
  130. vdl-1.0.1/tests/unit/test_imports.py +64 -0
  131. vdl-1.0.1/tests/unit/test_input_parser.py +77 -0
  132. vdl-1.0.1/tests/unit/test_interactive.py +307 -0
  133. vdl-1.0.1/tests/unit/test_interactive_helpers.py +69 -0
  134. vdl-1.0.1/tests/unit/test_mcp_server.py +28 -0
  135. vdl-1.0.1/tests/unit/test_mcp_setup.py +93 -0
  136. vdl-1.0.1/tests/unit/test_models.py +224 -0
  137. vdl-1.0.1/tests/unit/test_naming.py +183 -0
  138. vdl-1.0.1/tests/unit/test_paths.py +212 -0
  139. vdl-1.0.1/tests/unit/test_probe.py +17 -0
  140. vdl-1.0.1/tests/unit/test_progress.py +233 -0
  141. vdl-1.0.1/tests/unit/test_prompt_utils.py +85 -0
  142. vdl-1.0.1/tests/unit/test_selection.py +153 -0
  143. vdl-1.0.1/tests/unit/test_serialization.py +158 -0
  144. vdl-1.0.1/tests/unit/test_sidecars_and_layout.py +139 -0
  145. vdl-1.0.1/tests/unit/test_site_rules.py +90 -0
  146. vdl-1.0.1/tests/unit/test_state.py +204 -0
  147. vdl-1.0.1/tests/unit/test_tools.py +157 -0
  148. vdl-1.0.1/tests/unit/test_urls.py +335 -0
  149. vdl-1.0.1/tests/unit/test_ytdlp_downloader_unit.py +460 -0
  150. vdl-1.0.1/tests/unit/test_ytdlp_playlist_unit.py +155 -0
  151. vdl-1.0.1/uv.lock +1151 -0
@@ -0,0 +1,24 @@
1
+ # VDL local release environment template.
2
+ #
3
+ # Copy to `.env` only if you want to override release defaults locally.
4
+ # Most release settings live in GitLab CI, and PyPI publishing should use
5
+ # Trusted Publishing instead of a long-lived token.
6
+
7
+ # PyPI fallback only.
8
+ # Leave unset unless Trusted Publishing is unavailable.
9
+ PYPI_API_TOKEN=
10
+
11
+ # Local GitLab release upload helper.
12
+ # Use a token with `api` and `write_repository` scopes when running `glab`.
13
+ GITLAB_TOKEN=
14
+ GITLAB_PROJECT_ID=bildcraft/products/video-downloader
15
+ GITLAB_RELEASE_TAG=
16
+
17
+ # GitLab Pages installer defaults.
18
+ # These match the current release flow in scripts/install.sh.
19
+ VDL_RELEASE_BASE_URL=https://bildcraft.gitlab.io/products/video-downloader/vdl/stable
20
+ VDL_INSTALL_DIR=${HOME}/.local/bin
21
+
22
+ # Local release-gated build flags.
23
+ VDL_BUILD_LINUX_CI=0
24
+ VDL_BUILD_WINDOWS_CI=0
vdl-1.0.1/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .venv/
5
+ .pytest_cache/
6
+ *.egg-info/
7
+ .coverage
8
+ htmlcov/
9
+
10
+ # Build artifacts
11
+ dist/
12
+ build/
13
+ *.spec.bak
14
+
15
+ # OS/editor
16
+ .DS_Store
17
+ .idea/
18
+ .vscode/
19
+
20
+ # Local env
21
+ .env
22
+ .env.*
23
+ !.env.example
@@ -0,0 +1,62 @@
1
+ # Root GitLab CI/CD entrypoint for VDL.
2
+ #
3
+ # This file wires together the release-specific CI files under `ci/`.
4
+ #
5
+ # Current release model:
6
+ # - PyPI package build/publish runs in GitLab CI via ci/release-vdl.yml.
7
+ # - Linux standalone binary build is available in GitLab CI, but gated by
8
+ # VDL_BUILD_LINUX_CI=1.
9
+ # - Windows standalone binary build is available in GitLab CI, but gated by
10
+ # VDL_BUILD_WINDOWS_CI=1.
11
+ # - macOS arm64 standalone binary is built locally with scripts/build-macos.sh
12
+ # and uploaded manually to the GitLab Release with glab.
13
+ #
14
+ # Release trigger:
15
+ # git tag vdl-vX.Y.Z
16
+ # git push origin vdl-vX.Y.Z
17
+ #
18
+ # Required/expected CI variables:
19
+ # VDL_BUILD_LINUX_CI=0 # set to 1 to enable Linux binary builds
20
+ # VDL_BUILD_WINDOWS_CI=0 # set to 1 to enable Windows binary builds
21
+ #
22
+ # PyPI:
23
+ # Preferred: configure PyPI Trusted Publishing with environment `pypi`.
24
+ # Fallback: set protected masked PYPI_API_TOKEN.
25
+ #
26
+ # Important:
27
+ # The Linux and Windows CI files are included here, but their jobs do not run
28
+ # unless their trigger variables are set to 1. This keeps the pipeline wired
29
+ # while allowing platform builds to be enabled deliberately.
30
+
31
+ workflow:
32
+ rules:
33
+ # Run release pipeline for VDL release tags.
34
+ - if: '$CI_COMMIT_TAG =~ /^vdl-v[0-9]+\.[0-9]+\.[0-9]+$/'
35
+
36
+ # Run normal validation on merge requests.
37
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
38
+
39
+ # Run normal validation on branch pushes.
40
+ - if: '$CI_COMMIT_BRANCH'
41
+
42
+ # Otherwise do not create a pipeline.
43
+ - when: never
44
+
45
+ include:
46
+ # Main release orchestrator:
47
+ # - dependency preparation/cache
48
+ # - tests
49
+ # - PyPI sdist/wheel build
50
+ # - PyPI publish
51
+ # - manual GitLab Pages release manifest
52
+ - local: ci/release-vdl.yml
53
+
54
+ # Optional Linux release build.
55
+ # Job is gated by:
56
+ # VDL_BUILD_LINUX_CI=1
57
+ - local: ci/release-linux.yml
58
+
59
+ # Optional Windows release build.
60
+ # Job is gated by:
61
+ # VDL_BUILD_WINDOWS_CI=1
62
+ - local: ci/release-windows.yml
vdl-1.0.1/AGENTS.md ADDED
@@ -0,0 +1,59 @@
1
+ ## 1. Think Before Coding
2
+
3
+ **Don't assume. Don't hide confusion. Surface tradeoffs.**
4
+
5
+ Before implementing:
6
+ - State your assumptions explicitly. If uncertain, ask.
7
+ - If multiple interpretations exist, present them - don't pick silently.
8
+ - If a simpler approach exists, say so. Push back when warranted.
9
+ - If something is unclear, stop. Name what's confusing. Ask.
10
+
11
+ ## 2. Simplicity First
12
+
13
+ **Minimum code that solves the problem. Nothing speculative.**
14
+
15
+ - No features beyond what was asked.
16
+ - No abstractions for single-use code.
17
+ - No "flexibility" or "configurability" that wasn't requested.
18
+ - No error handling for impossible scenarios.
19
+ - If you write 200 lines and it could be 50, rewrite it.
20
+
21
+ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
22
+
23
+ ## 3. Surgical Changes
24
+
25
+ **Touch only what you must. Clean up only your own mess.**
26
+
27
+ When editing existing code:
28
+ - Don't "improve" adjacent code, comments, or formatting.
29
+ - Don't refactor things that aren't broken.
30
+ - Match existing style, even if you'd do it differently.
31
+ - If you notice unrelated dead code, mention it - don't delete it.
32
+
33
+ When your changes create orphans:
34
+ - Remove imports/variables/functions that YOUR changes made unused.
35
+ - Don't remove pre-existing dead code unless asked.
36
+
37
+ The test: Every changed line should trace directly to the user's request.
38
+
39
+ ## 4. Goal-Driven Execution
40
+
41
+ **Define success criteria. Loop until verified.**
42
+
43
+ Transform tasks into verifiable goals:
44
+ - "Add validation" → "Write tests for invalid inputs, then make them pass"
45
+ - "Fix the bug" → "Write a test that reproduces it, then make it pass"
46
+ - "Refactor X" → "Ensure tests pass before and after"
47
+
48
+ For multi-step tasks, state a brief plan:
49
+ ```
50
+ 1. [Step] → verify: [check]
51
+ 2. [Step] → verify: [check]
52
+ 3. [Step] → verify: [check]
53
+ ```
54
+
55
+ Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
56
+
57
+ ---
58
+
59
+ **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.
vdl-1.0.1/CHANGELOG.md ADDED
@@ -0,0 +1,50 @@
1
+ # Changelog
2
+
3
+ All notable changes to VDL are documented here.
4
+
5
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+
7
+ ---
8
+
9
+ ## [Unreleased]
10
+
11
+ ### Added
12
+ - First-run bootstrap (`vdl/bootstrap.py`): creates required directories, `config.toml`, `websites.yaml` (from bundled copy), and state DB on first startup; idempotent on subsequent runs.
13
+
14
+ ### Changed
15
+ - `VDLPaths` now describes only the modern XDG layout; `legacy_site_rules_file` field removed.
16
+ - `_default_config()` no longer falls back to legacy `~/.config/video-downloader/` paths.
17
+ - `resolve_site_rules_path()` resolves only the modern config location; legacy fallback removed.
18
+ - CLI startup no longer calls `migrate_legacy_config()`; migration path removed from active runtime code.
19
+
20
+ ### Removed
21
+ - `migrate_legacy_config()` removed from `paths.py`.
22
+ - `migrate_from_yaml()` alias removed from `site_rules.py`.
23
+
24
+ ---
25
+
26
+ ## [1.0.0]
27
+
28
+ ### Added
29
+ - Rebuilt VDL as a proper Python package under `src/vdl/` with `pyproject.toml` and `hatchling` build backend.
30
+ - Headless CLI (`vdl download`, `vdl playlist`, `vdl resolve`, `vdl status`, `vdl doctor`, `vdl config`) with `--json` output flag.
31
+ - Interactive CLI mode via Rich (launched by `vdl` with no arguments).
32
+ - Python library API (`VDLClient`, `DownloadRequest`, `DownloadResult`, `PlaylistInfo`).
33
+ - MCP server (`vdl-mcp`) for LLM-assisted media automation; distributed as optional `vdl[mcp]` extra.
34
+ - XDG-compliant path layout with `ensure_paths()` and `get_default_paths()`.
35
+ - SQLite-backed state store for idempotent downloads, status tracking, and reconciliation.
36
+ - Site-specific crawler support via `websites.yaml` rule files and Selenium-based discovery.
37
+ - Legacy config migration from `~/.config/video-downloader/` to `~/.config/vdl/`.
38
+ - GitLab CI release pipeline (`ci/release-vdl.yml`) with PyPI Trusted Publishing.
39
+ - macOS arm64 binary build (`scripts/build-macos.sh`) with smoke-test and SHA256 checksums.
40
+ - Installer (`scripts/install.sh`) with platform detection, checksum verification, and `PATH` warning.
41
+ - Release manifest (`release.json`) published to GitLab Pages for the installer to resolve.
42
+ - `vdl doctor` command for verifying `ffmpeg`, `ffprobe`, and `yt-dlp` availability.
43
+
44
+ ### Changed
45
+ - Previous implementation archived under `frozen/vdl-v0/` and kept buildable.
46
+
47
+ ---
48
+
49
+ [Unreleased]: https://gitlab.com/bildcraft/products/video-downloader/-/compare/vdl-v1.0.0...HEAD
50
+ [1.0.0]: https://gitlab.com/bildcraft/products/video-downloader/-/releases/vdl-v1.0.0
vdl-1.0.1/CLAUDE.md ADDED
@@ -0,0 +1,221 @@
1
+ ## 1. Think Before Coding
2
+
3
+ **Don't assume. Don't hide confusion. Surface tradeoffs.**
4
+
5
+ Before implementing:
6
+ - State your assumptions explicitly. If uncertain, ask.
7
+ - If multiple interpretations exist, present them - don't pick silently.
8
+ - If a simpler approach exists, say so. Push back when warranted.
9
+ - If something is unclear, stop. Name what's confusing. Ask.
10
+
11
+ ## 2. Simplicity First
12
+
13
+ **Minimum code that solves the problem. Nothing speculative.**
14
+
15
+ - No features beyond what was asked.
16
+ - No abstractions for single-use code.
17
+ - No "flexibility" or "configurability" that wasn't requested.
18
+ - No error handling for impossible scenarios.
19
+ - If you write 200 lines and it could be 50, rewrite it.
20
+
21
+ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
22
+
23
+ ## 3. Surgical Changes
24
+
25
+ **Touch only what you must. Clean up only your own mess.**
26
+
27
+ When editing existing code:
28
+ - Don't "improve" adjacent code, comments, or formatting.
29
+ - Don't refactor things that aren't broken.
30
+ - Match existing style, even if you'd do it differently.
31
+ - If you notice unrelated dead code, mention it - don't delete it.
32
+
33
+ When your changes create orphans:
34
+ - Remove imports/variables/functions that YOUR changes made unused.
35
+ - Don't remove pre-existing dead code unless asked.
36
+
37
+ The test: Every changed line should trace directly to the user's request.
38
+
39
+ ## 4. Goal-Driven Execution
40
+
41
+ **Define success criteria. Loop until verified.**
42
+
43
+ Transform tasks into verifiable goals:
44
+ - "Add validation" → "Write tests for invalid inputs, then make them pass"
45
+ - "Fix the bug" → "Write a test that reproduces it, then make it pass"
46
+ - "Refactor X" → "Ensure tests pass before and after"
47
+
48
+ For multi-step tasks, state a brief plan:
49
+ ```
50
+ 1. [Step] → verify: [check]
51
+ 2. [Step] → verify: [check]
52
+ 3. [Step] → verify: [check]
53
+ ```
54
+
55
+ Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
56
+
57
+ ---
58
+
59
+ **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.
60
+
61
+ ## 5. Repository Context
62
+
63
+ **VDL is a local-first media workflow toolkit, not just a downloader wrapper.**
64
+
65
+ Treat the current package under `src/vdl` as the active implementation. The historical frozen implementation under `frozen/vdl-v0` is reference material only unless the user explicitly asks to run or inspect it.
66
+
67
+ Core product boundaries:
68
+ - `vdl` is the Python package and shared library.
69
+ - `vdl` is also the primary CLI command.
70
+ - `vdl-mcp` is an MCP server command exposed by the same package.
71
+ - `vdl` and `vdl-mcp` are commands/interfaces, not separate libraries.
72
+ - Shared business logic belongs in the library/core layer, not in CLI-only or MCP-only code.
73
+ - CLI, headless mode, Python API, and MCP should be adapters over the same core workflows.
74
+
75
+ Current release model:
76
+ - PyPI package name: `vdl`.
77
+ - Release tags: `vdl-vX.Y.Z`.
78
+ - PyPI publishing happens in GitLab CI using Trusted Publishing where possible.
79
+ - macOS arm64 standalone builds are local-first via `scripts/build-macos.sh`.
80
+ - Linux and Windows standalone builds are optional CI paths behind release variables.
81
+ - Do not commit generated binaries, wheels, sdists, archives, or release assets.
82
+
83
+ ## 6. Development Commands
84
+
85
+ Prefer these commands for local validation:
86
+
87
+ ```bash
88
+ uv sync --frozen --all-extras --dev
89
+ PYTHONPATH=src uv run pytest -q
90
+ uv build --no-sources
91
+ ```
92
+
93
+ Useful Taskfile commands, when available:
94
+
95
+ ```bash
96
+ task --list
97
+ task test
98
+ task build
99
+ task release:validate
100
+ ```
101
+
102
+ Before changing release behavior, inspect:
103
+ - `.gitlab-ci.yml`
104
+ - `ci/release-vdl.yml`
105
+ - `ci/release-linux.yml`
106
+ - `ci/release-windows.yml`
107
+ - `scripts/build-macos.sh`
108
+ - `scripts/install.sh`
109
+ - `docs/RELEASE_PLAYBOOK.md`
110
+
111
+ ## 7. Python Style and Docstrings
112
+
113
+ **Public code needs useful docstrings. Private implementation details need clarity, not noise.**
114
+
115
+ Add or update docstrings when creating or materially changing:
116
+ - public modules
117
+ - public classes
118
+ - public functions
119
+ - public methods
120
+ - dataclasses or models exposed to users/tests
121
+ - CLI/MCP entry points whose behavior is not obvious
122
+
123
+ Use concise Google-style docstrings by default:
124
+
125
+ ```python
126
+ def resolve_playlist(url: str, limit: int | None = None) -> PlaylistResolution:
127
+ """Resolve a playlist URL into selectable media items.
128
+
129
+ Args:
130
+ url: Playlist or page URL to inspect.
131
+ limit: Optional maximum number of items to return.
132
+
133
+ Returns:
134
+ A playlist resolution containing discovered media items.
135
+
136
+ Raises:
137
+ VdlError: If the URL cannot be resolved.
138
+ """
139
+ ```
140
+
141
+ Docstring rules:
142
+ - Document intent and externally relevant behavior, not line-by-line mechanics.
143
+ - Include `Args`, `Returns`, and `Raises` only when they add useful information.
144
+ - Do not add verbose docstrings to trivial private helpers.
145
+ - Do not write misleading docstrings that claim behavior not covered by code or tests.
146
+ - Update stale docstrings when behavior changes.
147
+ - Prefer precise domain language: `download plan`, `playlist resolution`, `selection policy`, `local state`, `MCP tool`.
148
+
149
+ ## 8. Tests and Verification
150
+
151
+ Every behavior change should be verified. Prefer the smallest meaningful test.
152
+
153
+ Testing expectations:
154
+ - Unit tests for pure logic and parsing.
155
+ - Contract tests for downloader/playlist interfaces.
156
+ - Integration tests for SQLite state and filesystem behavior.
157
+ - Smoke checks for CLI entry points, release scripts, and installer behavior.
158
+ - Regression tests for every bug fix when practical.
159
+
160
+ When changing CLI behavior:
161
+ - Verify command help still works.
162
+ - Verify error messages are actionable.
163
+ - Avoid breaking existing scripts unless the change is intentional and documented.
164
+
165
+ When changing MCP behavior:
166
+ - Keep MCP as an adapter over core functionality.
167
+ - Do not make MCP depend on the interactive CLI.
168
+ - If the optional `mcp` dependency is missing, `vdl-mcp` should fail gracefully with an install hint such as `pip install "vdl[mcp]"`.
169
+
170
+ ## 9. Release and Packaging Guardrails
171
+
172
+ Be conservative with release code. A broken release pipeline wastes time and can publish bad artifacts.
173
+
174
+ Packaging rules:
175
+ - Keep `pyproject.toml` as the source of package metadata.
176
+ - Keep the PyPI package name aligned with `[project].name`.
177
+ - Use `uv build --no-sources` for release package builds.
178
+ - Standalone binary builds should include both `vdl` and `vdl-mcp` when intended.
179
+ - Do not include Windows in installer-facing `release.json` until there is a native Windows install path or explicit manual-download semantics.
180
+ - Linux/Windows CI artifacts must be attached to the GitLab Release before the Pages manifest advertises them.
181
+ - Avoid checksum filename collisions across platforms.
182
+
183
+ Release validation should check:
184
+ - package metadata
185
+ - console scripts
186
+ - included package data such as `vdl/data/websites.yaml`
187
+ - YAML validity for GitLab CI files
188
+ - shell syntax/linting for release scripts
189
+ - artifact naming conventions
190
+ - `release.json` URLs and SHA256 values
191
+
192
+ ## 10. Documentation and Branding
193
+
194
+ Keep documentation professional, concise, and product-oriented.
195
+
196
+ Preferred positioning:
197
+ > VDL is a local-first media workflow toolkit for downloads, playlists, and automation through CLI, library, and MCP interfaces.
198
+
199
+ Avoid top-level branding like:
200
+ - “yt-dlp wrapper”
201
+ - “thin wrapper”
202
+ - “lightweight wrapper around yt-dlp”
203
+ - “powered by yt-dlp” in the headline
204
+
205
+ It is fine to mention later that VDL uses `yt-dlp` under the hood for media extraction and download support.
206
+
207
+ Documentation rules:
208
+ - Keep `README.md` as a professional landing page, not a full manual.
209
+ - Put deep release details in `docs/RELEASE_PLAYBOOK.md`.
210
+ - Put verification summaries in dedicated docs such as `docs/RELEASE_SETUP_VERIFICATION.md`.
211
+ - Do not claim features that are not implemented.
212
+ - Prefer short examples that can be copied and run.
213
+
214
+ ## 11. Final Response Expectations
215
+
216
+ When finishing a task:
217
+ - Summarize what changed.
218
+ - List verification commands run and their results.
219
+ - Mention anything not run and why.
220
+ - Mention follow-up manual steps only when they are genuinely required.
221
+ - If a patch was created, keep the explanation concise and tie it directly to the user request.
vdl-1.0.1/CODEX.md ADDED
@@ -0,0 +1,221 @@
1
+ ## 1. Think Before Coding
2
+
3
+ **Don't assume. Don't hide confusion. Surface tradeoffs.**
4
+
5
+ Before implementing:
6
+ - State your assumptions explicitly. If uncertain, ask.
7
+ - If multiple interpretations exist, present them - don't pick silently.
8
+ - If a simpler approach exists, say so. Push back when warranted.
9
+ - If something is unclear, stop. Name what's confusing. Ask.
10
+
11
+ ## 2. Simplicity First
12
+
13
+ **Minimum code that solves the problem. Nothing speculative.**
14
+
15
+ - No features beyond what was asked.
16
+ - No abstractions for single-use code.
17
+ - No "flexibility" or "configurability" that wasn't requested.
18
+ - No error handling for impossible scenarios.
19
+ - If you write 200 lines and it could be 50, rewrite it.
20
+
21
+ Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
22
+
23
+ ## 3. Surgical Changes
24
+
25
+ **Touch only what you must. Clean up only your own mess.**
26
+
27
+ When editing existing code:
28
+ - Don't "improve" adjacent code, comments, or formatting.
29
+ - Don't refactor things that aren't broken.
30
+ - Match existing style, even if you'd do it differently.
31
+ - If you notice unrelated dead code, mention it - don't delete it.
32
+
33
+ When your changes create orphans:
34
+ - Remove imports/variables/functions that YOUR changes made unused.
35
+ - Don't remove pre-existing dead code unless asked.
36
+
37
+ The test: Every changed line should trace directly to the user's request.
38
+
39
+ ## 4. Goal-Driven Execution
40
+
41
+ **Define success criteria. Loop until verified.**
42
+
43
+ Transform tasks into verifiable goals:
44
+ - "Add validation" → "Write tests for invalid inputs, then make them pass"
45
+ - "Fix the bug" → "Write a test that reproduces it, then make it pass"
46
+ - "Refactor X" → "Ensure tests pass before and after"
47
+
48
+ For multi-step tasks, state a brief plan:
49
+ ```
50
+ 1. [Step] → verify: [check]
51
+ 2. [Step] → verify: [check]
52
+ 3. [Step] → verify: [check]
53
+ ```
54
+
55
+ Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
56
+
57
+ ---
58
+
59
+ **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.
60
+
61
+ ## 5. Repository Context
62
+
63
+ **VDL is a local-first media workflow toolkit, not just a downloader wrapper.**
64
+
65
+ Treat the current package under `src/vdl` as the active implementation. The historical frozen implementation under `frozen/vdl-v0` is reference material only unless the user explicitly asks to run or inspect it.
66
+
67
+ Core product boundaries:
68
+ - `vdl` is the Python package and shared library.
69
+ - `vdl` is also the primary CLI command.
70
+ - `vdl-mcp` is an MCP server command exposed by the same package.
71
+ - `vdl` and `vdl-mcp` are commands/interfaces, not separate libraries.
72
+ - Shared business logic belongs in the library/core layer, not in CLI-only or MCP-only code.
73
+ - CLI, headless mode, Python API, and MCP should be adapters over the same core workflows.
74
+
75
+ Current release model:
76
+ - PyPI package name: `vdl`.
77
+ - Release tags: `vdl-vX.Y.Z`.
78
+ - PyPI publishing happens in GitLab CI using Trusted Publishing where possible.
79
+ - macOS arm64 standalone builds are local-first via `scripts/build-macos.sh`.
80
+ - Linux and Windows standalone builds are optional CI paths behind release variables.
81
+ - Do not commit generated binaries, wheels, sdists, archives, or release assets.
82
+
83
+ ## 6. Development Commands
84
+
85
+ Prefer these commands for local validation:
86
+
87
+ ```bash
88
+ uv sync --frozen --all-extras --dev
89
+ PYTHONPATH=src uv run pytest -q
90
+ uv build --no-sources
91
+ ```
92
+
93
+ Useful Taskfile commands, when available:
94
+
95
+ ```bash
96
+ task --list
97
+ task test
98
+ task build
99
+ task release:validate
100
+ ```
101
+
102
+ Before changing release behavior, inspect:
103
+ - `.gitlab-ci.yml`
104
+ - `ci/release-vdl.yml`
105
+ - `ci/release-linux.yml`
106
+ - `ci/release-windows.yml`
107
+ - `scripts/build-macos.sh`
108
+ - `scripts/install.sh`
109
+ - `docs/RELEASE_PLAYBOOK.md`
110
+
111
+ ## 7. Python Style and Docstrings
112
+
113
+ **Public code needs useful docstrings. Private implementation details need clarity, not noise.**
114
+
115
+ Add or update docstrings when creating or materially changing:
116
+ - public modules
117
+ - public classes
118
+ - public functions
119
+ - public methods
120
+ - dataclasses or models exposed to users/tests
121
+ - CLI/MCP entry points whose behavior is not obvious
122
+
123
+ Use concise Google-style docstrings by default:
124
+
125
+ ```python
126
+ def resolve_playlist(url: str, limit: int | None = None) -> PlaylistResolution:
127
+ """Resolve a playlist URL into selectable media items.
128
+
129
+ Args:
130
+ url: Playlist or page URL to inspect.
131
+ limit: Optional maximum number of items to return.
132
+
133
+ Returns:
134
+ A playlist resolution containing discovered media items.
135
+
136
+ Raises:
137
+ VdlError: If the URL cannot be resolved.
138
+ """
139
+ ```
140
+
141
+ Docstring rules:
142
+ - Document intent and externally relevant behavior, not line-by-line mechanics.
143
+ - Include `Args`, `Returns`, and `Raises` only when they add useful information.
144
+ - Do not add verbose docstrings to trivial private helpers.
145
+ - Do not write misleading docstrings that claim behavior not covered by code or tests.
146
+ - Update stale docstrings when behavior changes.
147
+ - Prefer precise domain language: `download plan`, `playlist resolution`, `selection policy`, `local state`, `MCP tool`.
148
+
149
+ ## 8. Tests and Verification
150
+
151
+ Every behavior change should be verified. Prefer the smallest meaningful test.
152
+
153
+ Testing expectations:
154
+ - Unit tests for pure logic and parsing.
155
+ - Contract tests for downloader/playlist interfaces.
156
+ - Integration tests for SQLite state and filesystem behavior.
157
+ - Smoke checks for CLI entry points, release scripts, and installer behavior.
158
+ - Regression tests for every bug fix when practical.
159
+
160
+ When changing CLI behavior:
161
+ - Verify command help still works.
162
+ - Verify error messages are actionable.
163
+ - Avoid breaking existing scripts unless the change is intentional and documented.
164
+
165
+ When changing MCP behavior:
166
+ - Keep MCP as an adapter over core functionality.
167
+ - Do not make MCP depend on the interactive CLI.
168
+ - If the optional `mcp` dependency is missing, `vdl-mcp` should fail gracefully with an install hint such as `pip install "vdl[mcp]"`.
169
+
170
+ ## 9. Release and Packaging Guardrails
171
+
172
+ Be conservative with release code. A broken release pipeline wastes time and can publish bad artifacts.
173
+
174
+ Packaging rules:
175
+ - Keep `pyproject.toml` as the source of package metadata.
176
+ - Keep the PyPI package name aligned with `[project].name`.
177
+ - Use `uv build --no-sources` for release package builds.
178
+ - Standalone binary builds should include both `vdl` and `vdl-mcp` when intended.
179
+ - Do not include Windows in installer-facing `release.json` until there is a native Windows install path or explicit manual-download semantics.
180
+ - Linux/Windows CI artifacts must be attached to the GitLab Release before the Pages manifest advertises them.
181
+ - Avoid checksum filename collisions across platforms.
182
+
183
+ Release validation should check:
184
+ - package metadata
185
+ - console scripts
186
+ - included package data such as `vdl/data/websites.yaml`
187
+ - YAML validity for GitLab CI files
188
+ - shell syntax/linting for release scripts
189
+ - artifact naming conventions
190
+ - `release.json` URLs and SHA256 values
191
+
192
+ ## 10. Documentation and Branding
193
+
194
+ Keep documentation professional, concise, and product-oriented.
195
+
196
+ Preferred positioning:
197
+ > VDL is a local-first media workflow toolkit for downloads, playlists, and automation through CLI, library, and MCP interfaces.
198
+
199
+ Avoid top-level branding like:
200
+ - “yt-dlp wrapper”
201
+ - “thin wrapper”
202
+ - “lightweight wrapper around yt-dlp”
203
+ - “powered by yt-dlp” in the headline
204
+
205
+ It is fine to mention later that VDL uses `yt-dlp` under the hood for media extraction and download support.
206
+
207
+ Documentation rules:
208
+ - Keep `README.md` as a professional landing page, not a full manual.
209
+ - Put deep release details in `docs/RELEASE_PLAYBOOK.md`.
210
+ - Put verification summaries in dedicated docs such as `docs/RELEASE_SETUP_VERIFICATION.md`.
211
+ - Do not claim features that are not implemented.
212
+ - Prefer short examples that can be copied and run.
213
+
214
+ ## 11. Final Response Expectations
215
+
216
+ When finishing a task:
217
+ - Summarize what changed.
218
+ - List verification commands run and their results.
219
+ - Mention anything not run and why.
220
+ - Mention follow-up manual steps only when they are genuinely required.
221
+ - If a patch was created, keep the explanation concise and tie it directly to the user request.