Skip to content

fix(ga): pre-publish wheel-import guard for sdk-python + repair stale isolation marker - #84

Open
yakimoto wants to merge 3 commits into
mainfrom
fix/cleanroom-registry-defects
Open

yakimoto wants to merge 3 commits into
mainfrom
fix/cleanroom-registry-defects

Conversation

@yakimoto

@yakimoto yakimoto commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

User description

Summary

Tracking: claude-workstation#4321 item 6 — fix the SOURCE causes of the wave-av/sdks registry clean-room acceptance failures (run 33933317710, 7 checks failing across 6 published artifacts).

Finding, independently re-verified in this lane (not taken on trust from existing docs): all 7 failing checks were already root-cause fixed in source before this PR, spread across three repositories, and every one is blocked solely on an operator-triggered publish this lane may not perform:

# Check Root cause Where it's fixed Status
1 @wave-av/cli npm-provenance-attested release.yml already runs npm publish --provenance under id-token: write OIDC wave-av/cli origin/main (verified: .github/workflows/release.yml) different repo — nothing to change here; pending publish
2 @wave-av/cli bin-version-matches-package src/lib/version.ts derives CLI_VERSION from package.json at runtime instead of a hardcoded literal wave-av/cli origin/main (verified directly) different repo — nothing to change here; pending publish
3 @wave-av/cli declared-dep-ranges-pinned @wave-av/sdk pinned to exact 2.0.14 (was ^2.0.11) wave-av/cli package.json on origin/main (verified directly) different repo — nothing to change here; pending publish
4,6 wave-sdk (PyPI) py-import-module / py-no-stdlib-shadow top-level module renamed wavewave_sdk wave-av/sdk-python origin/main, version 2.1.0 (verified directly — separate repo, confirmed via the live package's own project_urls.Repository) different repo — nothing to change here; pending publish
5,7 wave-av-sdk (PyPI) py-import-module / py-no-stdlib-shadow same rename, sdk-python/ in this repo, version 3.0.0 already on origin/main before this PR re-verified in this PR by actually building the wheel, installing into a fresh venv, and running scripts/ga/cleanroom_python_assert.py against the installed artifact — both checks pass; pytest 31/31 (36/36 with the new tests this PR adds)

None of that needed a source change. What this PR actually changes:

Changes

  1. scripts/ga/cleanroom_python_assert.py — the cleanroom-isolation guard (meant to catch a repo checkout accidentally on sys.path, which would make the whole clean-room probe meaningless) was keyed on a hardcoded "wave" directory name. That was the pre-rename package directory. After wavewave_sdk landed, the guard silently stopped matching either checkout's real layout and could never again detect a genuine leak. Demonstrated the regression directly: with PYTHONPATH pointed at the repo root, the old code reported cleanroom-isolation ok=true (wrong); the fix — keyed on args.module, the same name already used for the import check — reports ok=false (correct). Re-ran the full probe against a real built wheel afterward to confirm cleanroom-isolation / py-import-module / py-no-stdlib-shadow still all pass.

  2. sdk-python/tests/test_packaging.py (new) — offline packaging guards: no shipped top-level package may shadow a stdlib name, bare import wave still resolves to the stdlib from inside the checkout, wave_sdk.__version__ matches pyproject.toml, and the distribution name is still wave-av-sdk. These run in the normal pytest pass, before any wheel is built — closing the gap that let 2.0.0 ship broken in the first place (an editable install / repo-checkout test run hides exactly this class of stdlib-shadow bug, because the checkout directory wins import wave under pytest regardless of what the built wheel would actually ship). Mirrors the equivalent guard already proven out in wave-av/sdk-python's tests/test_packaging.py, adapted to this package's name/module. pyproject.toml gains the matching tomli dev-extra for Python < 3.11 (tomllib is stdlib only from 3.11).

  3. .github/workflows/test-python.yml — new smoke-install job: builds the real wheel, installs it (no -e, no repo on sys.path) into a throwaway venv, and runs this repo's own cleanroom_python_assert.py probe against the installed artifact, on every PR touching sdk-python. This is the same probe the GA registry clean-room gate runs against the live PyPI package after a publish — the difference is this one runs pre-publish, offline, on every PR, so the wave/wave_sdk defect class cannot reach a registry a second time.

Verification performed (all run in this lane, not asserted from docs)

  • pytest -q in sdk-python: 36/36 pass (31 pre-existing + 5 new in test_packaging.py)
  • ruff check tests/test_packaging.py: clean
  • actionlint .github/workflows/test-python.yml: clean
  • Built the real wheel (python -m build --wheel), installed into a fresh venv with no repo checkout on sys.path, ran the actual scripts/ga/cleanroom_python_assert.py --dist wave-av-sdk --module wave_sdk --symbol Wave against it: cleanroom-isolation / py-import-module / py-no-stdlib-shadow all pass
  • Demonstrated the isolation-marker regression concretely: same probe run with PYTHONPATH pointed at the repo root reports cleanroom-isolation ok=false with the fix, ok=true (silently wrong) with the pre-fix code
  • Independently confirmed (read-only, no changes) that wave-av/cli's origin/main already carries the version-derivation, provenance, and exact-pin fixes, and that wave-av/sdk-python's origin/main already carries the wave_sdk rename — both are separate repositories this PR cannot and does not touch

What still requires a republish (explicitly out of scope for this lane)

All 7 originally-failing checks remain failing against the live registries until an operator publishes: @wave-av/cli (npm), wave-sdk (PyPI, from wave-av/sdk-python), and wave-av-sdk (PyPI, via a sdk-python-v3.0.0 tag on this repo). No npm/PyPI publish, git tag push, or workflow dispatch of a publish workflow was performed or attempted in this lane, per the hard constraint on this task.

Test plan

  • pytest -q sdk-python: 36/36 pass
  • ruff check on new test file: clean
  • actionlint on modified workflow: clean
  • Manual wheel build + fresh-venv install + clean-room probe: pass
  • Manual regression demonstration of the isolation-marker fix (before/after)
  • CI run of the new smoke-install job on this PR (will run automatically; not yet observed since this PR was just opened)

🤖 Generated with Claude Code

https://claude.ai/code/session_01MLCfz2w3xiGLfFFgFmbe5j


Note

Low Risk
Changes are limited to CI, GA clean-room tooling, and offline tests; they strengthen pre-publish checks without altering runtime SDK behavior or auth/data paths.

Overview
Hardens Python SDK packaging validation so stdlib-shadow and “repo on sys.path” bugs are caught before PyPI, after the wavewave_sdk rename had left a key clean-room check effectively always passing.

cleanroom_python_assert.py replaces a hardcoded sdk-python/wave leak detector with checkout_paths_providing() keyed on the module under test and common checkout layouts ("", sdk-python, src, python), treats '' on sys.path as cwd, and skips interpreter-owned paths (site-packages, stdlib, venv roots) so legitimate installs are not flagged.

cleanroom-targets.mjs and the new smoke-install CI job copy the probe into the throwaway environment before running it, because executing the script from the repo prepends scripts/ga onto sys.path and violated the same isolation promise.

CI (test-python.yml) adds smoke-install: build wheel → fresh venv → non-editable install → run the same JSON probe as registry clean-room (wave-av-sdk / wave_sdk / Wave) on Python 3.10 and 3.12; workflow path filters now include the probe script.

Tests: new test_packaging.py (stdlib name collisions, bare import wave, version/name vs pyproject.toml) and test_cleanroom_probe.py (unit coverage for isolation helpers); pyproject.toml adds tomli for dev on Python < 3.11.

Reviewed by Cursor Bugbot for commit 4faf619. Bugbot is set up for automated code reviews on this repo. Configure here.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Review in cubic

Summary by Sourcery

Harden Python package validation and clean-room checks to catch broken wheel imports and checkout isolation regressions before publishing.

New Features:

  • Add a fresh-install smoke test that builds and installs the Python wheel in an isolated virtual environment before running clean-room import checks.

Bug Fixes:

  • Repair clean-room isolation detection so it recognizes current module names and checkout layouts, including the current working directory, instead of relying on the stale wave path.
  • Prevent clean-room probe execution from adding the repository's scripts/ga directory to sys.path.

Enhancements:

  • Add offline packaging guards for standard-library name collisions, import resolution, version metadata, and distribution naming.
  • Add unit coverage for clean-room isolation behavior across supported checkout layouts and false-positive cases.

Build:

  • Add the Python 3.10 compatibility dependency for parsing TOML metadata in packaging tests.

CI:

  • Run the installed-wheel smoke test on Python 3.10 and 3.12, and trigger Python CI when the clean-room probe changes.

Tests:

  • Expand the Python test suite with packaging metadata and clean-room isolation regression tests.

CodeAnt-AI Description

Prevent Python packaging and clean-room checks from passing when they cannot detect a broken or locally sourced package

What Changed

  • Clean-room isolation now detects SDK source checkouts across supported layouts, including renamed packages, single-file modules, and the current working directory.
  • Published-package checks now run the probe from a temporary location, preventing the probe itself from adding repository paths to Python’s import path.
  • Added packaging tests that catch standard-library name collisions, verify wave resolves to Python’s standard library, and keep the package version and distribution name aligned with project metadata.
  • Added an always-on workflow that builds and installs a real wheel in a fresh virtual environment on Python 3.10 and 3.12 before checking imports.

Impact

✅ Fewer falsely passing clean-room checks
✅ Prevented Python standard-library import collisions
✅ Earlier detection of broken wheels before publishing

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

… isolation marker

All 7 checks the registry clean-room gate (run 33933317710) reported failing were
already root-cause fixed in source before this change, across three repositories
(verified independently in this lane, not merely re-read from docs):

  - @wave-av/cli npm-provenance-attested / bin-version-matches-package /
    declared-dep-ranges-pinned: fixed on wave-av/cli's origin/main (release.yml already
    runs `npm publish --provenance` under `id-token: write` OIDC; src/lib/version.ts
    derives CLI_VERSION from package.json at runtime; @wave-av/sdk pinned to exact
    "2.0.14"). Owned by a different repository; nothing to change here.
  - wave-sdk (PyPI) py-import-module / py-no-stdlib-shadow: fixed on
    wave-av/sdk-python's origin/main (module renamed wave -> wave_sdk, version 2.1.0,
    with its own tests/test_packaging.py + smoke-install.yml). Owned by a different
    repository; nothing to change here.
  - wave-av-sdk (PyPI) py-import-module / py-no-stdlib-shadow: fixed on THIS repo's
    origin/main already (sdk-python/ renamed wave/ -> wave_sdk/, version 3.0.0).
    Re-verified here by actually building the wheel, installing it into a fresh venv,
    and running scripts/ga/cleanroom_python_assert.py against the installed artifact —
    py-import-module and py-no-stdlib-shadow both pass; full pytest suite 31/31 (36/36
    with the new tests below).

None of the above needed a source change; all are blocked solely on an operator
publish, which this lane may not perform.

What this commit actually changes:

1. scripts/ga/cleanroom_python_assert.py: the cleanroom-isolation guard keyed its
   repo-checkout-on-sys.path detection on a hardcoded "wave" directory name. That was
   the PRE-rename package directory; after wave -> wave_sdk landed (in the same source
   fix this file is supposed to help verify), the guard silently stopped matching
   either checkout's real layout and could never again detect a genuine repo-on-path
   leak. Demonstrated the regression directly: with PYTHONPATH pointed at the repo
   root, the old code reports cleanroom-isolation ok=true (wrong); the fix (keyed on
   `args.module`, the same name already used for the import check) reports ok=false
   (correct). Re-ran the full probe against a real built wheel afterward to confirm it
   still passes cleanroom-isolation / py-import-module / py-no-stdlib-shadow.

2. sdk-python/tests/test_packaging.py (new): offline packaging guards — no shipped
   top-level package may shadow a stdlib name, `import wave` (bare) still resolves to
   the stdlib from inside the checkout, `wave_sdk.__version__` matches
   pyproject.toml's version, and the distribution name is still `wave-av-sdk`. These
   run in the normal `pytest` pass, before any wheel is ever built — closing the gap
   that let 2.0.0 ship broken in the first place (an editable install / repo-checkout
   test run hides the exact stdlib-shadow class this guards). Mirrors the equivalent
   guard already proven out in wave-av/sdk-python's tests/test_packaging.py, adapted
   to this package's name/module. pyproject.toml gains the matching `tomli` dev-extra
   for Python < 3.11 (tomllib is stdlib only from 3.11).

3. .github/workflows/test-python.yml: new `smoke-install` job — builds the real wheel,
   installs it (no `-e`, no repo on sys.path) into a throwaway venv, and runs THIS
   repo's own scripts/ga/registry-cleanroom.mjs probe (cleanroom_python_assert.py)
   against the installed artifact on every PR touching sdk-python. This is the same
   probe the GA gate runs against the live PyPI package after a publish — the
   difference is this one runs pre-publish, offline, on every PR, so the wave/wave_sdk
   defect class cannot reach a registry a second time. Verified end-to-end locally:
   built the wheel, installed into a fresh venv, ran the exact copy/probe/parse
   sequence the job runs — all three checks (cleanroom-isolation, py-import-module,
   py-no-stdlib-shadow) pass; actionlint clean on the workflow file.

Verified: `pytest -q` sdk-python 36/36 pass (31 pre-existing + 5 new); `ruff check
tests/test_packaging.py` clean; `actionlint .github/workflows/test-python.yml` clean;
manual wheel build + fresh-venv install + cleanroom_python_assert.py probe pass
against the real built artifact, both before and after the isolation-marker fix (with
the fix demonstrated to catch a real injected leak the old code missed).

Tracking: claude-workstation#4321 item 6.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MLCfz2w3xiGLfFFgFmbe5j
@codeant-ai

codeant-ai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your workspace is out of credits. Ask your workspace admin to add credits to resume reviews. Manage billing

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @yakimoto, this account has used its review budget of 2,500,000 diff characters for the last 7 days.

You can request another review in 22 hours and 48 minutes by commenting @sourcery-ai review.

@cursor

cursor Bot commented Sep 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_b479bfc2-c5df-4549-9ab9-4db2bd400765)

@sourcery-ai

sourcery-ai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds pre-publish safeguards for the Python SDK by fixing the stale repository-isolation marker, testing packaging metadata and stdlib-shadowing risks offline, and exercising the real wheel in a clean virtual environment on pull requests.

Sequence diagram for pre-publish Python wheel smoke validation

sequenceDiagram
    participant CI as GitHub Actions
    participant Build as Wheel Builder
    participant Venv as Fresh Virtualenv
    participant Probe as cleanroom_python_assert.py

    CI->>Build: python -m build --wheel
    Build-->>CI: wave-av-sdk wheel
    CI->>Venv: Install wheel without editable mode
    Venv->>Probe: Run probe with --dist wave-av-sdk --module wave_sdk --symbol Wave
    Probe->>Probe: Check cleanroom-isolation
    Probe->>Probe: Check py-import-module
    Probe->>Probe: Check py-no-stdlib-shadow
    Probe-->>CI: Report clean-room checks
Loading

Flow diagram for offline Python packaging safeguards

flowchart LR
    Checkout[Repository checkout] --> Tests[pytest packaging guards]
    Tests --> Metadata[Validate distribution and version metadata]
    Tests --> Imports[Validate wave_sdk import and Wave symbol]
    Tests --> Stdlib[Validate import wave resolves to stdlib]
    Tests --> Wheel[Build real wheel]
    Wheel --> Install[Install into fresh virtualenv]
    Install --> Probe[Run cleanroom_python_assert.py]
    Probe --> Publish[Safe to publish]
Loading

File-Level Changes

Change Details Files
Repair the clean-room isolation check to detect repository leakage after the package rename.
  • Derive the checkout marker directory from the requested module argument instead of the obsolete wave literal.
  • Preserve validation that the installed module, distribution, and stdlib-shadow checks pass.
scripts/ga/cleanroom_python_assert.py
Add offline packaging tests that catch metadata drift and stdlib-shadow regressions before publication.
  • Detect shipped top-level packages that collide with standard-library module names.
  • Verify bare import wave resolves to the stdlib from the checkout.
  • Verify wave_sdk.__version__ matches pyproject.toml and the distribution name remains wave-av-sdk.
  • Add the Python <3.11 tomli development dependency needed to parse project metadata.
sdk-python/tests/test_packaging.py
sdk-python/pyproject.toml
Add a pre-publish wheel smoke test that validates the actual installed artifact in isolation.
  • Build and install a non-editable wheel into a fresh virtual environment on Python 3.10 and 3.12.
  • Run the clean-room probe against the installed wheel and fail on any unsuccessful check.
  • Trigger the workflow when the probe script changes as well as when the SDK or workflow changes.
.github/workflows/test-python.yml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@socket-security

socket-security Bot commented Sep 5, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedpypi/​tomli@​2.4.1100100100100100

View full report

@macroscopeapp

macroscopeapp Bot commented Sep 5, 2026

Copy link
Copy Markdown

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — The PR is limited to CI, tests, development metadata, and GA clean-room tooling, with no changes to customer-facing SDK runtime behavior. Human review is appropriate because every changed file is owned by the sdk-owners team rather than the PR author.

Not approved because:

  • Credit balance exhausted. Approvability relies on correctness review in order to determine eligibility

Review your spending limits in Billing settings. You can add or adjust custom eligibility rules. Learn more.

@gitar-bot

gitar-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown

Note

Automatic reviews are paused because your team has used its included automatic processing for this billing period (headroom scales with your seat count). You can still comment "Gitar review" to run one anytime, and automatic reviews resume on their own by October 1. Add seats for more headroom.
Learn more

Code Review ✅ Approved

Fixes the cleanroom-isolation guard in scripts/ga/cleanroom_python_assert.py by updating the stale wave directory name check to use the actual module name (wave_sdk), adds comprehensive offline packaging tests in sdk-python/tests/test_packaging.py to prevent stdlib shadowing regressions, and introduces a pre-publish smoke-install workflow job that validates the built wheel against the clean-room probe before deployment. All 36 tests pass, and manual verification confirms the isolation marker now correctly detects leaks.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@coderabbitai

coderabbitai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: 7108cdb8-517f-428f-9be9-dda39a463512

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Team

Run ID: b03efe05-41ce-490c-bf2d-521e9b6ec40e

📥 Commits

Reviewing files that changed from the base of the PR and between 6fe7c01 and 80576ba.

📒 Files selected for processing (4)
  • .github/workflows/test-python.yml
  • scripts/ga/cleanroom_python_assert.py
  • sdk-python/pyproject.toml
  • sdk-python/tests/test_packaging.py

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

📜 Recent review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: semgrep-cloud-platform/scan
  • GitHub Check: Analyze (rust)
⚠️ CI failures not shown inline (2)

GitHub Actions: registry clean-room acceptance / 0_cleanroom.txt: fix(ga): pre-publish wheel-import guard for sdk-python + repair stale isolation marker

Conclusion: failure

View job details

##[group]Run if [ "$CODE" != "0" ]; then
 �[36;1mif [ "$CODE" != "0" ]; then�[0m
 �[36;1m  echo "::error title=registry clean-room::published artifacts failed clean-room acceptance (exit $CODE) — see the job summary"�[0m

GitHub Actions: registry clean-room acceptance / cleanroom: fix(ga): pre-publish wheel-import guard for sdk-python + repair stale isolation marker

Conclusion: failure

View job details

##[group]Run if [ "$CODE" != "0" ]; then
 �[36;1mif [ "$CODE" != "0" ]; then�[0m
 �[36;1m  echo "::error title=registry clean-room::published artifacts failed clean-room acceptance (exit $CODE) — see the job summary"�[0m
🧰 Additional context used
🪛 zizmor (1.29.0)
.github/workflows/test-python.yml

[warning] 57-57: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[info] 43-43: workflow or action definition without a name (anonymous-definition): this job

(anonymous-definition)

🔇 Additional comments (4)
sdk-python/tests/test_packaging.py (1)

1-150: LGTM!

sdk-python/pyproject.toml (1)

74-76: LGTM!

scripts/ga/cleanroom_python_assert.py (1)

87-95: LGTM!

.github/workflows/test-python.yml (1)

10-11: LGTM!

Also applies to: 43-86


📝 Summary

Summary by CodeRabbit

  • New Features

    • The Python SDK now ships under the wave_sdk package name while preserving the wave-av-sdk distribution name.
    • The SDK version is consistently reported from its package metadata.
  • Bug Fixes

    • Fixed package resolution so importing Python’s standard-library wave module is no longer shadowed by the SDK.
  • Tests

    • Added packaging and clean-install validation across Python 3.10 and 3.12.

Walkthrough

The pull request adds packaging regression tests, updates clean-room package detection for wave_sdk, adds the Python 3.10 TOML parser fallback, and introduces isolated wheel-install smoke tests for Python 3.10 and 3.12.

Changes

Python packaging validation

Layer / File(s) Summary
Packaging regression tests
sdk-python/tests/test_packaging.py, sdk-python/pyproject.toml
The tests validate wave_sdk, standard-library import resolution, package-name collisions, version metadata, and distribution naming. Python versions below 3.11 use tomli.
Module-aware clean-room detection
scripts/ga/cleanroom_python_assert.py
The clean-room check derives the expected repository package directory from the requested module name.
Isolated CI smoke installation
.github/workflows/test-python.yml
CI builds and installs the SDK wheel in isolated Python 3.10 and 3.12 environments, then runs the clean-room probe.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: ⚪ Minimal · up to 80576

This change repairs the clean-room package check and adds packaging and isolated-install validation for the Python SDK. No merge-blocking risk is currently identified.

Sequence Diagram(s)

sequenceDiagram
  participant GitHub Actions
  participant Wheel Builder
  participant Isolated Virtualenv
  participant Clean-room Probe
  GitHub Actions->>Wheel Builder: Build SDK wheel
  Wheel Builder->>Isolated Virtualenv: Install wheel
  Isolated Virtualenv->>Clean-room Probe: Run import checks
  Clean-room Probe-->>GitHub Actions: Return check results
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 2 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately identifies the clean-room wheel-import guard and stale isolation-marker fix. It is specific and related to the main changes.
Description check ✅ Passed The description clearly explains the workflow fix, packaging tests, smoke-install job, verification results, and out-of-scope republishing work.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 2 files. (2 skipped: 2 unsupported.)

✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cleanroom-registry-defects
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/cleanroom-registry-defects

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

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 4 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant Dev as Developer
    participant GH as GitHub Actions
    participant Unit as pytest (sdk-python)
    participant Pack as test_packaging.py
    participant Build as Wheel Build
    participant Venv as Fresh Venv
    participant Probe as cleanroom_python_assert.py
    participant Registry as GA Registry Gate (post-publish)

    Note over Dev,Registry: PR-time Guard Flow (new smoke-install job)

    Dev->>GH: Push PR touching sdk-python/**
    GH->>GH: Trigger test-python.yml

    rect rgb(240, 248, 255)
        Note over Unit,Pack: Offline unit tests (existing job)
        GH->>Unit: Run pytest
        Unit->>Pack: Execute test_packaging.py
        Pack->>Pack: Scan top-level packages for stdlib shadow (NEW)
        alt Stdlib collision found
            Pack-->>Unit: FAIL (e.g., wave/ reappears)
        else No collision
            Pack->>Pack: Verify import wave resolves to stdlib
            Pack->>Pack: Check wave_sdk.__version__ vs pyproject
            Pack->>Pack: Confirm dist name is wave-av-sdk
            Pack-->>Unit: Pass
        end
    end

    rect rgb(245, 245, 245)
        Note over GH,Probe: New smoke-install job (pre-publish, offline)
        GH->>Build: Build real wheel (python -m build)
        Build-->>GH: wheel file
        GH->>Venv: Create throwaway venv (no repo on sys.path)
        GH->>Venv: Install wheel (pip install, no -e)
        GH->>Venv: Copy cleanroom probe into venv
        Venv->>Probe: Run probe (--module wave_sdk)
        Note over Probe: Isolation guard keyed on args.module (CHANGED)
        alt Repo checkout leaks onto sys.path
            Probe-->>Venv: cleanroom-isolation ok=false (now correctly detects)
            Venv-->>GH: FAIL (guard catches leak)
        else Clean environment
            Probe->>Probe: Import wave_sdk
            Probe->>Probe: Check no stdlib shadow
            Probe-->>Venv: All checks pass
            Venv-->>GH: Pass
        end
    end

    Note over Registry: Post-publish (unchanged, out of scope)
    GH->>Registry: Publish wave-av-sdk to PyPI (operator action)
    Registry->>Registry: Run same probe against live registry
    Note over Registry: Uses same cleanroom_python_assert.py — now with fixed isolation marker
Loading

Re-trigger cubic

…estable

The `cleanroom-isolation` check is the load-bearing assertion of the registry
clean-room gate: `py-import-module` and `py-no-stdlib-shadow` only mean anything
if no source checkout can satisfy the import the PUBLISHED wheel is supposed to
satisfy. It was keyed on one hardcoded path.

The first fix on this branch replaced the stale `<entry>/sdk-python/wave` literal
with `<entry>/sdk-python/<module>`. That restores the guard for wave-av/sdks'
own layout only. The probe also runs against wave-av/sdk-python, whose package
sits at the REPOSITORY ROOT (`wave_sdk/`, verified on that repo's origin/main) —
a checkout of it on sys.path still passed the guard. Measured, both directions:

  fake root-level checkout on PYTHONPATH, probe at this branch's head
    cleanroom-isolation ok=true   (wrong — leak invisible)
  same sys.path, probe after this commit
    cleanroom-isolation ok=false  REPO ON sys.path: [.../wave_sdk]

`checkout_paths_providing()` now asks the layout-independent question — can this
sys.path entry supply the module under test, at the entry itself or under any of
the conventional source roots — after excluding the entries that legitimately
can (site-packages, stdlib, user-site, the venv prefix), read from sysconfig and
`site` rather than assumed to sit under sys.prefix. It also resolves the `''`
entry to cwd, which the previous code skipped outright.

cleanroom-targets.mjs now COPIES the probe into the throwaway room before running
it. Python unconditionally prepends the executed script's directory to sys.path,
so running it in place put `<repo>/scripts/ga` first on the path of every
clean-room probe — a repository directory inside the clean room, which is the one
thing this suite promises never happens. (`-P`/PYTHONSAFEPATH is 3.11+; the
venv's interpreter version is not ours to assume.) test-python.yml's
smoke-install job already copies it for exactly this reason.

sdk-python/tests/test_cleanroom_probe.py: 8 offline unit tests over real
directory trees — both repository layouts, single-file module, the cwd entry, the
site-packages false-positive control, and the self-maintenance property (rename
the package and the guard follows it). A hardcoded-path guard had no test that
could catch it going blind; that is why the rename disarmed it silently.

Verification in this lane:
- pytest -q in sdk-python: 44/44 pass (36 before this commit + 8 new)
- ruff check under the repo's own config: clean on both changed/added files
- full pypi clean-room gate re-run against the LIVE registries with these
  changes: identical evidence fingerprint 8e6537fd84b4859d003e6787d3c4b585ceb5
  ee39da5e681d4d4f2cb098cc8e04 to the run at this branch's head and to
  origin/main — the hardening changes no verdict on real artifacts

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MLCfz2w3xiGLfFFgFmbe5j
@codeant-ai

codeant-ai Bot commented Sep 5, 2026

Copy link
Copy Markdown

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@cursor

cursor Bot commented Sep 5, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_931c09c3-2ff8-470e-a149-d0ddac726449)

@yakimoto

yakimoto commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Clean-room triage 2026-09-05 — the red cleanroom is the gate working, and it also found a second defect in the guard this PR repairs

Corrections to the description above, measured today (the description was accurate when written and has since been overtaken):

  • It lists wave-av-sdk (PyPI) as pending publish. wave-av-sdk 3.0.0 was published 2026-09-05T03:17:38Z and both of its clean-room checks now PASS against the live artifact. The live failing set is 5, not 7.
  • It describes the isolation-marker fix as restoring the guard for "either checkout's real layout". It does not — see below. b419a85 fixes that.

Bucket triage of every failing check

Run 33940473680 reported 7; the current run on b419a85 (33942707861) reports 5.

# Artifact Check Bucket Status today
1 @wave-av/cli@1.0.8 npm-provenance-attested (a) real artifact defect still failing — #85
2 @wave-av/cli@1.0.8 bin-version-matches-package (a) real artifact defect still failing — #85
3 @wave-av/cli@1.0.8 declared-dep-ranges-pinned (a) real artifact defect still failing — #85
4 wave-sdk@2.0.0 (PyPI) py-import-module (a) real artifact defect still failing — #86
5 wave-sdk@2.0.0 (PyPI) py-no-stdlib-shadow (a) real artifact defect still failing — #86
6 wave-av-sdk (PyPI) py-import-module (a) real artifact defect PASS since 3.0.0
7 wave-av-sdk (PyPI) py-no-stdlib-shadow (a) real artifact defect PASS since 3.0.0

Nothing lands in bucket (c) "introduced by this PR".

Control against main

The gate was run against origin/main (6fe7c01) in a clean detached worktree and against this branch's head, same interpreter, same live registries. Identical verdict and identical evidence fingerprint 8e6537fd84b4859d003e6787d3c4b585ceb5ee39da5e681d4d4f2cb098cc8e04. In CI the same failing set appears on two unrelated Renovate branches (runs 33933317710, 33933289317) whose only diff from main is sdk-typescript/pnpm-lock.yaml.

The second guard defect, fixed in b419a85

The first commit replaced the stale <entry>/sdk-python/wave literal with <entry>/sdk-python/<module>. That restores the guard for this repository's layout only. The probe also runs against wave-av/sdk-python, whose package sits at the repository root (wave_sdk/, verified on that repo's main), so a checkout of it on sys.path still passed the guard. Measured with a fabricated checkout on PYTHONPATH:

probe revision root-level wave_sdk/ sdk-python/wave_sdk/
origin/main ok=true (blind) ok=true (blind)
this branch, 80576ba ok=true (still blind) ok=false
this branch, b419a85 ok=false ok=false

checkout_paths_providing() now asks the layout-independent question — can this sys.path entry supply the module under test, at the entry itself or under any conventional source root — after excluding the entries that legitimately can (site-packages, stdlib, user-site, venv prefix), read from sysconfig/site rather than assumed to sit under sys.prefix. It also resolves the '' entry to cwd, which the old code skipped outright.

The clean room was not actually clean

cleanroom-targets.mjs executed the probe from scripts/ga/. Python unconditionally prepends the executed script's directory to sys.path, so a repository directory was first on the path of every clean-room probe — the one thing the suite promises never happens. It is now copied into the throwaway room first, exactly as test-python.yml's smoke-install job already does.

sdk-python/tests/test_cleanroom_probe.py adds 8 offline unit tests over real directory trees: both repository layouts, single-file module, the cwd entry, the site-packages false-positive control, and the self-maintenance property (rename the package and the guard follows it). A hardcoded-path guard had no test that could catch it going blind, which is why the rename disarmed it silently.

Verification on b419a85

  • python test: all four jobs green (test and smoke-install, 3.10 and 3.12)
  • local pytest -q in sdk-python: 44/44
  • ruff check under the repo's own config: clean on both changed files and the new test
  • registry parity, license consistency, governance-enforce, public-repo-guard, foundation-gate: green
  • cleanroom: red with exactly the 5 published-artifact defects above, evidence artifact ga-evidence-registry-cleanroom on run 33942707861

Still advisory

cleanroom is not a required status check on main. The only required context is Secrets + content policy (org ruleset public-repo-guard-required); classic branch protection 404s on this repo because it is ruleset-protected, and a sibling-repo control returns a populated list, so the short answer is a measurement rather than a permissions artifact. Tracked in #87 together with the stale "Arming window" ledger in GA-READINESS.md, which still reports 7 outstanding failures.

Deferred deliberately, not fixed here: all five live artifact defects (#85, #86) — no change in this repository can alter what a registry already serves, and both fixes need an operator-gated publish from a different repo. GA-READINESS.md's arming ledger was left alone too: its ART-001/VER-001/SUPPLY-001 blocks carry verified_revision and evidence sha256 fields that must be regenerated from a real run, not hand-edited (#87).

🤖 Generated with Claude Code

https://claude.ai/code/session_01MLCfz2w3xiGLfFFgFmbe5j

# Conflicts:
#	scripts/ga/cleanroom-targets.mjs
@codeant-ai

codeant-ai Bot commented Sep 8, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Reviewed your PR 4faf619 Sep 08, 2026 · 18:09 18:12

@codeant-ai

codeant-ai Bot commented Sep 8, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@cursor

cursor Bot commented Sep 8, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_2244b286-04d4-461e-9177-b1f47243d578)

@codeant-ai codeant-ai Bot added the size:L This PR changes 100-499 lines, ignoring generated files label Sep 8, 2026
branches: [main]
paths:
- "sdk-python/**"
- "scripts/ga/cleanroom_python_assert.py"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The push filter adds the probe path but not this workflow file, so workflow-only changes merged to main will not run the smoke-install gate. [logic error]

Assessment: 🟠 Major · 🔁 Occurrence: Rarely

Use CodeAnt Skill Fix in Cursor Fix in VSCode Claude

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** .github/workflows/test-python.yml
**Line:** 16:16
**Comment:**
	*Logic Error: The push filter adds the probe path but not this workflow file, so workflow-only changes merged to `main` will not run the smoke-install gate.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@codeant-ai

codeant-ai Bot commented Sep 8, 2026

Copy link
Copy Markdown

CodeAnt Nitpicks

1 code suggestion

1. copyFileSync errors escape the target runner, so missing or unwritable probe files become generic resolve failures without install or probe diagnostics.

Possible bug · scripts/ga/cleanroom-targets.mjs:255

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant