Skip to content

fix(runtime): diagnose the interpreter or runner actually selected - #4647

Merged
huangruiteng merged 1 commit into
mainfrom
codex/runtime-probe-20260917
Sep 17, 2026
Merged

huangruiteng merged 1 commit into
mainfrom
codex/runtime-probe-20260917

Conversation

@huangruiteng

Copy link
Copy Markdown
Collaborator

A missing SDK in one interpreter must not look like a machine-wide runtime outage. The managed binding now identifies an interpreter import probe separately from an injected runner; runner availability no longer falsely claims the SDK was probed. Chat uses its existing failure gate to direct operators to loopx doctor in the service environment and installation into that same environment.

Replaces #4623 and absorbs the runtime-test seam from #4620. The manager and Turn continue to share one binding resolver. Host selection, credentials, refusal precedence and effects are unchanged; no paths or credential values enter the added probe data. No frontend editor change is needed: the existing Chat error gate already renders the supplied next action, and this change adds no configuration.

Validation: 108 binding/manager/Turn tests; managed-executor, operator-flow and credential API smokes; 24 baseline/candidate combinations preserving every pre-existing binding field. Two actual isolated Python environments prove SDK-absent and SDK-present readbacks using the pinned SDK. Ruff, configured mypy, public-boundary checks, exact-scope quality qualification and standard premerge pass. These are import/readiness checks, not provider-authentication or model-call qualification.

Refactor pass: remove the misleading probe wrapper and reuse the existing environment adapter and Chat error path. Python owns interpreter probing; no second state-machine authority is introduced.

Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

Reviewed exact head: cddb58143d29d07e7cc91cf29962ac9c5d90309d (fix(runtime): scope SDK diagnostics to the actual execution source).

动机

一个解释器里缺 DeepSeek Harness SDK,看起来和「整机运行时不可用」是同一句话 dsh_runtime_unavailable;而当注入 runner 时,可用性判定根本没做导入探测却照样报可用。Chat 的拒绝文案又只说 pip install,没说装到哪个环境。后果是操作者在错误的解释器里装 SDK,装完仍然被拒,循环往复。动机成立。

改动思路

不新增探测路径,而是在既有的共享 resolver 上把「这个判定是关于什么的」显式说出来:managed 执行器返回 runtime_probe{schema_version, scope, module, available},scope 区分 probing_interpreter(真的 find_spec 了 deepseek_harness)与 configured_runner(注入 runner,module: None,没有探测);非 managed 执行器同样带这个字段但为 None,这样读者不必靠「字段是否存在」分支。Chat 侧只改文案,走既有错误门指向服务环境。

具体改动

9 个文件、+160/-16,生产改动约 30 行:

  • loopx/control_plane/turn_driver/host_binding.py:新增 MANAGED_RUNTIME_PROBE_SCHEMA_VERSION、RUNTIME_PROBE_SCOPE_INTERPRETER,managed 分支返回 probe,其余分支返回 None。
  • loopx/chat_manager.py:manager_channel_binding 增加可选 module_probe 并透传,把 probe 投影进 channel binding。
  • loopx/chat_agent.py:dsh_runtime_unavailable 的 next action 改为「服务解释器 / loopx doctor / python.executable / 在同一个环境安装 / 重启」,且不含解释器路径。
  • docs/integrations/deepseek-harness-connector.md:写明 probe 语义与「可用性只对回答的那个解释器或 runner 成立,且不证明 provider 鉴权」。
  • 三个 smoke 与两个测试文件:断言 probe 作用域、单机无关性(credential smoke 注入 _runtime_installed)与公共安全(序列化 probe 无路径、无凭据值)。

我复核的关键点(都在这个 head 上自己跑过):

  • probe 矩阵(直接调用):无 runner + probe False → scope=probing_interpreter, module=deepseek_harness, available=False,unavailable_reason=dsh_runtime_unavailable;无 runner + probe True → available True;dsh_runner_configured=True → scope=configured_runner, module=None, available=True;individual host → runtime_probe 为 None。
  • pytest -q tests/test_manager_channel_binding.py tests/test_turn_managed_executor_binding.py tests/test_loopx_turn_driver.py tests/test_loopx_turn_executor.py tests/test_loopx_turn_host_failure.py tests/test_loopx_turn_managed_step.py tests/test_chat_manager_context.py tests/test_chat_manager_inspection.py → 237 passed。
  • examples/loopx-turn-managed-executor-binding-smoke.py、examples/loopx-managed-turn-operator-flow-smoke.py、examples/operator-provider-credential-smoke.py → 全部 ok/exit 0。
  • 拒绝优先级未变:缺 SDK 仍 dsh_runtime_unavailable,缺凭据仍 operator_credential_unconfigured,run-once --execute 仍 fail-closed。

遗留问题(非阻塞,P3)

PR body 的验证段写「两个真实隔离 Python 环境证明 SDK 缺失/存在的 readback」。仓库里提交的 smoke 实际是用 sys.meta_path 的 _HarnessRuntimeFinder 伪造运行时存在性,没有创建环境或拉起第二个解释器。行为本身仍有证据(注入 probe 的矩阵 + 测试),但最吸引这次改动的那个多环境场景没有可复现的仓内检查。最小修法:把两环境 readback 落成 smoke 的一步,或在正文里注明它是人工证据、仓内覆盖靠注入 probe。

对主干的风险

改动面是「一个附加字段 + 一段操作者文案」。最强回归是「注入 runner 却被读成探测过 SDK」,这正是新字段要消掉的信息缺失,现在由 smoke 与测试双向钉住(available True/False 都断言 scope 与 module)。公共/私有边界我也看了:probe 里只有 schema 版本、scope 字符串、模块名与布尔值,smoke 显式断言序列化结果不含 / 与凭据值,解释器路径留给本地 loopx doctor。未验证维度:没有对真实 managed host 或 provider 发起调用(PR 明确把范围限定为 import/readiness),多环境场景见 P3。回退成本一个 commit。

我的整体评价

结论 APPROVE。它把「进程级答案」与「机器级事实」分开,并使用既有 resolver 而不是再造一条探测路径;Chat 的失败不再是无法行动的 pip install,而是点名服务环境、python.executable 与同环境安装。我用四态矩阵、237 个测试与三个 smoke 独立复核了行为与公共安全边界。唯一 P3 是正文引用的多环境证据不可复现。

English verdict: APPROVE - exact head cddb581; the managed executor binding now states what its availability verdict is a claim about (scope probing_interpreter with module deepseek_harness, or configured_runner with module null), the field is an explicit null for every non-managed executor, and the Chat refusal names the service environment, loopx doctor and python.executable. I verified the four-way probe matrix directly, ran 237 binding/manager/Turn tests and three smokes (all ok), and confirmed host selection, credential gating and refusal precedence are unchanged. One non-blocking P3: the PR body's two-isolated-interpreter evidence is not reproducible from the repository, since the committed smoke injects a meta_path finder instead.

@huangruiteng
huangruiteng merged commit 36cf2d8 into main Sep 17, 2026
29 checks passed
@huangruiteng
huangruiteng deleted the codex/runtime-probe-20260917 branch September 17, 2026 13:32
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