Skip to content

fix(hooks): strip interpreter flags from launcher shebang#2045

Open
nowage wants to merge 1 commit into
Graphify-Labs:v8from
nowage:pr/pipx-shebang-flags
Open

fix(hooks): strip interpreter flags from launcher shebang#2045
nowage wants to merge 1 commit into
Graphify-Labs:v8from
nowage:pr/pipx-shebang-flags

Conversation

@nowage

@nowage nowage commented Jul 19, 2026

Copy link
Copy Markdown

Problem

The post-commit hook's third interpreter probe parses the graphify launcher's shebang. pipx writes launchers with an interpreter flag:

#!/Users/me/.local/pipx/venvs/graphifyy/bin/python -E

The probe keeps the whole string, including -E. The path allowlist immediately below rejects it because of the space, GRAPHIFY_PYTHON is blanked, and the last-resort probe falls through to python3 on PATH — which is a different environment that may hold an older graphify.

The failure is silent and the symptom is misleading. On my machine the fallback interpreter had a stale graphify, so every commit rebuilt a smaller graph and tripped the shrink guard:

[graphify] WARNING: new graph has 10195 nodes but existing graph.json has 10216.
Refusing to overwrite — you may be missing chunk files from a previous session.

The guard was doing its job; nothing was wrong with the graph. It took a while to trace the warning back to interpreter selection rather than graph corruption, and the tempting "fix" (--force) would have been the wrong move.

The pinned-interpreter probe and graphify-out/.graphify_python usually prevent this, so the shebang path is only reached when both miss — a stale pinned path after a reinstall, or a repo whose graphify-out/ has not been written yet. When it is reached, it currently fails for the most common isolated install layout.

Fix

Keep the first whitespace-delimited token before the allowlist check:

GRAPHIFY_PYTHON="${GRAPHIFY_PYTHON%% *}"

Shebangs without flags are unaffected — the parameter expansion is a no-op when there is no space. This also covers -s / -I, which uv and some venv launchers emit.

Tests

Two tests in tests/test_hooks.py, both driving the generated snippet with a fake pipx-style launcher rather than asserting on the template text:

  • test_shebang_probe_strips_interpreter_flags — flagged shebang resolves to the venv interpreter. Fails on v8 without this patch.
  • test_shebang_probe_accepts_plain_interpreter — unflagged shebang keeps working.

tests/test_hooks.py passes in full (60 passed). The 4 pre-existing failures in tests/test_ollama_retry_cap.py are unrelated (missing openai from the ollama extra) and reproduce on a clean v8.

Notes

This is deliberately a minimal fix to the existing probe. I noticed #1619 argues for dropping shebang parsing in the skill templates in favour of probing uv/pipx directories; if you want the hook to move the same way, this patch is easy to drop in favour of that. It touches only graphify/hooks.py and does not overlap with #1962, which is confined to skill-*.md.

pipx writes launcher shebangs as `#!/path/to/venv/bin/python -E`. The
shebang probe in _PYTHON_DETECT kept the trailing flag, so the path
allowlist that runs right after rejected the whole value (a space is not
a valid path character) and blanked GRAPHIFY_PYTHON. Detection then fell
through to the last-resort `python3` probe, which on many machines is an
unrelated system interpreter carrying an older graphify — every commit
rebuilt the graph with a stale version and tripped the node-shrink guard.

Drop everything after the first token before the allowlist check, so both
`#!/path/to/python -E` (pipx) and `#!/usr/bin/env python3 -E` resolve to a
usable interpreter. Flagless shebangs are unaffected.

Adds a regression test that runs the generated detection snippet against a
fake pipx-style launcher and asserts the venv interpreter is picked.
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.

1 participant