diff --git a/.agents/docs/2026-08-30-graphics-stack-coverage-design.md b/.agents/docs/2026-08-30-graphics-stack-coverage-design.md index d1e6bb9..4bcb4e8 100644 --- a/.agents/docs/2026-08-30-graphics-stack-coverage-design.md +++ b/.agents/docs/2026-08-30-graphics-stack-coverage-design.md @@ -1,6 +1,6 @@ # mcpp 图形栈:从「能跑通」到「能开发」的覆盖面设计 -Date: 2026-08-30 · 前置:[`2026-08-30-gbm-cross-repo-closed-loop-plan.md`](2026-08-30-gbm-cross-repo-closed-loop-plan.md) §19/§20 · 状态:待 review +Date: 2026-08-30 · 前置:[`2026-08-30-gbm-cross-repo-closed-loop-plan.md`](2026-08-30-gbm-cross-repo-closed-loop-plan.md) §19/§20 · **状态:已实现并闭环验证(v1.0,见 §11 交付总账)** ## 0. 这份文档解决什么 @@ -930,3 +930,83 @@ xim#732 加 `XKB_CONFIG_ROOT` 那天就出了回归(xim#733 修):`mesa` 一直 G6 仍是需要决策的:合成器可以在「已有 DRM master」的前提下开发(从 TTY 直接启动、或 `SEATD_SOCK`),把 session 管理留到最后。 + +--- + +## 11. 交付总账(v1.0) + +### 11.1 完整变更集 + +八个 PR,两个仓,全部已合入: + +| 仓 | PR | 内容 | 性质 | +|---|---|---|---| +| mcpp-index | #298 | libinput 测试成员 + 描述符四个 bug | 功能 | +| mcpp-index | #301 | 沙箱脚本纳入输入链 / RMLVO / quirks 断言 + 文档 | 验证 | +| xim | #731 | nvidia-gl-host-link 声明 Vulkan ICD | 功能 | +| xim | #732 | xkeyboard-config 键盘布局数据集 | 功能 | +| xim | #733 | mesa 只声明自己填的路径 | **#732 的回归** | +| xim | #734 | libinput-quirks 设备 quirks 数据集 | 功能 | +| xim | #735 | consumer_envs 跳过标量 + `libs/**` 纳入 CI | **#732/#734 的回归** | +| xim | #736 | publish-artifact 也看 `libs/**`,并把自己列进 paths | **#735 的交付缺口** | + +### 11.2 为什么不是单 PR —— 两条硬约束和一处我的失误 + +**硬约束一:跨仓。** mcpp-index 打包代码,xim 发布数据目录与运行期发现变量;一个 +GitHub PR 无法跨两个仓库。这个切分不是选择,§10.9 论证过它是两个索引各做各建模的 +事 —— 而**正是这条约束**决定了这套东西必须至少两个 PR。 + +**硬约束二:发布顺序。** #301 的沙箱脚本从**已发布索引**解析 `compat.libinput` +(它只声明一个索引键,见脚本注释),所以它只能在 #298 合入**并且索引产物发布之后** +才可能被验证。合成一个 PR 会让脚本引用一个还不存在的包。 + +**我的失误:#733 与 #735 本可以不存在。** 它们修的是 #732 引入的回归,而找到它们 +靠的是自我 review 而非新信息 —— 也就是说,如果我在合 #732 之前就跑完那份检查清单, +两处都会在 #732 里。清单本身是被这两次回归**逼出来**的(§10.10.1 与下节),这正是 +代价:**规则是从事故里学的,而事故已经进了历史**。 + +### 11.3 `libs/**` 三处缺席 —— 本轮最可迁移的发现 + +`libs/graphics.lua` 被四个 recipe `import`,是这个索引里波及面最大的文件,而它同时 +是**唯一完全不被看见**的一类改动: + +| workflow | 缺席 `libs/**` 的代价 | +|---|---| +| `ci-test.yml` | 评审覆盖 —— 改动不跑任何检查 | +| `ci-xpkg-test.yml` | 评审覆盖 | +| **`publish-artifact.yml`** | **交付** —— 产物不重出,用户拿到旧版 | + +第三处最隐蔽:#735 合进 main、11 个检查全绿、gitee 镜像同步到 `ea36f6b`,而 +`xlings update` 仍在发 `xim-index-f1702a1.tar.gz` —— 修复**之前**那一版。夜间 +cron 最终会补上,所以是**慢漏**不是断供,但「合了、绿了、用户拿到的还是旧的」骗过了 +每一个常规检查。 + +**这解释了本轮四处问题为什么全部靠自我 review 发现、没有一处是 CI 抓到的** —— +CI 从来没有机会看那个文件。 + +两条操作性结论: + +1. 判断共享文件有没有被覆盖,**读 `on.paths`,别看 workflow 名字**。反查: + `grep -rln "pkgs/\*\*" .github/workflows/ | xargs grep -L "libs/\*\*"` +2. 修复合入后**核验产物,不要核验 PR 状态**:`xlings update` 之后直接 grep 本地 + 索引里那段代码。「PR merged + CI green」不蕴含「用户拿到了」。 + +发布器现在把**自己**也列进 paths(沿用 `ci-test.yml` 既有做法),于是改发布器的 PR +自验 —— 实测:合入后立刻自触发一次 `push` 发布,而合入前同样的改动零触发。 + +### 11.4 加一行 DISCOVERY = 三项检查 + +被 #733 与 #735 各逼出来一项: + +1. 新提供方 `config()` 里要有**两个**调用(`declare_*` 放置 + `declare_subos_env` + 声明)—— 只声明会让变量指向不存在的目录(§10.9.1); +2. 回头看每个 `declare_subos_env` 调用点传没传集合 —— 不传 `only` 就是「声明每一 + 行」,新行会被现有提供方自动继承(§10.10.1); +3. 回头看 `consumer_envs()` 的消费者 —— 新行会自动进入**每一个** shim,而 shim 侧 + **没有 `op`**,标量会被拼成冒号路径(#735)。 + +### 11.5 最终状态 + +发现变量表六格全部有提供方,第七格经核实不该补(§10.9.4)。闭环验证一次跑完 +(§10.8.2),用户侧产物已核验为 `xim-index-ea36f6b.tar.gz`(含全部修复),两份数据 +归档的 GLOBAL/CN 镜像均已发布且逐字节一致(sha256 比对,非可达性)。