Co-Study4Grid / CONTRIBUTING.md
github-actions[bot]
Deploy 7688ef1
13d4e44
|
Raw
History Blame Contribute Delete
6.43 kB
# Contributing to Co-Study4Grid
Thanks for taking the time to contribute. This document captures the
conventions that keep the codebase easy to work in. For the project
overview and architecture see [`CLAUDE.md`](./CLAUDE.md).
## Development setup
### Backend
```bash
python -m pip install --upgrade pip
pip install ".[test]"
pip install --no-deps expert_op4grid_recommender
uvicorn expert_backend.main:app --host 0.0.0.0 --port 8000
```
#### System prerequisite — Graphviz (`dot`)
The overflow-graph rendering pipeline shells out to Graphviz's
`dot` binary. `pip install` attempts a best-effort auto-install via
the platform's package manager (apt / dnf / pacman / apk on Linux,
Homebrew or MacPorts on macOS, Chocolatey / winget / Scoop on
Windows); set `COSTUDY4GRID_SKIP_GRAPHVIZ_INSTALL=1` to opt out.
Modern wheel-based installs may skip the `setup.py` post-install
hook — re-run it manually with the bundled console script if
`dot -V` fails:
```bash
costudy4grid-install-graphviz
```
If the auto-install can't elevate (no `sudo`, locked package DB,
unsupported package manager), install Graphviz by hand:
| Platform | Command |
|-------------------------|---------------------------------------------------|
| Debian / Ubuntu | `sudo apt-get install graphviz` |
| RHEL / Fedora | `sudo dnf install graphviz` (or `yum`) |
| Arch | `sudo pacman -S graphviz` |
| Alpine | `sudo apk add graphviz` |
| macOS (Homebrew) | `brew install graphviz` |
| macOS (MacPorts) | `sudo port install graphviz` |
| Windows (Chocolatey) | `choco install graphviz` |
| Windows (winget) | `winget install Graphviz.Graphviz` |
| Windows (Scoop) | `scoop install graphviz` |
### Frontend
```bash
cd frontend
npm install
npm run dev # Vite dev server with HMR (default port 5173)
```
## Running tests
```bash
# Backend
pytest
# Frontend
cd frontend
npm run test
npm run lint
```
## Code-quality checks
Continuous quality metrics are generated by
[`scripts/code_quality_report.py`](./scripts/code_quality_report.py) and
enforced by [`scripts/check_code_quality.py`](./scripts/check_code_quality.py).
Both run locally and in CI (see `.github/workflows/code-quality.yml`).
```bash
# Generate a full JSON + Markdown report
python scripts/code_quality_report.py --output reports/code-quality.json \
--markdown reports/code-quality.md
# Gate a pull request (non-zero exit on regression)
python scripts/check_code_quality.py
```
The gate enforces (full table in
[`scripts/check_code_quality.py`](./scripts/check_code_quality.py)):
- No new `print()` or `traceback.print_exc()` calls in backend sources
- No new bare `except Exception: pass` patterns
- Backend modules stay under **1150 lines** (the "god-object" ceiling);
functions under **240**. The scan covers all of `expert_backend/`
except the test suite and the setup-time / ad-hoc scripts.
- Backend functions also stay under **cyclomatic complexity 38** and
**nesting depth 8** (computed from the AST — no external tool).
- Frontend components stay under **1450 lines** (`utils/**` under
**1000**); `App.tsx`, the orchestration hub, has a bounded **2100**
ceiling rather than a blanket exemption.
- No `any` / `as any` annotations, and no `@ts-ignore` /
`@ts-expect-error` / `@ts-nocheck` in frontend sources
- **Ratcheted** (frozen at today's count, may only go down): backend
`# noqa` / `# type: ignore` (**3**), `as unknown as` casts (**12**),
`Record<string, unknown>` usages (**45**)
- **No hex color literals** in frontend source. The ceiling is zero —
every colour must come from a named token. Define new colours in
[`frontend/src/styles/tokens.css`](./frontend/src/styles/tokens.css)
(the canonical CSS variables) and re-export them from
[`frontend/src/styles/tokens.ts`](./frontend/src/styles/tokens.ts)
for inline-style consumers (`colors` / `space` / `text` / `radius`,
plus `pinColors` / `pinChrome` for SVG-attribute use cases). Both
token files are exempt from the gate; nothing else is.
Lower the thresholds — don't raise them. Tightening the gate
is how we protect the hard-won reductions documented in
[`docs/architecture/code-quality-analysis.md`](./docs/architecture/code-quality-analysis.md).
**mypy gates the build.** The shared-state base
([`expert_backend/services/_recommender_state.py`](./expert_backend/services/_recommender_state.py))
makes the mixin composition type-check cleanly, so mypy sits at 0 and any
new type error fails CI. **Test coverage gates** on both ends: frontend
via `frontend/vite.config.ts` (`coverage.thresholds`, enforced by
`npm run test:coverage`) and backend via `pyproject.toml`
(`[tool.coverage.report] fail_under = 72`, enforced by `pytest --cov`).
Both floors sit a few points below the measured baseline — raise them as
coverage climbs, don't lower them. All are wired into the GitHub Actions
pipelines; see §§19–20 of the analysis doc.
## Commit & PR conventions
- **Conventional-commit prefixes**: `feat:`, `fix:`, `perf:`, `docs:`,
`test:`, `refactor:`, `build:`, `chore:`. Match the surrounding git log.
- Keep PRs focused. One logical change per PR.
- Run `pytest`, `npm run test`, `npm run lint`, and
`python scripts/check_code_quality.py` before opening a PR.
- Update [`docs/architecture/code-quality-analysis.md`](./docs/architecture/code-quality-analysis.md)
when a fix resolves a documented issue.
## Style
- **Python**: PEP 8 manually (4-space indent, type hints where helpful,
snake_case). Use `logging`, not `print`. Ruff runs in CI with a light
ruleset — see `pyproject.toml`.
- **TypeScript**: strict mode (`strict: true`, `noUnusedLocals`,
`noUnusedParameters`). No `any`. Functional components + hooks.
ESLint flat config enforces the rest.
- **Editor defaults** live in `.editorconfig`.
## Reporting bugs
Open a GitHub issue with:
1. Steps to reproduce (network path, action file, settings, contingency).
2. Expected vs. actual behaviour.
3. Browser console + backend stderr when UI-related.
4. The attached session folder when reproducible via save/reload.