fix(ci)+test(packaging): 关掉「门禁关死而自检全绿」三条路:outputs 绑定、判据步真跑、自检步指向

r2 复审:r1 那 11 条 + M3 已闭合(复审自己重放 12/12 红),但它新造的 40 条变异仍有 11 条漏网,
其中三条是「1 行改绿」:把 `probe.outputs.available` 改指向 `reason`/字面量(门永久关、每次绿);
判据步的退出码在标记表之外被吞(`|| echo 先忽略` / `; :` / `| cat` / `if !` / `true # 原行`,
复审真 bash 实测 exit 0);自检步被指向另一个脚本(自检根本不跑)。

三条 P1:
- 新判据 9:`probe.outputs.{available,log,png}` 必须逐个等于 `${{ steps.detect.outputs.<同名> }}`;
- 新判据 5:把 `id: judge` 的 `run` 原文真跑两次 —— 正例必须 exit 0、CPU 档日志必须 exit≠0,
  且 `bash -e` 与**裸 bash** 各跑一遍(`; :` 只在后者现形,实测 `bash -e`=1 / 裸 bash=0)。
  这一条一次封掉整类「吞码」,不依赖标记表;
- 判据 2:`id: wiring` 的 `run` 必须含 `gpu_shot_ci_selftest.py`,且 `vectors`/`wiring` 必须是**单条命令**
  (不许换行/管道/`;`/`&`/反引号/`#`/`$(`)⇒ `|| echo 先忽略` 无从下手。

两条 P2:
- 新判据 10:`on:` 必须同时有 `push`(含 `main`)/`pull_request`/`workflow_call`;
- 「载体依赖」这条边界补进四处(自检 docstring / gpu-evidence.md §8 / README / workflow 头注释):
  整个 workflow 被删掉就没有东西会跑自检,`guards.yml` 399/400 行塞不进去。

止步线(写进 docstring 与 §8):封闭清单 10 类 / 33 条变异向量;明确不覆盖「改判据脚本」「删掉整个
workflow」「求值器与 GitHub 语义差」「判据 4 的合法调用替换」;本文档不宣称「不可能被改成总是绿」;
**自 2026-11-11 起停止加固,扩项须由人类新开 mission**。

新增 `packaging/tests/gpu_shot_ci_expr.py`(`if:` 小求值器,判据脚本仍守 ≤400 行:377/215/64)。
This commit is contained in:
AskaEth committed 2026-11-11 18:31:30 +08:00
1 parent 2e9702790d
commit 8722c5a0ab
7 files changed
+358 -139

No files matched your search

+30 -14
View File
@@ -193,24 +193,40 @@ GPU 证据:无硬件适配器(/dev/dri 下没有 renderD*,也没有可用
就地往 workspace 里拷文件(不提交、靠上一步的产物)**在这个设计里做不到**:没有 artifact 传递环节。
**接线自检保证什么**:`packaging/tests/gpu_shot_ci_selftest.py` 用 6 条判据 + 21 条变异向量把上面这些
口径钉住 —— 判据 1 按 `id:` 认「五步必须在场」(`vectors` / `exitcodes` / `wiring` / `detect` / `judge`,
删步或加 `if:` 即红);判据 2 **解析 `if:` 表达式后求值**(`available` 取 `'true'`/`'false'`/`''` 分别
必须真/假/假,认不出的表达式一律判红);判据 3 要求两种调用形态都在场;判据 4 把 `probe` 的 `run` 原文
**实跑 7 种输入**;判据 5 按 YAML 布尔语义判 `continue-on-error`(`'true'` / `${{ true }}` 都算开启);
判据 6 扫所有 `python`+`packaging/` 的 `run`(含自测步与自检步自己)。
**它保证不了**:连判据一起改(它不自守)、`if:` 的 GitHub 语义(那是本脚本的小求值器模拟的)、以及
真 Actions 里的 job skip / required check 行为。r1 那一版把「不可能被改成总是绿」写进本文件,而实测
19 条变异漏 11 条 —— 所以这里只写**能复跑的覆盖面**(21 条向量,逐条见
`packaging/tests/gpu_shot_ci_vectors.json`),不再给绝对化的安全证书。
**接线自检的覆盖面**:`packaging/tests/gpu_shot_ci_selftest.py` 用 **10 条判据 + 33 条变异向量**
(r1 复审表 20 条 + 1 条补充 + r2 复审 12 条)把上面这些口径钉住,逐条见
`packaging/tests/gpu_shot_ci_vectors.json`:
1. 五步按 `id:` 必须在场且无条件(`vectors`/`exitcodes`/`wiring`/`detect`/`judge`),`exitcodes` 还得真断言 0/1/2;
2. 自测步必须**指向本脚本且是单条命令**(`|| echo 先忽略` 无从下手);
3. **解析 `if:` 表达式后求值**判「判定挂门」(`available` 取 `'true'`/`'false'`/`''` 必须真/假/假,认不出即红);
4. 两种调用形态都在场,且产物来自 `needs.probe.outputs.*`;
5. **判据步真跑两次**(正例必须 0、CPU 档必须非 0,`bash -e` 与裸 bash 两种模式都跑);
6. 跳过路径**实跑 7 种输入**;
7. `continue-on-error` 按 YAML 布尔语义判(`'true'` / `${{ true }}` 都算开启);
8. 吞码标记表(`|| true` / `; true` / `|| exit 0` / 裸 `exit 0`,兜底用);
9. `probe.outputs.*` 必须逐个绑到 `${{ steps.detect.outputs.* }}`;
10. `on:` 必须同时有 `push`(含 `main`)/`pull_request`/`workflow_call`。
**它不覆盖**:连判据一起改(它不自守);`if:` 的 GitHub 语义(那是本脚本的小求值器模拟的);真 Actions 里的
job skip / required check 行为;判据 4 的「合法调用替换」(后果是假红不是假绿);`exitcodes` 见证步自己的
断言被削弱;判据 6 那 7 种输入之外的新分支。
**载体依赖**:整个 `gpu-evidence.yml` 被删掉/替换后,**没有任何东西会跑这个自检** —— 守门人住在被守对象
自己的文件里(`guards.yml` 已经 399/400 行,塞不进去)。
本文件**不宣称**「不可能被改成总是绿」:r1 那一版这么写过,实测 19 条变异漏 11 条;r2 那一版
(6 条判据)实测 40 条新变异漏 11 条。所以这里只写**能复跑的封闭清单**(10 类 / 33 条向量)。
**这条门禁自 2026-11-11 起停止加固**:再往下是「守卫守守卫守守卫」,边际收益很低;要扩覆盖面必须由
人类新开 mission。
### 8.1 这一节**没验**的部分
- **CI 上从没真跑过**:本 workflow 是本地写的,**一次 GitHub Actions 运行都没有**(未 push)。
本地验的是两件事:① 把三个 step 的 `run:` 原文抽出来用 bash 跑(跳过 / 约定成对 / 约定半套 /
dispatch 成对 / 点名不存在 / 正例缺 PNG / 负例 —— 这 7 条已由判据 4 **每次自检都重跑**);
② `evidence` 的判据命令本地实跑过 0 与 1。**这不是 CI 实测**:`if:` 求值、job skip 在 UI 上的呈现、
`needs` 的输出传递在真 Actions 里仍未跑过。
本地验的是两件事,且都**已固化成每次自检都重跑的功能断言**:① `detect` 的 `run` 原文跑 7 种输入
(跳过 / 约定成对 / 约定半套 / dispatch 成对 / 点名不存在 / 正例缺 PNG / 负例 —— 判据 6);
② `judge` 的 `run` 原文跑两次(正例必须 0、CPU 档必须非 0,`bash -e` 与裸 bash 各跑一遍 —— 判据 5)。
**这不是 CI 实测**:`if:` 求值、job skip 在 UI 上的呈现、`needs` 的输出传递在真 Actions 里仍未跑过。
- **没在真 GPU runner 上跑过**:`evidence` 的真判定只在本地用合成向量走过(0 与 1 都到达过),
「真产物 + 真 GPU runner」这个组合没实测。
- **没验「跳过是否满足 required status check」**:本 workflow 没挂成必需检查;GitHub 对 skipped job