Skip to content

fix(tests): repair v0.32.0 release validation contracts - #3081

Merged
Daniel Meppiel (danielmeppiel) merged 1 commit into
mainfrom
danielmeppiel-release-ci-blockers
Sep 25, 2026
Merged

Daniel Meppiel (danielmeppiel) merged 1 commit into
mainfrom
danielmeppiel-release-ci-blockers

Conversation

@danielmeppiel

Copy link
Copy Markdown
Collaborator

fix(tests): repair v0.32.0 release validation contracts

TL;DR

Repair the two test contracts that blocked the unpublished v0.32.0 release after #3080.
Plugin uninstall now checks removed files/lock ownership and the unchanged retained skill instead of obsolete cleanup wording.
The live Windows-marker collection check gets a finite 300-second budget with explicit environment and fail-closed timeout coverage.

Important

Test-only release repair: no runtime, workflow, version, dependency, README, or changelog changes.
This PR does not merge, move the v0.32.0 tag, or publish.
Protected-branch review, required checks, and merge queue still apply.

Problem (WHY)

  • The v0.32.0 tag run failed plugin sequential-install coverage on Linux ARM and macOS ARM. The install/uninstall succeeded, but the test required Cleaned up and integrated while actual cleanup reported Cleaned 2 stale files. Linux x64 was cancelled by matrix fail-fast, not a separately confirmed assertion failure.
  • The same run's macOS Intel unit job timed out after 120 seconds during live nested collection. Its four-worker suite otherwise reported 22,768 passed, 4 skipped, and 21 xfailed. The parent also diagnosed this timeout in main run 36155951461.
  • [!] -m windows_compat deselects only after importing and collecting both roots. A small selected family does not imply a small collection workload.

The scope follows the observed failures rather than changing production behavior to fit a test.
Validation is execution-backed, following the Agent Skills instruction to
"do the work, run a validator (a script, a reference checklist, or a self-check), fix any issues, and repeat until validation passes."

Approach (WHAT)

  • Replace the cleanup-message check with one shared filesystem/lockfile assertion used by local and network-backed sequential-install cases.
  • Extend the existing local fixture case to cover both an independent skill and a separately installed skill from the plugin.
  • Keep real pytest collection, both collection roots, Unix-import blocking, plugin-autoload isolation, and strict non-empty subset selection; change only the finite subprocess budget.

Implementation (HOW)

File Intent
tests/integration/test_plugin_e2e.py Snapshot retained skill bytes, require non-vacuous plugin deployment cleanup, remove plugin lock ownership, and preserve the complete surviving skill entry and files. Reuse these assertions in the existing network case; require deps tree success.
tests/unit/test_windows_compat_gate_workflow.py Increase nested collection from 120 to 300 seconds, matching the existing repository taxonomy collection budget. Pin timeout/cwd/interpreter/environment arguments and propagation of TimeoutExpired.
docs/src/content/docs/contributing/integration-testing.md Document the collection budget and state-based plugin lifecycle assertions. No user-facing release entry for internal test machinery.

Diagrams

Omitted under the template's omission provision: these are independent test-contract repairs, with no runtime architecture or workflow-topology change.

Trade-offs

  • Finite headroom, not a timeout bypass. A stuck collector can now consume up to five minutes instead of two. The existing taxonomy guard already uses 300 seconds; the collector still raises on timeout and never returns a success-shaped fallback.
  • Hermetic local evidence, retained hosted coverage. Local real-CLI fixtures cover standalone and plugin-origin skills. The pinned external network-backed case remains intact, but was not run locally; hosted integration/release validation remains necessary.
  • No collection optimization refactor. Avoid per-file allowlists, skipping the live selector, or changing production output. The measured workload and existing slower-runner failures support a bounded budget change; they do not prove a future hosted run will pass.

Benefits

  1. Both hermetic skill-origin variants prove plugin files disappear while the survivor's SKILL.md, other deployed file bytes, and dependency entry stay unchanged.
  2. The real network-backed lifecycle case shares the same state assertions instead of coupling cleanup correctness to prose.
  3. Full-root marker selection remains live, with explicit regression coverage that a real timeout fails closed.

Validation

Local validation passed; hosted PR/release checks are not claimed green.
All commands used the editable 0.32.0 checkout and its locked dependencies.
Local dependency setup used the ambient Microsoft proxy without committing proxy configuration.
UV_NO_SYNC=1 prevented lockfile rewrites.

Collection evidence and targeted results

Before the change, the entire Windows-gate contract file:

23 passed in 32.66s

Its nested collection call took 30.36 seconds cold.
The exact helper on a warm cache:

wall time: 9.45s; exit: 0
566/32601 tests collected (32035 deselected) in 6.94s

A separate cProfile collection imported 1,156 test modules:

566/32601 tests collected (32035 deselected) in 12.58s

UV_NO_SYNC=1 uv run --extra dev pytest -p no:cacheprovider -q tests/unit/test_windows_compat_gate_workflow.py tests/integration/test_plugin_e2e.py::TestPluginHeroScenarios::test_local_plugin_uninstall_after_sequential_skill_install_cleans_deployed_files --durations=5

26 passed in 15.29s

UV_NO_SYNC=1 uv run --extra dev pytest -p no:cacheprovider -q tests/integration/test_plugin_e2e.py -m 'not requires_e2e_mode and not requires_network_integration' --durations=5

15 passed, 12 skipped in 10.55s

The skipped cases are the existing network opt-in class; no skip was added.

UV_NO_SYNC=1 uv run --extra dev pytest -p no:cacheprovider -q tests/unit/test_windows_compat_gate_workflow.py -n 4 --dist worksteal --durations=3

24 passed in 11.30s
Full lint, strict test-quality ratchets, and scope checks

After fetching and merging origin/main, the canonical lint chain used UV_NO_SYNC=1:

uv run --extra dev ruff check src/ tests/ scripts/lint_architecture_boundaries.py scripts/architecture_linter/
uv run --extra dev ruff format --check src/ tests/ scripts/lint_architecture_boundaries.py scripts/architecture_linter/
uv run --extra dev python -m pylint --disable=all --enable=R0801 --min-similarity-lines=10 --fail-on=R0801 src/apm_cli/ scripts/lint_architecture_boundaries.py scripts/architecture_linter/
bash scripts/lint-auth-signals.sh
bash scripts/lint-architecture-boundaries.sh

Output excerpts:

All checks passed!
1881 files already formatted
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
[+] auth-signal lint clean

The architecture-boundary script exited 0 without output.
The remaining YAML I/O, 2100-line, and portable-path guards also passed using Python equivalents of the CI grep/awk predicates because ripgrep is unavailable in the local shell.

UV_NO_SYNC=1 uv run --frozen python scripts/check_test_assertions.py and UV_NO_SYNC=1 uv run --frozen python scripts/check_exact_test_duplicates.py:

[+] assertion-quality ratchet clean: AQ001=4, AQ002=12
[+] exact test duplicate ratchet clean: 1241 files, 0 allowed duplicate group(s)

git diff --check and git diff --exit-code origin/main -- uv.lock pyproject.toml CHANGELOG.md README.md exited 0.
The docs-impact classifier returned schema-valid no_change, high confidence, at deterministic L0: only tests and contributor documentation changed.

Scenario Evidence

# Scenario (user promise) Principle(s) Test(s) proving it Type
1 Install a plugin, then an independent skill; removing the plugin must preserve that skill. DevX (pragmatic as npm), Governed by policy tests/integration/test_plugin_e2e.py::TestPluginHeroScenarios::test_local_plugin_uninstall_after_sequential_skill_install_cleans_deployed_files[standalone] e2e
2 Keep a separately installed plugin skill while removing the plugin's other files and lock ownership. DevX (pragmatic as npm), Governed by policy Same local test with [plugin-skill]; TestPluginNetworkE2E::test_lockfile_preserved_on_sequential_install retains hosted coverage (regression contract for run 36156463741). e2e
3 New Windows-marked regressions remain discoverable without maintaining a file list. Portability by manifest, OSS / community-driven tests/unit/test_windows_compat_gate_workflow.py::test_windows_compat_gate_marker_selects_nonempty_subset integration
4 A hung validation collector must fail, with isolated plugin loading and a finite budget. OSS / community-driven tests/unit/test_windows_compat_gate_workflow.py::test_nested_collection_preserves_environment_and_bounded_timeout and ::test_nested_collection_timeout_fails_closed unit

How to test

  • Use a frozen development environment, or the documented local proxy-safe bootstrap; keep UV_NO_SYNC=1 when dependencies are already installed.
  • Run the combined 26-case command above; expect both local skill variants and the live collection contract to pass.
  • Run the four-worker Windows-gate contract command; expect 24 passing tests, including fail-closed timeout coverage.
  • Run the canonical lint and strict test-quality commands above; expect exit 0 and no uv.lock diff.
  • Let protected PR checks and hosted integration validation complete before merge. The parent release session owns subsequent tag correction and publication follow-through.

Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com

Assert plugin removal and retained skill state instead of obsolete cleanup prose. Allow a finite 300s live marker collection budget on contended release runners and pin fail-closed timeout/environment behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

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

Exclude shared retained-skill paths from the plugin-only removal assertion.

Get a fresh assessment by requesting another Copilot review.

Review effort: Lite
Findings: 1 High severity

Open (1)
What changed in this PR

Test-only repair for plugin lifecycle validation and Windows compatibility-gate collection.

Changes:

  • Adds filesystem and lockfile cleanup assertions.
  • Adds bounded, fail-closed collection timeout coverage.
  • Documents the revised test contracts.
File Summary
tests/​unit/​test_windows_compat_gate_workflow.py Adds bounded timeout and environment validation.
tests/​integration/​test_plugin_e2e.py Strengthens plugin cleanup and retained-skill checks.
docs/​src/​content/​docs/​contributing/​integration-testing.md Documents updated test contracts.

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

Comment thread tests/integration/test_plugin_e2e.py
@danielmeppiel
Daniel Meppiel (danielmeppiel) merged commit f0509d7 into main Sep 25, 2026
20 checks passed
@danielmeppiel
Daniel Meppiel (danielmeppiel) deleted the danielmeppiel-release-ci-blockers branch September 25, 2026 16:57
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.

2 participants