substrateverifiedp0

Local CI foundation — uv workspace + ruff + mypy + pytest + poe

ci-foundation · updated — · owner rritz

Use the pencil to edit title, status, priority, and owner. Changing status auto-prepends a changelog entry.

Every later spec in the substrate inherits this layer. CI runs
locally — not on GitHub Actions — so contributors can replicate the
exact same checks pre-push, no cloud minutes burnt. The single entry
point is uv run poe ci: lint + format-check + typecheck + unit +
contract + spec-validate, all in <30s on a warm cache. Without this,
every new spec's "success determiner" runs in an undocumented,
drift-prone environment.

As a contributor, I want one command that runs every check before push so that I don't push code that fails verification.

As a future-spec author, I want shared lint + typecheck + test config inherited from the root so that my new code is held to the same bar without re-configuring.

  1. When a developer runs `uv run poe ci` from a clean working tree, the system shall lint, format-check, typecheck, run unit + contract tests, and validate spec YAMLs — exiting 0 on success.
  2. Where pre-existing modules fail strict linting (B/SIM/RUF rules) or strict typing, the substrate shall exclude them via documented per-path overrides rather than touch their code.
  3. Where new code lives under `josh_substrate.embedding.*`, `josh_embedder.*`, `app.embedding`, or `app.routes.embed`/`health_embedding`, the substrate shall enforce strict mypy.
  4. When pre-commit hooks are installed, the system shall run fast checks on staged files at commit time and the full `poe ci` at push time.
  5. When CI runs, the total wall time shall be under 30 seconds on a warm cache.
kindbash

Command

set -euo pipefail
uv run poe ci

Expect

exit-zero

From repo root, on a clean working tree.

None.

None.

None.

Top-level pyproject.toml declares the uv workspace, dev dep group,
and tool config (ruff, mypy, pytest). Tasks live in [tool.poe.tasks].
Pre-commit config in .pre-commit-config.yaml wires both stages.
Pre-existing modules grandfathered out of ruff via extend-exclude
and out of strict mypy by being absent from the per-module override
block. New code opts in via the override.

7 of 7 done.

  • t1 Top-level pyproject.toml with uv workspace + dev deps
  • t2 Per-service pyproject.toml for josh-core, josh-embedder, josh-substrate
  • t3 ruff + mypy + pytest config inherited from root
  • t4 poe tasks: lint, format, typecheck, test, test-contract, test-live, smoke, ci, ci-full, spec-validate
  • t5 .pre-commit-config.yaml with pre-commit + pre-push stages
  • t6 uv 0.11+ workspace verified to sync all 4 packages cleanly
  • t7 Conservative ruff rule set (E/F/I/UP), with cleanup spec deferred for B/SIM/RUF
  • 2026-05-10T11:00:00Z plannedverified Foundation in place; uv run poe ci exits 0 with 73 tests passing.

docs/spec/ci-foundation.html · generated by bin/build-spec.py