只读核对补旧协议指针的分区断言
Project CI / AI game creator shell Rust smoke (push) Successful in 1m21s
Project CI / AI game creator shell Rust crates (push) Successful in 1m37s
Project CI / Backend tests (push) Successful in 3m49s
Project CI / Frontend tests (push) Successful in 1m37s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 8m20s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 9m39s
Project CI / Native shell tests (push) Successful in 5m50s
Project CI / AI game creator shell web tests (push) Successful in 2m18s
Project CI / Repository checks (push) Successful in 2m49s

- check:agc-update-channel-manifests:非 dev 的 Windows 渠道核对时断言 agc/latest.json 仍指向 dev-win 分区(全局单对象只属于 dev)
- 渠道隔离里程碑与 decision-log 记录线上证据:release-win 核对通过,指针指向 dev-win 0.1.155
This commit is contained in:
kdletters
2026-09-28 22:30:15 +08:00
parent e055cb1d7c
commit 93af29314c
3 changed files with 20 additions and 0 deletions
@@ -58,4 +58,5 @@
- `release-mac`(0.1.139,commit `87e52860a7`):清单只登记 `darwin-aarch64`(符合 2026-09-21 决策);解出更新包内 `Info.plist` 是 `world.genarrative.ai-game-creator.release` / `陶泥儿 Release` / `0.1.139`,与清单版本、渠道身份一致。
- **`dev-mac` 有真实缺陷**:清单 `0.1.142` 指向的更新包解出来是 `world.genarrative.ai-game-creator.release` / `陶泥儿 Release` / `0.1.139`,而且与 `release-mac/0.1.139` 的产物**字节完全相同**(`sha256=1dfc9deb79f7…`)。也就是说 dev 分区里放的其实是 release 渠道那份包,渠道隔离在这一次发布上被破坏(签名字段都是真的,只有身份和版本错了)。根因是 mac 构建目录残留产物被清单扫描挑中,已在 2026-09-28 修复(构建前清空同类产物 + 构建后断言包内版本与渠道身份),需要用修好的 mac 管线重发一次 `dev-mac`。
- 新增的跨渠道断言:同一次核对里不同渠道的更新包不得字节相同(`1dfc9deb79f7: dev-mac/darwin-aarch64 = release-mac/darwin-aarch64` 就是修复前会命中的形态)。
- 新增的分区断言:旧协议迁移指针 `agc/latest.json` 是**全局单对象**,只属于 dev 的 Windows 系统——核对 `release-win` 时脚本会断言它仍指向 `/agc/dev-win/…`。本轮实测 `release-win` 通过:指针指向 `agc/dev-win/0.1.155/陶泥儿开发版_0.1.155_x64-setup.exe`,没有被 release 渠道改写。
- 仍未勾选:真机上同时安装 `dev` 与 `release`、各自原地更新。上面这些只证明「产物身份正确」,不代替真机并存验收。
@@ -9710,6 +9710,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 决策(统一总号也要线上核对):同一脚本读 `agc/global-version.json`,断言「任何渠道清单版本都不高于统一总号」;渠道低于总号按 INFO 提示(可能正在构建),只有渠道高于总号才失败关闭。本轮线上:总号 `0.1.155`(2026-09-28T14:11:19Z 由 dev-win 取号),四个渠道清单分别为 0.1.154 / 0.1.150 / 0.1.142 / 0.1.139,均不高于总号。
- 决策(Windows 侧也要能核产物内部身份):新增 `scripts/pe-version-info.mjs`(纯 Node 解析 PE `RT_VERSION`,无第三方依赖),核对脚本下载 Windows 安装包后断言 `ProductName` 与 `FileVersion` 等于本渠道身份与本轮版本。理由与 mac 侧一致:文件名可以改,PE 版本资源是产物自己写的;两侧对称以后「产物里的渠道身份」不再只靠源码级用例。实测 `dev-win` 0.1.155 → `陶泥儿开发版`/`0.1.155`,`release-win` 0.1.150 → `陶泥儿 Release`/`0.1.150`。
- 事实(同日稍后):`dev-win` 的 0.1.155(commit `3702e0f8e`)在 14:26:13 发布完成,总号、渠道清单与旧协议指针三者对齐;该构建的源码早于 `assertArtifactVersionMatches()`,所以那条守卫仍待下一次真实渠道构建验证。
- 决策(旧协议指针也要线上核对):`agc/latest.json` 是全局单对象,只属于 dev 的 Windows 系统;核对任何非 dev 的 Windows 渠道时,脚本断言它仍指向 `/agc/dev-win/…`。本轮 `release-win` 通过(指针指向 `dev-win/0.1.155` 的安装包),把「release 不能写 dev 桥」这条从单测扩到线上状态。
- 决策(口径回归):macOS 现行契约是 arm64 单架构(2026-09-21 决策),里程碑里「两个 macOS 平台键指向 universal 产物」的旧文字按现行决策改写;不得据此重新切回 universal,除非按该决策给出的恢复路径补齐按架构的 Node 运行时。
- 影响范围:`apps/ai-game-creator-shell/scripts/build-macos-ci.mjs`、新增 `apps/ai-game-creator-shell/scripts/macos-release-identity.mjs` 与其 `.test.mjs`、`apps/ai-game-creator-shell/scripts/prepare-macos-codex.test.mjs`、`jenkins/Jenkinsfile.ai-game-creator-shell-macos-build`、`scripts/check-agc-update-channel-manifests.mjs`、两份里程碑与本文件、pitfalls。
- 验证:`node --test apps/ai-game-creator-shell/scripts/*.test.mjs` → **110 passed / 0 failed**(其中定向批次 `macos-release-identity / prepare-macos-codex / verify-updater-signature / build-release / cargo-features` 60 passed;新增的 mac 身份回归用例直接喂线上那份 0.1.139 release 身份 plist,必须抛错;新增的产物版本守卫用例喂 `_0.1.153_` 残留安装包,必须抛错);`npm run check:production-ops`、`check:encoding`、`check:doc-index`、prettier、eslint、`git diff --check` 通过;只读核对对线上 `dev-win` 全 PASS(含 158 MiB 产物下载验签与旧协议 sha256 一致),对线上 `dev-mac` 精确报出上面两条 FAIL。
@@ -332,6 +332,24 @@ async function verifyChannel(channel, tempDir) {
`sha256=${String(bridgeJson.sha256 ?? '').slice(0, 12)} size=${bridgeJson.size ?? ''}`,
);
}
} else if (channel.endsWith('-win')) {
// 旧协议迁移指针是**全局单对象**,只属于 dev 渠道的 Windows 系统;其它渠道发布
// 不得改写它,否则 dev 用户会被推去装别的渠道的包。
const bridge = await fetch(`${OSS_BASE_URL}/latest.json`);
if (bridge.status === 200) {
const bridgeJson = await bridge.json();
const bridgeUrl = String(bridgeJson.downloadUrl ?? '');
check(
`${channel} 没有改写 dev 的旧协议迁移指针`,
bridgeUrl.includes('/agc/dev-win/'),
`bridge=${bridgeUrl}`,
);
} else {
skip(
`${channel} 没有改写 dev 的旧协议迁移指针`,
`旧协议指针不可读:status=${bridge.status}`,
);
}
}
// 可选:下载产物,核对 sha256/size 并用产物内公钥验签。