Skip to content

fix(lc): lc code 在 registry 没有默认上游时说人话,不吐 subprocess traceback - #48

Merged
LouisDM merged 1 commit into
mainfrom
fix/issue-47
Aug 12, 2026
Merged

fix(lc): lc code 在 registry 没有默认上游时说人话,不吐 subprocess traceback#48
LouisDM merged 1 commit into
mainfrom
fix/issue-47

Conversation

@LouisDM

@LouisDM LouisDM commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Closes #47

问题

registry.jsondefaultnull、且网关活着时跑 lc code

TypeError: expected str, bytes or os.PathLike object, not NoneType

cmd_codereg.get("default")None 直接塞进了 subprocess.call 的参数
列表,用户看到的是一段 CPython 内部的栈,看不出根因是「没有默认上游」。

这个状态不难到达:lc rm 掉最后一个上游时 cmd_rm 会把 default 置回 None
而网关还在跑着。网关没起时被 die("网关没起来") 提前短路,所以这条只在
「网关正常 + registry 没有默认上游」时暴露。

#12 第三梯队给 lc test / lc e2e 修过同一个形态(_targets() 的 docstring 里
写着这段历史),lc code 不走那条路,于是漏了。

改了什么

bin/lc — 新增 _default_target(reg)cmd_code 用它取 profile。

不直接复用 _targets():那个函数把 argv 当上游名解析,而 lc code 的 argv 是要
原样透传给 Codex 的参数(--sandbox read-only 之类)。失败措辞与 _targets()
对齐——空注册表指向 lc init,有上游但没选默认指向 lc use <name> 并列出可用的。

按 issue 里「顺带扫一遍同类」,多挡下一条:default 指向一个已经不存在
上游(手改 registry 之后)。它不会炸,但后果更坏——Codex 对不存在的 profile 是
静默回落到默认 model 的,表现成「以为在用 A 其实在用 B」,正是本项目在别处
一直当作缺陷处理的那个形态。

扫过的其它读 default 的地方:cmd_e2e_targets(),已经干净;gen_codex
defaultNone 时回落到排序后的第一个上游,只影响生成配置里的顶层
model =,不会传进 subprocess,行为可接受,未改动。

scripts/test-lc-commands.sh — 新增 [6f] / [6g](网关桩此时还活着,正是
这条 bug 的先决条件)。

CI 覆盖

ci.yml 已经在跑 bash scripts/test-lc-commands.sh(static job),断言随脚本
一起进 CI,不需要改 .github/

新增断言:

场景 断言
default: null 非零退出 / 输出无 Traceback / 无 TypeError / 说「没有默认上游」/ 指向 lc use <name> / 列出 alpha, beta / 压根没启动 Codex
default: "ghost" 非零退出 / 点名 默认上游 'ghost' 不在 registry 里 / 没拿不存在的 profile 去启动 Codex
upstreams: {} 指向 lc init、且建议 lc use

「无 TypeError」和「压根没启动 Codex」是这条 issue 真正的不变量——只查「非零
退出」的话,一段 traceback 也能让它绿。

验证

cmd_code 那一行改回 profile = reg.get("default"),新增断言 9 条变红
(含 argv=--profile ghost 那条,证明失效 default 确实会带着不存在的 profile
启动 Codex);改回来后全绿。

本地跑过(无 GPU / 无模型 / 无 API Key):

  • python3 -m py_compile bin/lc scripts/*.py
  • bash -n scripts/*.sh docker/entrypoint.sh
  • python3 bin/lc --help
  • bash scripts/test-lc-commands.sh → 全部通过
  • test-lc-secrets.sh / test-export.sh / test-version.sh / test-doctor-probe.sh / test-entrypoint.sh / test-codex-review-script.sh / test-project-metadata.py → 全部通过

🤖 Generated with Claude Code

registry 里 default 是 null 时(`lc rm` 掉最后一个上游就会到这个状态),
`cmd_code` 把 None 直接塞进 subprocess.call 的参数列表,用户看到的是
`TypeError: expected str, bytes or os.PathLike object, not NoneType`
和一段 CPython 内部的栈,完全看不出根因是「没有默认上游」。

#12 第三梯队给 test / e2e 修过同一个形态(`_targets()`),code 漏了。
`_targets()` 不能直接复用——它把 argv 当上游名解析,而 `lc code` 的 argv
是要透传给 Codex 的参数。所以抽了一个只取默认值的 `_default_target()`,
两条失败路径的措辞和 `_targets()` 保持一致。

顺带挡下第三条:default 指向一个已经不存在的上游(手改 registry 之后)。
它不会炸,但更坏——Codex 对不存在的 profile 是静默回落到默认 model 的。

Closes #47

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@LouisDM
LouisDM merged commit 91f9544 into main Aug 12, 2026
4 checks passed
@LouisDM
LouisDM deleted the fix/issue-47 branch August 12, 2026 02:39
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.

lc code 在 registry 没有 default 时抛 TypeError traceback——#12 第三梯队给 test/e2e 修了这个,code 漏了

1 participant