tests/test_prune_babysit_worktrees.py's repo fixture sets a throwaway identity but not commit.gpgsign false. On any machine with commit.gpgsign = true globally — the default for anyone who signs — there is no secret key for the fixture identity, every fixture commit fails, and 17 of the suite's 45 tests error out.
Reproduced
Machine has commit.gpgsign true and gpg.program set globally. At main (312d7a6a merge-base), with no local edits:
$ cd plugins/source-control/skills/babysit-prs/scripts
$ python3 -m unittest tests.test_prune_babysit_worktrees
Ran 45 tests in 11.876s
FAILED (errors=17)
Every one of the 17 fails the same way, in fixture setup rather than in an assertion:
Traceback (most recent call last):
File ".../tests/test_prune_babysit_worktrees.py", line 205, in test_a_live_linked_worktree_is_not_an_orphan
main = make_repo(tmp)
File ".../tests/test_prune_babysit_worktrees.py", line 55, in make_repo
git("-C", str(main), "commit", "-q", "--allow-empty", "-m", "init")
The underlying git error:
error: gpg failed to sign the data:
gpg: skipped "t <t@t>": No secret key
gpg: signing failed: No secret key
The site
tests/test_prune_babysit_worktrees.py:48-56 — make_repo, and the sibling make_bare_hub below it:
def make_repo(tmp: pathlib.Path) -> pathlib.Path:
"""A one-commit repository with committer identity set locally."""
main = tmp / "mainrepo"
main.mkdir()
git("init", "-q", str(main))
git("-C", str(main), "config", "user.email", "t@t")
git("-C", str(main), "config", "user.name", "t")
git("-C", str(main), "commit", "-q", "--allow-empty", "-m", "init") # <-- signs, and fails
return main
The docstring already says "committer identity set locally" — signing configuration is the half it misses.
Why this is worth fixing rather than shrugging at
The failure does not look like an environment problem. Fixture setup dies, so the creation cases error while every case that asserts a refusal still passes — a suite reporting "17 errors, 28 pass" reads as a real regression in the code under test. A reader who does not open the traceback will go hunting in prune_babysit_worktrees.py, which is fine. I hit exactly this shape twice in #2309 and lost time to it the first time before recognising it.
CI does not catch it because GitHub runners do not sign by default, so this only ever bites a contributor on their own machine — the worst place for a false regression signal.
Fix
One repo-local line per fixture repo, on a directory the fixture itself just created:
git("-C", str(main), "config", "commit.gpgsign", "false")
Prefer routing through the shared helper #2333 just added. scripts/test-git-helpers.sh already encodes this correctly (git_test_config "$dir" config commit.gpgsign false, and -c commit.gpgsign=false on its init path), so the Python fixture should adopt the same contract rather than open-code a third variant. That also keeps this from recurring in the next Python fixture.
Note the scope constraint from #2162, which is satisfied here: this writes repo-local config into a directory the fixture just created under tmp, never into a caller-supplied or ambient directory. That is the same shape the shell suites use.
Prior art in this exact class
Same defect, same remedy, already fixed twice in #2309 (source-control 0.52.0):
hooks/worktree-create-gate.test.sh — mkrepo
scripts/worktree-create.test.sh — both fixture sites; that suite went 94/154 → 154/154 on this machine
This is the third instance. Fixing it and pointing all three at the shared helper would close the class.
Separately observed, NOT filed here
The same full-suite run also shows 3 failures in tests/test_guards.py (merge.wrapper-reaches-failclosed-cli, resolve.wrapper-reaches-failclosed-cli, resolve.wrapper-filters-nothing). Those are not this bug and I am not claiming they are a defect: the child process dies during interpreter startup (from dataclasses import dataclass → import inspect → truncated), yielding exit 1 where the guard row expects 3. That looks environment-specific to this box (Python 3.14 on Windows via uv), and I did not verify it anywhere else — recorded only so the next person running the full suite here is not surprised by it.
Found by wave-2 lane SC, handoff-inbox batch 4, while verifying #2265's shipped fix at main. Windows, Git Bash, Python 3.14.
tests/test_prune_babysit_worktrees.py's repo fixture sets a throwaway identity but notcommit.gpgsign false. On any machine withcommit.gpgsign = trueglobally — the default for anyone who signs — there is no secret key for the fixture identity, every fixture commit fails, and 17 of the suite's 45 tests error out.Reproduced
Machine has
commit.gpgsign trueandgpg.programset globally. Atmain(312d7a6amerge-base), with no local edits:Every one of the 17 fails the same way, in fixture setup rather than in an assertion:
The underlying git error:
The site
tests/test_prune_babysit_worktrees.py:48-56—make_repo, and the siblingmake_bare_hubbelow it:The docstring already says "committer identity set locally" — signing configuration is the half it misses.
Why this is worth fixing rather than shrugging at
The failure does not look like an environment problem. Fixture setup dies, so the creation cases error while every case that asserts a refusal still passes — a suite reporting "17 errors, 28 pass" reads as a real regression in the code under test. A reader who does not open the traceback will go hunting in
prune_babysit_worktrees.py, which is fine. I hit exactly this shape twice in #2309 and lost time to it the first time before recognising it.CI does not catch it because GitHub runners do not sign by default, so this only ever bites a contributor on their own machine — the worst place for a false regression signal.
Fix
One repo-local line per fixture repo, on a directory the fixture itself just created:
Prefer routing through the shared helper #2333 just added.
scripts/test-git-helpers.shalready encodes this correctly (git_test_config "$dir" config commit.gpgsign false, and-c commit.gpgsign=falseon its init path), so the Python fixture should adopt the same contract rather than open-code a third variant. That also keeps this from recurring in the next Python fixture.Note the scope constraint from #2162, which is satisfied here: this writes repo-local config into a directory the fixture just created under
tmp, never into a caller-supplied or ambient directory. That is the same shape the shell suites use.Prior art in this exact class
Same defect, same remedy, already fixed twice in #2309 (
source-control0.52.0):hooks/worktree-create-gate.test.sh—mkreposcripts/worktree-create.test.sh— both fixture sites; that suite went 94/154 → 154/154 on this machineThis is the third instance. Fixing it and pointing all three at the shared helper would close the class.
Separately observed, NOT filed here
The same full-suite run also shows 3 failures in
tests/test_guards.py(merge.wrapper-reaches-failclosed-cli,resolve.wrapper-reaches-failclosed-cli,resolve.wrapper-filters-nothing). Those are not this bug and I am not claiming they are a defect: the child process dies during interpreter startup (from dataclasses import dataclass→import inspect→ truncated), yielding exit 1 where the guard row expects 3. That looks environment-specific to this box (Python 3.14 on Windows via uv), and I did not verify it anywhere else — recorded only so the next person running the full suite here is not surprised by it.Found by wave-2 lane SC, handoff-inbox batch 4, while verifying #2265's shipped fix at
main. Windows, Git Bash, Python 3.14.