# noeta — developer convenience wrapper. # # make install first time: uv sync with every extra # make check the local CI gate (mirrors .github/workflows/ci.yml) # make test the test suite with coverage # make lint static checks only (ruff, mypy, naming + import layering) # make example the example plugin, installed as its own package, and its tests # make tui the terminal UI's tests (tui/, its own package) # make web the web app: install, typecheck, unit and e2e tests (web/) # make desktop the desktop app: install, typecheck, unit and e2e tests (desktop/) # make frontends every front end's tests (tui/, web/, desktop/) # make docs build the docs site (docs/, VitePress); make docs-dev serves it live # make e2e live tests: real LLM / real container (needs credentials) # make eval prompt-regression eval vs evals/baseline.json (needs credentials) # make parity replay Claude Code's recorded scenarios against noeta, report every difference # make cluster worker processes on Postgres under random kills (needs docker or a DSN) # make build wheel + sdist into dist/, with the built web app (when npm is there) .DEFAULT_GOAL := help .PHONY: help install check test lint example tui tui-screenshots web desktop frontends docs docs-dev e2e eval eval-baseline \ parity cluster build web-bundle help: @echo "noeta" @echo "" @echo " make install first time: uv sync with every extra" @echo " make check the local CI gate: lint + tests with coverage + doc hygiene" @echo " make test the test suite with coverage" @echo " make lint static checks only: ruff, mypy, naming + import layering" @echo " make example install examples/hello-plugin as a package and run its tests" @echo " make tui the terminal UI's tests (tui/), with coverage" @echo " make tui-screenshots rewrite tui/screenshots/*.svg" @echo " make web web/: install, typecheck, unit tests, e2e against a real noeta serve" @echo " make desktop desktop/: install, typecheck, unit tests, e2e of the built app (xvfb-run)" @echo " make frontends every front end's tests (tui/, web/, desktop/)" @echo " make docs build the docs site into docs/.vitepress/dist (docs-dev: live preview)" @echo " make e2e live tests: real LLM / real container (needs credentials)" @echo " make eval prompt-regression eval vs evals/baseline.json (needs credentials)" @echo " make eval-baseline 9-trial run, then rewrite evals/baseline.json" @echo " make parity replay Claude Code's recorded scenarios, write parity/report.md" @echo " make cluster worker processes on Postgres under random kills (docker or a DSN)" @echo " make build wheel + sdist into dist/, with the built web app (when npm is there)" install: uv sync --all-extras test: uv run pytest -n auto --cov=noeta --cov-report=term lint: uv run ruff check noeta tests evals bench scripts examples tui uv run mypy uv run python scripts/lint-naming.py uv run python scripts/lint-layout.py uv run lint-imports ## a third-party plugin end to end: built and installed from examples/hello-plugin ## (found through its entry point, nothing patched), in a throwaway environment; ## then the single-file plugins of examples/ (docs/guides/plugins.md), loaded as plain files PLUGIN_FILE_EXAMPLES = examples/run-tests/tests examples/house-style/tests examples/web-panel/tests example: uv run --with-editable ./examples/hello-plugin python -m pytest -q -p no:cacheprovider examples/hello-plugin/tests uv run pytest -q -p no:cacheprovider $(PLUGIN_FILE_EXAMPLES) ## the terminal UI, its own package (tui/, a uv workspace member): Textual pilot tests tui: cd tui && uv run pytest -n auto -q --cov=noeta_tui --cov-report=term:skip-covered --cov-fail-under=85 ## the screenshots tui/screenshots/README.md compares with Claude Code's tui-screenshots: cd tui && rm -rf /tmp/noeta-demo && NOETA_TUI_SCREENSHOTS=1 uv run pytest -q --basetemp=/tmp/noeta-demo tests/test_screenshots.py ## every front end's own tests frontends: tui web desktop ## the docs site: diagrams on the shared style, then a VitePress build (dead links fail it) docs: cd docs && npm ci && npm run build docs-dev: cd docs && npm ci && npm run dev ## the web app: typecheck, unit tests, Playwright against a real noeta serve web: cd web && npm ci && npm run typecheck && npm test && npm run e2e ## the desktop app over the web build: typecheck, unit tests, Playwright's Electron ## driver under xvfb-run against the noeta serve it starts desktop: cd web && npm ci && npm run build cd desktop && npm ci && npm run typecheck && npm test && npm run e2e ## live tests against a real LLM backend / sandbox container (opt-in, never in check) e2e: uv run pytest -m live ## prompt-regression eval against a real model (opt-in, never in check); ## exits 1 when a scenario falls below evals/baseline.json by more than its tolerance ## the model: EVAL_MODEL if given, else NOETA_LIVE_MODEL from the git-ignored .env ## (the baseline is recorded on DeepSeek V4.1 Flash) eval: uv run python -m evals $(if $(EVAL_MODEL),--model $(EVAL_MODEL)) ## rewrite evals/baseline.json from a 9-trial run (a steadier mean than eval's 3) eval-baseline: uv run python -m evals $(if $(EVAL_MODEL),--model $(EVAL_MODEL)) --trials 9 --write-baseline ## noeta replayed through Claude Code's recorded scenarios (scripts/parity/README.md), ## offline; writes parity/report.md and exits 1 while any mismatch is left (never in check). ## First, an advisory report of model-visible texts that repeat Claude Code's ## recorded text (scripts/parity/own_words.py; never fails, ADR-020) parity: uv run python -m scripts.parity.own_words uv run python -m scripts.parity.replay ## several worker processes on one Postgres (a throwaway postgres:16 container, ## or NOETA_TEST_POSTGRES_DSN) under random SIGKILL / SIGSTOP, offline with a ## scripted provider (tests/cluster); NOETA_CLUSTER_SEED replays a run (never in check). ## `python -m pytest` so the run's interpreter sees the scripted package; a skipped ## cluster test fails the run (NOETA_CLUSTER_REQUIRED) cluster: NOETA_CLUSTER_REQUIRED=1 uv run --all-extras --with-editable ./tests/cluster/scripted python -m pytest -m cluster -p no:cacheprovider -s -v tests/cluster ## the built web app copied into the package (noeta/host/web_dist, kept out of the ## repository), so the wheel carries it and noeta serve serves it; ## without npm the wheel has none and says so WEB_BUNDLE = noeta/host/web_dist web-bundle: @if command -v npm >/dev/null 2>&1; then \ cd web && npm ci && npm run build && cd .. && \ rm -rf $(WEB_BUNDLE) && cp -R web/dist $(WEB_BUNDLE); \ else \ echo "make: npm not found; the wheel carries no web app (noeta serve serves it)"; \ fi build: web-bundle uv build ## the front ends, each its own project with its own test command (never in check: ## it needs node and a browser). web/: the e2e test runs a real noeta serve on the ## offline scripted provider in web/e2e/provider ## every automated gate — CI's test job runs this same target. CI-only on top: ## the Postgres params of the store contract tests (skipped unless ## NOETA_TEST_POSTGRES_DSN points at a live server) and the Python 3.11-3.13 matrix. check: uv sync -q --all-extras $(MAKE) --no-print-directory lint uv run pytest -n auto -q --cov=noeta --cov-report=term:skip-covered --cov-fail-under=85 $(MAKE) --no-print-directory example $(MAKE) --no-print-directory tui bash scripts/check-docs.sh