You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Promotes develop to main, carrying #1942. That PR settles the behavior-changing edge cases in the Python directory gate, applying the maintainer's decision on each #1936 item:
Item 1: mypy on a declared pip directory follows the repo's config. It runs from .venv when installed there, and a python_version the loaded config pins is no longer overridden.
Item 2: a declared subdirectory with no type-checker config falls back to the root's and names itself as the target. A setup.cfg[mypy] section also counts.
Item 3: a lint-only unittest run that exits 5 explains the likely causes.
Item 5: the audit reports a caller it cannot read, a renamed or extra job calling validate-task.yml or a flow-mapping with:, rather than skipping or misreading it.
Item 6: the audit selftest covers malformed types at the caller level.
Item 7: the Python profiles document a pyproject.toml beside requirements*.txt as the build profile.
## Summary
This PR applies the maintainer's decisions on #1936, recorded in [this
comment](#1936 (comment)).
- **Item 1, mypy on a declared pip directory.** mypy runs from `.venv`
when it is installed there. Otherwise it runs under `uvx`, and
`--python-version` is dropped when the config mypy actually loads pins
`python_version`. The pin check reads that config's mypy section only,
and accepts the INI `:` form.
- **Item 2, where checker config is found.** A declared subdirectory
with no checker config uses the repository root's config and runs the
checker from the root, naming the directory as the target so the root
config's file selection cannot skip it. A `setup.cfg` `[mypy]` section
now counts as config.
- **Item 3, unittest exit 5.** When a lint-only `unittest` run exits 5
because it found no tests, the step says why: pytest-style functions,
files not named `test*.py`, or a nested directory with no `__init__.py`.
- **Item 4:** left as is, by decision.
- **Item 5, the audit's caller check.** A caller that invokes
`validate-task.yml` from a job other than `validate`, or passes a
flow-mapping `with:`, is now reported instead of skipped or misread.
- **Item 6, audit selftest.** Adds malformed-`types` cases for the
callers that had none.
- **Item 7, profile docs.** `python.profile.detect` and the
python-codestyle profiles now name a `pyproject.toml` beside a
`requirements*.txt` as the build profile.
The local strict review ran three rounds. The four real findings from
round 1 and the one from round 2 are fixed on this branch, and round 3
found nothing. One finding was already there before this change, and is
filed as #1941.
## Test plan
- `tests/test_release_guards.py`: runs the type-check step against stub
tools. It covers the venv mypy, a pinned or unpinned config, a pin in
the wrong section or in a file mypy does not load, the INI colon form,
`setup.cfg`, and the root fallback's target. It also covers the exit-5
message. Each new behavior was mutated and the mutant failed its test.
- `spec/audit.py --selftest` covers the renamed job, a second calling
job, the flow mapping, and malformed `types`. Each case was
mutation-checked.
- The full local gate block from OPERATIONS.md passes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
❌ Patch coverage is 0% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.36%. Comparing base (9b594b9) to head (29a9690). ⚠️ Report is 287 commits behind head on main.
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🟡 Changes recommended
The new audit DRIFT message for non-validate jobs is grammatically unclear when multiple jobs call validate-task.yml, which can confuse audit output interpretation.
Promotes develop to main with the Python directory gate updates that clarify several edge-case behaviors (type-checker config discovery/fallbacks, mypy execution environment selection, and improved audit/selftest coverage), plus documentation/test updates to lock the behavior in.
Changes:
Update the reusable validate-task.yml workflow to (a) prefer venv-installed mypy when available, (b) avoid overriding a config-pinned python_version, (c) fall back to root type-checker config for declared subdirectories, and (d) explain unittest discovery exit-5 failures.
Extend spec/audit.py to report unreadable caller shapes (renamed/extra job keys calling validate-task.yml, flow-mapping with:) and add selftests for malformed types.
Update specs/docs and regression tests to reflect and validate the new Python gate behavior.
File
Description
tests/test_release_guards.py
Expands regression coverage for the updated Python gate behavior (mypy environment selection, pinned python_version handling, root-config fallback, unittest exit-5 explanation).
spec/project-types.json
Updates the Python profile contract to treat pyproject.toml + requirements*.txt as build profile (pip-installed), even without [project].
spec/audit.py
Enhances caller auditing to report unreadable caller shapes and adds selftests for malformed types inputs.
docs/reusable-workflows.md
Documents root-config fallback behavior for type checking in declared subdirectories.
## Summary
Fixes the grammar finding Copilot raised on promotion PR
[#1943](#1943). When
several non-`validate` jobs call validate-task.yml, the audit's DRIFT
message used singular wording ("from job a, b, whose ..."). It now says
"from job X" for one and "from jobs X, Y" for several, followed by "and
only the job keyed 'validate' has its python-directories input compared
against the registry."
## Test plan
- `spec/audit.py --selftest` passes.
- The message was printed for a two-job caller and reads correctly.
- A local strict review found nothing.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🔵 Needs a closer look
The workflow’s pins_python_version() selects pyproject.toml before setup.cfg, which can miss a python_version pin in setup.cfg when both exist and lead to an unintended --python-version override.
Prefer setup.cfg over pyproject.toml for python version pinning
.github/workflows/validate-task.yml:322
pins_python_version() checks pyproject.toml before setup.cfg. In a directory that has both a [tool.mypy] section in pyproject.toml and a [mypy] section in setup.cfg, this will treat pyproject.toml as the authoritative config and may miss a python_version pinned in setup.cfg, causing the workflow to pass --python-version and potentially override the intended pin. Prefer setup.cfg over pyproject.toml here to match the "one config file" intent and avoid silently ignoring pins.
Prefer setup.cfg over pyproject.toml for python version pinning: pins_python_version() checks pyproject.toml before setup.cfg ... may miss a python_version pinned in setup.cfg
Declining: mypy itself loads pyproject.toml (when it holds [tool.mypy]) ahead of setup.cfg, so a pin found only in setup.cfg is one mypy never reads. Checking setup.cfg first would honor a pin mypy ignores. The step follows mypy's own lookup order: mypy.ini, .mypy.ini, pyproject.toml, setup.cfg. I confirmed this with mypy 2.3.1 on a constructed directory whose pyproject.toml has [tool.mypy] and whose setup.cfg has [mypy] python_version = 3.12:
… and Setup Tooling (#2000)
## Summary
Promotes develop to main, carrying the 16 pull requests merged to
develop since #1943.
- **Wait-loop guard (requirement 7):**
[#1999](#1999) credits a
comparison bound only inside a `[`, `[[`, or `test` invocation, and
[#1996](#1996) reconciles
the requirement's README count and diagram with its hook.
- **Registry:**
[#1994](#1994) and
[#1976](#1976) record
Vantage-Config's line endings and description.
- **Scripts and tooling:**
- [#1988](#1988) and
[#1972](#1972) harden
`ruleset_id()`.
- [#1974](#1974) and
[#1949](#1949) fix
`pr_review.py` `reply --match` and `wait`.
- [#1969](#1969),
[#1964](#1964),
[#1954](#1954) and
[#1951](#1951) fix
host-setup tool shadowing, shims, hook ownership and dpkg ownership
checks.
- **Gates and audit:**
- [#1980](#1980) triages a
path collision.
- [#1967](#1967) and
[#1962](#1962) tighten
sha-pin and version-literal checks.
- [#1956](#1956) keeps a
folded `if:` visible to the interface audit.
Closes#1636Closes#1639Closes#1948Closes#1971Closes#1718Closes#1934Closes#1877Closes#1880Closes#1865Closes#1889Closes#1966Closes#1906Closes#1935Closes#1901Closes#1905Closes#1866Closes#1897
🤖 Generated with [Claude Code](https://claude.com/claude-code)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Promotes develop to main, carrying #1942. That PR settles the behavior-changing edge cases in the Python directory gate, applying the maintainer's decision on each #1936 item:
.venvwhen installed there, and apython_versionthe loaded config pins is no longer overridden.setup.cfg[mypy]section also counts.unittestrun that exits 5 explains the likely causes.validate-task.ymlor a flow-mappingwith:, rather than skipping or misreading it.typesat the caller level.pyproject.tomlbesiderequirements*.txtas the build profile.Item 4 stays as is, by decision.
Closes #1936
🤖 Generated with Claude Code