Skip to content

Latest commit

 

History

History
135 lines (96 loc) · 5.01 KB

File metadata and controls

135 lines (96 loc) · 5.01 KB

Development

Prerequisites

  • Python 3.14 (see pyproject.toml requires-python)
  • Node 24 LTS (see frontend/package.json engines.node)
  • uv for Python deps + venv
  • just for the task runner (optional but recommended)
  • Docker (for the local stack: app + frontend + Jaeger)

First-time setup

git clone https://github.com/constk/harness-python-react.git
cd harness-python-react

# Backend deps + venv
uv sync --extra dev

# Pre-commit hooks (commit-msg + pre-commit stages)
uv run pre-commit install --hook-type pre-commit --hook-type commit-msg

# Frontend deps
cd frontend && npm ci && cd ..

Running the stack

docker compose up

For backend-only iteration without Docker:

uv run uvicorn src.api.main:app --reload --port 8000

For frontend-only iteration:

cd frontend && npm run dev

The justfile

just (no args) lists every recipe. The most-used:

Recipe What it runs
just lint ruff check . + ruff format --check .
just typecheck mypy --strict src/ tests/
just test pytest tests/ -m "not integration"
just architecture lint-imports
just check lint typecheck architecture test (the pre-push gate)
just frontend-check npm run lint && format:check && check && test
just docker-build Builds harness-python-react:dev for sanity checks

Every recipe uses uv run --frozen — bare uv run silently re-resolves when pyproject.toml drifts from uv.lock; --frozen aborts loudly instead.

Branching

        main  ◄── release PR ◄── develop ◄── feat/123-short-name
                                          ◄── fix/124-bug-name
                                          ◄── chore/125-config-change
  • main is protected: every required CI context must pass + 1 review + commit-type sync + branch-protection sync.
  • develop is the integration branch; same gates as main minus a strictness flag (strict: false so PRs don't need rebases).
  • Feature branches are short-lived and named <type>/<issue-number>-<kebab-title>.

Commit messages

Seven allowed prefixes (enforced in three places — [tool.commitizen], pr-title.yml, check_commit_types.py):

  • feat: — new capability
  • fix: — bug fix
  • docs: — documentation only
  • test: — tests / eval-harness changes
  • refactor: — internal change with no behaviour delta
  • chore: — tooling, deps, infra
  • release:develop → main release PRs only

Subject is lowercase after the colon (Title Case is rejected unless it's an all-caps initialism).

CI pipeline (.github/workflows/)

Workflow Triggers Required?
ci.yml push/PR to develop+main Yes — 8 backend + 2 frontend jobs
security.yml push/PR + weekly schedule Yes — 4 jobs (gitleaks, pip-audit, npm audit, trivy)
pr-title.yml PR open/edit/sync Yes — conventional-commit lint
release.yml tag v*.*.* No — tag-triggered
release-drafter.yml push to main + PR label events No
branch-protection.yml weekly + push to .github/branch-protection/** No
artifact-cleanup.yml weekly No
eval-nightly.yml workflow_dispatch only by default No
codeql.yml workflow_dispatch only (placeholder) No

Local agent hook setup

The .claude/hooks/ scripts enforce the harness from the LLM-coder side: blocking --no-verify, scanning staged diffs for secrets, formatting after every Write/Edit. Opt in by copying the example settings file:

cp .claude/settings.local.json.example .claude/settings.local.json

The example wires:

  • PreToolUse:Bashpretooluse_bash.py (forbidden-flag blocker + secret scan + audit log)
  • PostToolUse:Write|Editposttooluse_writeedit.py (ruff / prettier on touched files)
  • SessionStart:startup|resumesessionstart.py (injects current branch + git status --short as session context)

.claude/settings.local.json and .claude/bash-log.txt are gitignored — your local config never ships.

Pre-commit setup

uv run pre-commit install --hook-type pre-commit --hook-type commit-msg wires both stages. The hooks:

  1. Ruff (lint + format auto-fix)
  2. Generic hygiene (YAML/TOML/JSON parse, merge conflicts, large files >500 KB, trailing whitespace, EOF, line endings)
  3. Gitleaks (secret scan)
  4. Commitizen (conventional-commit lint at commit-msg)
  5. Local mypy --strict against the project's uv env

pre-commit run --all-files runs the full suite against every file — the same job CI runs.

Branch-protection sync setup

The branch-protection.yml workflow needs a BRANCH_PROTECTION_TOKEN secret with admin:repo scope on this repo. The default GITHUB_TOKEN cannot edit branch protection on the repo it runs in. Create a fine-grained PAT scoped to this repo only.