Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# harness-python-react

[![CI](https://github.com/constk/harness-python-react/actions/workflows/ci.yml/badge.svg?branch=develop)](https://github.com/constk/harness-python-react/actions/workflows/ci.yml)
[![Security](https://github.com/constk/harness-python-react/actions/workflows/security.yml/badge.svg?branch=develop)](https://github.com/constk/harness-python-react/actions/workflows/security.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.14](https://img.shields.io/badge/python-3.14-blue.svg)](https://www.python.org/)
[![Node 24 LTS](https://img.shields.io/badge/node-24%20LTS-43853d.svg)](https://nodejs.org/)
[![React 19.2](https://img.shields.io/badge/react-19.2-61dafb.svg)](https://react.dev/)
[![Coverage 98%](https://img.shields.io/badge/coverage-98%25-brightgreen.svg)](docs/HARNESS.md)

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

## What ships
Expand Down Expand Up @@ -27,6 +35,61 @@ docker compose up # backend :8000, frontend :5173, Jaeger :16686

The pre-push gate is `just check` (= ruff + mypy + import-linter + pytest). For frontend changes add `just frontend-check`.

## Screenshots

### `just check` — local pre-push gate

What every contributor sees before pushing:

```text
$ uv run --frozen ruff check .
All checks passed!

$ uv run --frozen ruff format --check .
37 files already formatted

$ uv run --frozen mypy --strict src/ tests/
Success: no issues found in 31 source files

$ uv run --frozen lint-imports
Analyzed 24 files, 15 dependencies.

src layers flow one-way (api/eval -> agent -> tools -> data -> observability ->
models) KEPT
src.models depends on nothing in src/ KEPT

Contracts: 2 kept, 0 broken.

$ uv run --frozen pytest tests/ --cov=src --cov-report=term
============================= 40 passed in 0.75s ==============================
TOTAL 221 3 99%
Required test coverage of 75.0% reached. Total coverage: 98.64%
```

### CI on a sample PR

Eight backend + two frontend + four security jobs all green on every PR:

![CI status](docs/images/ci-green.png)

> **Capture:** open <https://github.com/constk/harness-python-react/actions/workflows/ci.yml>, click any green run on `develop`, screenshot the job-list panel. Save as `docs/images/ci-green.png`.

### Hello page (`docker compose up`)

The scaffold's React page hits `/api/v1/health` on load and renders the version + status badge:

![Hello page](docs/images/hello-page.png)

> **Capture:** `docker compose up`, open <http://localhost:5173>, screenshot.

### Jaeger trace for `/api/v1/health`

OTel auto-instrumentation produces one span per request, exported via OTLP gRPC to the local Jaeger:

![Jaeger trace](docs/images/jaeger-trace.png)

> **Capture:** with the stack running, hit `/api/v1/health` once, then open <http://localhost:16686>, select service `harness-python-react`, click the most recent trace, screenshot the span timeline.

## Why a harness

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.
Expand Down
Empty file added docs/images/.gitkeep
Empty file.
Loading