# Contributing to OrgState ## Dev setup ```bash # clone + install runtime deps + test deps pip install -r requirements-runtime.txt pip install pytest # install pre-commit hooks (Stage 94) — runs ruff lint+format # and basic file hygiene before every commit pip install pre-commit pre-commit install # now `git commit` automatically runs the hooks ``` ## Style - **Python**: ruff handles lint + format (config in `pyproject.toml`). No black / isort / flake8 — ruff replaces all three. - **Line length**: 100. Existing long lines grandfathered (E501 deferred); new code stays under. - **Hebrew for chat / commit body OK**. Code identifiers + comments stay English. ## Pre-commit hooks — what they enforce | Hook | What | Why | |---|---|---| | `ruff` | Lint with `--fix` | Auto-fixes safe issues (sort imports, remove unused, etc) | | `ruff-format` | Format like black | Eliminates style bikeshedding | | `trailing-whitespace` | Strip trailing spaces | Cleaner diffs | | `end-of-file-fixer` | Ensure final newline | POSIX text files | | `check-yaml` / `check-json` / `check-toml` | Parse config files | Catches typos before push | | `check-added-large-files` | Refuse > 500KB | Repo bloat guard | | `check-merge-conflict` | Catch unresolved `<<<<<` | Pre-flight check | | `detect-private-key` | Refuse SSH/PGP keys | Defense against leaks | ## Run hooks manually ```bash # run on all files (first time after installing) pre-commit run --all-files # run only on staged files (default behavior — git commit triggers) pre-commit run # skip hooks for an emergency commit (use sparingly) git commit --no-verify ``` ## Running tests ```bash # full suite pytest # one file pytest tests/test_infra_billing.py # coverage subset pytest -k webhook # skip slow tests (npm build, locust import, etc — gated by # tool availability already, but you can be explicit) pytest -m "not slow" ``` The CI pipeline runs the full suite against both SQLite and Postgres on every PR — see `.github/workflows/ci.yml`. If pre-commit hooks pass locally, CI usually does too. ## Adding a new stage 1. Plan the work in MIGRATION_MAP.md (per-stage narrative is part of the deliverable). 2. Code + tests in same commit. Test count goes UP on every stage. 3. Run `pre-commit run --all-files` + `pytest` before committing. 4. Commit message format: `Stage N: ` + body explaining the WHY (see git log for examples). ## When ruff finds something - **Auto-fixable** (most I/F rules): `ruff check . --fix` and commit. - **Manual fix needed**: address the underlying issue. Don't `# noqa: X` unless there's a good reason — the rule probably matters. - **Codebase-wide false positive**: add to `[tool.ruff.lint.ignore]` or `per-file-ignores` in `pyproject.toml`, with a comment explaining the trade-off. ## License + provenance All commits become part of the project history under the repo's existing license. By contributing, you agree your changes can be redistributed under that license. For questions: see `RUNBOOK.md` (operator concerns) or `MIGRATION_MAP.md` (per-stage decisions).