CONTRIBUTING.md
Rama main · réplica de lectura del repositorio original.
# Contributing
## Ground rules
- Start with an issue for large changes
- Keep pull requests small and reviewable
- Any write-path change must include tests and docs
- No secrets, personal libraries, or copyrighted books in the repo
## Forge workflow
Calibre Bookwarden has a canonical development forge and a public mirror; it
does not maintain an automatic dual-forge synchronization:
1. **Gitea (maintainer-hosted primary & hermetic CI)**:
- The canonical forge is private to the maintainer's homelab.
- Hosts full-stack hermetic CI runners (PostgreSQL, Valkey, Tesseract, Calibre lab).
- Core release gates and vulnerability scans run here.
2. **GitHub (Public mirror & Community)**:
- URL: `https://github.com/felixapel/calibre-bookwarden`
- Public distribution, issues, and external contributor PRs.
- Does not automatically mirror commits, releases, or tags. GitHub workflow
results do not replace canonical Gitea release evidence.
### Contribution Workflow
1. Fork the repository in the forge where the contribution will be reviewed.
2. Create a feature branch: `git checkout -b feat/my-improvement`.
3. Run formatting, linting, and local tests.
4. Open a Pull Request in that forge with:
- Problem statement and motivation
- Technical approach and risk assessment
- Test evidence and benchmark diffs
- Screenshots or CLI snippets if UI/terminal output changed
## Branch naming
Examples:
- `feat/cover-provider-cache`
- `fix/author-sort-particle-rule`
- `refactor/direct-engine-cursor`
- `docs/roadmap-update`
## Commit style
Use Conventional Commits format:
- `feat:` New user-facing feature or capability
- `fix:` Bug fix or error resolution
- `docs:` Documentation updates
- `refactor:` Code refactoring without behavior change
- `test:` Adding or updating tests
- `chore:` Build scripts, dependencies, CI configuration
## Coding standards
- Python: Python 3.12+ using `uv`.
- Type annotations: Strictly typed where practical (`mypy` compliant).
- Favor pure, deterministic functions for normalization and rule checking.
- Keep provider adapters thin, bounded, and failure-tolerant.
- Zero silent mutations: All writes require explicit confirmation or authorization.
- Fast execution: Direct engine queries must use streaming keysets, avoiding full-table memory loads.
## Required local checks
All checks must pass before opening a PR:
```bash
# Linting & Formatting
uv run ruff check .
uv run ruff format --check .
# Static Type Checking
uv run mypy src
# Deterministic backend gate (excludes service-backed suites explicitly)
uv run pytest \
-m 'not benchmark and not ocr_live and not network' \
--ignore=tests/test_retention_postgres_valkey.py \
--ignore=tests/test_v2_supervised_pilot_integration.py
# Frontend Build (if modifying webui/)
cd webui && npm run build && cd ..
```
## PR checklist
- [ ] code follows project structure
- [ ] schemas updated if payloads changed
- [ ] CLI reference updated if flags changed
- [ ] tests added or updated
- [ ] snapshots reviewed intentionally
- [ ] no secrets or private evidence committed
## Test data rules
Allowed:
- synthetic fixtures
- public-domain books
- generated images
- mocked provider responses
Forbidden:
- commercial ebook uploads
- DRM-protected files
- full private evidence packages from real libraries
## Security and privacy
If the change affects:
- remote uploads
- credentials
- write/apply logic
- backups and undo
then mention it explicitly in the PR description.
## Publishing an exact revision
After an automatically triggered Gitea run passes for the candidate SHA, the
repository owner records a GitHub commit status named `bookwarden/gitea-canonical`
for that same SHA, linking its canonical Gitea run. The GitHub release workflow
requires this owner-attested result in addition to its local checks and immutable
image gates. This is a deliberate publication attestation because hosted GitHub
runners cannot reach the private Gitea endpoint; it is not an automatic mirror.
Never attest a failed, skipped, incomplete or different-revision run as successful.
Promote the reviewed source to both main branches without rewriting history,
then create the matching new version tag. Existing release tags are immutable.
All three image matrix jobs must finish successfully before the aggregate job
validates their receipts, emits `release-images.json`, and promotes semver image
tags. Create matching forge release notes and attach the manifest only after the
publication workflow succeeds. A source tag alone does not prove image delivery.