Skip to content

Promote develop to main: Gate Each Declared Python Directory on Its Code - #1918

Merged
ptr727 merged 3 commits into
mainfrom
develop
Sep 27, 2026
Merged

ptr727 merged 3 commits into
mainfrom
develop

Conversation

@ptr727

@ptr727 ptr727 commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Summary

Promotes develop to main, carrying three changes:

  • 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.
  • Let the Unit-Test Job's uv Setup Find Nothing to Cache #1919, Let the Unit-Test Job's uv Setup Find Nothing to Cache. It fixes the empty-cache failure this promotion's first CI run hit, and answers this PR's three review threads.
  • Refuse a Non-List Types Value at the Registry Gate #1920, Refuse a Non-List Types Value at the Registry Gate. It answers this PR's previously-missed finding on an unguarded types read.

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

## 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>
Copilot AI lite review requested due to automatic review settings September 27, 2026 15:57
@ptr727

ptr727 commented Sep 27, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 37 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: ptr727/ProjectTemplate/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 5390483e-b637-41b2-ac94-71ccb7ef4465

📥 Commits

Reviewing files that changed from the base of the PR and between 1801ee7 and caa4467.

⛔ Files ignored due to path filters (10)
  • .claude-plugin/fleet-skills/.source-digests/python-codestyle is excluded by !.claude-plugin/fleet-skills/**
  • .claude-plugin/fleet-skills/.source-digests/workflow-ci-contract is excluded by !.claude-plugin/fleet-skills/**
  • .claude-plugin/fleet-skills/skills/python-codestyle/SKILL.md is excluded by !.claude-plugin/fleet-skills/**
  • .claude-plugin/fleet-skills/skills/python-codestyle/references/profiles.md is excluded by !.claude-plugin/fleet-skills/**
  • .claude-plugin/fleet-skills/skills/python-codestyle/references/testing.md is excluded by !.claude-plugin/fleet-skills/**
  • .claude-plugin/fleet-skills/skills/workflow-ci-contract/references/d-guarantees.md is excluded by !.claude-plugin/fleet-skills/**
  • .github/skills/python-codestyle/SKILL.md is excluded by !.github/skills/**
  • .github/skills/python-codestyle/references/profiles.md is excluded by !.github/skills/**
  • .github/skills/python-codestyle/references/testing.md is excluded by !.github/skills/**
  • .github/skills/workflow-ci-contract/references/d-guarantees.md is excluded by !.github/skills/**
📒 Files selected for processing (22)
  • .agents/skills/python-codestyle/SKILL.md
  • .agents/skills/python-codestyle/references/profiles.md
  • .agents/skills/python-codestyle/references/testing.md
  • .agents/skills/workflow-ci-contract/references/d-guarantees.md
  • .github/actions/python-directories/action.yml
  • .github/actions/python-directories/python_directories.py
  • .github/workflows/validate-task.yml
  • AUDIT.md
  • CODESTYLE.md
  • WORKFLOW.md
  • docs/reusable-workflows.md
  • pyproject.toml
  • registry/repos.json
  • registry/repos.schema.json
  • scripts/tests/test_python_directories.py
  • scripts/tests/test_release_guards.py
  • scripts/tests/test_spec_validate.py
  • spec/audit.py
  • spec/project-types.json
  • spec/secrets.json
  • spec/type-model.md
  • spec/validate.py

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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.

Review effort: Lite
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

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.
.github/​skills/​workflow-ci-contract/​references/​d-guarantees.md Generated skill copy reflecting updated D1.2/D1.6 language.
.claude-plugin/​fleet-skills/​skills/​workflow-ci-contract/​references/​d-guarantees.md Generated plugin skill copy reflecting updated D1.2/D1.6 language.
.claude-plugin/​fleet-skills/​skills/​python-codestyle/​SKILL.md Generated plugin skill copy reflecting updated Python profile guidance.
.claude-plugin/​fleet-skills/​skills/​python-codestyle/​references/​testing.md Generated plugin skill copy reflecting updated coverage guidance.
.claude-plugin/​fleet-skills/​skills/​python-codestyle/​references/​profiles.md Generated plugin skill copy reflecting updated lint-only profile expectations.
.claude-plugin/​fleet-skills/​.source-digests/​workflow-ci-contract Digest update for generated workflow skill distribution.
.claude-plugin/​fleet-skills/​.source-digests/​python-codestyle Digest update for generated Python skill distribution.
.agents/​skills/​workflow-ci-contract/​references/​d-guarantees.md Source skill update for workflow contract D1.2/D1.6.
.agents/​skills/​python-codestyle/​SKILL.md Source skill update for Python profile guidance (directory-based gating).
.agents/​skills/​python-codestyle/​references/​testing.md Source skill update for coverage guidance (directory-local coverage.xml).
.agents/​skills/​python-codestyle/​references/​profiles.md Source skill update for lint-only profile expectations under directory gating.
.github/​skills/​python-codestyle/​SKILL.md Generated skill copy reflecting updated Python profile guidance.
.github/​skills/​python-codestyle/​references/​testing.md Generated skill copy reflecting updated coverage guidance.
.github/​skills/​python-codestyle/​references/​profiles.md Generated skill copy reflecting updated lint-only profile expectations.
.github/​actions/​python-directories/​python_directories.py New resolver script for declared Python directories + shape classification and uncovered warnings.
.github/​actions/​python-directories/​action.yml New composite action wrapper exposing the resolver to workflows.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread .github/actions/python-directories/python_directories.py
Comment thread spec/audit.py Outdated
Comment thread spec/secrets.json Outdated
## 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>
Copilot AI review requested due to automatic review settings September 27, 2026 16:17
@ptr727

ptr727 commented Sep 27, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

spec/audit.py can raise a TypeError during driftNote processing if a registry entry has a malformed non-list types value, aborting the audit run.

Review effort: Lite
Findings: None

Resolved since last review (3)
Previously missed (1)

In code that hasn't changed since last review

Medium severity 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>
Copilot AI review requested due to automatic review settings September 27, 2026 16:34
@ptr727

ptr727 commented Sep 27, 2026

Copy link
Copy Markdown
Owner Author

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.

@ptr727

ptr727 commented Sep 27, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
⚠️ Action not completed

Review rate limited.

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.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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.

Review effort: Lite
Findings: None

@ptr727
ptr727 merged commit 437a20d into main Sep 27, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gate Every Repository's Python on Its Code, Not on Its Config Spec: python.profile.detect does not describe a virtual uv workspace root

2 participants