Repository navigation
test(project): make the no-git registry fixture actually degrade the probe - #8163
Conversation
…probe Signed-off-by: Weimr2627 <134630546+Weimr2627@users.noreply.github.com>
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
维护者运行现有 registry 边界 smoke 时,缺失 Git 的用例实际仍调用本机 Git。 旧 fixture 没拦住生产代码使用的 Popen,断言总落到健康 Git;补丁补齐拦截后,原有降级断言才真正执行。 这让已有边界保护重新具备维护价值,而不是为了增加通过数量。完整 smoke 在 base 失败、head 通过,且正常与异常路径都恢复 subprocess 全局对象。 本次只修复测试隔离,不改变生产 registry、CLI、权限或默认策略。
改动思路 / Approach
保留现有 fixture 和所有结果断言,让同一个 reject_git 在 run 与 Popen 两个本地 seam 都拒绝 Git。生产 probe 已使用可清理进程树的 Popen,因此只拦 run 无法形成缺失 Git 的前置状态。两个原对象在进入临时 patch 前保存,并在同一个 finally 恢复;成功与异常都回到可继续运行真实 Git 的状态。这个边界属于测试隔离,现有生产 owner 足够,不需要新 runtime 状态或抽象。
具体改动 / Changes
完整评审 base 54e26effd9cc958179b9fe555d50ba22d13538a6 → head 03caf71ce2e85395757803adebbd07b833858c18,仅一个现有文件 +16/−2。先读原有 fixture 的全部断言及 docs/development/good-smokes.md,规范固定版本 54e26effd9cc958179b9fe555d50ba22d13538a6。原文无编号,本次段落映射 durable-boundary-guard 与 independent-negative-oracle 均已实现:守护已交付的 registry 公私边界,负例使用原有独立断言且没有新增重复 smoke。
关键内容讲解
fixture_without_git 增加 Popen 的保存、Git 拦截与 finally 恢复;run_without_git 复用同一个命令识别 helper,非 Git 调用仍委托原函数。原有 available=False、git_unavailable、inside_worktree=False、空 risks 断言全部保留,没有跳过或放宽。源码比对确认生产 registry 与 CLI 整体未变。
对主干的风险 / Risks
未发现阻塞问题。主要风险是 monkeypatch 泄漏到后续用例:独立检查实际调用修改后的 fixture,分别验证正常路径、在 inspect 时注入异常、两函数原对象身份恢复、恢复后真实 git --version 可运行,以及再次调用 fixture,均 PASS。完整 public smoke 在 base 按原断言 FAIL、head PASS,说明新 seam 确实覆盖原来漏掉的路径。底层 probe 的五项测试两端也 PASS;它们的 which=None 快路不能代替这里的 Popen 异常路径,因此不是重复新增测试。
PASS:CI 声明的 Ruff 范围、配置 mypy 范围、变更编译、全 semantic vocabulary、diff advisory 与 public scan;native quick 的直接检查和必要选中检查通过,change-quality receipt 有效。保留一项 diagnostic FAIL:原始 maintainability ratchet 在两端同样报告未改动的 _admitted_interaction_next_cli_actions,完整失败内容一致、相关因果源码未变,独立 smoke 已覆盖本次变化;native 将其列为 inherited advisory。未轮询或等待 CI。UNVERIFIED:原生 Windows 与完整远端套件,不将本地结果说成平台或安装态资格。
我的整体评价 / Verdict
批准当前 exact head,无阻塞 finding。这是有独立仓库价值的既有 harness 修复,同作者当前批次的另一 PR 修复实际 CLI 导入边界,没有重复堆积 fixture 的证据。长程行为保持原样,只恢复可重复的保护;用户体验改善为同一条验证命令能测试其本来要测试的降级场景,无额外准备或确认。Popen 单 seam 可作为可选简化,但保留两个局部 seam 不构成维护阻塞,也无需新建后续任务。没有渲染界面变更,视觉检查不适用;原生 Windows 仍未验证。评审结论与合并权限、独立 readiness 门禁分别成立。
English verdict: APPROVE — the existing no-Git smoke now exercises the real probe and restores both subprocess seams.
Goal And Delivered Outcome
examples/project/registry-boundary-contract-smoke.pyturned red in the nightlyFull Public Smokessweep of 2026-11-05 (no issue filed for it).fix(registry): retire the git probe process tree on timeout, merged2026-11-05T14:16:13Zasc917c8936) moved the registry git probe tosubprocess.Popenso a timed-out probe can retire its whole process tree (loopx/registry.py:133_registry_git_probe,:151subprocess.Popen, withexcept OSErrorfalling through to thegit_unavailableshape). The shipped no-git fixture still patched onlysubprocess.run, so on any runner that has git installed the patch intercepts nothing:payload["git"]["available"]staysTrue,probe_statusstaysok, and the assertionpayload["git"]["available"] is Falsefails.The consequence is larger than one red smoke: the
git_unavailablefail-closed branch was no longer being exercised at all. I searched the whole repository for other no-git fixtures —grep -rn 'run_without_git|FileNotFoundError("git")|subprocess.Popen = ' --include=*.py examples tests scriptsreturns only this file — so this fixture is the sole owner of that branch, and it had silently stopped testing it.git.availableassertion; after, it printsregistry-boundary-contract-smoke ok, and the same run with the fixture restored to its pre-fix form fails again — so the restored coverage is the fixture, not a loosened expectation.loopx-project/loopx:mainat54e26effd9cc958179b9fe555d50ba22d13538a6.Onset evidence
41937099939(2026-11-04T23:52:34Z)42132115859(2026-11-05T23:47:56Z)loopx/registry.pyin that window#8115(c917c8936), which introduced thePopenseamAuthor Declaration
Implemented against
loopx/registry.pyat54e26effd9cc(_registry_git_probe,unavailable()reportingavailable=False,probe_status="git_unavailable",inside_worktree=False), and the fixture's own assertions inexamples/project/registry-boundary-contract-smoke.py:162-165.OSErrorpath, whichever seam it usesexamples/project/registry-boundary-contract-smoke.py:133-158git.available is False,probe_status == "git_unavailable",inside_worktree is False,risks == []:162-165finally, so no other check inherits the stub:157-158loopx/registry.py)loopx/registry.py:133-151_registry_git_probeto confirmPopen(notrun) is now the seam and thatOSErroris what routes to the unavailable shape; enumerated the equivalence class of no-git fixtures acrossexamples,testsandscriptsand found exactly one site, so no sibling fixture was left patched against the old seam; ran the fix twice (once as the working copy, once after restoring it byte-identically from a saved copy) and ran the negative control by writing the pre-fix file back, which fails. Deliberately did not touch the probe, did not weaken any assertion, and did not add a skip or an environment guard — the branch is supposed to be covered, not excused.Scope And Continuation
subprocess, that is a product decision inloopx/registry.pyand belongs to a separate, owner-led change.Validation
03caf71ce2e85395757803adebbd07b833858c18integrationpassedPYTHONUTF8=1 python examples/project/registry-boundary-contract-smoke.py→registry-boundary-contract-smoke ok, run twice on the tested revision.regression_paritypassedgit.availableassertion; nightly records show green 2026-11-04 and red 2026-11-05, which dates the break to#8115.staticpassedpython -m py_compile;git diff --check.unitnot_rungit_unavailablefail-closed projection path, restored to actually running. Not covered — hosted CI on this head: fork workflows wait on the maintainerapprove workflowsgate, so no required-check result is attached yet. The remaining nightly failures on this head are unrelated (context_capture_navigation_v1envelope migration, theloopx.statusfacade re-exports addressed by fix(status): restore the open_todo_items and todo_item_task_class compat re-exports #8160, and two module-size ratchet rows whose files already have open PRs).Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md). Temporary fixture directories and local tracebacks are deliberately omitted from this description.none.Signed-off-bytrailer (git commit -s).