Skip to content

fix: root-cause CI failures inherited from sync#39

Merged
samtuckerdavis merged 2 commits into
mainfrom
fix/sync-ci-failures-2026-05-14
May 13, 2026
Merged

fix: root-cause CI failures inherited from sync#39
samtuckerdavis merged 2 commits into
mainfrom
fix/sync-ci-failures-2026-05-14

Conversation

@samtuckerdavis
Copy link
Copy Markdown

@samtuckerdavis samtuckerdavis commented May 13, 2026

Summary

PR #38 merged with 5 failing tests. This PR fixes each at the root, verified locally before push.

The 5 failures, root-caused

1. Three test_bash_unused_imports failures → tree-sitter-language-pack 1.6.3 is broken

tree-sitter-language-pack 1.6.3 (released 2026-04-23 by kreuzberg-dev) is a deliberate breaking refactor: the public module moved from tree_sitter_language_pack to _native, removing the top-level package name that desloppify/languages/_framework/treesitter/analysis/extractors.py:102 imports. The ImportError gets swallowed by PARSE_INIT_ERRORS in analysis/unused_imports.py:65, so failures surface as silently-empty findings rather than ImportError — that's why CI reported "assert [] == ['helpers']" instead of a parser-init error.

Verification: clean Python 3.12 venv on 1.6.3 → 3 bash tests fail; downgrade to 1.6.2 → all bash tests pass.

Fix: pin to >=0.3,<1.6.3 in pyproject.toml (both treesitter and full extras). Updated test_treesitter_language_pack_is_capped_below_incompatible_release to assert the new cap — the test exists to ensure the cap doesn't accidentally regress, and the cap value was hardcoded as <1.8.

Upstream peteromallet/desloppify is also affected — their recent CI runs are failing too. This fix can be sent upstream as a follow-up.

2. test_successful_dedicated_install_rovodev → missing _read_local_docs_file mock

OP's update_skill/cmd.py prefers local docs/ files over remote download (local-first when running from a checkout). The test mocked only _download, so _read_local_docs_file('ROVODEV.md') returned the real shipping docs/ROVODEV.md content (which doesn't contain the string "rovodev overlay"), bypassing the mock entirely.

The test class already had this _read_local_docs_file mock pattern on test_download_failure and test_bad_content (added together with the local-first feature). The three test_successful_* tests were inconsistent — written or copied before the mock pattern was established.

Fix: add @patch("desloppify.app.commands.update_skill.cmd._read_local_docs_file", return_value=None) to test_successful_dedicated_install, test_successful_dedicated_install_rovodev, and test_successful_shared_install. Consistently exercises the download path the tests intend to test. All 25 tests in the file now pass.

3. test_show_structural_loads_medium_confidence_matches → scope.py regression

The sync's per-file restoration of OP versions reverted app/commands/show/scope.py to a stale variant that routes everything through build_work_queue. That path applies standalone_threshold filtering in ranking.py:148-156 (medium-confidence structural < high threshold → filtered out).

Upstream's evolved load_matches has an explicit "show should surface persisted matching issues even when a detector has a higher standalone confidence threshold" branch: it calls build_issue_items directly with forced_ids=_matching_issue_ids_for_scope(state, scope), bypassing the confidence-threshold filter. This is the feature the test verifies.

OP's only divergence in scope.py was a docstring example mentioning show advocacy_language — not load-bearing code; upstream's load_matches handles advocacy scopes identically via the same scope_matches helper.

Fix: take upstream's scope.py wholesale + revert engine/work_queue.py to upstream (no longer needs build_work_queue_for_visibility export, which only OP's old scope.py used). All 42 tests in test_cmd_show.py pass.

What's NOT in this PR

On Python 3.12 locally (not CI's 3.11), I see ~30 additional latent test failures across test_review_commands, detector adapters, and treesitter imports. These don't appear in CI on Python 3.11. Separate triage — out of scope for this PR's "fix the 5 documented findings" mandate.

Test plan

  • CI on this PR (lint, typecheck, ci-contracts, tests-core, tests-full, package-smoke, CodeQL, Code Quality Gate, no-animal-violence)
  • CodeRabbit pass
  • Verify the 5 originally-failing tests now pass on CI

Summary by CodeRabbit

  • Refactor

    • Improved issue-matching and surfacing behavior in the show command.
  • Chores

    • Simplified work-queue API surface.
    • Tightened tree-sitter-language-pack dependency to avoid incompatible upstream changes.
  • Tests

    • Added conditional skipping for Bash tests when the treesitter pack is unavailable.
    • Updated mocks and test scaffolding for skill update-related tests.

Review Change Stack

PR #38 merged with 5 failing tests. Each had a real root cause now fixed,
verified locally before push.

1. tree-sitter-language-pack 1.6.3 breaks 3 bash detector tests

   1.6.3 (released 2026-04-23) is a deliberate breaking refactor by upstream
   (kreuzberg-dev): the public module moved from `tree_sitter_language_pack`
   to `_native`, removing the top-level package that desloppify's parser
   bootstrap imports. ImportError gets caught by PARSE_INIT_ERRORS in
   analysis/unused_imports.py and returns empty findings, masking the
   regression as test assertion failures rather than import failures.

   Verified: on a clean Python 3.12 venv with 1.6.3, all 3 bash tests fail
   with `[] == ['helpers']` etc. Pin to 1.6.2 → all 5 bash tests pass.

   Fix: cap at <1.6.3 in pyproject.toml (treesitter + full extras) and
   update test_treesitter_language_pack_is_capped_below_incompatible_release
   to assert the new cap.

2. test_successful_dedicated_install_rovodev: missing _read_local_docs_file mock

   OP's update_skill/cmd.py prefers local docs/ files over the download
   path (sensible: local-first when running from a checkout). Test mocked
   only `_download`, so _read_local_docs_file('SKILL.md') and
   ('ROVODEV.md') returned real local content (the actual ROVODEV.md
   shipping with the package), bypassing the mock.

   The test class already had this mock pattern on test_download_failure
   and test_bad_content; the three "successful_install" tests were
   inconsistent. Added @patch on `_read_local_docs_file, return_value=None`
   to all three to consistently exercise the download path the tests
   intend to test. Verified all 25 tests in the file pass.

3. test_show_structural_loads_medium_confidence_matches: scope.py regression

   The sync's per-file restoration of OP versions reverted scope.py's
   load_matches to a stale variant that routes everything through
   build_work_queue, which applies standalone_threshold filtering (medium
   structural < high threshold → filtered). Upstream's evolved load_matches
   has an explicit "show should surface persisted matching issues even
   when a detector has a higher standalone confidence threshold" path
   that calls build_issue_items directly with forced_ids, bypassing the
   filter.

   OP's only difference in scope.py was a docstring example mentioning
   advocacy_language — not load-bearing code. Upstream's load_matches
   handles advocacy scopes identically.

   Fix: take upstream's scope.py + revert engine/work_queue.py to upstream
   (no longer needs build_work_queue_for_visibility export, which only
   OP's old scope.py used). Verified all 42 tests in test_cmd_show.py pass.

Excluded from this PR: ~30 additional latent failures visible in Python
3.12 local runs that don't appear in CI on Python 3.11. Separate triage.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3930fcf6-7699-4221-bf23-6a9a29980a9a

📥 Commits

Reviewing files that changed from the base of the PR and between 2db8b7a and be04563.

📒 Files selected for processing (1)
  • desloppify/tests/lang/common/test_bash_unused_imports.py

📝 Walkthrough

Walkthrough

This PR stabilizes the work-queue facade (removes visibility exports), refactors show command matching to use persisted issue state, tightens tree-sitter-language-pack bounds, and updates tests to mock local docs reads and skip Bash tests when the language pack is missing.

Changes

Work-queue API stabilization and persisted-state matching refactor

Layer / File(s) Summary
Work-queue API facade cleanup
desloppify/engine/work_queue.py
Removes QueueVisibility and build_work_queue_for_visibility from public exports; imports build_work_queue directly from the core module.
Show command scope matching refactor
desloppify/app/commands/show/scope.py
load_matches now builds issue items from persisted state via build_issue_items and computes matching IDs with _matching_issue_ids_for_scope using scope_matches, replacing queue/backlog-derived matching.
Skill installation test mocking
desloppify/tests/commands/test_transitive_modules_update_skill.py
Three tests now mock _read_local_docs_file (returning None) in addition to existing _download mocks.
Tree-sitter-language-pack constraint tightening
pyproject.toml, desloppify/tests/core/test_pyproject_optional_dependencies.py
Upper bound for tree-sitter-language-pack changed from <1.8 to <1.6.3 in optional dependency groups; inline comments added and test assertion updated.
Conditional skip for Bash tests
desloppify/tests/lang/common/test_bash_unused_imports.py
Adds pytestmark = pytest.mark.skipif(not is_available(), reason="tree-sitter-language-pack not installed") to skip tests when the tree-sitter language pack is unavailable.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

breaking-change

🚥 Pre-merge checks | ✅ 7 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (7 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly maps to the changeset: it addresses CI failures (from tree-sitter pinning, update_skill mocking, and scope.py regression fixes) inherited from sync.
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.
No Hardcoded Secrets Or Credentials ✅ Passed No hardcoded secrets, credentials, API keys, tokens, or passwords found in non-test files. All three modified non-test files (scope.py, work_queue.py, pyproject.toml) are clean.
No Speciesist Idioms ✅ Passed Comprehensive search across all PR-modified files found zero instances of prohibited speciesist idioms (livestock, master/slave, whitelist/blacklist, cattle, guinea pig, kill two birds, farm).
No Tier 3 Data Committed ✅ Passed Six PR files scanned. No Tier 3 data: no activist IDs, legal comms, opsec details, investigative records, activist PII, NGO financials, or credentials detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sync-ci-failures-2026-05-14
  • 🛠️ fix NAV violations

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

coderabbitai[bot]
coderabbitai Bot previously approved these changes May 13, 2026
tests-core runs via `make tests` → `install-ci-tools` which installs the
core package without [full] extras (no tree-sitter-language-pack). The
new test_bash_unused_imports.py module (came in via the sync from upstream)
lacked the skipif guard that every other test_treesitter module uses:

    pytestmark = pytest.mark.skipif(
        not is_available(),
        reason="tree-sitter-language-pack not installed",
    )

Without the guard, the parser-init catch in detect_unused_imports returns
empty findings on missing parser, and the test assertions fail with
"assert [] == ['helpers']" — exactly the symptom the previous commit's
1.6.3 pin fixed for tests-full but couldn't fix for tests-core (parser
not installed at all there).

Verified locally: tests still pass when tree-sitter is installed; will
skip cleanly when it isn't.
@samtuckerdavis samtuckerdavis merged commit 8ef608d into main May 13, 2026
12 checks passed
@samtuckerdavis samtuckerdavis deleted the fix/sync-ci-failures-2026-05-14 branch May 13, 2026 21:59
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