Repository navigation
fix(claude): reject unsupported Python launcher candidates - #7886
Conversation
Signed-off-by: BigDataDZ <76271875+BigDataDZ@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
1) 问题定义(为什么改、要解决什么)
- 修复 Claude Goal Mode 安装脚本(
loopx/claude_goal_mode/scripts/install.py)在探测python3/python解释器时仅检查python -c ""退出码为 0、未校验 Python>= 3.11最低版本要求的问题(当宿主PATH中python3指向老旧的 Python 3.8/3.10 而python指向 3.11+ 时会导致写入的 Hook 静默运行失败)。
2) 改动摘要(按模块分组)
- 解释器最低版本探针 (
loopx/claude_goal_mode/scripts/install.py):在_launches_python中执行import sys; raise SystemExit(sys.version_info < (3, 11)),确保被选中的解释器满足 Python 3.11+ 要求。 - 参数化测试 (
tests/test_claude_goal_install_python_launcher.py):新增 Python(3, 8)/(3, 10)/(3, 11)/(3, 12)参数化探针测试与跳过旧版python3回退至合标python的单元测试。
3) 逐点审阅结论(架构、语义、正确性、测试、风险)
- 正确性:探针轻量且向后兼容,准确拦截低于 3.11 的解释器候选。
4) 建议修改项(分 P0/P1/P2,带文件路径和行号)
- 无阻塞项。
5) 最终结论(Verdict)
Approved — ready to merge once CI completes (exact head bef833d415dda712f58e525a9ad5c67d4468b32a verified).
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max
动机 / Motivation
安装 Claude 适配器的用户会在 PATH 先出现旧 Python 时遇到此问题。 旧实现把能启动的 Python 3.10 当作合格解释器;新实现执行最低版本检查,失败就继续找 python 或使用当前安装器解释器。 对照复现旧版本被错误选中,并确认修复后拒绝 3.8/3.10、接受 3.11/3.12,且能回落到兼容 python。 边界是现有安装器的解释器选择,不证明真实 Claude 会话或自动启用 hardening。
改动思路 / Approach
最低版本是现有包要求,放在既有候选解释器探针中可让所有命令生成消费者共同使用;无需新增 bootstrap owner。 当前 PR 仅修改安装器共同解释器探针,并补充五个回归情形。 不修改会继续选择已知不支持的解释器;在每个 hook builder 再判断会复制规则;复用现有 _launches_python 并保留当前安装器回落是最小完整修复。 正向路径从 _python_cmd → hardening_block / command generation 进入既有 owner,旧 python3 被拒绝,返回 python。;异常路径保留 原安装器的候选回落及配置恢复逻辑,不接受失败探针;保持 sys.executable 回落、原 shell quoting 和默认 hardening 关闭。。本次完整审查当前 head,没有继承先前模板审查的通过结论。
具体改动 / Changes
2 files +47/-3,生产变化是一个已有 probe 的子进程表达式和准确注释,新增测试不冻结私有环境。 候选有效性仍归 _launches_python,优先级和回落仍归 _python_cmd;没有平行规则。 没有新增持久化事实、分类字段或第二份 authority;沿用现有 canonical input。
关键代码讲解
-
_launches_python:判断候选是否真的启动受支持解释器。 由空程序改为当前包下界检查;异常处理和 timeout=10 保留。 输入为具体可执行文件路径,关键条件是exit code 0 才合格。OSError/SubprocessError 返回 False -
_python_cmd:为所有生成命令选择解释器。 顺序和 sys.executable 最终回落未变。 输入为python3/python PATH 及当前安装器,关键条件是仅合格候选返回。跳过旧候选而继续搜索
规格为 pyproject.toml,spec_revision 867615e2c3aa2a32516a71d46f11a20d6fcb3289;requires-python >=3.11 是现有下界;既有 _python_cmd 顺序和 sys.executable 回落是兼容边界。
- Python floor:implemented。候选必须能运行 Python >=3.11。 对应
_launches_python;五个配对真实子进程 oracle。 - candidate fallback:implemented。旧 python3 不得阻断兼容 python;两者不可用时保持当前解释器回落。 对应
_python_cmd;完整安装器套件 52 passed / 3 platform skips。
对主干的风险 / Risks
最强风险是探针只改了字面量却破坏候选回落,或将无效路径写进所有后续命令。 为区分修复与无效测试,我对不可变 base/head 执行相同输入:base 3 个 oracle 失败、2 个通过:3.8/3.10 被错误接受,选择器没有跳过旧 python3。;head 五个 oracle 全部通过;完整模块 52 passed / 3 skipped。。只 monkeypatch subprocess 返回 0 会让任何程序被视为支持,因此额外实际执行探针并控制 reported version,避免测试只复述表达式。 已比较两个合法版本、两个非法版本和候选回落;没有状态投影、分页或未来 subject 覆盖变化。
- PASSED:
same five controlled-version base/head probes— base 3 oracle failures;head 全通过。 - PASSED:
full installer module— 52 passed / 3 platform skips;未声明原生 Windows 完整安装。 - PASSED:
uv run --extra test python -m pytest -q tests/test_claude_goal_install_python_launcher.py; git diff --check 867615e2c3aa2a32516a71d46f11a20d6fcb3289...HEAD— 52 passed / 3 skipped;完整 diff read。
语义与 CI 对齐
复用既有 Python >=3.11 安装约束;不新增共享 vocabulary,不改变既有 shell 策略。 没有新增 opt-in claim 或开关;既有 adapter 的激活保持原状。完整相关套件保留未配置、拒绝及异常分支。 独立证据覆盖当前 changed invariant;远端 CI 的其他状态与合并 readiness 另行保留,没有把检查颜色当作正确性证明。 版本矩阵使用真实子进程和受控 sys.version_info,未安装 Python 3.8/3.10,也未开启真实 Claude 会话;本机 3 个平台测试跳过。
我的整体评价 / Verdict
APPROVE:当前完整 diff 在所声明边界内达到 goal_achieved;long_horizon 为 improved,既有 hook/statusline 的重复调用不再被已知不支持的解释器持续阻断;运行时策略和恢复未变。 user_experience 为 improved,授权安装后生成的命令直接使用受支持解释器,减少手工改配置。 本次检查的是既有安装命令或进程发现 owner,没有渲染页面、布局或设置交互变化;visual_review not_applicable。 最低版本是现有包要求,放在既有候选解释器探针中可让所有命令生成消费者共同使用;无需新增 bootstrap owner。 当前 PR 仅修改安装器共同解释器探针,并补充五个回归情形。 已复用共同探针;不需要为两个 PATH 名字新增发现框架。 不把本次 review 当作合并授权。
English verdict: APPROVE — bef833d415dda712f58e525a9ad5c67d4468b32a; the installer rejects unsupported runnable Python candidates while retaining fallback and command generation. Five paired child-process oracles pass at head; 52 local tests pass, with 3 platform skips.
Goal And Delivered Outcome
_launches_pythonaccepts any interpreter that exits successfully for an empty program. A runnable Python 3.8/3.10 on PATH can therefore be baked into/loopx, PreToolUse and statusline commands even though LoopX requires Python 3.11+.python3preference,pythonfallback, dead-alias handling and the executing installer's fallback are preserved.mainat867615e2c3aa2a32516a71d46f11a20d6fcb3289. No new roadmap acceptance is claimed.Author Declaration
Implemented against
pyproject.toml'srequires-python = ">=3.11"and the existing installer selection contract at the base above.python3to compatiblepython_python_cmdconsumer, package Python requirement and existing shell execution regressions. The probe runs in the candidate interpreter, with the same bounded timeout and failure handling. No new interpreter installation or duplicate control-plane decision owner.Scope And Continuation
Complete within this existing opt-in Claude adapter install path. No hooks are enabled automatically, no model is invoked and no host authorization changes. This changes the default selection of an unsupported PATH candidate during an authorized install; compatible candidate ordering is unchanged. It does not certify an installed Claude Code session or availability of older Python distributions.
Bounded refactoring pass: keep the existing common interpreter probe serving the existing command builders; no extra abstraction or parallel discovery mechanism is needed.
Validation
regression_paritypassedunitpassedtests/test_claude_goal_install_python_launcher.py: 44 passed, 11 skipped on native Windows Python 3.12; existing platform/host-shell skips retained. Generated-command tests use disposable settings/projects.staticpassedintegrationnot_runA separate baseline diagnostic found the existing global subprocess UTF-8 guard failing on the Antigravity adapter and three native installation tests failing at long-path release copying. Those are independent owning paths; they are not waived or claimed fixed here.
Frontend / Visual Evidence
UI impact: none. Existing adapter install/command generation only; no frontend or Lark capability is added.
Type of Change
LoopX Area
Technical Direction
Existing Python bootstrap/provider boundary. No new capability, provider, shared state or TypeScript decision owner.
Shared-authority RFC fixture impact
N/A: no authority/provider-routing schema or production-scale fixture changes.
Boundary Checklist