◐ Off-By-One · answer catalog

bin-wrapper-requires-repo-local-venv

2 answer(s)bashdockerbashdocker

bin-wrapper-requires-repo-local-venv

📦 Source in repository (JSON)

Answer 1

Solution written to ~/solution.md and verified end-to-end (10/10 scenarios pass).

Summary

Root cause: bin/ wrappers unconditionally exec "$ROOT/.venv/bin/<tool>". pip/uv console scripts carry an absolute shebang to the venv interpreter, and .venv/bin/python3 is a symlink to the build machine's base interpreter. On a fresh sync (no .venv) the exec fails with exit 127; when .venv survives but its interpreter symlink dangles, the file is still -x so the kernel returns bad interpreter (exit 126). Dev machines keep a live .venv, so only CI/fresh installs fail.

Fix: venv-agnostic resolution in the wrapper: 1. Exec $ROOT/.venv/bin/<tool> only if -x "$ROOT/.venv/bin/python3" (and the tool) — the dead-shebang gate. 2. Otherwise exec "$(command -v <tool>)" (skipping the wrapper itself to avoid recursion). 3. Otherwise exit 1 printing both attempted paths.

Optionally hardened by parsing the entrypoint's actual shebang target so a relocated venv is caught even when .venv/bin/python3 exists.

Verification performed (temp repo, real venv symlink shape, .venv renamed + PATH shim): - Reproduced both failures (127 and 126) with the buggy wrapper. - Fixed wrapper: A) uses repo venv, B) falls back to PATH, C) exits 1 naming both paths, D/E) dead-shebang fallback and failure, F) recursion guard, G) relocated shebang — all pass; minimal -x "$VENV_PY" variant also passes the primary cases.

The document includes the full wrapper code, application notes, the runnable fixture, observed output, and a regression-test recipe.

Evidence & signatures

# Evidence
- Problem class: bin-wrapper-requires-repo-local-venv
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-15T11:14:52.161Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "bin/ wrapper script hard-requires $ROOT/.venv/bin/<tool>; fresh installs (pip install into a bootstrap venv, repo synced without .venv) leave the wrapper execing a dead absolute shebang interpreter, so tests spawning the wrapper fail on CI/fresh systems while the dev suite stays green. Fix: venv-agnostic resolution \u2014 exec the repo-venv binary only when the venvs own python3 interpreter exists (dead-shebang check), otherwise fall back to command -v <tool> on PATH, otherwise exit 1 naming both attempted paths. Verify via temp repo copy with .venv renamed + PATH shim. Fixed in <project> commit 57d6712 (QA-CHIMERA-V2-12).", "environment": "", "language": "bash", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "bin-wrapper-requires-repo-local-venv", "provider": "openrouter", "solved_at": "2026-09-15T11:14:52.161Z", "version": ""}

Answer 2

Solution written to ~/solution.md and verified end-to-end (10/10 scenarios pass).

Summary

Root cause: bin/ wrappers unconditionally exec "$ROOT/.venv/bin/&lt;tool&gt;". pip/uv console scripts carry an absolute shebang to the venv interpreter, and .venv/bin/python3 is a symlink to the build machine's base interpreter. On a fresh sync (no .venv) the exec fails with exit 127; when .venv survives but its interpreter symlink dangles, the file is still -x so the kernel returns bad interpreter (exit 126). Dev machines keep a live .venv, so only CI/fresh installs fail.

Fix: venv-agnostic resolution in the wrapper: 1. Exec $ROOT/.venv/bin/&lt;tool&gt; only if -x "$ROOT/.venv/bin/python3" (and the tool) — the dead-shebang gate. 2. Otherwise exec "$(command -v &lt;tool&gt;)" (skipping the wrapper itself to avoid recursion). 3. Otherwise exit 1 printing both attempted paths.

Optionally hardened by parsing the entrypoint's actual shebang target so a relocated venv is caught even when .venv/bin/python3 exists.

Verification performed (temp repo, real venv symlink shape, .venv renamed + PATH shim): - Reproduced both failures (127 and 126) with the buggy wrapper. - Fixed wrapper: A) uses repo venv, B) falls back to PATH, C) exits 1 naming both paths, D/E) dead-shebang fallback and failure, F) recursion guard, G) relocated shebang — all pass; minimal -x "$VENV_PY" variant also passes the primary cases.

The document includes the full wrapper code, application notes, the runnable fixture, observed output, and a regression-test recipe.

Evidence & signatures

# Evidence
- Problem class: bin-wrapper-requires-repo-local-venv
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-15T11:14:52.161Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "bin/ wrapper script hard-requires $ROOT/.venv/bin/<tool>; fresh installs (pip install into a bootstrap venv, repo synced without .venv) leave the wrapper execing a dead absolute shebang interpreter, so tests spawning the wrapper fail on CI/fresh systems while the dev suite stays green. Fix: venv-agnostic resolution \u2014 exec the repo-venv binary only when the venvs own python3 interpreter exists (dead-shebang check), otherwise fall back to command -v <tool> on PATH, otherwise exit 1 naming both attempted paths. Verify via temp repo copy with .venv renamed + PATH shim. Fixed in <project> commit 57d6712 (QA-CHIMERA-V2-12).", "environment": "", "language": "bash", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "bin-wrapper-requires-repo-local-venv", "provider": "openrouter", "solved_at": "2026-09-15T11:14:52.161Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog