Skip to content

fix(skills): persist durable uv and pipx interpreters - #3980

Open
azizur100389 wants to merge 3 commits into
Graphify-Labs:v8from
azizur100389:codex/durable-interpreter
Open

azizur100389 wants to merge 3 commits into
Graphify-Labs:v8from
azizur100389:codex/durable-interpreter

Conversation

@azizur100389

@azizur100389 azizur100389 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3943.

Step 1 and the subcommand guard now share a resolver that probes persistent uv/pipx tool environments, verifies imports, rejects uv archive-cache interpreters and skips PE launchers before any shebang read. The guard also repairs stale sidecars; installation or import failure stops before persisting a new path.

Interpreter invocations are quoted throughout POSIX skill fragments so Windows paths containing spaces remain usable. Generated hosts and snapshots are regenerated, PowerShell translation remains validated, and monolith allowances enumerate only the old/new resolver and quoting lines. Sixteen regressions execute the snippets for POSIX and Windows tool layouts, native Windows paths, missing imports, hostile shebangs and stale sidecars.

Validation: Ruff, pre-commit, all five skillgen validators, fresh wheel installation, installed-artifact smoke checks, CLI help/install and the AST graph refresh pass. Regression tests reproduce the defects on unchanged upstream and pass with these changes.

Full CI passes on Python 3.10 (6234 passed, 13 repository-defined skips) and 3.12/3.13/3.14 (6233 passed, 14 repository-defined skips each). Frozen dependencies include all extras; CLI help/install passes on every version. No test filters or new skips were added.

The full Windows Python 3.12 suite finished with 6152 passed, 37 failed and 58 repository-defined skips. All 37 failing test IDs were rerun on unchanged upstream with the same Git Bash environment and reproduced there; none are introduced by this PR. All 16 new interpreter regressions pass under Git Bash. An isolated real uv tool installation with spaces in its path persisted the durable tool interpreter, imported Graphify after the uv cache was removed, and passed the subcommand guard.

Pyright reports the same 586 baseline diagnostics with no introduced diagnostics. Bandit has the same 12 filtered baseline findings (4 high, 8 medium); pip-audit has the same 41 vulnerability records across 8 packages, matched by advisory aliases to upstream. Security CI is non-blocking in this repository, so its green status is not represented as a clean security audit. Dependencies and lockfile are unchanged.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

Thanks for the pull request, @azizur100389. A maintainer will review it soon.

Want to talk it through while it is in review? Come join us on our Discord server. For longer-form discussion there is also GitHub Discussions.

A couple of things that speed up review: make sure the test suite passes on Python 3.10 and 3.13, and that the change keeps extraction deterministic.

Co-Authored-By: OpenAI Codex <noreply@openai.com>
@azizur100389
azizur100389 marked this pull request as ready for review October 1, 2026 18:53

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 4 advisory finding(s) below merit a look before merge.


Graphify review — findings

Hardens the graphify skill's Step 1 interpreter detection so it saves only a persistent Python to .graphify_python, one that imports graphify and isn't an ephemeral uv archive-v cache. graphify_find_python probes the uv tool dir and pipx venvs (POSIX and Windows layouts) first, then a literal text-launcher shebang (never .exe or evaluated contents), then python3/python, and exits with an error rather than silently falling back when install or resolution fails. Every later step now quotes "$(cat graphify-out/.graphify_python)" so interpreter paths with spaces work, and the same resolver replaces the old which/head -1 re-resolution for subcommands when .graphify_python is missing.

Worth a look

  • Existing .graphify_python is trusted and executed without validation for subcommands — graphify/skill-agents.md:694 · Escalate · high · 2 independent checks
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Workspace sidecar path is trusted as an executable interpreter — graphify/skill-agents.md · Escalate · high
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • save-result still splices question/answer text into double-quoted shell args — graphify/skill-aider.md:1083 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
  • Removed --break-system-packages fallback breaks pip-only installs on PEP 668 systems — graphify/skill-aider.md:115 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review

Review partial — this diff was larger than one review pass covers, so later files were not reviewed; some findings may be missing.

Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 1891 functions depend on the 1826 functions this change touches.

Health — this change adds coupling hotspots:

  • new: render() — 15 callers, 5 callees
  • new: audit_coverage() — 8 callers, 6 callees
  • new: run_fragment() — 6 callers, 6 callees
  • new: main() — 3 callers, 11 callees
  • new: monolith_roundtrip() — 3 callers, 5 callees
  • new: test_audit_catches_a_dropped_non_allowlisted_heading() — 0 callers, 6 callees

Verification — 1891 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 1891 function(s) in the blast radius were not formally verified this run

Test selection

Test selection

313 of 313 test file(s) selected (100%) via static blast radius.

Escalated to a full run for safety — the selection is not trustworthy on its own (see below). CI should run the whole suite.

  • tests/test_affected_cli.py — full-run-safety
  • tests/test_affected_member_seed.py — full-run-safety
  • tests/test_agents_platform.py — full-run-safety
  • tests/test_analyze.py — full-run-safety
  • tests/test_anthropic_custom_endpoint.py — full-run-safety
  • tests/test_antigravity_install.py — full-run-safety
  • tests/test_apm_fallback_version.py — full-run-safety
  • tests/test_architecture_doc.py — full-run-safety
  • tests/test_astro_extraction.py — full-run-safety
  • tests/test_astro_import_ids.py — full-run-safety
  • tests/test_atomic_canvas_export.py — full-run-safety
  • tests/test_atomic_version_stamp.py — full-run-safety
  • tests/test_atomic_writes.py — full-run-safety
  • tests/test_backend_env_isolation.py — full-run-safety
  • tests/test_backend_extras.py — full-run-safety
  • tests/test_benchmark.py — full-run-safety
  • tests/test_benchmark_raw_graph.py — full-run-safety
  • tests/test_blade_extractor.py — full-run-safety
  • tests/test_build.py — full-run-safety
  • tests/test_build_merge_dedup_scope.py — full-run-safety
  • tests/test_build_merge_hyperedges_and_prune.py — full-run-safety
  • tests/test_build_merge_shrink_guard.py — full-run-safety
  • tests/test_builtin_global_type_refs.py — full-run-safety
  • tests/test_cache.py — full-run-safety
  • tests/test_callflow_html.py — full-run-safety
  • tests/test_cargo_introspect.py — full-run-safety
  • tests/test_cargo_missing_manifest.py — full-run-safety
  • tests/test_carried_hyperedge_remap.py — full-run-safety
  • tests/test_case_sensitive_resolution.py — full-run-safety
  • tests/test_charmap_encoding.py — full-run-safety
  • tests/test_chunking.py — full-run-safety
  • tests/test_cjs_module_extension.py — full-run-safety
  • tests/test_claude_cli_backend.py — full-run-safety
  • tests/test_claude_md.py — full-run-safety
  • tests/test_cli_broken_pipe.py — full-run-safety
  • tests/test_cli_export.py — full-run-safety
  • tests/test_cli_help.py — full-run-safety
  • tests/test_cluster.py — full-run-safety
  • tests/test_cluster_exclude_hubs.py — full-run-safety
  • tests/test_cobol_extractor.py — full-run-safety
  • tests/test_codebuddy.py — full-run-safety
  • tests/test_community_hub_labels.py — full-run-safety
  • tests/test_community_labels_skill.py — full-run-safety
  • tests/test_confidence.py — full-run-safety
  • tests/test_corrupt_graph_json.py — full-run-safety
  • tests/test_cpp_nested_and_cli.py — full-run-safety
  • tests/test_cpp_objc_cross_file_calls.py — full-run-safety
  • tests/test_cpp_preprocess.py — full-run-safety
  • tests/test_cross_extension_reexport_self_cycle.py — full-run-safety
  • tests/test_cross_language_call_resolution.py — full-run-safety
  • … and 263 more

non-code file(s) changed (graphify/skill-agents.md, graphify/skill-aider.md, graphify/skill-amp.md, graphify/skill-claw.md, graphify/skill-codex.md …) → running the full suite for safety (a code graph can't see config/fixture/data deps)

changed code file(s) with no mapped test (graphify/skill-agents.md, graphify/skill-aider.md, graphify/skill-amp.md, graphify/skill-claw.md, graphify/skill-codex.md …) — a coverage gap or a missing link — running the full suite rather than only the selected tests

Selection is safe under the controlled-regression assumption; always-run tests + a periodic full run are the backstops. Advisory — it never changes the check verdict.

Risky patterns (advisory)

  • medium no-stderr-to-stdout in tools/skillgen/gen.py:1272: stderr redirected to stdout: 'if [ -z "$PYTHON" ] && command -v uv >/dev/null 2>&1; then',
  • medium no-stderr-to-stdout in tools/skillgen/gen.py:1274: stderr redirected to stdout: 'if command -v pipx >/dev/null 2>&1; then',
  • medium no-stderr-to-stdout in tools/skillgen/gen.py:1275: stderr redirected to stdout: 'if command -v uv >/dev/null 2>&1; then',
  • medium no-stderr-to-stdout in tools/skillgen/gen.py:1278: stderr redirected to stdout: 'uv tool install --upgrade graphifyy -q 2>&1 tail -3',
  • medium no-stderr-to-stdout in tools/skillgen/gen.py:1280: stderr redirected to stdout: ' "$PYTHON" -m pip install graphifyy -q --break-system-packages 2>&1 tail -3',

Docs that may be stale (advisory)

…and 10 more.

· 1 grounded finding(s) anchored inline below; 5 more finding(s) on lines outside this diff (see the check run).

'''"$REAL_PYTHON" -c 'import os, sys; sys.executable=os.environ["FAKE_PYTHON_PATH"]; exec(sys.argv[1])' "$2"''')


def run_fragment(tmp_path, fragment, *, uv_root="", pipx_root="", launcher=b"MZlauncher", shebang=None, valid_system=False):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Health regression — run_fragment()

fans out to 6 callees (efferent coupling); 6 callers depend on it (afferent coupling).

Grounded coupling-delta finding (deterministic), not an LLM guess.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

This branch has not been deployed

No deployments
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.

Windows + uv: Step 1 pins an ephemeral uv cache interpreter, and the subcommand guard still parses graphify.exe as a shebang

1 participant