Skip to content

fix(xpkg): 0.0.47 and 0.0.48 were swallowed by a malformed 0.0.49 entry - #160

Merged
Sunrisepeak merged 1 commit into
mainfrom
fix/xpkg-0.0.49-entry
Aug 5, 2026
Merged

fix(xpkg): 0.0.47 and 0.0.48 were swallowed by a malformed 0.0.49 entry#160
Sunrisepeak merged 1 commit into
mainfrom
fix/xpkg-0.0.49-entry

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

Fixesopenxlings/xlings#486.

The file parses as valid Lua — the damage is semantic. 0.0.49's entry lost its sha256 line and closing brace, so 0.0.48 and 0.0.47 became fields of 0.0.49 instead of siblings. xlings info mcpplibs:xpkg listed 0.0.50, 0.0.49, 0.0.46, 0.0.45, and a missing version reads exactly like an unpublished one.

Mine, from #156: the reorder used a non-greedy regex that stopped at the nested url table's closing brace rather than the entry's own.

Verified by parsing with lua5.4 and enumerating keys: 9 versions before, 11 after.

`mcpplibs.xpkg@0.0.48` stopped resolving — openxlings/xlings#486. The index
file parses as valid Lua, which is why nothing caught it: the damage is
semantic, not syntactic.
0.0.49's entry lost its `sha256` line and its closing brace, so every entry
below it became a FIELD OF 0.0.49 rather than a sibling:
["0.0.49"] = {
url = { ... },
["0.0.48"] = { ... }, <- nested
["0.0.47"] = { ... }, <- nested
sha256 = "45f23...", <- 0.0.49's, orphaned down here
},
Lua reads that happily. `xlings info mcpplibs:xpkg` then listed
0.0.50, 0.0.49, 0.0.46, 0.0.45 — with 0.0.47 and 0.0.48 simply absent, and
absent reads exactly like never published.
Mine, from #156: the reorder that moved 0.0.49 to the top of the list used a
non-greedy regex, which stopped at the closing brace of the nested `url`
table instead of the entry's own. Half the entry moved; the tail stayed.
Verified by parsing the file with lua5.4 and enumerating the keys — 9 versions
before, 11 after. A structural check is the only thing that would have caught
this, since every text-level check passes.
@Sunrisepeak
Sunrisepeak merged commit 3f9f2c2 into mainAug 5, 2026
5 checks passed
@Sunrisepeak
Sunrisepeak deleted the fix/xpkg-0.0.49-entry branch August 5, 2026 17:51
Sunrisepeak pushed a commit to mcpp-community/mcpp that referenced this pull request Aug 5, 2026
真因是 **mcpp-index 的描述符**:pkgs/x/xpkg.lua 里一个格式错误的 0.0.49 条目把
0.0.47 / 0.0.48 一起吞掉了,那两个版本根本不可解析。已由 mcpplibs/mcpp-index#160
修复。
时间线是决定性的:我最后一次失败在 **17:41:31**,#160 合并在 **17:51:19** ——
失败早于修复 10 分钟。
我的归因链有两处错误,记下来:
1. 先怪 xlings 2026.8.5.2,依据是「#360(.5.1)绿、#361(.5.2)红,且两版之间
只有一个代码提交」。**相关性是真的,因果是假的** —— 那段时间 mcpp-index 的
xpkg.lua 也刚好坏了。
2. 回退 xlings 后**仍然失败**,这本该立刻推翻结论,我却先去怀疑自己新加的命令
长度校验(本地复现证明它没误报)。
内带 xlings 恢复到 2026.8.5.2;已在 openxlings/xlings#486 更正并说明。
另记一条待办:mcpp 调 xlings 用 `install_packages ... 2>/dev/null`,把对方的
报错吞了,失败只剩一行「install_packages failed (exit 1)」,分不清是「版本不存在」
还是「构建失败」。这是我误判的助力之一,应当改掉。
speak-agent added a commit to mcpp-community/mcpp that referenced this pull request Aug 5, 2026
* fix(link): 命令长度上限从架构上消掉,不再补第八个洞 (2026.8.5.4)
mcpp-index 的 opencv-module 在 windows 上 LNK1170 —— 这是同一族缺陷的**第七次**。
架构分析见 .agents/docs/2026-08-06-command-length-architecture.md。
前七次:#247(CreateProcess 32 KiB)、#261 两处(cmd.exe 8191)、#274(argv 50781
字符,失败是裸 127)、#344(POSIX MAX_ARG_STRLEN 128 KiB)、2026.8.5.3(link.exe
响应文件单行 128 KiB)、本次。共同形状:
- **发现方式永远是崩溃**,且崩在构建最后一步(本次:编译完 356 秒之后);
- **失败不可归因** —— 三种报错谁都不说是哪条边;
- **触发者从来不是「写了很长的命令」**,而是无关改动:#344 修缓存正确性、#274 改
错误粒度、本次是**把 CI 的 pin 抬过 2026.8.3.4**。
每次修完都在注释里写「构建系统不该有靠崩溃才发现的规模上限」,然后换个地方再犯。
── 为什么现在才出现 ──────────────────────────────────────────────────────
#344 给每个依赖的对象加了一层包目录(缓存正确性要求),路径因此变长 —— 同一条边
在 linux 上从 56 840 涨到 161 687 字节。而 mcpp-index 的 CI 一直 pin 在
**2026.8.3.3**,正好是那之前一版,windows 腿从没用长路径链接过。抬 pin 才第一次撞到。
── P1:让长度不再是变量 ─────────────────────────────────────────────────
2026.8.5.3 把 mcpp**自己**写的响应文件改成按行分隔。但 clang 作为 driver 时会
**再生成一个**响应文件转发给链接器,那个是单行的 —— 我们改不到它。所以 windows
上的 clang 链接改用 `-fuse-ld=lld`。
**不是 workaround**:lld 用 LLVM 的 tokenizer 解析响应文件,**没有单行上限**,消掉
的是一整类而不是把数字调大;路径也缩不短(那层包目录正是 #344 需要的);而且
**linux 与 macOS 早就在用 lld**,windows 是唯一还在用系统链接器、也是唯一有单行
上限的平台 —— 这是消除平台不一致。原生 cl.exe 保持 link.exe(那里响应文件是我们
自己写的,2026.8.5.3 已覆盖)。
── P2:上限进表(新模块 cmdlimits.cppm)──────────────────────────────────
根因是命令构造层对「这条命令要穿过哪些通道、各自上限多少」一无所知,而这份知识
只在注释和 CHANGELOG 里 —— 是「同一决策 N 处推导」的镜像:**一个关键约束在零处
被表达**。
表里除字节数还记**症状**:这一族最贵的从来不是修,是**认出**。
`Argument list too long` / `LNK1170` / 裸 `127` 三种表现毫无共同点。新增通道必须
回答「你的上限是多少」,与 directives::kTable 里「Scope 是必填字段」同一手法。
── P3:计划期拦截并指名道姓 ────────────────────────────────────────────
生成完 build.ninja 统一扫描,超限时报出边名/通道/实测字节/上限/解法/文档路径,
且发生在**还没编译任何东西**的时候。
实施中纠正两处判断:
- 校验点选「manifest 生成后统一扫描」而非「逐 emit site 插桩」—— 后者在新增一种边
时没人会想起来加,而那正是前七次的漏法;
- **phony 必须排除**,否则会误报到 **#274 的修复本身**:它为解决 argv 超限,正是把
几千个目标收进一条 phony 聚合边,而 phony 根本没有 command。走 rspfile 的规则
同样豁免。判据是「rule 有 command 且不走 rspfile」。
── 测试 ────────────────────────────────────────────────────────────────
单测 test_cmdlimits 8 条:每个通道都在表里、数字是实测的那些(MAX_ARG_STRLEN 是
32 页,不是谁都会先想到的 2 MiB ARG_MAX)、每条都记了症状与解法、诊断含边名/字节/
上限/解法/文档路径。
**没做超限 e2e**:P1 之后本地造不出自然超限的边,要造只能人为破坏 rspfile 规则,
那测的是被破坏的代码而不是真实路径。windows 的真实验证由 mcpp-index CI 承担。
全量单测 58/58;mcpp 自身 351 条边零误报。
── 其他 ────────────────────────────────────────────────────────────────
内带 xlings 升到 2026.8.5.2,.github/ 下 16 处 pin 由 check_version_pins.sh 校验同步。
(校验脚本当场抓到 7 处不同步,包括带 v 前缀的 5 处;并拦下了我一次误改 —— 全局
替换差点把它自己注释里的**历史记录** available: 2026.8.5.1 也改掉。)
* revert: 内带 xlings 回退到 2026.8.5.1 —— 2026.8.5.2 有回归
`mcpp builds & runs xlings` 集成 CI 在 2026.8.5.2 上挂掉,**重跑可复现**:
error: xlings install_packages failed (exit 1) for 'mcpplibs.xpkg@0.0.48'
归因:同一条 job 在 PR #360(xlings 仍是 2026.8.5.1)上是绿的;两个 xlings 版本
之间只有一个代码提交(xlings#481,把 runtime_deps 的版本匹配从字符串相等换成
semver 范围满足),而失败正好发生在依赖安装阶段。同一批里 cmdline / tinyhttps /
capi.lua 都装成功,所以不是全部包受影响。
已报 openxlings/xlings#486。等对方发新版再升 —— 用一个已知有回归的版本去满足
「用最新版」不是升级,是把回归带进来。
.xlings.json 的 mcpp bootstrap pin(2026.8.5.3)不受影响,不动。
本 PR 其余部分(命令长度架构)与此无关,照常。
* docs: #359 的架构设计 —— 两个缺口是同一个形状
在等 xlings 修回归的间隙做 #359 的架构分析。
**关键发现:模型早就存在,新东西没接进去。** mcpp 有一套完整的「依赖提供什么 ×
提供给谁」模型 —— `UsageRequirements` × {privateBuild, publicUsage, linkUsage},
include dirs / defines / ldflags / modules 全走它。而 #355 引入的两种新提供物
(host 工具、host 模块)**没有进这个模型**,各自硬编码成「只给发出请求的那条边」:
prepare.cppm:4113 toolEnvByConsumer[edge.consumerPackageIndex]
prepare.cppm:4016 只遍历 m->dependencies(只认 root 的直接依赖)
所以「库代用户拉起整条 codegen 工具链」在架构上不可能:工具被构建了,但环境变量
记在库的账上,消费者看不见。实测确认过,不是推断。
**根因不是少了一次传播,而是:新增一种提供物时,没有任何地方逼你回答「它怎么
传播」。** 这是「同一决策 N 处推导」的镜像 —— 一个必答问题在**零处**被表达。
缺口 B 同构:build.mcpp 的输入只有「文件内容哈希」与「环境变量」两种形态,
`hash_file` 读的是内容,于是「我的输出取决于这个目录里有哪些文件」无法表达 ——
新增 .proto 静默不生成。同样是「新增一种输入时,没地方回答它的指纹怎么取」。
设计主张:两个都收敛成「表 + 必答字段」,与 directives::kTable 同一范式,而不是
各打一个补丁。三条语义写死:传播的是可见性不是自动执行、必须显式声明不能默认
传播(否则是供应链问题)、目录指纹只取成员集合不取内容(否则一次重跑放大成全量
重编)。
两条必须一起做:只做 A 仍要逐个列 proto,只做 B 仍要写 4 条依赖。
* revert: 撤回 xlings 回退 —— 我的归因是错的,与 xlings 无关
真因是 **mcpp-index 的描述符**:pkgs/x/xpkg.lua 里一个格式错误的 0.0.49 条目把
0.0.47 / 0.0.48 一起吞掉了,那两个版本根本不可解析。已由 mcpplibs/mcpp-index#160
修复。
时间线是决定性的:我最后一次失败在 **17:41:31**,#160 合并在 **17:51:19** ——
失败早于修复 10 分钟。
我的归因链有两处错误,记下来:
1. 先怪 xlings 2026.8.5.2,依据是「#360(.5.1)绿、#361(.5.2)红,且两版之间
只有一个代码提交」。**相关性是真的,因果是假的** —— 那段时间 mcpp-index 的
xpkg.lua 也刚好坏了。
2. 回退 xlings 后**仍然失败**,这本该立刻推翻结论,我却先去怀疑自己新加的命令
长度校验(本地复现证明它没误报)。
内带 xlings 恢复到 2026.8.5.2;已在 openxlings/xlings#486 更正并说明。
另记一条待办:mcpp 调 xlings 用 `install_packages ... 2>/dev/null`,把对方的
报错吞了,失败只剩一行「install_packages failed (exit 1)」,分不清是「版本不存在」
还是「构建失败」。这是我误判的助力之一,应当改掉。
Sunrisepeak added a commit that referenced this pull request Aug 5, 2026
main 上合入了 #159(compat.websocket)与 #160(修 xpkg.lua 里那个把 0.0.47/0.0.48
一起吞掉的畸形 0.0.49 条目),分支落后并冲突。
**冲突让 CI 一个 run 都不建** —— GitHub 在 PR 有冲突时算不出 merge ref,于是
`pull_request` 触发的 workflow 完全不启动。表现是 "no checks reported",极易被
误读成 CI 挂了或 push 没生效。
冲突只在两个 README 的同一张表:main 新增了 websocket 那一行,而我改的是同表的
protobuf 那一行。两边都保留。
合并后核验:74 个描述符全部解析通过;members 同时含 protobuf-protoc 与
websocket / websocket-features。
Sign up for freeto 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.

2026.8.5.2 回归:install_packages 装不上 mcpplibs.xpkg@0.0.48(#481 的 semver 范围匹配)

1 participant

@Sunrisepeak