Skip to content

babysit-prs engine.test.sh: 3 python-cli refusal rows fail only when a local uv python3 shim leaks PYTHONHOME into the wrappers' py -3 — not a repo bug; passes on Linux CI #1678

Description

@kyle-sexton

plugins/source-control/skills/babysit-prs/scripts/engine.test.sh fails on clean main.
Reproduced at 9f73fc2e with no working-tree changes:

FAIL: test_every_refusal_row (test_guards.RefusalsFireOnArgumentShape.test_every_refusal_row)
      (row='merge.wrapper-reaches-failclosed-cli')     AssertionError: 1 != 3
      (row='resolve.wrapper-reaches-failclosed-cli')   AssertionError: 1 != 3
      (row='resolve.wrapper-filters-nothing')          AssertionError: 1 != 2

FAILED (failures=3)

The three rows assert a specific exit code from the guarded wrapper and get 1 instead of the
expected 3 / 2.

Why main looks green

scripts/check-changed-skills.sh runs a skill's script tests only when that skill changes.
babysit-prs has not changed recently, so the gate has not executed engine.test.sh and the
failure has stayed latent.

It surfaces on the next PR that touches babysit-prs for any reason — including a
documentation-only edit, which is how it was found (#1619 pre-compute migration). That PR then
inherits a red gate it did not cause.

Why this matters beyond the noise

The failing rows are all fail-closed refusal assertions — wrapper-reaches-failclosed-cli for both
the merge and resolve wrappers, and resolve.wrapper-filters-nothing. These are exactly the tests
that are supposed to prove the merge/resolve guards refuse rather than fall through. An exit code of
1 where 3 is expected means either the guard is exiting on a different path than the contract
says, or the test's expectation has drifted from the wrapper. Which of those it is has not been
determined
— this issue reports the failure, it does not diagnose it.

Note the same run's own inline checks all pass (merge wrapper rejects --allow-unpinned-head,
… reaches fail-closed CLI (no allowlist), and the rest), so the wrappers are refusing something
correctly. The disagreement is narrower than "the guard is broken", which is why it needs a real
look rather than a re-baselined assertion.

Ask

  1. Determine whether the wrapper's exit code or the test's expectation is wrong. Do not simply
    update the expected value to 1 — if the wrapper's fail-closed path changed, that is the finding.
  2. Once fixed, consider whether a latent-test-failure sweep belongs in CI. A gate that only runs on
    changed paths will keep accumulating this class silently; a periodic --all run would catch it.

Related

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: lowNice-to-have, cosmetic, or speculative; opportunistic.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions