From a8c106d7b94aad2acc74a3e497ec4cca28f092e5 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Sat, 10 Oct 2026 00:44:46 -0700 Subject: [PATCH 1/3] State the build profile's CI type check as the validator runs it The hub validator runs one type checker per Python directory, mypy wherever a config declares both, and passes the checker no path where the config sits in the project directory. The python-codestyle skill said CI may run pyright, mypy, or both, and gave `uv run mypy src` as the command CI runs, so a mypy config with no `files` setting passed locally and failed in CI. State the one-checker rule with where a second checker goes, and give `uv run mypy` with the `files` setting it depends on. Closes on promotion: #2025 Co-Authored-By: Claude Opus 5.5 --- .agents/skills/python-codestyle/SKILL.md | 23 +++++++++++-------- .../python-codestyle/references/profiles.md | 4 +++- .../.source-digests/python-codestyle | 2 +- .../skills/python-codestyle/SKILL.md | 23 +++++++++++-------- .../python-codestyle/references/profiles.md | 4 +++- .github/skills/python-codestyle/SKILL.md | 23 +++++++++++-------- .../python-codestyle/references/profiles.md | 4 +++- 7 files changed, 52 insertions(+), 31 deletions(-) diff --git a/.agents/skills/python-codestyle/SKILL.md b/.agents/skills/python-codestyle/SKILL.md index 00ab2f7c7..d5800a356 100644 --- a/.agents/skills/python-codestyle/SKILL.md +++ b/.agents/skills/python-codestyle/SKILL.md @@ -33,7 +33,8 @@ Then read the `pyproject.toml` shape and pick the profile before running Python - **build** (Project): third-party runtime dependencies, or the repo's deliverable. Either a uv project (`[project]` + `[build-system]` + committed `uv.lock`, run with `uv run`) or a `pyproject.toml` beside a `requirements*.txt` and no `uv.lock`, installed with pip. Uses pytest, - and pyright strict, mypy with its strict flags, or both as the CI type checker. + and pyright strict or mypy with its strict flags as the hub validator's type checker, with a + repo running both adding the second itself, per Toolchain below. - **lint-only** (Scripts): no `[project]`, no `[build-system]`, no lockfile, no `requirements*.txt` (the hub validator runs pytest wherever one sits). Uses `uvx` for third-party tools, unittest for tests, and mypy as the CI gate. Do not run pytest or diagnose its absence as an environment @@ -76,10 +77,12 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar `mypy --strict` because the platinum `strict-typing` quality-scale tier requires it, and a pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy -command joins the clean-compile. mypy may also be a build repo's only CI checker, run with its -strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A -pyright-only repo is the lightest and is inherently consistent, since the editor and CI run one -engine. +command joins the clean-compile. The hub validator runs one checker in each Python directory, +mypy wherever the config declares both, so a repo enforcing pyright beside mypy runs it from its +own `.github/actions/validate/action.yml` hook. mypy may also be a build repo's only CI checker, +run with its strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs +them. A pyright-only repo is the lightest and is inherently consistent, since the editor and CI run +one engine. ## Local development loop @@ -101,9 +104,11 @@ uv build # produce wheel + sdist in ./dist (published pa ``` The **build**-profile Python clean-compile, in its uv form, is `uv run ruff format` + -`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy src` where mypy is -the CI checker, or both where the repo runs both (see Type checking above). Run it, plus -`uv run pytest`, before committing. +`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy` where mypy is +the CI checker, or both where the repo runs both (see Type checking above). CI passes the checker no +path where the config sits in the project directory, so the config selects what is checked, and a +mypy config there sets `files`, without which mypy exits with an error naming no target. Run it, +plus `uv run pytest`, before committing. A **build**-profile directory in its pip form builds its environment the way CI does, through uv's pip interface, which writes no `uv.lock`. It installs every `requirements*.txt` in one command, since @@ -226,7 +231,7 @@ Before pushing or opening a PR: (via the `charliermarsh.ruff` extension) and pyright (via the `ms-python.python` extension's bundled Pylance). - The **build**-profile CI gate, in its uv form, is `uv run ruff check`, - `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy src`), and + `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy`), and `uv run pytest`, the same commands as the local loop above, run from the Python project directory (invoked as separate steps, not `&&`-chained, so the runner shell is irrelevant). The pip form's CI gate is its commands in the local loop above, and a **lint-only** profile's is its `uvx` diff --git a/.agents/skills/python-codestyle/references/profiles.md b/.agents/skills/python-codestyle/references/profiles.md index 092a9bd25..cc9c89e56 100644 --- a/.agents/skills/python-codestyle/references/profiles.md +++ b/.agents/skills/python-codestyle/references/profiles.md @@ -9,7 +9,9 @@ than copying verbatim (a verbatim copy that misdescribes the repo is inaccurate in review). The axes that commonly vary per repo: - **Type checker in CI**: pyright strict, mypy with its strict flags (run in CI and the editor, with - pyright kept editor-only through Pylance), or both. The clean-compile runs every checker CI runs. + pyright kept editor-only through Pylance), or both, the hub validator running one per directory + and the repo running the second, per `SKILL.md` "Toolchain". The clean-compile runs every + checker CI runs. - **Dependency declaration**: the uv form declares the dev tools CI runs in the `dev` group of `[dependency-groups]`, the one group a plain local `uv sync` or `uv run` installs, and which CI's `uv sync --all-groups --frozen` installs too, since it takes every group and no extra. PEP 621 diff --git a/.claude-plugin/fleet-skills/.source-digests/python-codestyle b/.claude-plugin/fleet-skills/.source-digests/python-codestyle index 0fc961d55..3dd74b65a 100644 --- a/.claude-plugin/fleet-skills/.source-digests/python-codestyle +++ b/.claude-plugin/fleet-skills/.source-digests/python-codestyle @@ -1 +1 @@ -29f1d243d1548ec9 +2db4f23ec9e351cc diff --git a/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md b/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md index 00ab2f7c7..d5800a356 100644 --- a/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md +++ b/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md @@ -33,7 +33,8 @@ Then read the `pyproject.toml` shape and pick the profile before running Python - **build** (Project): third-party runtime dependencies, or the repo's deliverable. Either a uv project (`[project]` + `[build-system]` + committed `uv.lock`, run with `uv run`) or a `pyproject.toml` beside a `requirements*.txt` and no `uv.lock`, installed with pip. Uses pytest, - and pyright strict, mypy with its strict flags, or both as the CI type checker. + and pyright strict or mypy with its strict flags as the hub validator's type checker, with a + repo running both adding the second itself, per Toolchain below. - **lint-only** (Scripts): no `[project]`, no `[build-system]`, no lockfile, no `requirements*.txt` (the hub validator runs pytest wherever one sits). Uses `uvx` for third-party tools, unittest for tests, and mypy as the CI gate. Do not run pytest or diagnose its absence as an environment @@ -76,10 +77,12 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar `mypy --strict` because the platinum `strict-typing` quality-scale tier requires it, and a pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy -command joins the clean-compile. mypy may also be a build repo's only CI checker, run with its -strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A -pyright-only repo is the lightest and is inherently consistent, since the editor and CI run one -engine. +command joins the clean-compile. The hub validator runs one checker in each Python directory, +mypy wherever the config declares both, so a repo enforcing pyright beside mypy runs it from its +own `.github/actions/validate/action.yml` hook. mypy may also be a build repo's only CI checker, +run with its strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs +them. A pyright-only repo is the lightest and is inherently consistent, since the editor and CI run +one engine. ## Local development loop @@ -101,9 +104,11 @@ uv build # produce wheel + sdist in ./dist (published pa ``` The **build**-profile Python clean-compile, in its uv form, is `uv run ruff format` + -`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy src` where mypy is -the CI checker, or both where the repo runs both (see Type checking above). Run it, plus -`uv run pytest`, before committing. +`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy` where mypy is +the CI checker, or both where the repo runs both (see Type checking above). CI passes the checker no +path where the config sits in the project directory, so the config selects what is checked, and a +mypy config there sets `files`, without which mypy exits with an error naming no target. Run it, +plus `uv run pytest`, before committing. A **build**-profile directory in its pip form builds its environment the way CI does, through uv's pip interface, which writes no `uv.lock`. It installs every `requirements*.txt` in one command, since @@ -226,7 +231,7 @@ Before pushing or opening a PR: (via the `charliermarsh.ruff` extension) and pyright (via the `ms-python.python` extension's bundled Pylance). - The **build**-profile CI gate, in its uv form, is `uv run ruff check`, - `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy src`), and + `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy`), and `uv run pytest`, the same commands as the local loop above, run from the Python project directory (invoked as separate steps, not `&&`-chained, so the runner shell is irrelevant). The pip form's CI gate is its commands in the local loop above, and a **lint-only** profile's is its `uvx` diff --git a/.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md b/.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md index 092a9bd25..cc9c89e56 100644 --- a/.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md +++ b/.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md @@ -9,7 +9,9 @@ than copying verbatim (a verbatim copy that misdescribes the repo is inaccurate in review). The axes that commonly vary per repo: - **Type checker in CI**: pyright strict, mypy with its strict flags (run in CI and the editor, with - pyright kept editor-only through Pylance), or both. The clean-compile runs every checker CI runs. + pyright kept editor-only through Pylance), or both, the hub validator running one per directory + and the repo running the second, per `SKILL.md` "Toolchain". The clean-compile runs every + checker CI runs. - **Dependency declaration**: the uv form declares the dev tools CI runs in the `dev` group of `[dependency-groups]`, the one group a plain local `uv sync` or `uv run` installs, and which CI's `uv sync --all-groups --frozen` installs too, since it takes every group and no extra. PEP 621 diff --git a/.github/skills/python-codestyle/SKILL.md b/.github/skills/python-codestyle/SKILL.md index 00ab2f7c7..d5800a356 100644 --- a/.github/skills/python-codestyle/SKILL.md +++ b/.github/skills/python-codestyle/SKILL.md @@ -33,7 +33,8 @@ Then read the `pyproject.toml` shape and pick the profile before running Python - **build** (Project): third-party runtime dependencies, or the repo's deliverable. Either a uv project (`[project]` + `[build-system]` + committed `uv.lock`, run with `uv run`) or a `pyproject.toml` beside a `requirements*.txt` and no `uv.lock`, installed with pip. Uses pytest, - and pyright strict, mypy with its strict flags, or both as the CI type checker. + and pyright strict or mypy with its strict flags as the hub validator's type checker, with a + repo running both adding the second itself, per Toolchain below. - **lint-only** (Scripts): no `[project]`, no `[build-system]`, no lockfile, no `requirements*.txt` (the hub validator runs pytest wherever one sits). Uses `uvx` for third-party tools, unittest for tests, and mypy as the CI gate. Do not run pytest or diagnose its absence as an environment @@ -76,10 +77,12 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar `mypy --strict` because the platinum `strict-typing` quality-scale tier requires it, and a pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy -command joins the clean-compile. mypy may also be a build repo's only CI checker, run with its -strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A -pyright-only repo is the lightest and is inherently consistent, since the editor and CI run one -engine. +command joins the clean-compile. The hub validator runs one checker in each Python directory, +mypy wherever the config declares both, so a repo enforcing pyright beside mypy runs it from its +own `.github/actions/validate/action.yml` hook. mypy may also be a build repo's only CI checker, +run with its strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs +them. A pyright-only repo is the lightest and is inherently consistent, since the editor and CI run +one engine. ## Local development loop @@ -101,9 +104,11 @@ uv build # produce wheel + sdist in ./dist (published pa ``` The **build**-profile Python clean-compile, in its uv form, is `uv run ruff format` + -`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy src` where mypy is -the CI checker, or both where the repo runs both (see Type checking above). Run it, plus -`uv run pytest`, before committing. +`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy` where mypy is +the CI checker, or both where the repo runs both (see Type checking above). CI passes the checker no +path where the config sits in the project directory, so the config selects what is checked, and a +mypy config there sets `files`, without which mypy exits with an error naming no target. Run it, +plus `uv run pytest`, before committing. A **build**-profile directory in its pip form builds its environment the way CI does, through uv's pip interface, which writes no `uv.lock`. It installs every `requirements*.txt` in one command, since @@ -226,7 +231,7 @@ Before pushing or opening a PR: (via the `charliermarsh.ruff` extension) and pyright (via the `ms-python.python` extension's bundled Pylance). - The **build**-profile CI gate, in its uv form, is `uv run ruff check`, - `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy src`), and + `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy`), and `uv run pytest`, the same commands as the local loop above, run from the Python project directory (invoked as separate steps, not `&&`-chained, so the runner shell is irrelevant). The pip form's CI gate is its commands in the local loop above, and a **lint-only** profile's is its `uvx` diff --git a/.github/skills/python-codestyle/references/profiles.md b/.github/skills/python-codestyle/references/profiles.md index 092a9bd25..cc9c89e56 100644 --- a/.github/skills/python-codestyle/references/profiles.md +++ b/.github/skills/python-codestyle/references/profiles.md @@ -9,7 +9,9 @@ than copying verbatim (a verbatim copy that misdescribes the repo is inaccurate in review). The axes that commonly vary per repo: - **Type checker in CI**: pyright strict, mypy with its strict flags (run in CI and the editor, with - pyright kept editor-only through Pylance), or both. The clean-compile runs every checker CI runs. + pyright kept editor-only through Pylance), or both, the hub validator running one per directory + and the repo running the second, per `SKILL.md` "Toolchain". The clean-compile runs every + checker CI runs. - **Dependency declaration**: the uv form declares the dev tools CI runs in the `dev` group of `[dependency-groups]`, the one group a plain local `uv sync` or `uv run` installs, and which CI's `uv sync --all-groups --frozen` installs too, since it takes every group and no extra. PEP 621 From 640413ce6ae6af03e5885a9e7735c0ff0cb000cd Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Sat, 10 Oct 2026 00:47:57 -0700 Subject: [PATCH 2/3] Name pyright as the second checker and give the root-config command The local review pass found the summary sentences read "the second" as mypy, the `files`-only claim overstated what gives mypy a target, and the bare `uv run mypy` broke the case where a declared subdirectory uses the repository root's config, which CI runs from the root with the directory as its path. Co-Authored-By: Claude Opus 5.5 --- .agents/skills/python-codestyle/SKILL.md | 26 ++++++++++--------- .../python-codestyle/references/profiles.md | 5 ++-- .../.source-digests/python-codestyle | 2 +- .../skills/python-codestyle/SKILL.md | 26 ++++++++++--------- .../python-codestyle/references/profiles.md | 5 ++-- .github/skills/python-codestyle/SKILL.md | 26 ++++++++++--------- .../python-codestyle/references/profiles.md | 5 ++-- 7 files changed, 49 insertions(+), 46 deletions(-) diff --git a/.agents/skills/python-codestyle/SKILL.md b/.agents/skills/python-codestyle/SKILL.md index d5800a356..6064d9ac1 100644 --- a/.agents/skills/python-codestyle/SKILL.md +++ b/.agents/skills/python-codestyle/SKILL.md @@ -33,8 +33,8 @@ Then read the `pyproject.toml` shape and pick the profile before running Python - **build** (Project): third-party runtime dependencies, or the repo's deliverable. Either a uv project (`[project]` + `[build-system]` + committed `uv.lock`, run with `uv run`) or a `pyproject.toml` beside a `requirements*.txt` and no `uv.lock`, installed with pip. Uses pytest, - and pyright strict or mypy with its strict flags as the hub validator's type checker, with a - repo running both adding the second itself, per Toolchain below. + and pyright strict or mypy with its strict flags as the CI type checker. A repo enforcing + pyright beside mypy runs pyright itself, per Toolchain below. - **lint-only** (Scripts): no `[project]`, no `[build-system]`, no lockfile, no `requirements*.txt` (the hub validator runs pytest wherever one sits). Uses `uvx` for third-party tools, unittest for tests, and mypy as the CI gate. Do not run pytest or diagnose its absence as an environment @@ -78,11 +78,11 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy command joins the clean-compile. The hub validator runs one checker in each Python directory, -mypy wherever the config declares both, so a repo enforcing pyright beside mypy runs it from its -own `.github/actions/validate/action.yml` hook. mypy may also be a build repo's only CI checker, -run with its strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs -them. A pyright-only repo is the lightest and is inherently consistent, since the editor and CI run -one engine. +mypy where both are configured. A repo enforcing pyright beside mypy runs it from its own +`.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it sets up +its own Python environment. mypy may also be a build repo's only CI checker, run with its strict +flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A pyright-only +repo is the lightest and is inherently consistent, since the editor and CI run one engine. ## Local development loop @@ -104,11 +104,13 @@ uv build # produce wheel + sdist in ./dist (published pa ``` The **build**-profile Python clean-compile, in its uv form, is `uv run ruff format` + -`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy` where mypy is -the CI checker, or both where the repo runs both (see Type checking above). CI passes the checker no -path where the config sits in the project directory, so the config selects what is checked, and a -mypy config there sets `files`, without which mypy exits with an error naming no target. Run it, -plus `uv run pytest`, before committing. +`uv run ruff check` + the repo's type checker. That checker is `uv run pyright`, or `uv run mypy` +where mypy is the CI checker, or both where the repo runs both (see Type checking above). Where the +config sits in the project directory, CI passes the checker no path, so the config's own target +settings decide what is checked. mypy left with no target that way exits with an error. A declared +subdirectory with no config of its own uses the repository root's instead. CI then runs the checker +from the root with the directory as its path, `uv run --project `, so run it +the same way. Run the clean-compile, plus `uv run pytest`, before committing. A **build**-profile directory in its pip form builds its environment the way CI does, through uv's pip interface, which writes no `uv.lock`. It installs every `requirements*.txt` in one command, since diff --git a/.agents/skills/python-codestyle/references/profiles.md b/.agents/skills/python-codestyle/references/profiles.md index cc9c89e56..4151386b9 100644 --- a/.agents/skills/python-codestyle/references/profiles.md +++ b/.agents/skills/python-codestyle/references/profiles.md @@ -9,9 +9,8 @@ than copying verbatim (a verbatim copy that misdescribes the repo is inaccurate in review). The axes that commonly vary per repo: - **Type checker in CI**: pyright strict, mypy with its strict flags (run in CI and the editor, with - pyright kept editor-only through Pylance), or both, the hub validator running one per directory - and the repo running the second, per `SKILL.md` "Toolchain". The clean-compile runs every - checker CI runs. + pyright kept editor-only through Pylance), or both. A repo running both runs pyright itself, + per `SKILL.md` "Toolchain". The clean-compile runs every checker CI runs. - **Dependency declaration**: the uv form declares the dev tools CI runs in the `dev` group of `[dependency-groups]`, the one group a plain local `uv sync` or `uv run` installs, and which CI's `uv sync --all-groups --frozen` installs too, since it takes every group and no extra. PEP 621 diff --git a/.claude-plugin/fleet-skills/.source-digests/python-codestyle b/.claude-plugin/fleet-skills/.source-digests/python-codestyle index 3dd74b65a..b5398464e 100644 --- a/.claude-plugin/fleet-skills/.source-digests/python-codestyle +++ b/.claude-plugin/fleet-skills/.source-digests/python-codestyle @@ -1 +1 @@ -2db4f23ec9e351cc +be57f650296a99b3 diff --git a/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md b/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md index d5800a356..6064d9ac1 100644 --- a/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md +++ b/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md @@ -33,8 +33,8 @@ Then read the `pyproject.toml` shape and pick the profile before running Python - **build** (Project): third-party runtime dependencies, or the repo's deliverable. Either a uv project (`[project]` + `[build-system]` + committed `uv.lock`, run with `uv run`) or a `pyproject.toml` beside a `requirements*.txt` and no `uv.lock`, installed with pip. Uses pytest, - and pyright strict or mypy with its strict flags as the hub validator's type checker, with a - repo running both adding the second itself, per Toolchain below. + and pyright strict or mypy with its strict flags as the CI type checker. A repo enforcing + pyright beside mypy runs pyright itself, per Toolchain below. - **lint-only** (Scripts): no `[project]`, no `[build-system]`, no lockfile, no `requirements*.txt` (the hub validator runs pytest wherever one sits). Uses `uvx` for third-party tools, unittest for tests, and mypy as the CI gate. Do not run pytest or diagnose its absence as an environment @@ -78,11 +78,11 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy command joins the clean-compile. The hub validator runs one checker in each Python directory, -mypy wherever the config declares both, so a repo enforcing pyright beside mypy runs it from its -own `.github/actions/validate/action.yml` hook. mypy may also be a build repo's only CI checker, -run with its strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs -them. A pyright-only repo is the lightest and is inherently consistent, since the editor and CI run -one engine. +mypy where both are configured. A repo enforcing pyright beside mypy runs it from its own +`.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it sets up +its own Python environment. mypy may also be a build repo's only CI checker, run with its strict +flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A pyright-only +repo is the lightest and is inherently consistent, since the editor and CI run one engine. ## Local development loop @@ -104,11 +104,13 @@ uv build # produce wheel + sdist in ./dist (published pa ``` The **build**-profile Python clean-compile, in its uv form, is `uv run ruff format` + -`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy` where mypy is -the CI checker, or both where the repo runs both (see Type checking above). CI passes the checker no -path where the config sits in the project directory, so the config selects what is checked, and a -mypy config there sets `files`, without which mypy exits with an error naming no target. Run it, -plus `uv run pytest`, before committing. +`uv run ruff check` + the repo's type checker. That checker is `uv run pyright`, or `uv run mypy` +where mypy is the CI checker, or both where the repo runs both (see Type checking above). Where the +config sits in the project directory, CI passes the checker no path, so the config's own target +settings decide what is checked. mypy left with no target that way exits with an error. A declared +subdirectory with no config of its own uses the repository root's instead. CI then runs the checker +from the root with the directory as its path, `uv run --project `, so run it +the same way. Run the clean-compile, plus `uv run pytest`, before committing. A **build**-profile directory in its pip form builds its environment the way CI does, through uv's pip interface, which writes no `uv.lock`. It installs every `requirements*.txt` in one command, since diff --git a/.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md b/.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md index cc9c89e56..4151386b9 100644 --- a/.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md +++ b/.claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md @@ -9,9 +9,8 @@ than copying verbatim (a verbatim copy that misdescribes the repo is inaccurate in review). The axes that commonly vary per repo: - **Type checker in CI**: pyright strict, mypy with its strict flags (run in CI and the editor, with - pyright kept editor-only through Pylance), or both, the hub validator running one per directory - and the repo running the second, per `SKILL.md` "Toolchain". The clean-compile runs every - checker CI runs. + pyright kept editor-only through Pylance), or both. A repo running both runs pyright itself, + per `SKILL.md` "Toolchain". The clean-compile runs every checker CI runs. - **Dependency declaration**: the uv form declares the dev tools CI runs in the `dev` group of `[dependency-groups]`, the one group a plain local `uv sync` or `uv run` installs, and which CI's `uv sync --all-groups --frozen` installs too, since it takes every group and no extra. PEP 621 diff --git a/.github/skills/python-codestyle/SKILL.md b/.github/skills/python-codestyle/SKILL.md index d5800a356..6064d9ac1 100644 --- a/.github/skills/python-codestyle/SKILL.md +++ b/.github/skills/python-codestyle/SKILL.md @@ -33,8 +33,8 @@ Then read the `pyproject.toml` shape and pick the profile before running Python - **build** (Project): third-party runtime dependencies, or the repo's deliverable. Either a uv project (`[project]` + `[build-system]` + committed `uv.lock`, run with `uv run`) or a `pyproject.toml` beside a `requirements*.txt` and no `uv.lock`, installed with pip. Uses pytest, - and pyright strict or mypy with its strict flags as the hub validator's type checker, with a - repo running both adding the second itself, per Toolchain below. + and pyright strict or mypy with its strict flags as the CI type checker. A repo enforcing + pyright beside mypy runs pyright itself, per Toolchain below. - **lint-only** (Scripts): no `[project]`, no `[build-system]`, no lockfile, no `requirements*.txt` (the hub validator runs pytest wherever one sits). Uses `uvx` for third-party tools, unittest for tests, and mypy as the CI gate. Do not run pytest or diagnose its absence as an environment @@ -78,11 +78,11 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy command joins the clean-compile. The hub validator runs one checker in each Python directory, -mypy wherever the config declares both, so a repo enforcing pyright beside mypy runs it from its -own `.github/actions/validate/action.yml` hook. mypy may also be a build repo's only CI checker, -run with its strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs -them. A pyright-only repo is the lightest and is inherently consistent, since the editor and CI run -one engine. +mypy where both are configured. A repo enforcing pyright beside mypy runs it from its own +`.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it sets up +its own Python environment. mypy may also be a build repo's only CI checker, run with its strict +flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A pyright-only +repo is the lightest and is inherently consistent, since the editor and CI run one engine. ## Local development loop @@ -104,11 +104,13 @@ uv build # produce wheel + sdist in ./dist (published pa ``` The **build**-profile Python clean-compile, in its uv form, is `uv run ruff format` + -`uv run ruff check` + the repo's type checker: `uv run pyright`, or `uv run mypy` where mypy is -the CI checker, or both where the repo runs both (see Type checking above). CI passes the checker no -path where the config sits in the project directory, so the config selects what is checked, and a -mypy config there sets `files`, without which mypy exits with an error naming no target. Run it, -plus `uv run pytest`, before committing. +`uv run ruff check` + the repo's type checker. That checker is `uv run pyright`, or `uv run mypy` +where mypy is the CI checker, or both where the repo runs both (see Type checking above). Where the +config sits in the project directory, CI passes the checker no path, so the config's own target +settings decide what is checked. mypy left with no target that way exits with an error. A declared +subdirectory with no config of its own uses the repository root's instead. CI then runs the checker +from the root with the directory as its path, `uv run --project `, so run it +the same way. Run the clean-compile, plus `uv run pytest`, before committing. A **build**-profile directory in its pip form builds its environment the way CI does, through uv's pip interface, which writes no `uv.lock`. It installs every `requirements*.txt` in one command, since diff --git a/.github/skills/python-codestyle/references/profiles.md b/.github/skills/python-codestyle/references/profiles.md index cc9c89e56..4151386b9 100644 --- a/.github/skills/python-codestyle/references/profiles.md +++ b/.github/skills/python-codestyle/references/profiles.md @@ -9,9 +9,8 @@ than copying verbatim (a verbatim copy that misdescribes the repo is inaccurate in review). The axes that commonly vary per repo: - **Type checker in CI**: pyright strict, mypy with its strict flags (run in CI and the editor, with - pyright kept editor-only through Pylance), or both, the hub validator running one per directory - and the repo running the second, per `SKILL.md` "Toolchain". The clean-compile runs every - checker CI runs. + pyright kept editor-only through Pylance), or both. A repo running both runs pyright itself, + per `SKILL.md` "Toolchain". The clean-compile runs every checker CI runs. - **Dependency declaration**: the uv form declares the dev tools CI runs in the `dev` group of `[dependency-groups]`, the one group a plain local `uv sync` or `uv run` installs, and which CI's `uv sync --all-groups --frozen` installs too, since it takes every group and no extra. PEP 621 From 902b492fff55511d7716d25ec2c12de533322273 Mon Sep 17 00:00:00 2001 From: Pieter Viljoen Date: Sat, 10 Oct 2026 00:50:47 -0700 Subject: [PATCH 3/3] Name pyright in the hook sentence and drop the project-directory claim The second local review pass found "runs it" read as mypy, "one checker in each Python directory" missed the undeclared root that runs none, and the CI-gate bullet still said every command runs from the project directory although the root-config case runs from the root. Co-Authored-By: Claude Opus 5.5 --- .agents/skills/python-codestyle/SKILL.md | 21 ++++++++++--------- .../.source-digests/python-codestyle | 2 +- .../skills/python-codestyle/SKILL.md | 21 ++++++++++--------- .github/skills/python-codestyle/SKILL.md | 21 ++++++++++--------- 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/.agents/skills/python-codestyle/SKILL.md b/.agents/skills/python-codestyle/SKILL.md index 6064d9ac1..8a7ce101b 100644 --- a/.agents/skills/python-codestyle/SKILL.md +++ b/.agents/skills/python-codestyle/SKILL.md @@ -77,12 +77,13 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar `mypy --strict` because the platinum `strict-typing` quality-scale tier requires it, and a pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy -command joins the clean-compile. The hub validator runs one checker in each Python directory, -mypy where both are configured. A repo enforcing pyright beside mypy runs it from its own -`.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it sets up -its own Python environment. mypy may also be a build repo's only CI checker, run with its strict -flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A pyright-only -repo is the lightest and is inherently consistent, since the editor and CI run one engine. +command joins the clean-compile. The hub validator runs at most one checker in each Python +directory, mypy where both are configured. A repo enforcing pyright beside mypy runs pyright from +its own `.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it +sets up its own Python environment. mypy may also be a build repo's only CI checker, run with its +strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A +pyright-only repo is the lightest and is inherently consistent, since the editor and CI run one +engine. ## Local development loop @@ -232,10 +233,10 @@ Before pushing or opening a PR: - VS Code's Problems pane should be quiet for the files you touched. The relevant linters are ruff (via the `charliermarsh.ruff` extension) and pyright (via the `ms-python.python` extension's bundled Pylance). -- The **build**-profile CI gate, in its uv form, is `uv run ruff check`, - `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy`), and - `uv run pytest`, the same commands as the local loop above, run from the Python project directory - (invoked as separate steps, not `&&`-chained, so the runner shell is irrelevant). The pip form's +- The **build**-profile CI gate, in its uv form, runs the local loop's commands above, each from + where that loop runs it. Those are `uv run ruff check`, `uv run ruff format --check`, the repo's + type checker, and `uv run pytest`. CI invokes them as separate steps, not `&&`-chained, so the + runner shell is irrelevant. The pip form's CI gate is its commands in the local loop above, and a **lint-only** profile's is its `uvx` equivalents plus its `unittest` suite, each per `references/profiles.md`. The local loop names what CI relaxes for an undeclared root. diff --git a/.claude-plugin/fleet-skills/.source-digests/python-codestyle b/.claude-plugin/fleet-skills/.source-digests/python-codestyle index b5398464e..7e0dceef0 100644 --- a/.claude-plugin/fleet-skills/.source-digests/python-codestyle +++ b/.claude-plugin/fleet-skills/.source-digests/python-codestyle @@ -1 +1 @@ -be57f650296a99b3 +9c5b651ffcf53d3c diff --git a/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md b/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md index 6064d9ac1..8a7ce101b 100644 --- a/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md +++ b/.claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md @@ -77,12 +77,13 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar `mypy --strict` because the platinum `strict-typing` quality-scale tier requires it, and a pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy -command joins the clean-compile. The hub validator runs one checker in each Python directory, -mypy where both are configured. A repo enforcing pyright beside mypy runs it from its own -`.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it sets up -its own Python environment. mypy may also be a build repo's only CI checker, run with its strict -flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A pyright-only -repo is the lightest and is inherently consistent, since the editor and CI run one engine. +command joins the clean-compile. The hub validator runs at most one checker in each Python +directory, mypy where both are configured. A repo enforcing pyright beside mypy runs pyright from +its own `.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it +sets up its own Python environment. mypy may also be a build repo's only CI checker, run with its +strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A +pyright-only repo is the lightest and is inherently consistent, since the editor and CI run one +engine. ## Local development loop @@ -232,10 +233,10 @@ Before pushing or opening a PR: - VS Code's Problems pane should be quiet for the files you touched. The relevant linters are ruff (via the `charliermarsh.ruff` extension) and pyright (via the `ms-python.python` extension's bundled Pylance). -- The **build**-profile CI gate, in its uv form, is `uv run ruff check`, - `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy`), and - `uv run pytest`, the same commands as the local loop above, run from the Python project directory - (invoked as separate steps, not `&&`-chained, so the runner shell is irrelevant). The pip form's +- The **build**-profile CI gate, in its uv form, runs the local loop's commands above, each from + where that loop runs it. Those are `uv run ruff check`, `uv run ruff format --check`, the repo's + type checker, and `uv run pytest`. CI invokes them as separate steps, not `&&`-chained, so the + runner shell is irrelevant. The pip form's CI gate is its commands in the local loop above, and a **lint-only** profile's is its `uvx` equivalents plus its `unittest` suite, each per `references/profiles.md`. The local loop names what CI relaxes for an undeclared root. diff --git a/.github/skills/python-codestyle/SKILL.md b/.github/skills/python-codestyle/SKILL.md index 6064d9ac1..8a7ce101b 100644 --- a/.github/skills/python-codestyle/SKILL.md +++ b/.github/skills/python-codestyle/SKILL.md @@ -77,12 +77,13 @@ than one checker is normal when each serves a purpose (the .NET side pairs CShar `mypy --strict` because the platinum `strict-typing` quality-scale tier requires it, and a pydantic-heavy library may opt in for the plugin. When a repo uses mypy it runs in CI and the editor (the `ms-python.mypy-type-checker` extension) so the two stay consistent, and its mypy -command joins the clean-compile. The hub validator runs one checker in each Python directory, -mypy where both are configured. A repo enforcing pyright beside mypy runs it from its own -`.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it sets up -its own Python environment. mypy may also be a build repo's only CI checker, run with its strict -flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A pyright-only -repo is the lightest and is inherently consistent, since the editor and CI run one engine. +command joins the clean-compile. The hub validator runs at most one checker in each Python +directory, mypy where both are configured. A repo enforcing pyright beside mypy runs pyright from +its own `.github/actions/validate/action.yml` hook. That hook starts from a bare checkout, so it +sets up its own Python environment. mypy may also be a build repo's only CI checker, run with its +strict flags, and Pylance's pyright diagnostics are then advisory, since CI never runs them. A +pyright-only repo is the lightest and is inherently consistent, since the editor and CI run one +engine. ## Local development loop @@ -232,10 +233,10 @@ Before pushing or opening a PR: - VS Code's Problems pane should be quiet for the files you touched. The relevant linters are ruff (via the `charliermarsh.ruff` extension) and pyright (via the `ms-python.python` extension's bundled Pylance). -- The **build**-profile CI gate, in its uv form, is `uv run ruff check`, - `uv run ruff format --check`, the repo's type checker (`uv run pyright` or `uv run mypy`), and - `uv run pytest`, the same commands as the local loop above, run from the Python project directory - (invoked as separate steps, not `&&`-chained, so the runner shell is irrelevant). The pip form's +- The **build**-profile CI gate, in its uv form, runs the local loop's commands above, each from + where that loop runs it. Those are `uv run ruff check`, `uv run ruff format --check`, the repo's + type checker, and `uv run pytest`. CI invokes them as separate steps, not `&&`-chained, so the + runner shell is irrelevant. The pip form's CI gate is its commands in the local loop above, and a **lint-only** profile's is its `uvx` equivalents plus its `unittest` suite, each per `references/profiles.md`. The local loop names what CI relaxes for an undeclared root.