CONTRIBUTING.md
Rama main · réplica de lectura del repositorio original.
# Contributing to pawbot
Thank you for being here.
pawbot is built with a simple belief: good tools should feel calm, clear, and humane.
We care deeply about useful features, but we also believe in achieving more with less:
solutions should be powerful without becoming heavy, and ambitious without becoming
needlessly complicated.
This guide is not only about how to open a PR. It is also about how we hope to build
software together: with care, clarity, and respect for the next person reading the code.
## Project ownership
pawbot is an owner-led open-source project. The repository owner is responsible for
release decisions, security coordination, and final review of changes. Community
contributors are welcome to propose improvements through issues and pull requests;
review responsibility may be delegated for a specific change without creating a
permanent role roster.
## Contribution Flow
### What Should I Open a PR For?
PRs are welcome for:
- New features or functionality
- Bug fixes with no behavior changes
- Documentation improvements
- Minor tweaks that don't affect functionality
- Refactoring that is clearly scoped and easy to review
- Changes to APIs or configuration, when the impact is documented
For riskier or larger changes, please open an issue or draft PR early so the
shape of the work can be discussed before the implementation grows too large.
### Starting Work
Before making changes, sync your local checkout and create a topic branch.
```bash
git fetch origin
git switch main
git pull --ff-only origin main
git switch -c your-topic-branch
```
Use the remote configured for your checkout if it is not named `origin`.
Keep unrelated local changes out of the topic branch. If your checkout already has
work in progress, use a separate worktree or finish that work before starting a
new branch.
## Development Setup
Keep setup boring and reliable. The goal is to get you into the code quickly:
```bash
# Install with dev dependencies
uv sync --all-extras --dev
# Run tests
uv run pytest -q
# Lint code
uv run ruff check pawbot/
# Format code — optional. The existing tree predates `ruff format`,
# so running it broadly produces large unrelated diffs.
# Do not mix mechanical formatting churn into a functional PR.
# Use formatting only for the exact code your change intentionally touches.
uv run ruff format <files-you-changed>
```
### Strict Type Checking
Strict type checking covers optional providers and channels. Reproduce the CI environment
with the same dependency sources and commands:
```bash
uv sync --all-extras --dev
uv run --no-sync python -m scripts.install_channel_dependencies --all-channels
uv run --no-sync basedpyright
```
Keep `--no-sync` on the final commands: channel dependencies come from their package
manifests and are installed explicitly by the setup step.
## Contribution License
By submitting a contribution, you confirm that you have the right to submit it
and agree that it will be licensed under the project's MIT License.
## Code Style
We care about more than passing lint. We want pawbot to stay small, calm, and readable.
When contributing, please aim for code that feels:
- Simple: prefer the smallest change that solves the real problem
- Clear: optimize for the next reader, not for cleverness
- Decoupled: keep boundaries clean and avoid unnecessary new abstractions
- Honest: do not hide complexity, but do not create extra complexity either
- Durable: choose solutions that are easy to maintain, test, and extend
In practice:
- Line length: 100 characters (`ruff`)
- Target: Python 3.11+
- Linting: `ruff` with rules E, F, I, N, W (E501 ignored)
- Async: uses `asyncio` throughout; pytest with `asyncio_mode = "auto"`
- Prefer readable code over magical code
- Prefer focused patches over broad rewrites
- Do not mix mechanical formatting, line wrapping, import sorting, or quote churn
into a feature or bugfix PR. If formatting cleanup is needed, make it a
separate formatting-only PR.
- If a new abstraction is introduced, it should clearly reduce complexity rather than move it around
## Modifying CI Workflows
If your PR touches `.github/workflows/`, please keep the CI within
GitHub Actions' free tier:
- Use only standard GitHub-hosted runners (`ubuntu-latest`, `windows-latest`)
- Avoid macOS runners, larger runners (`*-cores`, `*-xlarge`, `*-gpu`),
and self-hosted runners
- Avoid uploading large artifacts or using long retention
- Avoid paid Marketplace actions
If your change genuinely needs to step outside this, please call it out
explicitly in the PR description so it can be discussed before merge.
## Release Packaging Contract
A stable install must never combine Python from one version with a TUI from another. Publish in
this order:
1. Set the package version and publish the matching GitHub release tag (`vX.Y.Z`).
2. Manually run **Publish native TUI** for the exact tag.
3. Wait for every platform archive and checksum to appear on the release, then publish the same
`X.Y.Z` package to PyPI by manually running **Publish package** with that tag.
Neither workflow starts merely because a release is published. The package workflow verifies
the tag against `pyproject.toml` and requires all five platform archives and their checksums.
Before tagging, merge a reviewed PR only after every CI check passes. The package smoke job
installs the wheel in a separate environment, starts that installed gateway, and exercises
the bundled lazy assets and authenticated settings mutations. This is in addition to the
frontend component tests; a source-only test run is insufficient for release validation.
The wheel contains the built WebUI. The native TUI stays a platform-specific release sidecar so
users download only the archive for their machine. Each archive must contain the executable,
target-specific third-party notices, project and runtime licenses, corresponding application
source, relinking instructions, and a checksum manifest. Never upload a
naked TUI executable. Source checkouts use an editable Python install, run `tui/` with Bun, and
rebuild stale `webui/` assets locally.
## Questions?
For questions or proposals, use the issue tracker and pull-request workflow of
the repository where pawbot is published. Keep reports focused and include the
reproduction command, platform, provider type, and relevant sanitized logs.