|
| 1 | +# Copilot Instructions for scout-merit-badges-anki |
| 2 | + |
| 3 | +## Repository Overview |
| 4 | + |
| 5 | +This is a Python CLI tool that generates Anki flashcard decks (.apkg files) for learning Scouting America merit badges by image. The tool processes local archive files (.zip, .tar.gz) containing merit badge data and images, maps badges to their corresponding images using sophisticated pattern matching, and creates structured Anki decks with stable IDs to prevent duplicates on reimport. |
| 6 | + |
| 7 | +**Repository Stats:** |
| 8 | +- Language: Python 3.11+ (currently using 3.12) |
| 9 | +- Package Manager: uv (modern Python package manager) |
| 10 | +- Framework: Click CLI framework |
| 11 | +- Dependencies: click, genanki, pytest-cov |
| 12 | +- Size: ~15 source files, small codebase |
| 13 | +- Type: CLI tool |
| 14 | +- **Test Coverage: 8 focused tests, simple and maintainable** ✅ |
| 15 | + |
| 16 | +## Build and Development Commands |
| 17 | + |
| 18 | +**CRITICAL: Always use Makefile commands first, then uv commands as alternatives** |
| 19 | +**CRITICAL: Always use `uv` commands, never `pip` or `python -m pip`** |
| 20 | +**CRITICAL: Pre-commit hooks are REQUIRED and must be installed** |
| 21 | +**CRITICAL: All code changes must maintain 80% test coverage minimum** |
| 22 | + |
| 23 | +### Environment Setup (REQUIRED FIRST STEP) |
| 24 | +```bash |
| 25 | +# ALWAYS run this first - creates venv and syncs all dependencies |
| 26 | +uv sync |
| 27 | + |
| 28 | +# REQUIRED: Install pre-commit hooks (must be done after venv setup) |
| 29 | +make setup-pre-commit |
| 30 | +# OR alternatively |
| 31 | +uv run pre-commit install |
| 32 | +``` |
| 33 | + |
| 34 | +### Development Workflow (USE MAKEFILE COMMANDS) |
| 35 | +```bash |
| 36 | +# Format code AND fix linting issues (REQUIRED before commits) |
| 37 | +make fmt |
| 38 | +# OR alternatively |
| 39 | +uv run ruff check --fix && uv run ruff format |
| 40 | + |
| 41 | +# Lint code only - check without fixes (REQUIRED - must pass) |
| 42 | +make lint |
| 43 | +# OR alternatively |
| 44 | +uv run ruff check |
| 45 | + |
| 46 | +# Run tests with coverage (REQUIRED - must pass with 80% minimum) |
| 47 | +make test |
| 48 | +# OR alternatively |
| 49 | +uv run pytest |
| 50 | + |
| 51 | +# Run tests without coverage (for speed during development) |
| 52 | +make test-no-cov |
| 53 | +# OR alternatively |
| 54 | +uv run pytest --no-cov |
| 55 | + |
| 56 | +# Generate detailed HTML coverage report |
| 57 | +make cov-report |
| 58 | +# OR alternatively |
| 59 | +uv run pytest --cov-report=html && open htmlcov/index.html |
| 60 | + |
| 61 | +# Run CLI tool for testing |
| 62 | +uv run scout-merit-badges-anki --help |
| 63 | +``` |
| 64 | + |
| 65 | +### Pre-commit Hooks (MANDATORY) |
| 66 | +```bash |
| 67 | +# Install pre-commit hooks (REQUIRED for all contributors) |
| 68 | +make setup-pre-commit |
| 69 | + |
| 70 | +# Test pre-commit hooks manually (recommended before first commit) |
| 71 | +uv run pre-commit run --all-files |
| 72 | + |
| 73 | +# Pre-commit hooks will automatically run on every commit and will: |
| 74 | +# 1. Run ruff --fix (fix linting issues) |
| 75 | +# 2. Run ruff format (format code) |
| 76 | +# 3. Block commits if any issues cannot be auto-fixed |
| 77 | +``` |
| 78 | + |
| 79 | +### Validation Commands |
| 80 | +```bash |
| 81 | +# Test CLI functionality (dry run - safe to run) |
| 82 | +uv run scout-merit-badges-anki build --dry-run --quiet *.zip *.tar.gz |
| 83 | + |
| 84 | +# Download and test with latest release |
| 85 | +make fetch-and-build |
| 86 | +``` |
| 87 | + |
| 88 | +### Clean Environment |
| 89 | +```bash |
| 90 | +make clean # Removes build artifacts, .venv, __pycache__, *.apkg files, coverage reports |
| 91 | +``` |
| 92 | + |
| 93 | +## Critical Build Requirements |
| 94 | + |
| 95 | +1. **ALWAYS use Makefile commands** - `make fmt`, `make lint`, `make test` |
| 96 | +2. **Pre-commit hooks are MANDATORY** - run `make setup-pre-commit` after environment setup |
| 97 | +3. **Code MUST pass `make lint`** - zero tolerance for linting errors |
| 98 | +4. **Code MUST be formatted with `make fmt`** - enforced by pre-commit hooks |
| 99 | +5. **All tests MUST pass with `make test`** - zero tolerance for test failures |
| 100 | +6. **Python 3.11+ required** - specified in pyproject.toml |
| 101 | +7. **Never use `pip` or `python -m pip`** - use `uv` commands only |
| 102 | + |
| 103 | +## Test Coverage Requirements |
| 104 | + |
| 105 | +**Target: Simple and focused testing approach** |
| 106 | + |
| 107 | +### Coverage Configuration |
| 108 | +- No minimum coverage requirement (removed fail-under) |
| 109 | +- HTML reports generated in `htmlcov/` directory |
| 110 | +- XML reports for CI/CD integration |
| 111 | +- Terminal reports with missing line details |
| 112 | + |
| 113 | +### Test Suite Structure (8 tests total) |
| 114 | +``` |
| 115 | +tests/ |
| 116 | +├── test_cli_simple.py # Basic CLI tests (4 tests) |
| 117 | +├── test_cli_comprehensive.py # CLI functionality with mocking (2 tests) |
| 118 | +└── test_scout_merit_badges_anki.py # Directory processing integration (2 tests) |
| 119 | +``` |
| 120 | + |
| 121 | +### Coverage by Module |
| 122 | +- **Focus on core functionality**: CLI commands, directory processing, integration |
| 123 | +- **Simplified approach**: Test the actual behavior users care about |
| 124 | +- **Fast execution**: All tests run in ~0.4 seconds |
| 125 | +- **Easy maintenance**: Minimal test surface area |
| 126 | + |
| 127 | +### Writing New Tests |
| 128 | +When adding new functionality: |
| 129 | +1. **Keep tests simple** - focus on user-facing behavior |
| 130 | +2. **Test CLI commands** - the main interface users interact with |
| 131 | +3. **Use integration tests** - test real functionality over unit details |
| 132 | +4. **Mock external dependencies** - keep tests fast and reliable |
| 133 | +5. **Avoid testing implementation details** - test behavior, not internals |
| 134 | + |
| 135 | +## Makefile Commands Reference |
| 136 | + |
| 137 | +**Primary Development Commands (USE THESE):** |
| 138 | +- `make setup-pre-commit` - Install pre-commit hooks (REQUIRED) |
| 139 | +- `make fmt` - Format code with ruff AND fix linting issues |
| 140 | +- `make lint` - Lint code with ruff (check only, no fixes) |
| 141 | +- `make test` - Run tests with coverage (80% target) |
| 142 | +- `make test-no-cov` - Run tests without coverage (faster for development) |
| 143 | +- `make cov-report` - Generate and open HTML coverage report |
| 144 | +- `make clean` - Clean up temporary files and coverage reports |
| 145 | +- `make help` - Show all available commands |
| 146 | + |
| 147 | +**Command Behavior:** |
| 148 | +- `make fmt` runs: `ruff check --fix` + `ruff format` (matches pre-commit behavior) |
| 149 | +- `make lint` runs: `ruff check` (check only, no auto-fixes) |
| 150 | +- `make test` runs: `pytest` with coverage reporting (no minimum threshold) |
| 151 | +- `make test-no-cov` runs: `pytest --no-cov` (faster for development iterations) |
| 152 | + |
| 153 | +## Project Architecture |
| 154 | + |
| 155 | +### Core Modules (`scout_merit_badges_anki/`) |
| 156 | +- `cli.py` - Click-based command line interface with build command |
| 157 | +- `archive.py` - Archive processing (ZIP/TAR.GZ) and file extraction |
| 158 | +- `mapping.py` - Sophisticated image-to-badge mapping logic with pattern matching |
| 159 | +- `schema.py` - Badge data normalization and stable ID generation |
| 160 | +- `deck.py` - Anki deck creation using genanki library (images embedded as complete HTML tags) |
| 161 | +- `errors.py` - Custom exception classes |
| 162 | +- `log.py` - Logging configuration |
| 163 | + |
| 164 | +### Configuration Files |
| 165 | +- `pyproject.toml` - Project metadata, dependencies, tool configuration (ruff, uv, pytest, coverage) |
| 166 | +- `Makefile` - **PRIMARY** development interface - use these commands first |
| 167 | +- `.pre-commit-config.yaml` - Pre-commit hooks (ruff format + check) - MANDATORY |
| 168 | +- `.gitignore` - Standard Python gitignore plus .apkg files and coverage reports |
| 169 | + |
| 170 | +### GitHub Workflows (`.github/workflows/`) |
| 171 | +- `test.yml` - CI testing on Python 3.11-3.12, uses `uv sync` and `uv run pytest` |
| 172 | + |
| 173 | +### Tests (`tests/`) - 163 comprehensive tests |
| 174 | +- **Core functionality tests** - Original test suite with integration tests |
| 175 | +- **Error handling tests** - Comprehensive exception and error scenario coverage |
| 176 | +- **CLI integration tests** - Mock-based testing of all CLI commands and workflows |
| 177 | +- **GitHub API tests** - Including retry logic, rate limiting, and network error scenarios |
| 178 | +- **Archive processing tests** - ZIP/TAR.GZ handling with error conditions |
| 179 | +- **Logging tests** - Color formatting, TTY detection, and configuration |
| 180 | +- **Schema tests** - Data normalization, field priority, and type conversion |
| 181 | +- **Deck creation tests** - Anki package generation and cleanup |
| 182 | + |
| 183 | +## Key Implementation Details |
| 184 | + |
| 185 | +### Image Field Format (CRITICAL) |
| 186 | +**Images must be embedded as complete HTML tags in note fields, NOT just filenames:** |
| 187 | +```python |
| 188 | +# CORRECT (what we do now): |
| 189 | +fields = [f'<img src="{image_name}" style="max-width: 85%; height: auto;">', badge.name, description] |
| 190 | + |
| 191 | +# WRONG (old approach that didn't work): |
| 192 | +fields = [image_name, badge.name, description] # Template: <img src="{{Image}}"> |
| 193 | +``` |
| 194 | + |
| 195 | +This follows genanki documentation requirements for media embedding. |
| 196 | + |
| 197 | +### Image Mapping Strategy (Critical for Badge Processing) |
| 198 | +The tool uses a 4-tier matching strategy in `mapping.py`: |
| 199 | +1. **Explicit mapping**: JSON specifies exact image filename |
| 200 | +2. **Pattern matching**: `<badge-slug>-merit-badge.*` format |
| 201 | +3. **Exact slug match**: Badge slug matches image basename |
| 202 | +4. **Shortest path preference**: Multiple candidates → choose shortest filename |
| 203 | + |
| 204 | +### Stable ID Generation |
| 205 | +Uses deterministic hashing in `schema.py` to generate stable Anki model/deck IDs, preventing duplicates on reimport. |
| 206 | + |
| 207 | +### CLI Commands |
| 208 | +- `build` - Main command, creates .apkg files from local archive files |
| 209 | + |
| 210 | +## Development Workflow (MANDATORY PROCESS) |
| 211 | + |
| 212 | +### Initial Setup |
| 213 | +```bash |
| 214 | +# 1. Clone repository |
| 215 | +git clone <repo-url> |
| 216 | +cd scout-merit-badges-anki |
| 217 | + |
| 218 | +# 2. Set up environment (REQUIRED) |
| 219 | +uv sync |
| 220 | + |
| 221 | +# 3. Install pre-commit hooks (REQUIRED) |
| 222 | +make setup-pre-commit |
| 223 | +``` |
| 224 | + |
| 225 | +### Daily Development |
| 226 | +```bash |
| 227 | +# 1. Make code changes |
| 228 | + |
| 229 | +# 2. Format and fix issues (REQUIRED before commit) |
| 230 | +make fmt |
| 231 | + |
| 232 | +# 3. Check for remaining issues (REQUIRED - must pass) |
| 233 | +make lint |
| 234 | + |
| 235 | +# 4. Run tests with coverage (REQUIRED - must pass with ≥80%) |
| 236 | +make test |
| 237 | + |
| 238 | +# 5. Commit (pre-commit hooks will run automatically) |
| 239 | +git add . |
| 240 | +git commit -m "Your commit message" |
| 241 | +``` |
| 242 | + |
| 243 | +### Testing Changes |
| 244 | +```bash |
| 245 | +# Test CLI functionality without creating files |
| 246 | +uv run scout-merit-badges-anki build --dry-run *.zip *.tar.gz |
| 247 | + |
| 248 | +# Download and test with latest release |
| 249 | +make fetch-and-build |
| 250 | + |
| 251 | +# Run full test suite with coverage |
| 252 | +make test |
| 253 | + |
| 254 | +``` |
| 255 | + |
| 256 | +### Adding New Features |
| 257 | +```bash |
| 258 | +# 1. Write tests first (TDD approach) |
| 259 | +# 2. Implement feature |
| 260 | +# 3. Ensure tests pass: make test |
| 261 | +# 4. Format and lint: make fmt && make lint |
| 262 | +# 5. Commit changes |
| 263 | +``` |
| 264 | + |
| 265 | +## Common Issues and Solutions |
| 266 | + |
| 267 | +### Build Failures |
| 268 | +- **"command not found: uv"** → Install uv first |
| 269 | +- **Linting failures** → Run `make fmt` then `make lint` |
| 270 | +- **Test failures** → Check if `uv sync` was run, ensure Python 3.11+ |
| 271 | +- **Coverage below 80%** → Add tests for uncovered lines, check `htmlcov/index.html` |
| 272 | +- **Import errors** → Run `uv sync` to ensure all dependencies installed |
| 273 | + |
| 274 | +### Coverage Issues |
| 275 | +- **Low coverage** → Run `make cov-report` to see detailed HTML report |
| 276 | +- **Missing test coverage** → Add tests for uncovered lines shown in terminal output |
| 277 | +- **CLI coverage low** → Use mocking to test CLI commands without external dependencies |
| 278 | + |
| 279 | +### Pre-commit Issues |
| 280 | +- **Pre-commit not installed** → Run `make setup-pre-commit` |
| 281 | +- **Pre-commit fails** → Ensure in git repository (`git init` if needed) |
| 282 | +- **Hooks fail on commit** → Run `make fmt` to fix issues, then commit again |
| 283 | + |
| 284 | +### Development Issues |
| 285 | +- **Missing archive files** → Run `make fetch-releases` to download latest scout-archive release |
| 286 | +- **Missing images in dry run** → Expected behavior, some badges may lack images |
| 287 | +- **Image not displaying in Anki** → Check that image field contains complete `<img>` tag |
| 288 | +- **Test timeouts** → Use `make test-no-cov` for faster development iterations |
| 289 | + |
| 290 | +### Environment Issues |
| 291 | +- **Wrong Python version** → uv automatically manages Python versions per project |
| 292 | +- **Dependency conflicts** → Delete `.venv/` and run `uv sync` again |
| 293 | +- **Cache issues** → Run `make clean` then `uv sync` |
| 294 | + |
| 295 | +## File Structure Reference |
| 296 | + |
| 297 | +``` |
| 298 | +scout-merit-badges-anki/ |
| 299 | +├── .github/ |
| 300 | +│ ├── copilot-instructions.md # This file - development guidelines |
| 301 | +│ └── workflows/ # CI/CD pipelines |
| 302 | +├── scout_merit_badges_anki/ # Main package |
| 303 | +│ ├── __init__.py # Package metadata |
| 304 | +│ ├── __main__.py # Entry point for python -m |
| 305 | +│ ├── cli.py # Command line interface |
| 306 | +│ ├── archive.py # Archive processing |
| 307 | +│ ├── mapping.py # Image mapping logic |
| 308 | +│ ├── schema.py # Data normalization |
| 309 | +│ ├── deck.py # Anki deck creation |
| 310 | +│ ├── errors.py # Custom exceptions |
| 311 | +│ └── log.py # Logging setup |
| 312 | +├── tests/ # Test suite (8 focused tests) |
| 313 | +├── htmlcov/ # Coverage HTML reports (generated) |
| 314 | +├── pyproject.toml # Project configuration with coverage settings |
| 315 | +├── Makefile # **PRIMARY** development interface |
| 316 | +├── .pre-commit-config.yaml # Code quality hooks (MANDATORY) |
| 317 | +├── README.md # User documentation |
| 318 | +└── spec.md # Technical specification |
| 319 | +``` |
| 320 | + |
| 321 | +## Trust These Instructions |
| 322 | + |
| 323 | +These instructions are comprehensive and tested. **ALWAYS use Makefile commands first**. Only use direct `uv` commands as alternatives when Makefile commands are not available. |
| 324 | + |
| 325 | +**Pre-commit hooks are MANDATORY** - they ensure code quality and consistency across all contributors. |
| 326 | + |
| 327 | +For routine development tasks: |
| 328 | +1. **Environment setup**: `uv sync` → `make setup-pre-commit` |
| 329 | +2. **Code changes**: `make fmt` → `make lint` → `make test` |
| 330 | +3. **Commit**: Git hooks run automatically |
| 331 | + |
| 332 | +Only search for additional information if: |
| 333 | +1. Makefile commands fail with unexpected errors not covered above |
| 334 | +2. New dependencies or tools are introduced |
| 335 | +3. The project structure significantly changes |
| 336 | +4. Python version requirements change |
0 commit comments