Skip to content

Commit e53204a

Browse files
fix(pack): 宿主能力清单从解析后的图取,不再从根 manifest 取 (2026.8.10.3) (#409)
* docs: 图形栈闭合的验收实测 + 设计文档标记实施状态 验收记录只写实测,并把「验过是好的」与「本机验不了」分开写 —— 这正是本轮到处在建的 那条判据,用在自己的验收上。 ## 验到的 - **#405 在真实 imgui 模板上端到端验过**:清缓存 → 项目 a(MISS)OK → 项目 b(HIT)`Cached imgui v0.0.6 (9 units)` OK。修复前 b 必挂。 - **加载器标签在真实图形产物上验过**:`bin/b` 是 DT_RPATH,12 个 X11 库全部 DT_RUNPATH,rule E 记录 13 条全 `ok`,零 violation。 - **CI 干净机器上 192 条 e2e 全过、0 失败**(本地 25 红全部是环境)。 ## 验不了的,写清楚为什么 GPU 那一半在本机是 **NOT_EXERCISED**:宿主 GL 本身好(RTX 4080 / GL 4.6 / direct rendering yes),但这个 home 的 `<subos>/lib` 里一个 GL 都没有、`.wiring` 不存在 —— 从来没有被接线过;而共享 gcc 载荷的 specs 又被历次安装污染 (`--dynamic-linker` 指向已改名的 glibc 2.44、rpath 里约 40 条已删除沙箱路径), 这也是本地 24 条 e2e 红的单一根因,用已发布的 2026.8.8.2 逐条复现过。 ## 记下一次我自己的测量错误 我一度报告产物 rpath「指向一个不存在的版本」—— 那是 `find … | head -1` 先返回了 同目录下另一个版本造成的。**`head -1` 不是判据。** 留在文档里,因为这一轮的主题 恰恰是「判据要说清楚验的是哪一片」。 ## 设计文档的两处出入(以实施为准) - `.wiring` 增强**没有做**:主判据(mcpp 自算路径身份)可独立成立,读别人一份 条件语义未表达的记录是净增耦合。 - `discovery` **不由 mcpp 推断**:第一版按能力名推断,被既有守卫 `test_runtime_contract` 当场拦下 —— 那是把 provider 专属知识写进 mcpp。 改为声明式。**守卫是对的。** * fix(pack): 宿主能力清单从解析后的图取,不再从根 manifest 取 (2026.8.10.3) `2026.8.10.2` 的「自带 libc 的档拒绝宿主能力」只在**根工程自己声明**能力时生效。 而几乎没有应用会自己声明 `capability:opengl.glx.driver` —— 它依赖某个声明了的包, resolver 给每条需求盖上请求者身份。读根 manifest 回答的是「作者写没写」 (几乎总是没写),该问的是「解析出来的图需不需要」。 ## 实测 真实 imgui 工程,`mcpp why runtime` 明明白白列着: capability:opengl.glx.driver [run] <- compat.glfw@3.4 (required) 而修复前 `mcpp pack --mode self-contained` **照打不误**,`HOST-REQUIREMENTS` 也是空的 (而空文件会被读成「什么都不需要」)。修复后: error: --mode self-contained cannot be used by a program that needs the host to provide abi:glibc, opengl.glx.driver, x11.display. use: --mode vendored — … `--mode vendored` 正常打包,三条全部写进清单。 ## 为什么原来的测试没抓到 `216` 的 fixture **在根工程声明了能力** —— 恰恰是真实工程唯一不具备的形态。 测试通过的理由比它声称覆盖的范围窄,而窄在哪里没有被说出来:本轮反复写的就是这条, 这次轮到我自己。 `216` 已改成:能力由**依赖**声明、消费方什么都不声明,并加一条前置断言 —— 那条需求必须先出现在 `mcpp why runtime` 里,否则「两档都拒绝」可能只是因为 根本没有需求可拒,测试等于空转。 顺带验到 `discovery` 的声明式链路端到端可用:依赖描述符里写的 `discovery = "rpath-of-dispatch"` 原样出现在消费方的 `HOST-REQUIREMENTS` 里。 unit 77/77 通过。 * docs: 回填 CI 结果 —— 192 通过 0 失败,并逐条确认五条新用例真的跑了 本地 25 红的对照结论因此闭环:干净机器上 0 失败。 另外特意确认五个用例名逐个出现在 PASS 行 —— `# requires:` 里一个不认识的 token 会让用例从不运行而不报错,只看总数是看不出来的。 * test(e2e): 216 的索引路径改用 host 拼写 `00_fixture_path_hygiene` 在 Windows 上抓到的:manifest 是 mcpp 读的、不是 shell 读的, 所以写进 mcpp.toml 的路径必须是**宿主拼写** —— 一个 MSYS `/c/...` 是 Windows 打不开的路径。 这条守卫正是为此存在的(记忆里已经炸过一次),而我新加的依赖索引 fixture 又撞上了。 在 Linux 上 `host_path` 是恒等,所以这条只在 Windows 上有差别 —— 也就是说 只在本机跑是看不出来的。 * docs: 生态验收 —— 用发布出去的那份重跑一遍,并记下 .2 的那处不足 「本地构建能跑」和「用户装到的能跑」是两个断言,所以按 xlings 生态路径重做: install -> use -> 版本核对 -> imgui 双项目(含缓存命中那格) -> 标签与 rule E。 ⚠️ `xlings install` 不会自动切换已装的旧版本,它会明说;只看 install 的成功输出 就以为切过去了,是这一步最容易的误读。 顺带把 .2 与 .3 在同一个真实工程上的差别写下来:.2 的那道门读根 manifest, 而真实工程的能力来自依赖 —— 这正是本 PR 修的东西,现在有了现场对照。 --------- Co-authored-by: speak-agent <248744407+speak-agent@users.noreply.github.com>
1 parent fd91ffd commit e53204a

9 files changed

Lines changed: 478 additions & 22 deletions
Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
# 验收记录:图形栈闭合与分发档位(2026.8.10.2)
2+
3+
> 日期:2026-08-10
4+
> 被测:`feat/graphics-closure-and-distribution-tiers`(PR #408)
5+
> 本机:x86_64-linux-gnu / gcc 16.1.0 / NVIDIA RTX 4080 / 550.144.03 / X11 `:1`
6+
> 设计:`2026-08-10-graphics-closure-and-distribution-tiers-design.md`
7+
>
8+
> **本文只写实测。** 每一条结论都带命令与输出;凡未实测的一律标 **未验**,
9+
> 凡本机环境导致的一律与代码结论分开。
10+
11+
---
12+
13+
## 0. 一句话
14+
15+
**mcpp 那一半全部验到了;GPU 那一半在本机验不了 —— 而"验不了"和"验过是好的"必须分开写,
16+
这正是本轮到处在建的那条判据。**
17+
18+
---
19+
20+
## 1. #405 —— 在真实 imgui 模板上端到端验过
21+
22+
不是构造的 fixture,是 issue 里那个模板本身。它生成的 `main.cpp` 只有:
23+
24+
```cpp
25+
import imgui.core;
26+
import imgui.app;
27+
```
28+
29+
**自己不 `import std`** —— 这正是复现所需的形状。
30+
31+
```console
32+
$ rm -rf ~/.mcpp/build-cache/v1/pkg/mcpplibs/imgui@* # 强制第一次 MISS
33+
$ mcpp new a --template imgui:window && (cd a && mcpp build)
34+
Compiling imgui v0.0.6
35+
Finished dev [unoptimized + debuginfo] in 1.15s ← 缓存 MISS,一直是好的
36+
37+
$ mcpp new b --template imgui:window && (cd b && mcpp build)
38+
Cached imgui v0.0.6 (9 units) ← 缓存 HIT
39+
Finished dev [unoptimized + debuginfo] in 0.78s ← 修复前这里必挂
40+
```
41+
42+
修复前的输出(同一形状,e2e `212` 的 RED 实录):
43+
44+
```
45+
std: error: failed to read compiled module: No such file or directory
46+
std: note: compiled module file is 'gcm.cache/std.gcm'
47+
mcpplibs.cmdline: error: failed to read compiled module: Bad import dependency
48+
```
49+
50+
**判据达成。** 顺带,这条也复核了 issue 里「第一个人好、后面都坏」的形状:
51+
`a``b` 是同一个 mcpp、同一个 home、同一分钟内建的,与版本无关。
52+
53+
---
54+
55+
## 2. 加载器标签 —— 在真实图形产物上验过
56+
57+
`b` 的产物,原生解析动态段:
58+
59+
```
60+
form= executable tag= RPATH
61+
```
62+
63+
`resolution.json``loader_tags`(rule E 的记录,共 13 条):
64+
65+
| 对象 | form | required | actual | status |
66+
|---|---|---|---|---|
67+
| `bin/b` | executable | DT_RPATH | **DT_RPATH** | ok |
68+
| `bin/libX11.so` | shared_library | DT_RUNPATH | DT_RUNPATH | ok |
69+
| `bin/libXcursor.so``bin/libxcb.so`(共 12 个) | shared_library | DT_RUNPATH | DT_RUNPATH | ok |
70+
71+
**一分为二的两侧都验到了**:可执行 RPATH、12 个库全部 RUNPATH,零 violation。
72+
73+
产物的 DT_RPATH 内容,四条全部存在(逐条核过):
74+
75+
```
76+
<store>/xim-x-glibc/2.39/lib64
77+
<store>/xim-x-gcc/16.1.0/lib64
78+
<store>/compat-x-glx-runtime/2026.08.08/mcpp_generated/glx_runtime/lib ← 52 个文件
79+
$ORIGIN
80+
```
81+
82+
> ⚠️ **一次我自己的测量错误,记在这里。** 我一度报告第三条"指向一个不存在的版本"
83+
> ——那是 `find … | head -1` 先返回了同目录下的 `2026.06.03` 造成的。
84+
> `2026.08.08` 存在且完整。**`head -1` 不是判据。**
85+
86+
---
87+
88+
## 3. GPU 那一半:本机 **NOT_EXERCISED**,不是 PASS 也不是 FAIL
89+
90+
程序能起来,窗口创建失败:
91+
92+
```console
93+
$ ./b
94+
imgui.app: window creation failed: GLFW error 65545 (GLX: Failed to find a suitable GLXFBConfig)
95+
```
96+
97+
**宿主 GL 本身是好的** —— 所以这不是"这台机器没有显卡":
98+
99+
```console
100+
$ DISPLAY=:1 glxinfo -B
101+
direct rendering: Yes
102+
OpenGL vendor string: NVIDIA Corporation
103+
OpenGL renderer string: NVIDIA GeForce RTX 4080/PCIe/SSE2
104+
OpenGL core profile version string: 4.6.0 NVIDIA 550.144.03
105+
```
106+
107+
派发与 vendor 也都在载荷里(`libGLX_nvidia.so.0 → 550.144.03`,与宿主驱动同版本)。
108+
109+
**但这台机器的载荷是被污染的**(见 §5),而 `<subos>/lib` 里一个 GL 都没有、
110+
`.wiring` 记录不存在 —— 也就是说**这个 home 从来没有被接线过**
111+
112+
> **所以本机的诚实判决是 `NOT_EXERCISED`**
113+
> mcpp 侧的三条职责(标签对、路径通且存在、不打包不该打包的)全部验到;
114+
> 「桥有没有搭上宿主驱动」需要一台接过线的机器,本轮**未验**
115+
> 这正是设计 §6.3 写的:那部分是 `xlings doctor` 的事,mcpp 该报 `NOT_EXERCISED`
116+
117+
`mcpp why runtime` 的实际输出(逐字),把 L3 的缺口直接摆出来:
118+
119+
```
120+
requirements:
121+
- capability:opengl.glx.driver [run] <- compat.glfw@3.4 (required)
122+
- capability:opengl.glx.driver [run] <- compat.glx-runtime@2026.08.08 (required)
123+
124+
providers:
125+
- opengl.glx.driver -> compat.glx-runtime@2026.08.08 [index+compat@2026.08.08]
126+
- x11.display -> compat.glx-runtime@2026.08.08 [index+compat@2026.08.08]
127+
artifacts:
128+
(not declared by the environment — nothing to verify)
129+
note: a resolved provider with no artifact is UNVERIFIED,
130+
not verified-good
131+
validation: pass (source post_link)
132+
- bin/b: pass ← 13 个对象逐条 pass(rule E + 闭包)
133+
134+
provider and host-service re-diagnostics are owned by xlings; run `xlings doctor`
135+
```
136+
137+
**一个 provider 按名字解析成功、身后一个物都没有** —— 这就是设计里那句
138+
「provider 有名无物,所以没有任何东西可以校验」的现场。
139+
身份判决因此无事可做,而它**说出来了**,没有伪装成 `(none declared)`
140+
那种可以被读成"没问题"的措辞。
141+
142+
---
143+
144+
## 4. 分发档位
145+
146+
|| 判据 | 结果 |
147+
|---|---|---|
148+
| `vendored` | bundle 内**每个** ELF 无构建机 store 路径;可执行 RPATH、库 RUNPATH | ✅ e2e `215` |
149+
| `self-contained` | 有 run 期能力需求时 plan 期硬拒并给出 `vendored` 出路 | ✅ e2e `216` |
150+
| `static` | 同上 | ✅ e2e `216` |
151+
| `self-contained`(无能力需求) | 仍然可打包、`run.sh` 可运行 | ✅ e2e `30` |
152+
153+
`215` 的 RED 实录(撤掉 F2 之后),正是设计里描述的那条:
154+
155+
```
156+
lib/libgcc_s.so.1 shared_library RUNPATH
157+
<store>/xim-x-glibc/2.39/lib : <store>/xim-x-gcc/16.1.0/lib64
158+
FAIL: bundled object still points at the BUILD MACHINE's store
159+
```
160+
161+
**一个真回归,由 `30_pack_modes` 抓到并已修**:第一版 F2 把 **动态加载器本身**
162+
也 patchelf 了。它不是被搜索的库,它是执行搜索的程序 —— 改它让 `self-contained`
163+
`main` 之前段错误。修法是把加载器排除在重写之外。
164+
165+
---
166+
167+
## 5. 本机环境的三个缺陷(与本 PR 无关,但解释了本地 e2e 的红)
168+
169+
本地 e2e:**183 通过 / 25 失败 / 8 跳过**
170+
**25 条里 24 条用已发布的 `2026.8.8.2` 逐条复现** —— 同一个根因,三种表现:
171+
172+
### 5.1 共享 gcc 载荷的 specs 被历史安装污染
173+
174+
```
175+
--dynamic-linker → <store>/xim-x-glibc/2.44/lib64/ld-linux-x86-64.so.2 ← 该目录已被改名为 2.44.aside
176+
rpath → 约 40 条 /tmp/tmp.XXXXXX/mcpphome/... (全部来自已删除的 e2e 沙箱)
177+
```
178+
179+
后果:每一个 `build.mcpp` helper 的 PT_INTERP 指向不存在的加载器,
180+
`posix_spawnp` 返回 **ENOENT**,报成 `exited with 127`
181+
这打掉了 112 / 124 / 125 / 179 / 181 / 186–194 全部。
182+
183+
> **这是设计 §3.1「specs 是共享可变状态,不能承载契约」的现场证据**,
184+
> 也正是 `mcpp-clean-link.specs` 存在的原因 —— mcpp 自己的构建因此不受影响,
185+
> **独立编译的 `build.mcpp` helper 走不到那条防线**。这条值得单独跟。
186+
187+
### 5.2 `-print-search-dirs` 指向另一个工程的 subos
188+
189+
```
190+
libraries: … /home/speak/workspace/github/openxlings/xim-pkgindex-fromsource/.xlings/subos/default/lib/ …
191+
```
192+
193+
与本工程毫无关系。同一族。
194+
195+
### 5.3 xim binutils 的 shim 指向已删除的会话目录
196+
197+
```
198+
[error] xlings: executable 'as' not found
199+
[error] path: /tmp/claude-1000/…/accept-run1/home/.mcpp/registry/data/xpkgs/xim-x-binutils/2.42/bin
200+
```
201+
202+
与记忆里 #293 同族。**因此本轮所有 ELF 判据都用原生解析,不 shell out** ——
203+
一个坏掉的 `readelf` 会让标签断言静默空转。
204+
205+
**CI 是这部分的真判据**(干净机器,四平台)—— 结果回填:
206+
207+
```
208+
e2e 1/2 (linux x86_64): 95 passed, 0 failed, 13 skipped
209+
e2e 2/2 (linux x86_64): 97 passed, 0 failed, 11 skipped
210+
```
211+
212+
**192 通过、0 失败**,并且五条新用例逐条确认真的跑了(不是被 `# requires:` 跳过):
213+
214+
```
215+
PASS: 212_cached_dep_std_is_ordered.sh
216+
PASS: 214_executable_carries_dt_rpath.sh
217+
PASS: 216_selfcontained_refuses_host_capability.sh ← shard 1
218+
PASS: 213_build_after_test_is_not_the_test_graph.sh
219+
PASS: 215_pack_has_no_build_machine_paths.sh ← shard 2
220+
```
221+
222+
> **这一条特意查了**:`# requires:` 里一个不认识的 token 会让用例**从不运行**
223+
> 而不报错(记忆里 `65_*` 就这样从未在 CI 跑过)。所以不是看总数,
224+
> 是看这五个名字逐个出现在 `PASS:` 行上。
225+
226+
18 项 PR 检查全绿,含 macOS 与 Windows —— 也就是说加载器契约没有扰动非 ELF 平台。
227+
228+
---
229+
230+
## 6. 未验 / 明确不做
231+
232+
|| 状态 |
233+
|---|---|
234+
| 图形程序真正拿到 GPU | **未验**,需要一台接过线的机器 |
235+
| pack 产物在没有 xlings 的机器上运行 | **未验**,需要第二台机器;e2e 只能验到「产物里没有构建机路径」 |
236+
| rule E 转硬门禁 | **不做**,结论只来自一台 NVIDIA/X11/x86_64 机器(与 xlings E5 同一笔欠账) |
237+
| `.wiring` 读取 | **不做**,主判据已改为 mcpp 自算;见设计 §2.1 |
238+
239+
---
240+
241+
---
242+
243+
## 7. 生态验收(用**发布出去的**那份,不是本地构建)
244+
245+
发布之后按生态路径重做了一遍 —— 因为「本地构建能跑」和「用户装到的能跑」是两个断言。
246+
247+
```console
248+
$ xlings update && xlings install mcpp@2026.8.10.2 -y
249+
✓ xim:mcpp@2026.8.10.2 done
250+
xim:mcpp@2026.8.10.2 installed, but 'mcpp' still resolves to 2026.8.8.2
251+
$ xlings use mcpp 2026.8.10.2
252+
[xlings] mcpp -> 2026.8.10.2 (xim:mcpp 2026.8.8.2 -> 2026.8.10.2)
253+
$ mcpp --version
254+
mcpp 2026.8.10.2
255+
```
256+
257+
> ⚠️ `install` **不会**自动切换已装的旧版本,它会明说。只看 `install` 的成功输出
258+
> 就以为切过去了,是这一步最容易的误读。
259+
260+
用这个生态装出来的 mcpp 重跑图形验收:
261+
262+
|| 结果 |
263+
|---|---|
264+
| imgui 模板 A(缓存 MISS) ||
265+
| imgui 模板 B(缓存 **HIT** —— #405 的那一格) |`Cached imgui v0.0.6 (9 units)` |
266+
| 产物标签 | ✅ 可执行 `DT_RPATH`,11 个库全 `DT_RUNPATH`,rule E 零 violation |
267+
| `artifacts` | `[]` —— 环境未声明,报 `NOT_DECLARED`(见 §3) |
268+
269+
### 顺带验到 2026.8.10.2 的一个不足(已由 2026.8.10.3 修)
270+
271+
同一个 imgui 工程,`mcpp pack --mode self-contained`:
272+
273+
```console
274+
# 生态里的 2026.8.10.2
275+
Packed b-0.1.0-x86_64-linux-gnu-bundle-all.tar.gz ← 照打不误,也没有 HOST-REQUIREMENTS
276+
277+
# 带 .3 修复的构建
278+
error: --mode self-contained cannot be used by a program that needs the host to
279+
provide abi:glibc, opengl.glx.driver, x11.display.
280+
use: --mode vendored — …
281+
```
282+
283+
原因:`.2` 的那道门读的是**根 manifest**,而这条能力来自依赖
284+
(`capability:opengl.glx.driver <- compat.glfw@3.4`)。**真实工程恰恰是这个形态。**
285+
`216` 的 fixture 当时在根工程声明能力,所以它通过的理由比它声称的范围窄 ——
286+
这一轮反复写的那条判据,这次落在自己头上。已改成依赖声明 + 前置断言。
287+
288+
### 身份判决的渲染也验了(环境没声明,就自己造一个)
289+
290+
符号链接仍指向 `0.1.1`、声明 `xim:vendor@0.1.2`:
291+
292+
```
293+
artifacts:
294+
- library …/current/lib/libvendor.so <- … [xim:vendor@0.1.2; identity=mismatch]
295+
^ STALE BINDING: this resolves into a different version than the one declared.
296+
```
297+
298+
正是设计里描述的那一格,而且是纯路径事实 —— 不需要认识 GL。
299+
300+
## 附:今天重复了三次的同一条
301+
302+
> **要说"验过了",先说清楚验的是哪一片。**
303+
304+
- e2e 25 红里 24 红是环境的 —— 不逐条对照已发布二进制,就会把它们当成回归,
305+
或者更糟,当成"本来就红"而放过其中真的那一条(`30_pack_modes`)。
306+
- `find | head -1` 让我报了一个不存在的缺陷。
307+
- 宿主 `glxinfo` 好、程序拿不到 context —— 只报前者是撒谎,只报后者也是。

.agents/docs/2026-08-10-graphics-closure-and-distribution-tiers-design.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,16 @@
88
> (三层故障的分层)、xlings `2026-08-10-graphics-stack-design.md`(标签契约与 E1–E5)
99
>
1010
> 本文所有"已验"结论都在本机跑过,命令与输出在正文里。凡未实测的一律标 **未验**
11+
>
12+
> **实施状态(2026-08-10):A–J 全部已实施,PR #408,版本 `2026.8.10.2`**
13+
> 实施计划见 `2026-08-10-graphics-closure-implementation-plan.md`,
14+
> 验收实测见 `2026-08-10-graphics-closure-acceptance.md`
15+
> 与本文的两处出入,以实施为准:
16+
> - **§2.1 的 `.wiring` 增强没有做**。主判据(mcpp 自算路径身份)已实施并可独立成立;
17+
> 读别人一份条件语义未表达的记录属于净增耦合,收益不足以抵。
18+
> - **§3.F 的 `discovery` 不由 mcpp 推断**。第一版按能力名推断,被既有守卫
19+
> `test_runtime_contract` 当场拦下 —— 那是把 provider 专属知识写进 mcpp。
20+
> 改为声明式(`[[runtime.requirements]] discovery`),未声明报 `unknown`**守卫是对的。**
1121
1222
---
1323

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,29 @@
33
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
44
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)
55
6+
## [2026.8.10.3] — 2026-08-10
7+
8+
### 修复
9+
10+
- **宿主能力清单从「解析后的图」取,不再从根 manifest 取。** `2026.8.10.2` 引入的
11+
「自带 libc 的档拒绝宿主能力」只在**根工程自己声明**能力时生效 —— 而几乎没有应用
12+
会自己声明 `capability:opengl.glx.driver`,它依赖某个声明了的包(glfw / SDL 封装 /
13+
GL runtime),resolver 会给每条需求盖上请求者身份。读根 manifest 回答的是
14+
「作者写没写」(几乎总是没写),而该问的是「解析出来的图需不需要」。
15+
16+
实测:一个真实 imgui 工程的 `mcpp why runtime` 列着
17+
`capability:opengl.glx.driver [run] <- compat.glfw@3.4 (required)`,
18+
`mcpp pack --mode self-contained` **照打不误**。修复后它正确拒绝,并列出
19+
`abi:glibc, opengl.glx.driver, x11.display` 三条;`--mode vendored` 正常打包
20+
并把三条写进 `HOST-REQUIREMENTS`
21+
22+
同一处也修好了 `mcpp pack``HOST-REQUIREMENTS`:此前对真实工程是空的
23+
(空文件会被读成「什么都不需要」,而它现在根本不写空文件)。
24+
25+
**为什么原来的测试没抓到:它的 fixture 在根工程声明了能力 —— 恰恰是真实工程
26+
唯一不具备的形态。** `216` 已改成依赖声明、消费方什么都不声明,并加了一条
27+
前置断言:那条需求必须先出现在 `mcpp why runtime` 里,否则测试等于什么都没验。
28+
629
## [2026.8.10.2] — 2026-08-10
730

831
图形栈闭合与分发档位。完整设计与实施计划见

mcpp.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mcpp"
3-
version = "2026.8.10.2"
3+
version = "2026.8.10.3"
44
description = "Modern C++ build & package management tool"
55
license = "Apache-2.0"
66
authors = ["mcpp-community"]

0 commit comments

Comments
 (0)