Spaces:
Sleeping
Sleeping
| # 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. | |