|
1 | 1 | # harness-python-react |
2 | 2 |
|
3 | | -Production-quality coding harness for Python (FastAPI) backends and Vite + React + TypeScript frontends. Designed for LLM-driven development: every gate — lint, types, architecture, security, eval — is enforced mechanically so code quality stays consistent across many human and AI contributors. |
| 3 | +> A production-quality coding harness for Python (FastAPI) + Vite/React/TypeScript projects. Designed for LLM-driven development: every gate — lint, types, architecture, security, eval — is enforced mechanically so code quality stays consistent across many human and AI contributors. |
4 | 4 |
|
5 | | -> **Status:** bootstrap. Full documentation, scaffolding, and the harness itself land across [issues #1–#28](https://github.com/constk/harness-python-react/issues). Track progress on the [project board](https://github.com/users/constk/projects/3). |
| 5 | +## What ships |
| 6 | + |
| 7 | +- **Backend:** Python 3.14, FastAPI, Pydantic v2 (`StrictModel` base), `uv` deps, OpenTelemetry SDK + OTLP exporter, structured JSON logs, generic tool-registry pattern. |
| 8 | +- **Frontend:** Node 24 LTS, React 19.2, Vite 8, TypeScript strict, ESLint 10 flat config, Prettier, Vitest + jsdom + Testing Library. |
| 9 | +- **Eval harness:** provider-agnostic runner + LLM-judge `Protocol`, three tolerance modes (exact / numeric / semantic), one example golden case, nightly workflow (disabled by default). |
| 10 | +- **CI:** 15 required status checks across `ci.yml` (lint/format, mypy strict, unit tests, coverage ≥75%, import-linter architecture, pre-commit, frontend build, frontend quality, branch-protection sync, commit-type sync) + `security.yml` (gitleaks, pip-audit, npm audit, trivy) + PR-title lint. |
| 11 | +- **Release:** tag-triggered workflow that builds the image, pushes to `ghcr.io`, generates a CycloneDX SBOM, and publishes the GitHub Release. |
| 12 | +- **Agent integration:** `.claude/hooks/` (forbidden-flag blocker, secret scan, formatter dispatch, SessionStart context) + six auto-activating skills (architect / code-reviewer / devops / frontend / qa-engineer / technical-writer). |
| 13 | +- **Docker:** multi-stage Dockerfile (non-root, healthcheck), `docker compose up` boots app + frontend + Jaeger. |
| 14 | + |
| 15 | +## Quickstart |
| 16 | + |
| 17 | +```sh |
| 18 | +git clone https://github.com/constk/harness-python-react.git |
| 19 | +cd harness-python-react |
| 20 | + |
| 21 | +uv sync --extra dev |
| 22 | +uv run pre-commit install --hook-type pre-commit --hook-type commit-msg |
| 23 | +(cd frontend && npm ci) |
| 24 | + |
| 25 | +docker compose up # backend :8000, frontend :5173, Jaeger :16686 |
| 26 | +``` |
| 27 | + |
| 28 | +The pre-push gate is `just check` (= ruff + mypy + import-linter + pytest). For frontend changes add `just frontend-check`. |
| 29 | + |
| 30 | +## Why a harness |
| 31 | + |
| 32 | +The differentiator isn't the scaffold — it's that every layer of the pipeline catches a different failure class **without relying on the human or LLM coder remembering to run anything**. The same posture protects code regardless of who wrote it. |
| 33 | + |
| 34 | +See [`docs/HARNESS.md`](docs/HARNESS.md) for the full umbrella. Highlights: |
| 35 | + |
| 36 | +- **Pydantic `StrictModel` everywhere a contract crosses a seam** (rejects unknown keys at construction). |
| 37 | +- **`import-linter` enforces one-way layer flow** (`api | eval → agent → tools → data → observability → models`). |
| 38 | +- **Three independent secret scans** (PreToolUse hook → pre-commit gitleaks → CI gitleaks). |
| 39 | +- **Two meta-gates** that catch *drift in the gates themselves*: `Branch-protection contexts sync` (workflow jobs vs branch-protection JSON) and `Commit-type sync` (commitizen schema vs PR-title allowlist). |
| 40 | +- **CycloneDX SBOM attached to every release** for supply-chain attestation. |
| 41 | + |
| 42 | +## Documentation |
| 43 | + |
| 44 | +| File | Purpose | |
| 45 | +|---|---| |
| 46 | +| [`docs/HARNESS.md`](docs/HARNESS.md) | Umbrella: every control + where it lives | |
| 47 | +| [`docs/INVARIANTS.md`](docs/INVARIANTS.md) | The numbered load-bearing rules | |
| 48 | +| [`docs/BOUNDARIES.md`](docs/BOUNDARIES.md) | Module layering + the import-linter contracts | |
| 49 | +| [`docs/DEVELOPMENT.md`](docs/DEVELOPMENT.md) | Local setup, branching, justfile, CI | |
| 50 | +| [`docs/EVAL_HARNESS.md`](docs/EVAL_HARNESS.md) | Eval flywheel + opt-in for the nightly workflow | |
| 51 | +| [`docs/SECURITY.md`](docs/SECURITY.md) | Threat model + defence-in-depth map | |
| 52 | +| [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | Scaffold-level component view | |
| 53 | +| [`CONTRIBUTING.md`](CONTRIBUTING.md) | Branching, commit format, PR flow | |
| 54 | +| [`CLAUDE.md`](CLAUDE.md) | Agent-facing project instructions | |
| 55 | + |
| 56 | +## Versions |
| 57 | + |
| 58 | +Verified April 2026 (`endoflife.date`): |
| 59 | + |
| 60 | +| Layer | Version | Sunset | |
| 61 | +|---|---|---| |
| 62 | +| Python | 3.14.4 | active feature release | |
| 63 | +| Node LTS | 24.15.0 | through 2028-04-30 | |
| 64 | +| React | 19.2.5 | current stable | |
| 65 | +| Vite | 8.x | current stable | |
| 66 | +| TypeScript | 6.x | current stable | |
| 67 | + |
| 68 | +Bump together (Python in `pyproject.toml`, Node in `frontend/package.json`, both in `Dockerfile` + the CI matrix). Document the bump in `docs/DEVELOPMENT.md`. |
| 69 | + |
| 70 | +## License |
| 71 | + |
| 72 | +[MIT](LICENSE). |
0 commit comments