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
{{ message }}
Repository navigation
Promote develop to main: Gate Each Declared Python Directory on Its Code - #1918
Gate Each Declared Python Directory on Its Code #1914, Gate Each Declared Python Directory on Its Code. It adds a python-directories input to the reusable validator, so each declared Python project directory gets lint, a type check, and a test suite under coverage. It classes each directory as uv, pip, lint-only, or unsupported, keeps the undeclared root on its old gate exactly, adds the registry's pythonDirectories and the audit checks that mirror it, and aligns the Python rules in WORKFLOW.md, the spec, and the python-codestyle Skill.
## Summary
Builds #1800: Python is gated in each directory a caller declares,
rather than only where a root `pyproject.toml` sits beside a root
`tests/` and a manifest. It also folds in #1778.
- **Validator.** A new `python-directories` input is resolved by the
`python-directories` composite action. That action classes each
directory as `uv` (its own `uv.lock`), `pip` (a `requirements*.txt`
beside it), `lint-only` (no `[project]` or `[build-system]`), or
`unsupported`, which includes a uv workspace member, since a workspace
is declared by its root.
- The `lint` job runs ruff and the type check in each directory. The
`unit-test` job runs `pytest` with coverage, or `coverage run -m
unittest` for lint-only, and uploads each report.
- A declared directory with no `tests/`, no type checker, or no
installable manifest fails.
- An undeclared root keeps the old gate exactly, which the tests prove
by running the real step against stub uv tools.
- Tracked `.py` files outside every declared directory warn rather than
fail (maintainer decision on #1800).
- **Registry and audit.**
- `pythonDirectories` mirrors the input. PlexCleaner declares
`RegressionTests`, the first repo in the agreed adoption order.
- The audit reports Python without the `python` type as a discovery
advisory, which a driftNote naming `(python.directories.declared)` may
suppress, per `spec/type-model.md`. It also reports `.py` files outside
the expected directories, a caller whose input differs from the registry
or is written as a folded scalar, and a root `tests/` suite that no gate
runs.
- Python's lint-only profile no longer exempts a repo from the Codecov
claim. Other lint-only languages keep the exemption.
- **Rules.** WORKFLOW.md D1.2 and D1.6, `spec/project-types.json`
(detect on `*.py`, #1778's workspace-root build shape, a new
`python.directories.declared` check), `spec/type-model.md`,
`spec/secrets.json`, AUDIT.md, the `python-codestyle` Skill, and
`docs/reusable-workflows.md`.
The new advisory fires on the hub itself, which is tracked in #1913.
## Verification
- 1739 script tests, `spec/audit.py --selftest`, `spec/validate.py`,
`build_dist.py --check`, ruff, and mypy all pass.
- actionlint, markdownlint, and editorconfig-checker pass through
`docker_lint.py`.
- The validator's test step was probed against constructed trees for
each shape, declared and undeclared, including a suite that reads stdin.
- New checks were mutation-proven: each fails its test when its
condition is removed.
- Local strict review passes ran before each push. The latest raised 4
findings, which the next fix round answers.
The `comments` label is applied because the new workflow steps carry
why-comments, moved or written with them.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Python validation can now cover explicitly declared project
directories, with checks for linting, formatting, type checking, and
runnable tests.
* CI runs tests and collects coverage for supported Python project
types, then uploads reports to Codecov on a best-effort basis.
* Validation warns when tracked Python files fall outside declared
directories and reports invalid or unsupported project configurations.
* **Documentation**
* Updated Python setup, testing, coverage, and repository configuration
guidance to reflect directory-based validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🟡 Changes recommended
The new audit/workflow support includes a confirmed parsing edge case (comment-indented with: inputs) that can misread python-directories and produce incorrect audit drift results.
Promotes develop to main with the Python-directory keyed validation contract: Python gating is driven by an explicit python-directories declaration (mirrored in the registry), with audit/spec/docs aligned to that model.
Changes:
Extend validate-task.yml with a python-directories input resolved by a new composite action, then run lint/type-check/tests+coverage per resolved directory.
Add pythonDirectories to the registry + schema and enforce/compare it in spec/validate.py and spec/audit.py.
Update the spec/docs/style references to reflect directory-based Python gating and Python lint-only coverage expectations.
File
Description
WORKFLOW.md
Updates D1.2/D1.6 narrative to describe directory-declared Python gating and coverage behavior.
spec/validate.py
Adds registry validation for optional pythonDirectories shape and invariants.
spec/type-model.md
Updates type model: Python lint-only still owes tests+coverage; coverage claims become more tests-aware.
spec/secrets.json
Adjusts prose note for Codecov claiming semantics.
spec/project-types.json
Switches Python detection to *.py and adds checks for directory declarations and workspace-root shape.
spec/audit.py
Implements registry/caller cross-checking for python-directories plus Python discovery/advisories and coverage logic changes.
scripts/tests/test_spec_validate.py
Adds tests for pythonDirectories validation behavior in the spec validator.
scripts/tests/test_release_guards.py
Refactors/extends workflow guard tests to cover new Python directory gating behavior.
scripts/tests/test_python_directories.py
Adds unit tests for the python-directories resolver/action logic.
registry/repos.schema.json
Adds pythonDirectories schema field for registry entries.
registry/repos.json
Adds pythonDirectories for PlexCleaner and updates drift notes to match new contract language.
pyproject.toml
Extends mypy_path to include the new python-directories action code.
docs/reusable-workflows.md
Updates reusable-workflow documentation for the new Python directory gating model.
CODESTYLE.md
Aligns Python guidance wording to directory-based gating expectations.
AUDIT.md
Updates audit classification guidance to treat tracked .py files as Python presence.
.github/workflows/validate-task.yml
Adds python-directories input, resolves declared Python directories, and gates lint/tests+coverage per directory.
## Summary
Fixes what the `develop` -> `main` promotion #1918 turned up in #1914's
Python directory gate.
- **The unit-test job's setup-uv ignores an empty cache.** A root that
takes the undeclared default's skip branch (a `pyproject.toml` with no
`tests/`, as the hub has) still sets uv up and never calls it. On a run
with no restored cache, setup-uv's post-job save then logs "Cache path
... does not exist on disk" as an error and fails the job, which is what
reddened #1918. The `lint` job always calls uv once it sets uv up, so it
can't reach that state.
- **A byte-order mark in `pyproject.toml` fails with its cause named.**
tomllib, mypy, and the workflow's own editable-install probe all reject
one, so the resolver now names the mark rather than stripping it for
itself alone. Stripping it there would have let mypy drop the whole
config silently.
- **The audit's `with:` reader skips comment lines** when it fixes the
key column, so a comment indented past the keys no longer hides them.
- **The `spec/secrets.json` note** now says the codecov mechanism
follows tests.
Each change has a test that fails with the fix reverted. The two edge
cases the local review raised are added to #1917.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Directory validation now identifies the configuration file that failed
to parse and notes when a byte-order mark may be the cause.
* Workflow input checks now correctly find inputs even when comment-only
lines appear in the mapping.
* **Chores**
* Updated the unit-test workflow’s cache setup.
* **Tests**
* Added coverage for byte-order-mark validation, commented workflow
inputs, and the updated cache setting.
* **Documentation**
* Clarified when language-specific test mechanisms are required.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
Guard entry.get("types") before iterable unpacking
spec/audit.py:686
Avoid iterable-unpacking entry.get("types") directly here. If a registry entry somehow has a malformed types value (for example null/string), ("", *entry.get("types", [])) raises TypeError and aborts the audit run. Other parts of this change already read defensively (for example python_directories_of()), so this should as well.
## Summary
Answers the "previously missed" finding on the promotion PR #1918:
`driftnote_findings` unpacked a registry entry's `types` straight into a
tuple, so a malformed value raised `TypeError` and aborted the audit
run.
- **The registry gate refuses a malformed `types`.** `spec/validate.py`
checked only that `types` was non-empty and that iterating it yielded
known names. So a dict passed, an integer crashed the gate itself, and a
string was read one character at a time. It now refuses anything that
isn't a list of strings.
- **Every audit read of `types` goes through one reader.**
`declared_types()` treats a malformed value as no types. `audit_repo`,
the repo selector, the issue renderer, the sweep header, the note check,
and the three Python checks all use it, since the first guard sat behind
unguarded reads earlier in `audit_repo`.
The gate test covers a dict, an integer, a string, and a mixed list, and
fails with the check removed. The local review's three edge cases are
added to #1917.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Guard entry.get("types") before iterable unpacking (spec/audit.py:686, previously missed): "If a registry entry somehow has a malformed types value (for example null/string), ("", *entry.get("types", [])) raises TypeError and aborts the audit run."
Fixed in caa4467 (#1920), at the source as well as the line. spec/validate.py now refuses a cataloged entry whose types is not a list of strings (a dict used to pass, an integer crashed the gate, and a string was read one character at a time). Every audit read of types now goes through one declared_types() reader, which treats a malformed value as no types, since the flagged unpack sat behind unguarded reads earlier in audit_repo.
Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.
The reason will be displayed to describe this comment to others. Learn more.
Copilot review overview
🔵 Needs a closer look
It modifies core CI workflow behavior plus the registry/spec/audit contract across many files, so a human should confirm the end-to-end impact on real repository shapes.
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
developtomain, carrying three changes:python-directoriesinput to the reusable validator, so each declared Python project directory gets lint, a type check, and a test suite under coverage. It classes each directory asuv,pip,lint-only, orunsupported, keeps the undeclared root on its old gate exactly, adds the registry'spythonDirectoriesand the audit checks that mirror it, and aligns the Python rules in WORKFLOW.md, the spec, and thepython-codestyleSkill.typesread.Closes #1800
Closes #1778
Follow-ups filed from that PR's reviews: #1913 (typing the hub itself as Python), #1915, #1916, and #1917 (deferred edge cases).
🤖 Generated with Claude Code