# 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` 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.