AskaEth
|
8e37bb9cf9
|
docs(packaging): §12 文件清单里本文的节号范围补到 §11–§16
复审观察 1:那张表还写「索引 + §11 / §12 / §13」,而本文现在也有 §14/§15/§16(含本次新编的
§16)。是改动前就存在的陈旧,顺手补全。
|
2026-11-09 09:49:44 +08:00 |
|
AskaEth
|
06fcbb8a51
|
docs(packaging): 修掉两个 §14 撞号(M190 让位到 §16)
台账 §10 第 5 条:packaging/README.md 里 §14 被 M169(更新链路测试通道)与 M190(产物署名与
清单签名)各用了一次。
判据(谁后插进来谁让位):§14 与 §15 都被仓库里的引用钉着——packaging/check_test_source_off.py
引 §14(M169),.github/workflows/release-build.yml 与 crates/app-iced/src/platform/win32/console.rs
引 §15(M196);这两处引用都在本 mission 的 scope 外。所以 M169 保持 §14、M196 保持 §15,
M190 那一节整段后移到文末编 §16,内容一字未改,只改编号与位置(新增一段「编号来历」说明为什么
它让位)。全文 §11/§12/§13/§14/§15/§16 各一次,无重复。
|
2026-11-09 09:32:54 +08:00 |
|
AskaEth
|
540b82e197
|
fix(m200-r1): 文档降到实测能撑的程度 + 守门收紧 core 声明内容(复审 P2-1 / P3-1)
复审 reviewer-presenterfix-r1 的 fix-then-merge 两条,逐条落地。
P2-1(a)「两档」措辞被本次提交自己作废 ⇒ 三处全改成三档:
* `crates/core/src/update/trust.rs` 模块文档(读者最先看到的那句,上次漏了)
* `crates/core/src/update/tests/support_sign.rs` 模块文档 + `TEST_SIGNING_SEED` 的文档
P2-1(b)「三者都进不了发布产物」被复证实测证伪(`cfg!()` 是运行时假分支,不是 `#[cfg]`
编译期剔除;无 feature 的 dev 与 --release 两档 core rlib 里公钥十六进制与 `test-only-key` 都在)
⇒ 降级到事实能撑的断言:「不会被 `keyring()` 并进信任表,正式构建永远不认这把测试钥」,
并明写「字节仍编在产物里」「字节级不在产物里未证、也未声称」「换 `#[cfg]` 是另一条结构性改动」。
没有换成 `#[cfg]`(那是复审建议另开的 mission)。
P3-1 守门对 core「自己的声明」只认形状 ⇒ 收紧为只许空数组:
`DECLARATION` 从 `^\s*update-test-key\s*=\s*\[` 改成 `^\s*update-test-key\s*=\s*\[\s*\]\s*$`,
并加一条自检向量(core 声明里偷偷带子 feature ⇒ 必须红)。`--self-test` 从 6 条变 7 条
(5 红 / 2 绿)+ 基线,`packaging/README.md` 的计数同步。
⚠ 一个自己踩出来的坑,已被既有守门抓住:收紧时我先在 `check_test_key_off.py` 里把那条更宽的
测试通道 feature 写成**字面量**(自检向量 + 文档表格),`check_test_source_off.py` 立刻红
(`packaging/**` 按字面扫,这次提交前它一直是绿的)。改法照该文件自己的声明办——用
`OTHER_FEATURE = "-".join(("update", "test", "source"))` 拼出来,源码里字面量为 0,
自检向量仍然构造出完整字符串并必须判红。
验证(均在最终树上):`cargo test --workspace --all-targets` 0、`cargo fmt --all --check` 0、
`check_test_key_off.py --self-test` 0(7 向量)/ 正式扫描 0、`check_test_source_off.py` 0、
`check_workflows_yaml.py` 0。
|
2026-11-09 07:56:33 +08:00 |
|
AskaEth
|
528f5706a0
|
docs(m200): 补 update-test-key 的两处文档一致性(cherry-pick 之外)
`80b291c` 原样落盘(与本提交前一个 commit 逐字节相同),这里只补两处**文档一致性**,
不改任何判据、不改任何 feature 行为:
1. `crates/core/src/update/trust.rs`:`TEST_ONLY` 的文档注释还写着「**只**在 `cfg(test)` 与
`update-test-source` 构建里存在」——同一文件里 `keyring()` 新增的表已经把三档(`cfg(test)` /
`update-test-source` / `update-test-key`)讲清了,上面这句变成了自相矛盾的旧口径。改成三档,
指向 `keyring()` 的说明。
2. `packaging/README.md` §12「文件清单」:新守门 `packaging/check_test_key_off.py` 已接进
`release-guard.yml`,但清单表里没有它(同类守门 `check_test_source_off.py` 在表里),补一行。
验证:`cargo test --workspace --all-targets` exit 0(311 passed)、`cargo clippy --workspace
--all-targets -- -D warnings` exit 0、`cargo fmt --all --check` exit 0、
`packaging/check_test_key_off.py`(自检 + 正式扫描)exit 0、`packaging/check_workflows_yaml.py`
exit 0。
|
2026-11-09 07:56:33 +08:00 |
|
AskaEth
|
19cc5c7950
|
fix(m190): presenter 更新链路用例补上清单签名(6 条既有测试回绿)+ 测试公钥守门
背景:M190 把「验签」做成了强制且唯一收口(`source::verified_manifest`,先验签再解析),而
`crates/presenter` 的更新链路用例只写 `manifest.json`、不写 `.sig` —— 它们写在验签之前,所以在
dev 上红成 6 条 `signature_missing`。真发布本来就必须带 `.sig`,所以修的是**夹具**,不是判据:
没有放宽任何断言、没有在测试里关掉验签、没有把 `available=true` 改成「接受 Failed」。
夹具(`crates/presenter/src/host/update_tests.rs`):
* `write_manifest()` 把清单**连签名**成对落盘(`dist/stable.json` + `dist/stable.json.sig`),
`dir_source()` 改走它;三处直接写清单的用例(坏清单 / 空清单 / 缺本平台产物)也改走它。
* 签名用 `TEST_SIGNING_SEED` + `key_id = test-only-key`,信封形状与 core 的
`tests/support_sign.rs` **同源**(文件头写明「改一处要改两处」;presenter 不依赖 core 的
`#[cfg(test)]` 资产,也没把测试资产导出成生产 API)。
为了让这把**公开**测试公钥在 presenter 的测试构建里被认得:
* core 新增 feature `update-test-key`(**只**把 `trust::TEST_ONLY` 并进信任表,不开任何数据源开关);
* 只有 `crates/presenter` 的 `[dev-dependencies]` 打开它(库/发布构建拿不到);锁里只多
`ed25519-dalek` 这一行(presenter 的 dev-dep,包已在锁里,无新包、无版本变动);
* 新守门 `packaging/check_test_key_off.py`(238 行,带 6 条变异自检)接进 `release-guard.yml`:
core 的 `Cargo.toml` 只许自己的声明、presenter 只许 `[dev-dependencies]` 段内,其余(workflow /
packaging 脚本 / 根 Cargo.toml / cargo 配置)出现即红 —— 这把钥进发布构建就等于「谁都能签出官方更新」。
* 没有用 `debug_assertions`/`cfg(test)` 旁路:那会让「测试构建的信任表和发布构建不同」变成一句注释,
而不是一条门禁。
|
2026-11-09 07:56:32 +08:00 |
|
tower-worker
|
1764301cdf
|
merge: 解 origin/dev 三处冲突(M182 / M184+M190 / README §14),两边都留
冲突(都来自别人后来改同一批文件):
- crates/app-iced/src/platform/mod.rs:保留 M182 的 HostOs / host·linux·macos 分册表 /
plan_corner_for,同时保留 M196 的 `[`win32::console`]` 落点说明;把 M182 措辞里已经不
成立的「唯一 unsafe 落点 / 只此一处」改成「两处落点(transparency + console)」
(unsafe-scope 门禁自 M196 起期望集合就是两处,不改这句文档就是错的)。
注意:`pub mod console;` 属于 `platform/win32/mod.rs`,本次解冲突时一度被误加到
`platform/mod.rs`(`cargo check` 立刻报 E0583 文件不存在),已修回。
- .github/workflows/release-build.yml:M190 的「PE 版本资源读回」步、M184 的
linux-x64 xvfb 冒烟步与首帧上传步**全部逐字保留**;M196 的 PE 子系统门禁作为**兄弟步**
插在导入表门禁之后(两道 PE 门禁互不替代)。按块比对:dev 的 10 个步骤逐字未变,
合并后 11 个步骤。
- packaging/README.md:保留 M184 的 §11 补充与 §12 行、M190 的 §14 签名段;§12 里
check_publish_slots 用 dev 的 11 条版本、另加 M196 的 check_pe_subsystem 行;§15 归位在
§14 之后。
行数:release-build.yml 合并后 413 行会撞 400 行红线(dev 侧本来 393),故把 M196 那一步
压到 6 行 + 1 空行(说明改由步骤名指路 packaging/README.md §15 与脚本 docstring 承载),
最终正好 400 行。
验证见 mission 报告:cargo check/test/fmt 全绿,两个 PE 门禁在同一批产物上都 exit 0
(子系统 GUI=2 / CLI=3,版本资源的 subsystem 读数同为 2 / 3)。
|
2026-11-09 05:49:38 +08:00 |
|
AskaEth
|
a219a21db8
|
fix(m190): r2 复审——dalek strict 口径照实测写正、补小阶 R 用例、锁里 toml_datetime 退回 1.1.2
三条 P2 都是「文档/注释与事实不符 + 一条上报事实错了」,代码行为没变。
P2-1 dalek 的 strict vs 非 strict 口径改成正测试出来的样子:
* `VerifyingKey::from_bytes` **不**校验编码规范性(`y = p` 的非规范写法返回 Ok,`is_weak() == true`),
先前写的「要求规范编码」是错的;
* 非 strict 的 `verify` **也**查 `S` 规范性 —— 先前把它写成「不做可锻检查」是半错;
* 于是这批拒绝类用例里,strict 与非 strict 唯一的分歧是**小阶点**:承重的是
`small_order_public_key_is_rejected`,其余几条(malleable / non_canonical_r / empty)换掉 strict 后
**仍然绿**,文件头的表与用例注释都改成这个口径,别让人误以为它们也是守卫。
* 新补 `small_order_r_is_rejected_only_by_strict`:R = 单位元 + S = k·a mod L 的伪造,**两边都断言**
—— dalek 的非 strict `verify` 接受它、我们的 `verify` 拒绝。这是第二条「只由 strict 拒」的判据。
* `non_canonical_r_encoding_is_rejected` 里那条「非规范公钥编码」原来对两种实现都绿(等于没测),
现在断言 dalek 的**真实**行为(`from_bytes(...).is_ok()` + `is_weak()`),dalek 升级改口径会红。
P2-2 `packaging/sign_manifest.py` 里指向已删除 `ed25519/{field,group}.rs` 的旧注释删掉(那段还写着
「same formulas」,而两套实现现在是**互相独立**才构成交叉验证)。
P2-3 `Cargo.lock`:`toml_datetime` 从 1.1.3 **退回 1.1.2**(`cargo update -p toml_datetime --precise
1.1.2` 实测可降、`cargo metadata --locked` 自洽)。先前报告里「被 `toml` 拒绝所以无法避免」的理由
**不成立**,已在报告里更正。现在相对 `44a0c87` 的锁变更是**纯新增**:16 个包、零既有版本变动。
变异证明(本轮按要求重跑):把 `verify_strict` 换成 `verify`(并补 `Verifier` trait 使其可编译)
⇒ `test result: FAILED. 110 passed; 2 failed`,红的两条正是
`small_order_public_key_is_rejected` 与 `small_order_r_is_rejected_only_by_strict`;其余拒绝类用例全绿
(与修正后的口径一致)。恢复后 `112 passed; 0 failed`。
|
2026-11-09 02:33:08 +08:00 |
|
AskaEth
|
918d826645
|
fix(m190): r1 复审——0x01 修成 \1 + YAML 门禁、被调方声明 secret、拆两个超限测试文件、验签换 ed25519-dalek
四条 P1 + 四条 P2 一并处置(不变的是判据,变的是「谁在承重」)。
P1-1 `.github/workflows/release-build.yml` 的 sed 替换串是裸 0x01(本意 `\1`):GitHub 解析该文件会
失败 ⇒ 整个 run 起不来;即便容忍,版本号也会被求值成单字节,PE 判据报「与 Cargo.toml 不同源?」把
排障引向错方向。修成字面 `\1`,并新增 `packaging/check_workflows_yaml.py`(真 YAML 解析器 parse
全部 workflow + 裸 C0 控制字符字节判据;带 --self-test 注入 0x01/坏结构断言必红),接进
`release-guard.yml` 两步。文本扫描型守卫看不见这类字节,这道门禁专门挡它。
P1-2 `release-publish.yml` 没在 `on.workflow_call.secrets` 里声明 `ULL_MANIFEST_SIGNING_KEY`,调用方
却传了:可复用工作流只拿得到自己声明过的 secret ⇒ 用户配好钥也会在签名步红,而错误文案反过来指控
Secret 没配。补声明(required: false,fail-closed 由步内 ::error:: + exit 1 承担,同
ULL_MSA_CLIENT_ID 的模式)。
P1-3 两个测试支撑文件越过 400 行守卫:签名夹具拆到 `tests/support_sign.rs`(support.rs 458→392),
CLI e2e 的签名部分拆到 `support/update_e2e_sign.rs`(update_e2e.rs 406→348)。纯搬家。
P2-2 「唯一收口点」改成结构事实:从 `UpdateSource` 删掉 `fetch_manifest` 默认实现,调用方只能拿
`verified_manifest(&source, channel)`(源只交原文,想绕过验签就得自己重写解析与渠道判据)。
P2-3 文档写的第 ④ 条命令补进流水线:`sign_manifest.py --verify-pinned` 用 trust.rs 里钉住的公钥
回验刚落盘的 .sig(不碰私钥),发布侧因此验证的是「客户端的判据」而不是「签名脚本的自我声明」。
P2-4 随自写实现一起删除(`Fe` 的错误 PartialEq 不再存在)。
P2-5 app-iced/build.rs 注释里那个 windows_subsystem 属性本分支不存在(M196 才有),改为说明
「本文件只写版本资源,子系统由 rustc 属性决定,check_pe_version.py 会把 subsystem 打出来」。
P2-6 坏清单不再带 error.path 是有意降级(来源 id 在 message 里),保持。
裁定项:自写 Ed25519 换成 `ed25519-dalek::verify_strict`(信任锚不许自写密码学;此刻信任表还是空表,
零兼容负担)。删除 `update/ed25519/{field,group,mod}.rs`(含只服务它们的单测),新 `update/ed25519.rs`
只剩一个薄封装;拒绝类用例(可锻 S+L / 小阶公钥 / 非规范 R / 空签名 / 未知 key)**一条没删**,
改成钉 dalek 的 strict 语义——实测 dalek 对全部五类的结论与旧实现一致(非规范 R 的拒绝理由不同:
dalek 走「小阶点」而非「编码非规范」,用例注释里写明)。签名侧留在 `packaging/ed25519_ref.py`
(纯 Python、零 pip 依赖),`--self-test` 用 RFC 8032 同一组向量钉两边。
|
2026-11-09 02:14:32 +08:00 |
|
AskaEth
|
b7d9b99e12
|
feat(m190): 产物署名(PE VERSIONINFO)+ 清单 Ed25519 多签名与更新前验签
两件事:让「这是谁发的」在产物与清单上都留下可验证的痕迹。
① PE 版本资源(两个 bin):`packaging/pe_version.rs` 是唯一口径(CompanyName
「Unlucky Launcher Project」/ ProductName、FileDescription「Unlucky Launcher」/
LegalCopyright「© 2026 … · Apache-2.0」/ 四段式版本号与 Cargo.toml 同源),被
`crates/{cli,app-iced}/build.rs` 各 include 一次;非 windows 目标整段不执行。
判据是读产物字节的 `packaging/check_pe_version.py`(CI 的 Windows 槽位)。
② 清单签名:`manifest.json` 旁边多一份 `manifest.json.sig`(分离签名,签的是清单**原始
字节**),信封是 `{format, signatures:[{alg,key_id,sig,manifest_sha256}]}` —— 多签名数组,
任意一条命中钉住的钥即放行(换钥窗口)。信任锚是 `crates/core/src/update/trust.rs`
里的编译期公钥表(正式表为空 = fail-closed,测试钥只在 cfg(test)/update-test-source 里)。
管线顺序改成「先验签、再解析」:`UpdateSource` 只交原文 + `.sig`,`verified_manifest`
是唯一收口点,`Job::apply` 因此在取包**之前**就拒。新增五类错误分类
(signature_missing / malformed / unknown_key / keyring_empty / invalid ),全部不可重试,
CLI 的 hint 单独说人话。
③ Ed25519 验签自带实现(`update/ed25519/*`,零新依赖):scope 不含 core 的 Cargo.toml,
用 RFC 8032 §7.1 向量 + 可锻/小阶/非规范编码的拒绝用例钉住;签名侧是
`packaging/sign_manifest.py`(纯 Python 参考实现,零 pip 依赖,`--self-test` 同向量)。
④ 守门:`release-publish.yml` 加签名步(`set +x`,只回显公钥;没 Secret / 钥没钉 / 签不上
一律红 ⇒ 不出 Release);`release-build.yml` 加 PE 资源读回;`release-guard.yml` 跑两个
脚本的 `--self-test`。密钥纪律与轮换(旧钥签新钥)写在 `packaging/docs/signing.md`。
Cargo.lock:新增 winresource(build-dependency)与 toml 系;toml_datetime 1.1.2→1.1.3 是
toml 1.2.1 的硬要求(`cargo update --precise 1.1.2` 已实测被拒)。
|
2026-11-09 01:59:05 +08:00 |
|
AskaEth
|
7e8b8740c4
|
fix(m184): r1 —— 证据账不再把「机制会跑」写成「已有运行时证据」,并收 5 条文档漂移
P2-1(唯一阻塞):`packaging/docs/linux-evidence.md` 里 `ull --version` 冒烟那条被写成
「两个槽位都有一份 CLI 运行时证据」——`make_artifacts.py::smoke_version` 只保证**机制**
(`slot == host_slot()` 时真跑),而仓库里找不到任何一次 linux-arm64 成功出包的记录
(`git grep -rn all_slots DevDocs/` 零命中),所以 arm64 侧运行时证据为零。§1 表格与
§5 改成「机制上会真跑 / 截至本分支没有那一次记录」,§6 解锁条件同步补一句。
P3 漂移:
1. `release-publish.yml` 注释 8 条 → 11 条自测回归(与脚本/其它三处一致)。
2. `packaging/docs/profiles-and-measurements.md` 同上 8 → 11。
3. `check_publish_slots.py` 注释示例 `PUBLISH_SLOTS: "windows-x64"` → 两档现值。
4. `release-build.yml` 注释「x64(当前唯一在发的槽位)」→ 两档已发布,并点名
linux-x64 的证据在自己的 xvfb 冒烟步。
5. `linux-evidence.md` 「20 倍以上余量」→ **8~37 倍**,并点明最紧的是亮度 σ
(24.06/3.0≈8×,与 check_screenshot.py 自述的 1/5~1/8 一致)。
自查(复审点名的五处之外):`只发 windows-x64` / `Windows only` / `暂未发布` /
`once published` / `8 条` 全仓再扫一遍,release-notes / README ×2 /
artifacts-and-version 剩下的都是准确表述(如「the only Windows asset」指 windows_x64.exe)。
验证:check_publish_slots --self-test EXIT=0、check_test_source_off EXIT=0,另
check_publish_slots(source) / check_release_semantics(+--self-mutation) /
make_manifest --self-test 均 EXIT=0。本轮无 cargo 构建,未创建 CARGO_TARGET_DIR。
|
2026-11-08 21:35:26 +08:00 |
|
AskaEth
|
2813e2984c
|
ci(m184): linux-x64 进发布名单,两档 Linux 转 mode=ci,arm64 只构建不发布
发布流水线默认从 2 个槽位变 4 个:`linux-x64`(ubuntu-22.04)与 `linux-arm64`
(ubuntu-22.04-arm)的 mode 由 probe 改 ci,tag 推送默认就编。
构建 ≠ 发布仍由 `PUBLISH_SLOTS` 决定,本轮只加 `linux-x64`:
- `linux-x64` 有运行时证据 —— release 产物在 Linux 真机(Ubuntu 22.04 + WSLg 真窗口)
渲出一帧、[theme]/[backend] final 日志齐全、像素判定通过,真窗口 1180x760 从 Windows
侧截屏可见;`release-build.yml` 另加一条**同槽位**的 xvfb 运行时门禁(只在
`inputs.slot == 'linux-x64'` 上跑,不给没验过的 arm64 造红)。
- `linux-arm64` 只有构建证据、运行时零证据,产物照出 artifact 取证但不发布;解锁条件
(真机渲出一帧 + 主题日志)写进 release-notes 与 §9。
守卫跟着扩(`packaging/check_publish_slots.py`):
- 自测从 8 条扩到 11 条,新增「声明的 linux-x64 构建红了 ⇒ 必须红(挡住发布)」、
「linux-arm64 有产物但没声明 ⇒ 只警告」、「提前把 linux-arm64 写进名单 ⇒ 缺产物必红」;
- probe 档样例从 linux-x64 换成仍是 probe 的 macos-arm64(否则该用例会从「必须红」
变成「本来该绿」);
- 新增「mode=ci 却本次没产物 ⇒ ::warning::」:红一档不能只表现为表里少一行。
文档矩阵同步(release-notes §Downloads/§Support matrix、compliance §9/§10、
artifacts §1、build-and-ci §3、README ×2),两份文档都把 Linux 写成
「已构建并发布(x64)/ 已构建未发布(arm64)」,并把新发现写实:Linux 上整窗透明
与圆角没有代码路径(hwnd=none / corner=policy=system),不是「未验」;Linux 上
`ull update apply` 会拒绝 portable-zip(清单里现在有 linux-x64 产物)。
证据账(含实测输出、CI 增量估算、未验清单):packaging/docs/linux-evidence.md。
|
2026-11-08 21:35:26 +08:00 |
|
tower-worker
|
26ba1579ab
|
docs(m196): r2 复审 —— 给「无控制台宿主」那条下边界声明
复审指出 README §15 把两个**近似**形态(父进程句柄不继承 / 父子都无句柄)直接叫「服务形状」,
顶层又写「服务 / 计划任务」,读者会把它当成「真服务也测过」。补一段边界:① ② 都是近似,
真 SCM 服务与计划任务(session 0、no window station)、start /b、ConPTY 全部未测,结论靠
「句柄无效时 std 写返回 Ok」这条机制外推;第三方交叉读数(复审 r2 那组)单独标注来源,
不混进我自己的读数。
同一处过度概括也出现在 console.rs 的 NoConsole 文档(原文「④ / 服务 / 计划任务」),
按同一口径改成「④ 双击,以及其他没有控制台的宿主」并指向 README §15 的边界段。
只改文档,不动代码。
|
2026-11-08 20:22:36 +08:00 |
|
tower-worker
|
3fd33a672f
|
fix(m196): r1 复审 P1(非 Windows dead_code)+ P2 四条
P1(阻断):console.rs 的 `INVALID_HANDLE_VALUE` 只被 `#[cfg(target_os = "windows")]`
的 usable() 用到,而这个模块在 Linux/macOS 上也编译(platform/mod.rs 的 pub mod win32;
没有 cfg)⇒ ubuntu 的 `clippy -- -D warnings` 会把它升级成 dead_code error。
按「精确 cfg」修(不用 dwm.rs 那种文件级 allow(dead_code):那会永久掩掉本文件在非
Windows 上的所有死项)。自证方式是真实文件翻转 cfg 的 rustc probe:修前 exit 1
(`constant INVALID_HANDLE_VALUE is never used`)、修后 exit 0 零告警;同一条命令写进
了注释,下一个人可以照着跑。
P2-1:自测条数按实现改成 8 条(红 6 / 绿 2),三处(脚本 docstring、release-build.yml
注释、README §12)一致。
P2-2:文件头那组句柄读数换成 release 产物的实测值(out 0x0→0x1F0 / err 0x0→0x1F4),
并说明数字随实例变化、单测里的 0xE4/0xE8 是示例。
P2-3:README §15 补这段边角语义——但**按实测改写了复审的结论**:两种「既无控制台也不
重定向」的宿主形态(父有句柄不继承 / 父子都无句柄)× 两条命令,child_exit_code 全是 0,
不是 EXIT_INTERNAL;原因是 Rust std 在 Windows 上对取不到的句柄直接返回 Ok(独立探针
实测 SetStdHandle(out)=0x0 / 0x1234 / (HANDLE)-1 三种取值 write/flush 都是 Ok),
所以 runner.rs 那条「写失败 ⇒ EXIT_INTERNAL」的分支不会被触发。
P2-4:NoParentConsole → NoConsole(这个名字同时覆盖「attach 成功但句柄仍不可用」),
诊断文案与注释同步。
|
2026-11-08 20:12:36 +08:00 |
|
tower-worker
|
14f9318e09
|
fix(m196): GUI 产物 PE Subsystem → WINDOWS_GUI(2),并用 AttachConsole 保住 CLI 输出
群友 2026-11-08 实测发布构建「运行时会带一个控制台窗口在底下」。根因:产物 PE 头
Subsystem 仍是 CUI(3)。同一个修复 2026-11-01 做过一次(37d3039),但只改了已被
workspace exclude 的 Slint 树(crates/app),从未到达 iced 产物。
- crates/app-iced/src/main.rs:加 #![cfg_attr(windows, windows_subsystem = "windows")],
并写清为什么放 bin 层而不是 build.rs(PE 子系统是每个 bin 目标的属性)。
- crates/app-iced/src/platform/win32/console.rs(新):AttachConsole(ATTACH_PARENT_PROCESS)
的落点 + 判据 should_attach(纯函数,可断言)。GUI 子系统进程不继承父控制台,实测
从 cmd 启动时三个 std 句柄全是 0;附着后 GetStdHandle 立刻给出控制台句柄(0x0→0x208),
所以不改 std 句柄、不碰用户的重定向(ATTACH_PARENT_PROCESS 只会附到已存在的控制台,
永不新建窗口)。
- packaging/check_pe_subsystem.py(新):读产物 PE 头 Subsystem 字段(GUI 必须 2、
CLI ull 必须 3),非 2 即红;--self-test 注入 5 条合成 PE 回归。
- 接进 release-build.yml(发布侧两槽位)与 ci.yml build job(PR 阶段)。
- guards.yml:unsafe 落点期望集合变成两处(console.rs + transparency.rs),集合相等判据其余不变;
平台层所有「全仓唯一 unsafe 落点」措辞同步改正。
|
2026-11-08 19:33:56 +08:00 |
|
worker-updatee2e
|
d7adbd1172
|
fix(m169): r3 四条就地修完 —— 只认同级 name:、纳入 .cargo/config.toml、登记 env 交接边界、校准两处数字
合并门禁只认 clean,r3 的 p2-4items 就地修掉(无行为改动,判据更严,不放松任何一条)。
P2-1(一行 + 三向量)`_name_of` 现在只认**同级** `name:`(`item.end() == key_indent`):更深缩进的
`- name:`(`env:`/`with:` 子列表、`run: |` 块标量里的行)不再被当成项名;同一项里出现两个**不同**
的 `name:` 返回 `None`(无法判定 ⇒ 默认拒绝,不去猜 YAML 重复键语义)。新向量:name 藏在 env 子项 /
藏在 `run: |` 里 / 两个不同 name ⇒ 必须红。
P2-2 `.cargo/config*.toml` 进扫描面(`CONFIG_GLOBS`:根与 `crates/*` 下的 `config.toml`/`config`),
新增 `scan_cargo_config`:feature 字面量(覆盖 `--cfg feature="…"`、`[env] RUSTFLAGS`)走原有判据,
`rustc-wrapper` / `rustc-workspace-wrapper` **一律判红**(wrapper 注入什么由程序决定,文本扫描看不见;
合法用途如 sccache 需要 review 明确同意,不能顺手加)。新向量:config.toml 用 `--cfg` 开该 feature
⇒ 红;设 rustc-wrapper ⇒ 红;普通 config.toml ⇒ 绿(防误杀)。
P2-3 运行期 env 交接写进守门自己的「抓不住」表(脚本头 + README §14):第一步把 feature 写进
`$GITHUB_ENV`、第二步只用 `--features "$FEAT"`——第二步没有字面量,**任何静态扫描都看不见**,这是本
守门的固有边界(引 YAML 解析器也修不了,因为这是数据流不是结构),不是漏判。
P2-4 两处过期数字:`release-guard.yml` 的「注入 14 条」→ 26 条注入 + 6 条防误杀/放行(另加基线,
条数以 `--self-test` 输出为准);README 的「26 条:21 红 + 6 绿」→「32 条向量:26 红 + 6 绿 + 基线」。
守门脚本 399 行(≤400,仍零第三方依赖);自测数据 32 条向量在 `packaging/tests/guard_vectors.json`。
验证(本机,未跑全量 cargo —— tower 已在合并态跑过 workspace 全量 EXIT=0/2648 passed):
- `--self-test`:26 条注入全红 + 7 条基线/防误杀绿,exit 0。
- **真仓注入 8 组**(改真 ci.yml / 新建真 .cargo/config.toml,改完即还原):env 子项里的 name ⇒ 红;
`run: |` 里的 name ⇒ 红;两个不同 name ⇒ 红;`--cfg feature=` ⇒ 红;`rustc-wrapper` ⇒ 红;
普通 config.toml ⇒ 绿;r2 的无名步骤 / flow 步骤回归 ⇒ 仍红;还原后基线绿。
- 正式扫描(真仓)exit 0;全仓 400 行扫描无超限;改动文件全 LF。
|
2026-11-08 11:27:21 +08:00 |
|
worker-updatee2e
|
68a1f90828
|
fix(m169): 复审 r2 —— 守门归属改成「列表项结构判定 + 默认拒绝」,堵掉无名步骤/无名 job/flow 步骤的继承放行
r2 复审(reviewer-updatee2e-r2,p2-4items;被抓出一个真洞,mission 翻回 active)逐条落地。
P2-1(本轮核心,真洞)allowlist 的归属原来按「最近一行 `- name:`」切块,于是任何不写成
`- name: <x>` 的步骤都继承上一块的名字;被放行的 `update-e2e` 恰好是 ci.yml 里最后一个
`- name:`,所以追加到文件末尾的一切都落在它的块里。复审三条真实注入(无名 `- run:`、无名步骤的
整个 job、flow 风格步骤)当时全绿。现在:
- `split_items()` 按 YAML **列表项**切块(每个 `- ` 起一项;比当前项深的行归当前项;同级或更浅的
非列表行**结束**当前项)。项名 = 该项内**同级**的 `name:` 键(键序无关;`run: |` 块里的
`name: dummy` 不算;`run: echo "name: x"` 也不算)。
- **默认拒绝**:落不到列表项上的行(`jobs:` 之前的孤儿行、job 级 `run:` 这类项外键)带 feature 即红;
没有 `name:` 的项带 feature 即红。不再有「继承上一块」这回事。
- 三条复审注入 + 本轮新增三条(`jobs:` 之前的孤儿行、`run: |` 里夹带并伪造 name、shell 变量拼接)
都进了自测向量;在**真仓库文件**上重跑也是全红。
P2-2(同族误杀):
- 键序无关:允许的那一步把 `run:` 写在 `name:` 之前仍绿(旧实现会报到上一块的名字上)。
- `cargo hack check --all-targets` 不再被误判成 `--all`(正则收紧到 `--all(?![-\w])`)。
- Cargo 的 `update-test-source = [ … ]` **跨行声明**不再被误判成「写进了别的 feature 列表」
(`scan_manifest` 增加 `in_declaration` 状态)。
P2-3 `Fixture::run` 的第二条断言比错对象:原来比夹具字段 `self.dest`,手写
`fx.run(&["apply","--dest","<测试二进制>","--json"])` 两条都过。现在从 `args` 里解析真实 `--dest`
值(含 `--dest=` 形式)再 canonicalize 比较;夹具字段那份作为额外一道保留。
P2-4 `release-guard.yml` 的步骤级注释还停在 r1 的扫描面:改成「含复合 action / packaging 递归 /
Makefile 等 + 归属按列表项判 + 唯一允许 ci.yml 的 update-e2e 一步」。
自测数据搬到 `packaging/tests/guard_vectors.json`(基线 8 个文件 + 26 条向量:21 红 / 6 绿),
脚本本身从 379 行降到 373 行(守门仍 ≤400);README §14 补上归属规则与「抓不住」清单。
验证(本机,全部 exit 0):
- 守门正式扫描绿;`--self-test` 21 条注入全红 + 6 条基线/放行绿;向量文件缺失时 exit 1(不静默)。
- **真仓注入**(在真 ci.yml / release-build.yml / cli/Cargo.toml 上改完即还原):复审三条(无名步骤 /
无名 job / flow 步骤)全红;本轮新增三条(孤儿行 / `run: |` 夹带 / shell 拼接)全红;
三条合法写法(键序、`--all-targets`、跨行声明)全绿;还原后基线绿。
- E2E:debug 6 绿、release 6 绿(`running 3 tests` ×2,0.26s / 0.23s,非 0 measured)。
- `cargo clippy -p unlucky-cli --all-targets --features update-test-source -- -D warnings` 干净;
`cargo fmt --all -- --check` 干净;全仓 400 行扫描无超限(守门 373 / 向量 194 / ci.yml 317)。
约束遵守:未 push;`PUBLISH_SLOTS` 只列 `windows-x64`(未动);release 侧仍无该 feature;跨卷 bug 未碰。
⚠ 仍未验:CI 里 E2E 真跑起来本机验不了(只证明 workflow 写对 + 守门放行,首跑要等推送后看 Actions)。
|
2026-11-08 11:12:11 +08:00 |
|
worker-updatee2e
|
28bf104041
|
fix(m169): 复审 r1 五条 p2 —— 守门开一个极窄 allowlist 并把 E2E 真接进 CI
r1 复审(reviewer-updatee2e-r1,p2-5items,均不挡合并)逐条落地:
P2-3(本轮主产出)守门把「E2E 进 CI」这条路堵死了:`scan_enabling_text` 对 workflow 里任何该
feature 字面量判红,于是 `cargo test --release … --features update-test-source --test
update_e2e_test` 这种**合法调用**也红,自己登记的 follow-up 无法实现。现在:
- `ALLOWED_STEP = {workflow: .github/workflows/ci.yml, name: update-e2e,
must_contain: --test update_e2e_test}`;按 `- name:` 把 workflow 切成步骤块再判,文件名 / 步骤名
/ 命令行**三者任一不符即红**(job 名不参与判据:改 job 名不该解锁新能力)。
- `ci.yml` **新增一个独立 job** `update-e2e`(windows-latest、timeout 45m、release 档;现有 job
一行未动,纯追加 27 行)。只在 Windows:夹具的「真形状」是裸 `.exe` + `portable-exe`,Linux/macOS
的真实产物是 `.tar.gz` + `portable-zip`(会被 `ensure_self_replaceable` 直接拒),在 ubuntu 上跑绿
是假绿。不降 debug:`debug_assertions`/优化/panic 行为都不同。
- self-test 覆盖 allowlist 六向量(允许 / 换文件 / 换步骤名 / 缺 `--test` / 发布工作流 / ci 内另一步)。
P2-2 守门 8 条绕过:注释剥离改**引号感知**(`echo "#"; cargo …` 不再吃掉真命令);扫描面扩到
`.github/actions/**`、`packaging/**` 递归子目录、`Makefile|justfile|Taskfile` 第二构建入口;
`--all-features` 之外补 `cargo hack --feature-powerset|--each-feature|--all`。大小写/下划线变体按
复审结论写进「抓不住」表(cargo feature 名敏感,写错编不过,不算漏检)。
P2-1 GUI 人工验收命令根本跑不起来:`-p unlucky-launcher-iced` 是 bin 名,改成 package 名
`-p unlucky-app-iced`(app-iced / presenter 两处,并写明 `-p` 只认 package)。
P2-5 夹具缺「不给 --dest 就 panic」的结构性保险:`Fixture::run` 加两条断言——`apply` 必带
`--dest`、`--dest` 不许等于本进程 exe 的 canonical 路径。抓得住「以后有人手写 fx.run(&["apply"])」,
抓不住「绕开 Fixture 直接调 unlucky_cli::run」。
P2-4 夹具「真形状」只在 Windows 成立:写进 `tests/support/update_e2e.rs` 文件头(说明 Linux 上跑绿
是假绿、CI 因此只在 Windows),**不改断言**。另按复审 ⑤ 补一行:失败路径三例抓不住回滚/备份
(摘要失败发生在 install_staged 之前),回滚靠正路备份断言 + install_cases。
跨卷替换 bug 按 tower 指令**未动**(另开 mission)。
验证:守门正式扫描 + self-test 绿(14 红 / 3 绿);真仓注入 6 组(基线绿、步骤改名红、缺 --test 红、
搬进 release-build 红、改 --all-features 红、还原绿);E2E debug 6 绿、**release 6 绿**;
`cargo clippy -p unlucky-cli --all-targets --features update-test-source -- -D warnings` 干净;
`cargo fmt --all -- --check` 干净;全仓 400 行扫描无超限(守门脚本 379 行、ci.yml 317 行)。
⚠ 未验:CI 里 E2E 真的跑起来这件事本机验不了——只证明 workflow 写对 + 守门放行,首次真实运行要等
推送后看 Actions。
|
2026-11-08 11:12:11 +08:00 |
|
worker-updatee2e
|
24826c1a7c
|
feat(m169): 更新通道端到端验收 —— 本地源改成编译期 feature,补一条可一键跑的 E2E + CI 守门
§6 欠账:更新链路的 GUI 端从来没验过,而 M167 发现它根本没法在本机验——`ULL_UPDATE_DIR` 只在
`debug_assertions` 下生效,发布产物却是 release;`apply` 又会替换本进程 exe,于是没人敢跑。
判据换档(tower 定案 B):`cfg!(debug_assertions)` → 编译期 cargo feature `update-test-source`
(core 定义,cli/presenter/app-iced 链式转发,**默认关**)。带 feature 的构建里还要两档环境变量
(`ULL_UPDATE_DIR` + `ULL_UPDATE_TEST_SOURCE=1`),只给路径什么都不会发生。官方发布二进制里那段
分支根本编不进来——README「release builds do not contain that path at all」这句因此继续为真。
- core: `job::default_source` 的本地源分支整段 `#[cfg(feature = "update-test-source")]`;判据抽成
纯函数 `test_source_root_from` 并逐条单测(半开一律关、空路径、承认值只认 `1`);
`the_test_channel_is_a_compile_time_opt_in` 在**两种构建下各断各的**(带 feature ⇒ 换源;
不带 ⇒ 环境变量设满也走 GitHub)。
- cli: `update check/apply` 的 `--json` 增加 `test_source` 字段(判据派生自实际用了哪个源,不是回读
环境变量),人读输出多一行点名;`help.rs` 的 `ULL_UPDATE_DIR` 说明按新判据重写。
- 验收:`crates/cli/tests/update_e2e_test.rs` + `update_e2e_tamper_test.rs` + 共用夹具
`tests/support/update_e2e.rs`。临时数据根 + 本地源 + 真形状清单(与 `manifest.golden.json` 同
字段)+ 真 PE 产物(现场构建的 ull.exe 前 1 MiB,理由写在 `PAYLOAD_LIMIT`)。断言覆盖:发现
新版本(source=file:… / test_source=true / size / notes)、下载 → 双检 → 就位(dest 字节、旧字节
进备份、暂存无残留)、重复 apply 的幂等终态、篡改 sha256(清单撒谎 / 包体被换)与截断都必须
拒绝且不动现有安装、修复后能重装。**永远带 `--dest`**:不带会真的改名换掉测试二进制。
- 守门:`packaging/check_test_source_off.py`(stdlib-only)扫 `.github/workflows/**`、
`packaging/*.py|*.sh` 与各 `Cargo.toml` 的 `default`,任何一处打开 feature(或 `--all-features`)
就红;`--self-test` 注入 5 条真实回归证明每条都会红。CI 挂在 release-guard.yml 两步。
验证(本机):core update 单测 80 绿 / 带 feature 6 绿;E2E debug 6 绿;
`cargo test --release --features update-test-source` 6 绿(tower 要求 release 档验收);
`cargo test -p unlucky-cli -p unlucky-presenter` 全绿;守门 self-test + 正式扫描绿(真注入后红)。
已知没验:真 GitHub Release 下载、GUI 点击与重启替换(人工);跨卷替换(另开 finding)。
|
2026-11-08 11:12:10 +08:00 |
|
AskaEth
|
5ff6cdb38b
|
fix(m164): 复审三条 P2 —— vcvarsall 用 wrapper .bat 真抓到 LIB/INCLUDE、ls 进 arm64 分支、两处数字与一句顺序承诺
P2-1(核心:上一轮的 ② 在 git-bash 下是死代码):`cmd //c "\"${vcvars//\//\}\" arm64 …"`
不行——MSYS 把参数里的 `"` 改写成 `\"` 交给 cmd.exe,cmd 的 `/c` 引号剥离接不住,LIB/INCLUDE
全空,只剩 `set` 的空输出;于是 ③「显式 link.exe」在**没有 LIB** 的状态下生效,正是本步注释里
写的那种会造出 `LNK1181: cannot open input file 'kernel32.lib'` 的组合。改法(复审验过的路线):
往 `$RUNNER_TEMP` 写一个 **CRLF** 的 wrapper `.bat`(`call "<vcvarsall>" arm64 >/dev/null 2>&1` + `set`),
`cmd //c` 只收**不含引号**的相对文件名(先 cd 进去)——引号留在 .bat 内部由 cmd 解析,路径带空格
也不受影响。同源的 ③ 也补齐:`vswhere -find` 的 `vcvarsall.bat` 与两个 `link.exe` 候选都改成
「反斜杠形态 + 正斜杠形态各试一次」(和同文件 dumpbin 步同规矩),不再赌一种形态。
P2-2:cargo build 步末尾那条 `ls -l` 移到 `if [ "$SLOT" = "windows-arm64" ]` 门内(并加 `|| true`):
x64 是当前唯一在发的槽位,不给它加一个失败面。
P2-3:① `release-publish.yml` 步数改对——主线 7 步、本分支 8 步(`release.yml` 与
`packaging/docs/build-and-ci.md` 两处都改,并列出 8 步是哪几步);② `check_publish_slots.py`
的 report() 全部改走 **stdout**:注解(`::error::`/`::warning::`)在 stdout 上同样被 Actions 识别,
而分两个流写会让「表格 → 注解」的顺序不可控(原注释承诺的顺序当时并不成立)。顺带在
`build-and-ci.md` 的 arm64 工具链段补一句「`cmd //c` 别收带引号的路径、要 wrapper .bat」,
免得下一个 agent 再把 ② 写回死代码。
本地证据(同一 worktree 复跑):
- P2-1 新证据:把本步 `run:` 块原样抽出,用 `bash --noprofile --norc -eo pipefail`(与 runner 同
语义)、假 vswhere + **路径带空格**的假 `vcvarsall.bat`(真 cmd)跑:新写法 LIB/INCLUDE/linker
三行全部写进 `$GITHUB_ENV`、rc=0;同一套假件跑 e858664 的老写法 ⇒ LIB/INCLUDE 全空、只有 linker
(与复审结果一致)。降级路径也复测:vswhere 不存在 ⇒ 只 1 条 warning、rc=0;vswhere 不给
vcvarsall ⇒ ② warning、③ 仍拿到 Hostx64 兜底、rc=0。
- 体检步 5 场景(无 VS / vswhere 全成功 / 报错退出 / 垃圾+非零 / 路径不存在)全部 rc=0、0 条
`::error::`。
- `check_publish_slots.py --self-test` 8 条 + 警告断言全绿;`--dist` 六场景复测(x64-only 绿 /
多一份 arm64 绿+warning / 缺 CLI rc=1 / 空 dist rc=1 / `--slots` 漂移 rc=1 / `--dist` 非目录
rc=1),并且缺产物时输出顺序是「表格 → warning → error → 汇总」,stderr 为空。
- 7 个 workflow `yaml.safe_load` OK;全部 `run:` 块 `bash -n` OK;全仓 400 行扫描 0 个超限
(release-build.yml 316、check_publish_slots.py 345)。
- `check_release_semantics.py`(+`--self-mutation`)、`release_marker.py --self-test`、
`make_manifest.py --self-test`、`cargo metadata --no-deps` 全绿。
边界不变:arm64 产物仍**从未被构建过、也从未在真机跑过**;`PUBLISH_SLOTS` 仍是 `"windows-x64"`,
发布语义与 x64 静态 CRT 门禁未动。下一次 tag 的 arm64 仍可能红,红点大概率换到 C 依赖编译
(aws-lc-sys 的 CMake + aarch64 cl.exe)或链接器(LNK1181)——**不是「arm64 修好了」**。
|
2026-11-08 08:45:02 +08:00 |
|
AskaEth
|
e858664fca
|
ci(release): M164 arm64 判定权交回编译器 + 发布名单守卫(不翻牌)
根因(拿到的真实证据,不是猜的):v0.2.2(run 42322062879 / job 128248713926)与 v0.2.3
(run 42429017002 / job 128573547829)两份 check-run 注解逐字一致 —— 失败步骤是第 6 步
`Windows ARM64 工具链体检`,第 7 步 `cargo build` 状态 skipped。也就是说 v0.2.1~v0.2.3 五轮
全红都红在一个**编译前的启发式探针**上,真正的编译器/链接器一次都没说话。该探针的结论还与它
自己打印的快照矛盾:`SDK Lib 版本→um 架构: 10.0.22621.0→um:[arm,arm64,x64,x86,]` 明明在,却
同时报 `kernel32=缺失`(同一个 `find -path` 模式在本地合成目录树上命中)。runner 实况是
Windows 11 Arm64 + Visual Studio 2026 镜像,`VC.Tools.ARM64` 与 `Windows11SDK.22621/26100`
都装好了,M142 的 `setup.exe modify` 反倒返回非 0。
改:
- release-build.yml:探针降级为「只取证」——vswhere 组件查询 + 各目录 `.lib` 计数 +
arm64 `link.exe` 候选,一条 `::error::` 都不写、永不 exit 1;不再自动补装 VS。红绿只由
cargo/链接/静态 CRT 导入表门禁决定。cargo build 步给 arm64 显式备齐工具链:
`rustup target add aarch64-pc-windows-msvc`、`vcvarsall.bat arm64` 取 `LIB`/`INCLUDE`、
vswhere 定位 arm64 `link.exe` 后导出 `CARGO_TARGET_AARCH64_PC_WINDOWS_MSVC_LINKER`
(顺序不能反:只给链接器不给 LIB ⇒ LNK1181 kernel32.lib)。
- 新增 packaging/check_publish_slots.py(344 行,零依赖):名单 ⇄ 产物**两个方向**。
声明了缺 GUI/CLI ⇒ `::error::` + exit 1;有产物没声明 ⇒ `::warning::` 明说未发布(M142 之后
这个方向是静默的,裁剪步只 echo 一行 drop:)。另有源码级断言(名单每项必须存在且 mode=ci、
运行期名单必须等于文件里那行)与 8 条 `--self-test` 注入回归。
- release-publish.yml:裁剪前插一步跑那个守卫,原来内联的齐全性循环搬进脚本(一套判据一处实现);
重算 SHA256SUMS 的步骤只负责重算。
- release-guard.yml:PR 阶段跑守卫自测 + 源码级断言。
- 文档同步:release.yml / release-publish.yml / release-build.yml 头注释、packaging/README §12、
§1 矩阵、§3 构建与发布、§9 支持矩阵、§7.5 arm64 取证、release-notes.md、README/README.zh-CN
的产物矩阵与说明。口径统一为「arm64 构建取证中、未发布」,不写成已支持。
没做的(按 tower 裁决「方案乙」):`PUBLISH_SLOTS` 本轮**不加回** arm64。arm64 从未产出过 PE、
本机也证不了,写进名单就等于拿 x64 的发布去赌它(M142 移出名单正是为避免这个事故)。下一 tag 的
CI 真出包后翻一行即可,守卫与 SHA256SUMS 自动跟着扩。
验证:workflow YAML 全部可被 PyYAML 解析;所有 `run:` 块过 `bash -n`;探针步在本机(无 VS/SDK)
实跑 exit 0 并打出实况注解;守卫 `--self-test` 8 条全绿、正反两个方向都在合成 dist 上实测过;
check_release_semantics.py(含 --self-mutation)/ release_marker / make_manifest 自检全绿;
cargo metadata 正常。**arm64 产物从未被构建过、也从未在真机跑过**——本机 `rustc --target
aarch64-pc-windows-msvc` 直接撞上没有 MSVC 链接器(git-bash 的 GNU `link` 被当成 link.exe),
`cargo check --workspace --target aarch64-pc-windows-msvc` 也死在 aws-lc-sys 的 cc-rs 阶段
(GNU host 上没有该 target 的 C 编译器)。真实结论只能等下一 tag 的 CI。
|
2026-11-08 08:33:44 +08:00 |
|
AskaEth
|
1d2e84ed61
|
fix(m163): push tag 默认建稳定版(发布标记语义 + 0.2.3 bump)
发布标记:`release.yml` 的 dispatch `prerelease` 默认值 true → false;`release-publish.yml`
的 create 路径不再塞 `--prerelease`(空串 = push tag ⇒ 稳定版),edit 路径行为不变(空串不碰
标记)。三种触发各创建什么改由 `packaging/release_marker.py` 一张表定义,流水线
`--emit-bash` 出来两个数组直接用,自己不再写 case——v0.2.2 至今 `releases/latest` 404 的根因
就是「push 默认 prerelease」这层叠上「dispatch 默认 true」。
守门:新增 `packaging/check_release_semantics.py`(CI 在 `.github/workflows/release-guard.yml`,
guards.yml 已 398 行不能再挂 job):①标记表逐条对(push tag 的 create 不含 --prerelease);
②把 `--emit-bash` 真灌进 bash 读回两个数组;③publish 的可执行内容里没有 --prerelease 字面量、
必须调用 emit-bash、两个数组各喂 create/edit;④release.yml 的 dispatch 默认值 == false(读
YAML 结构)。`--self-mutation` 注入三项真实回归(默认值改回 true / 塞回字面量 / 表里 push
改成预发布),断言每项都红、基线绿。
版本:0.2.2 → 0.2.3(workspace `[workspace.package]` + 五处 path 依赖 pin + Cargo.lock)。
文档:README 中英两版版本行改 0.2.3,并把本阶段能力补进现有章节(Modrinth 匿名在线内容源、
自更新与稳定通道、整合包导入逐文件决策、实例级启动参数),删掉「没有自动更新通道」「导入只有
两份全局策略」两条过期说法;`release-notes.md` 写 0.2.3 的真实更新摘要(保留 {{VERSION}} /
{{SUMS}});`packaging/README.md` 与 `docs/build-and-ci.md` 里「push 默认仍 prerelease」的旧口径
全部改掉。
|
2026-11-07 18:56:01 +08:00 |
|
AskaEth
|
3b3430a93e
|
docs(termux): 对外口径升级——CPU 软渲染 + 自编 Mesa GPU 两条路径各真机验证一次(用户拍板 A,四处同步)
|
2026-11-07 09:33:24 +08:00 |
|
AskaEth
|
394faad611
|
docs(termux): MC 1.20.4 真机跑通结论与剩余项
- README:MC 标 ✅(glibc JRE + arm64 natives + softpipe);后续收敛为
zink/DRI3、剪贴板/IME、narrator/音频
- 构建文档 §4.2 补真机启动命令、窗口尺寸与日志位置、非致命项
|
2026-11-07 09:33:23 +08:00 |
|
AskaEth
|
7eed6c6261
|
feat(termux): MC 启动接线——Linux arm64 natives + softpipe 子进程环境
- Library::native_classifier:Linux/aarch64 上把 LWJGL3 的 natives-linux
改写成 natives-linux-arm64(Mojang 清单只有 x86_64)
- install::libraries:arm64 分类器在清单里没有下载信息时,按 Maven 相对路径
兜底到阿里云镜像(实测 Mojang libraries 404、Aliyun 200);
单测覆盖 arm64 兜底与 x86_64 不变
- launch::defaults:Termux glibc 构建启动 MC 时默认带
MESA_LOADER_DRIVER_OVERRIDE=swrast / LIBGL_ALWAYS_SOFTWARE=1(用户可覆盖)
- 文档:JRE patchelf 一次性步骤与接线现状;README 同步
- 验证:patched Temurin java 直接执行;LWJGL arm64+GLFW 探针 gl-ok
|
2026-11-07 09:33:22 +08:00 |
|
AskaEth
|
02ed09ae49
|
docs(termux): 补 MC 运行时结论(glibc JRE + LWJGL arm64 + softpipe GL)
- §4.2:Temurin 21 JRE 在 glibc 下跑通;AWT/X11 正常;
LWJGL 3.3.3 arm64 + GLFW + GLX/softpipe 端到端探针通过(GL 3.3)
- zink 仍卡 DRI3;softpipe 可用(软件 GL)
- README 同步:MC 标 🟡(栈已验证,启动器接线待做),后续改为接线 + DRI3
|
2026-11-07 09:33:22 +08:00 |
|
AskaEth
|
173a18b842
|
feat(termux): glibc 构建自动启用自编 Mesa 26 turnip ICD(GPU 打通)
- app/boot/termux_gpu:glibc 构建 + Termux 且随附 ICD 存在时,在探测前设
VK_ICD_FILENAMES/VK_DRIVER_FILES;用户显式设置不覆盖
- 文档:Mesa 26.2.6 + KGSL 的完整构建/安装/验证步骤(含 shebang、
--wrap-mode=nofallback、C++/链接参数三处坑)
- 实测:wgpu 选中 Adreno 840(turnip Mesa 26.2.6),截图首帧 61 ms
- README.termux:GPU 标 ✅,MC 标 🟡(glibc JRE+AWT 已验证,GLX 待 GL 构建)
|
2026-11-07 09:33:21 +08:00 |
|
AskaEth
|
bbb316ca08
|
docs(termux): GPU 结论落地——glibc 侧被驱动版本挡住
实测结论:
- glibc Vulkan loader + 自写 ICD 能加载
- Termux glibc Mesa 24.2.6 不认识 Adreno 840(chip 0x44050A31 unsupported)
- Arch vulkan-freedreno 26.2.6 能加载但 Linux/DRM 构建找不到设备(缺 KGSL,
/dev/dri 对 untrusted_app 被 SELinux 拒绝)
- GPU 变体会打印具名错误并自动降级 tiny-skia
README.termux 同步:GPU 标 ⛔、MC 走 glibc JVM 的结论与后续路线
|
2026-11-07 09:33:21 +08:00 |
|
AskaEth
|
c434dbe335
|
feat(termux): 横屏自适应窗口、安装后清理 apt 工作区、补分支 README
- app/boot/termux_window:Termux 上默认窗口按 X 屏幕等比自适应
(横屏铺满、竖屏不溢出,最大 2×;日志 source=termux-screen),
ULL_WINDOW_SIZE 覆盖与 1180×760 验收基准不变;5 条单测
- termux::install 成功后清理 $PREFIX/tmp/ull-java-termux(一次安装约 100 MB)
- 构建文档补 clippy/rustfmt 组件、cargo-clippy 目标被带成 android 的坑、
门禁命令、横屏行为与 openjdk-17 实测
- 新增 README.termux.md(分支定位/已验证矩阵/快速开始/边界/路线图),
两份主 README 的 Termux 条目链过去
|
2026-11-07 09:33:21 +08:00 |
|
AskaEth
|
48d1ee6616
|
feat(java): Termux 上自动安装系统 openjdk(内置镜像 + 隔离 apt 状态)
- 新增 game::java::termux:内置 SAU/TUNA/USTC/官方四个 termux-main 镜像,
按顺序 apt-get update+install;lists/cache 隔离在 $PREFIX/tmp/ull-java-termux,
不改用户 apt 配置;装完从 $PREFIX/lib/jvm 定位,幂等(已装则不走网络)
- JdkVendor 增加 termux(17/21/25),--vendor termux 只走系统包;
Termux 上缺省安装先试系统包,失败再走归档链并带出每一跳原因
- standard_roots 已能扫 $PREFIX/lib/jvm(上一条提交),装完即被 java list 发现
- CLI/presenter 的 vendor 展示与帮助文案同步;设置白名单与契约测试同步
- 文档补 Termux 上的 Java 行为
|
2026-11-07 09:33:19 +08:00 |
|
AskaEth
|
1e0fc44fed
|
docs(packaging): 记录 Termux glibc 构建与 termux-x11 运行配方
新增 packaging/docs/termux-glibc-build.md:glibc 工具链(Rust gnu 组件 +
patchelf + clang/lld + Debian libgcc crt)、构建环境(LD_PRELOAD/CA/USTC 镜像)、
termux-x11 运行与截图取证、GPU 现状与已知边界。
支持矩阵四处同步:Termux 行从「GUI 未验证」改为「源码自建、CPU 渲染单机验证过」,
仍标注实验级、不在发布矩阵内。
|
2026-11-07 09:33:19 +08:00 |
|
AskaEth
|
06fe12d811
|
chore(release): M154 版本升到 0.2.2(第一个稳定通道版本,D51)
- 根 Cargo.toml `[workspace.package] version` 0.2.1 → 0.2.2;`crates/{agent,app-iced,cli,palette-extract,
presenter}` 里 9 处 intra-workspace path 依赖的 version 约束一并对齐(M137 既定做法)。`crates/app` 是
workspace `exclude` 的 Slint 退役树,manifest 不参与解析,原样保留。
- Cargo.lock 由 cargo 再生成:只有 8 个 `unlucky-*` 成员条目从 0.2.1 变 0.2.2,第三方依赖(含版本号恰好
也是 0.2.1 的 hexf-parse / windows-link / windows-threading / xkeysym / yazi)一字未动。这一步不是可选:
CI 与发布流水线全走 `--locked`(ci.yml:236,274 / release-build.yml:135,142 / make_artifacts.py:50),
lock 不跟就是「tag 一打就红」。
- packaging 文档里的**示例 tag** 跟到 v0.2.2:docs/artifacts-and-version.md 两处(命名规则示例 + 「tag 说
X、产物里写 Y」的事故示例)、docs/build-and-ci.md 三处(`--version v…`、两次 `gh workflow run --ref v…`)、
docs/profiles-and-measurements.md 的「同一槽位现在叫 `unlucky-launcher_0.2.2_windows_x64.exe`」、
make_manifest.py 四处(Usage 示例 / `normalize_version` docstring / `--version` 的 argparse help)。
- **历史注记一律不动**:docs/runtime-deps.md 的「v0.2.1 首次真跑即红在工具链体检」(M140 事故记录)、
`.github/workflows/release.yml:71` 同一事故的另一处记录、`crates/core` 更新模块测试里的样本版本串
(`checker_cases.rs` / `version_cases.rs`,是解析器测试夹具,不是发布事实)、`microsoft.rs:224` 的
`21.0.13.0.2.1` 负例。
- README.md / README.zh-CN.md、packaging/release-notes.md 核实后**无需改动**:三份文件里没有任何写死的
版本号——下载表是 `<version>` / `<版本>` 占位符(M153 刚统一的口径,含非发布档位标「暂未发布」的行,
原样保留未回退),release-notes 正文是 `{{VERSION}}` / `{{SUMS}}` 模板占位符。
验证:`cargo check -p unlucky-cli --all-targets --locked` 过(编译日志里 unlucky-core/agent/cli 均报 v0.2.2)、
`cargo test -p unlucky-cli --lib --locked` 42 passed 0 failed、`cargo metadata --locked --offline` 过(全
workspace manifest + lock 一致)、`python3 packaging/make_manifest.py --self-test` ok、
`ull --version` 实跑输出 `ull 0.2.2(unlucky-cli)`。
|
2026-11-07 08:13:29 +08:00 |
|
AskaEth
|
7946e5b804
|
docs(readme,cli,packaging): M153 清账四条被排忘的文档类 finding
① README 两版下载表:linux-x64 / linux-arm64 / macos-arm64 / macos-x64 四行补「not yet published /
暂未发布」标记(与 M143 的 windows-arm64 行同款措辞),表后改成「本版只发布 windows-x64」的口径,
并说明发布 job 只留 PUBLISH_SLOTS 里的槽位(现住 release-publish.yml);顺带把「produced by the CI
matrix」那句改成「矩阵里有、默认发布跑不编、all_slots=true 才编来取证」。
② packaging/make_artifacts.py 两处 docstring 还写 windows-arm64 是 cross-built:按 M140 后的原生
windows-11-arm 事实改写。(release-notes.md 的同一说法在 M139/M142 已改掉,本次核实无残留,未再动。)
③ cli 缺 id 的 hint:删掉「(id 不进仓库)」并改成与 cli/help.rs 一致的「官方构建已内置、环境变量优先、
自建时构建期注入」;Secret 透传的事实留在同处代码注释。
④ README 两版文件清单表:release.yml 从「six-slot build / 六槽位构建」改成「两个 Windows 槽位原生
构建 → 只发布 windows-x64;all_slots=true 才整表六槽位取证」。
纯文案,不动任何构建或运行时逻辑。
|
2026-11-07 07:57:32 +08:00 |
|
AskaEth
|
f9607c1246
|
docs(packaging): M151 复审 P2-1 两处未决注释按 D51 定案改写(方案甲/六件套/v0.2.2 起适用)
|
2026-11-07 07:52:50 +08:00 |
|
AskaEth
|
e3ee20bdcd
|
feat(packaging): M151 发布流水线生成更新清单 manifest.json(D50)
清单挂 GitHub Release 资产,固定文件名 manifest.json(D50)。字段形状的权威是 M146 的
crates/core/src/update/manifest.rs(ReleaseManifest,deny_unknown_fields + 逐字段校验),
生成器只负责把那套形状填对,不另立 schema。
同源,不双写:packaging/make_manifest.py 的每个 sha256 直接读 Release 自己的
SHA256SUMS.txt,size 取自同一批文件的 stat();产物名里的版本段必须等于 --version,
tag 与 Cargo.toml 漂了就没有产物可对,当场失败。CI 在「裁剪发布白名单后重算
SHA256SUMS」之后调它,所以清单描述的是真正要发的资产,不是构建出来的全部。
make_artifacts.py 只加 --manifest 开关,用子进程调同一份脚本(本地跑也产出
manifest.json),本文件继续是产物命名的唯一真相源。
只放启动器产物:DTO 的 Artifact 没有角色字段,Release::artifact_for() 取第一个
target 命中的产物,把 ull 并列写进去会让「覆盖哪个文件」取决于数组顺序;ull 照旧进
SHA256SUMS.txt 与 Release。
url 两种形态:默认裸文件名(DirSource 口径,本地/内网用);CI 传 --asset-base-url
拼绝对地址并钉 tag(不是 latest),清单里每条都指向与它自报版本相符的字节。
自验:--self-test 用 packaging/tests/manifest.golden.json 逐字节对拍(覆盖裸 exe 与
tar.gz 两种形态,并钉住「ull 不进清单」),再跑 14 条负例证明严格解析不是摆设;
发布步会先跑它再产文件。真 DTO 对拍已在本机用 M146 的 ReleaseManifest 实测:
golden 解析通过(2 个产物、min_supported、force 均正确落位),14 条篡改全部被拒。
未决(报告带利弊,未自行改发布默认值):releases/latest/download/* 只指向非 prerelease
的最新 Release,而发布默认 prerelease=true。
Refs: D50, M146
|
2026-11-06 22:15:58 +08:00 |
|
AskaEth
|
5597a4cc18
|
feat(release,docs): M149 发布构建烘入微软登录 id(仓库 Secret),文档改为「官方构建开箱即用」
构建侧:release-build.yml 声明 on.workflow_call.secrets.ULL_MSA_CLIENT_ID(required: false),
cargo build 步以 env 注入它,option_env! 把它烘进二进制;release.yml 的 build job 按名显式透传
(与 PUBLISH_TOKEN 同一模式,不用 inherit)。真值放仓库 Secret,不进任何 git 文件;Secret 未录入
或 Actions 之外求值为空串时,client_id.rs 的 blank_env_value_counts_as_missing 保证「空白=没配」,
不会拿空 id 去联网。
文档:README 两版 / help.rs 的 accounts topic / packaging/release-notes.md /
packaging/docs/build-and-ci.md 统一成「官方构建已内置登录所需配置、开箱即用,仍可用环境变量
ULL_MSA_CLIENT_ID 覆盖;自建想自带就构建时注入」的功能性口径 —— 不出现 id 本身,也不出现归属描述。
client_id.rs 的模块注释与测试注释同步(原文写「id 不进仓库(用户定案)」,已随 Secret 方案改写),
并记下「别把 ULL_MSA_CLIENT_ID 导出到跑 cargo test 的 shell」——presenter 的 M132 入口锚会在
已烘焙 id 的构建里故意红。
实测:ULL_MSA_CLIENT_ID=<id> cargo build --bin ull 后,清空 env 跑 ull accounts add msa 打出
用户码与链接(无「未配置」提示);同二进制设一个假 env id 则 AADSTS700016 点名该假 id(env 覆盖生效)。
单测:core auth 28、unlucky-cli 全套、i18n 30、presenter 222 全绿;M132 锚在烘焙构建里按设计红、
在不带 id 的构建里绿。cargo fmt --all --check 通过。
|
2026-11-06 21:08:53 +08:00 |
|
AskaEth
|
fdb9ebb014
|
build(packaging): M147 新增 linux-check-docker.sh,本机复跑 ci.yml 的两条 ubuntu 门禁
`linux-smoke-docker.sh` 复刻的是 runtime-smoke(能不能真跑起来),本脚本复刻的是**编译期
门禁**(能不能编过 / 测过):`cargo clippy --workspace --all-targets -- -D warnings` 与
`cargo test --workspace --all-targets --no-fail-fast`,命令与 ci.yml 逐字一致。
为什么值得单独一条脚本:M144 的两条 ubuntu 红只在「Linux + --all-targets + -D warnings」
三件事凑齐时才炸,Windows 本机永远复现不了(那些 `#[cfg(target_os = "windows")]` 分支在
Windows 上都有使用者)。本脚本是「本机提前挡住它们」的唯一通道。
实现:在现成的 `ull-linux-smoke:bookworm` 上只加一层 `cmake` + `ninja-build`(`aws-lc-sys`
缺 cmake 编不过,M144 实测),缓存卷挂 `registry` 子目录(直接挂 /usr/local/cargo 会盖掉
镜像里的 cargo 本体,M62 踩过),Git Bash 路径用 `cygpath -m` 归一。
- `ULL_CHECK_STAGES`(默认 `clippy test`):两阶段各自跑完再汇总退出码,一处红不掩盖另一处;
`ULL_CHECK_FAIL_FAST=1` 恢复首错即停。
- `ULL_CHECK_TEST_ARGS`(默认照抄 ci.yml):快查用 `-p unlucky-app-iced --lib`。
- 每阶段打印 `<命令> → exit=<code>`,便于与 CI 注解里的码对照。
诚实边界写在脚本头:基础镜像 Debian 12 / runner Ubuntu 24.04,只对齐编译期判定,不覆盖
发行版差异面;也不跑 fmt / build / runtime-smoke。
M147 实测(本机 Docker / ull-linux-check:bookworm / 2026-11-06):
- `ULL_CHECK_STAGES=clippy` → exit=0(1m27s,原 14 条错)
- `ULL_CHECK_STAGES=test ULL_CHECK_TEST_ARGS='-p unlucky-app-iced --lib'` → 623 passed / exit=0
|
2026-11-06 20:07:04 +08:00 |
|
AskaEth
|
374e168334
|
docs(packaging): M145 按主题拆分 README(索引 + docs/,节号不变)
packaging/README.md 也是 400 行整,且安装包与自动更新马上要动发布线。按主题分成
「索引 + 5 份承载文件」,每份 ≤124 行:
- README.md 只留真相源声明、§1–§12 的索引表、§11、§12
- docs/artifacts-and-version.md:§1 产物矩阵 + §2 版本来源
- docs/build-and-ci.md:§3 怎么构建
- docs/runtime-deps.md:§4 运行时依赖 + §5 软渲染兜底
- docs/profiles-and-measurements.md:§6 构建档位 + §7 实测
- docs/compliance-support-boundaries.md:§8 合规 + §9 支持矩阵 + §10 已知边界
节号沿用原编号,所以全仓「packaging/README.md §N」式引用(根 README / README.zh-CN /
make_artifacts.py / release-notes.md / ci-runtime-smoke.md / release*.yml 注释)都不用改。
搬家由脚本按原文件切片生成,逐行可查:旧 README 400 行全部出现在新位置,唯一改写的
旧行是 §12 清单里那两行(文件清单必须反映拆分后实况)。新增行 15 条:索引段、§3 的
M145 说明、§12 的 5 份新文件行。
|
2026-11-06 19:29:47 +08:00 |
|
AskaEth
|
a70e901bea
|
ci(release): M142 发布白名单只留 windows-x64 + 修掉诊断脚本在 -e 下先退出
1) PUBLISH_SLOTS 去掉 windows-arm64:白名单齐全性检查是「名单内少一档就 fail」,
arm64 连试四轮未成 ⇒ Release 永远 fail、x64 编成功也发不出去。arm64 仍留在矩阵里
照跑取证(诊断注解保留),红不挡发布;修好后把键加回这一行即可(一行可逆)。
2) 修 M141 自毁 bug:`shell: bash` 是 `bash -eo pipefail`,脚本里的 `set -uo pipefail`
关不掉 -e,于是 `vc_lib=$(find 不存在的根 | head -n1)` 被 pipefail 判非零后 errexit
当场退出,一条注解都没打(上一轮只剩 exit code 1)。现在显式 `set +e`、每处探测
`|| true`、问题记进 ERRORS、4 行实况快照无论齐不齐都先打完,再由显式 exit 定红绿;
齐全时快照降级为 notice(绿跑也留「探测没坏」的证据)。
3) 新增 arm64 失败收尾注解步骤(`if: failure()`),红在其他步骤时也能说清红在哪、不影响 x64。
4) packaging/README.md §1/§3/§4/§7.5/§9 与 release-notes.md 的 Downloads/Support matrix/
Install 同步为「当前只发布 windows-x64,arm64 待修」。
|
2026-11-06 12:30:07 +08:00 |
|
AskaEth
|
5678683561
|
fix(release): M140 r1 复审三条 p2 —— vswhere -find 单值、根因措辞、SDK 双根
P2-1(真缺陷):`-find` 是单值参数,老写法 `... "${find_args[@]}"` 一次传 4 个
`-find`,官方定位器只认其中一个(复现:last-wins 下取到 Hostx64),
所以 round-1 新加的「ARM64 优先 → Hostarm64」在 vswhere 分支上从未执行。
改成每个 pattern 各起一次定位器,不赌取值规则;注释同步为真话。
P2-2(措辞):README §4 不再声称 v0.2.1 那次是「x64 镜像缺库」——windows-2025
镜像清单里 VC.Tools.ARM64 与 SDK 26100 都在,根因未定论,更像自检的路径探测;
§7.4 的 dumpbin 门禁补一句覆盖 windows-latest 与 windows-11-arm 两个镜像。
P2-3(放宽):arm64 库体检的 SDK 侧也改成两个安装根(Program Files (x86) 与
Program Files),把「路径猜错 → fail-closed 误报」这个正是本次事故的形态再降一档。
行数:release.yml 400 / README 400(均 ≤400);PUBLISH_SLOTS 未动。
|
2026-11-06 11:59:31 +08:00 |
|
AskaEth
|
b27e86c65b
|
ci(release): M140 windows-arm64 改用原生 windows-11-arm runner
交叉编译路线在 CI 上从未成功过一次:v0.2.1 首次真跑即红在
「Windows ARM64 交叉工具链体检」(windows-latest 上探不到 VC/SDK 的
ARM64 库),故按文档标准 runner 表把 arm64 槽位改成原生
windows-11-arm(公开仓免费,4C/16G),产物回到 target/release。
- 槽位表:windows-arm64 os=windows-11-arm、build_dir=target/release;
无交叉槽位后 target 键与 rustup target add / cargo --target 一并删掉
- 体检步骤重写为「Windows ARM64 工具链体检」:失败时打印实际探测到的
VS 根、VC arm64 lib 目录、SDK 的 um/arm64 目录;SDK 不再只认
tail -n1 挑出的单一版本(全版本里找)
- dumpbin 定位链补 Hostarm64/arm64 分支,按 RUNNER_ARCH 选宿主工具族
(x64 上绝不挑 arm64 二进制),vswhere/find/PATH 三级与硬门禁不变
- packaging/README.md §1/§3/§4/§7.5 同步原生化与冒烟真跑的说法
|
2026-11-06 11:51:01 +08:00 |
|
AskaEth
|
9de51e16af
|
ci(release): M139 发布 CI 只跑两个 Windows 槽位,整表六槽位改为手动取证
build 矩阵从六个槽位裁到 windows-x64 / windows-arm64 两个:
- 矩阵改由新增的 `plan` job 生成(`fromJSON(needs.plan.outputs.matrix)`),槽位表只在该
job 里有一份,`mode: ci` 默认编、`mode: probe` 只有 `all_slots=true` 才编;
- `workflow_dispatch` 新增 `all_slots` 布尔输入(默认 false = 只跑 Windows),
Linux/macOS 四档保留完整定义与打开办法(改 mode 一行),取证能力没删;
- `PUBLISH_SLOTS` 不变(两个 Windows 槽位);齐全性检查仍按下载下来的产物判,
白名单槽位没编/编挂就 fail,不会因矩阵变小而永远过;
- packaging/README.md §1/§3/§4/§9 与 release-notes.md 的 Downloads / Support matrix
同步成「四档默认不构建」,不留「六槽位都构建」的旧说法。
|
2026-11-06 11:33:52 +08:00 |
|
AskaEth
|
54b81cbb7f
|
chore(release): M137 版本升到 0.2.1,发布只发两个 Windows 槽位
版本:`[workspace.package] version` 0.2.0 → 0.2.1,并把全部 intra-workspace path
依赖的 version 约束一并对齐(`"0.2"` → `"0.2.1"`,M121 的教训)。Cargo.lock 里只有
8 个 unlucky-* 成员条目变化。`crates/app` 是 workspace `exclude` 的 Slint 退役树(manifest
连解析都过不了),不参与解析,故原样保留。
release.yml:新增 `PUBLISH_SLOTS` 白名单(唯一开关)= `windows-x64 windows-arm64`。
六槽位一律构建取证,release job 先按白名单裁掉 Linux/macOS 四档产物再重算 SHA256SUMS,
所以 tag 触发的 Release 只有 4 个资产 + SHA256SUMS.txt。release job 改成
`always() && !cancelled()`:未验证槽位构建失败不连坐 Windows 发布,真正的门禁是白名单
齐全性检查。将来某槽位真机验过后把它加进那一行即打开。
顺手修掉一处从未生效的门禁:齐全性检查的 glob 用的是连字符形态
(`dist/$prefix-*-$slot*`),对 D49 之后的下划线资产名永远匹配不上,改成
`dist/${prefix}_*_${stem}*`。资产命名规则 / SHA256SUMS / 合规文本并列资产 /
`--version` 与 tag 交叉校验一律未动。
packaging/release-notes.md:清掉 v0.1.0 / Slint 时代的说明,Downloads 与 Support matrix
只描述本版实际发布的 Windows 两个槽位(其余标「built by CI, not published」)。
packaging/README.md §1/§3/§9 同步 gate(矩阵加「本版发布」列、§3 写清白名单与打开办法)。
起手顺带把示例 tag 从 v0.2.0 更到 v0.2.1,并把「winit / femtovg」更正为「winit / wgpu」。
|
2026-11-05 21:30:13 +08:00 |
|
AskaEth
|
3bc6d76b84
|
docs(readme,release-notes): M136 缺 client id 的对外文案改成现行行为
M132 之后界面已经直接说「微软登录未配置 + 要设 ULL_MSA_CLIENT_ID」并刻意不给重试按钮,
而 README / README.zh-CN / release-notes 还写着「只会弹通用登录失败 + Code: other」——
那是修前行为。三处改成:标题/正文/Code: msa_not_configured/无重试,并保留「其余失败
仍只给分类文案 + 码,原文只进日志」这半句(那是真的,也是有意的)。
|
2026-11-05 20:10:10 +08:00 |
|
AskaEth
|
592f0c26f6
|
docs(packaging): M131 压回 400 行内,删 Slint 遗留祈使句/软渲染块,修 smoke 脚本 bin
- packaging/README.md 401 -> 398 行(回归 file-size 红线内)
- §5 删 SLINT_BACKEND=winit-software 命令块;现役入口改注 iced 的 --software-renderer
- §8 删「关于页保留 AboutSlint、不得移除」两句祈使句,只留 v0.1.0 资产事实段
- §7 抬头标明连字符产物名属哪次实测(现名形态写下划线 0.2.0),§7.3/§7.5 同步标注
- §11 删「该脚本现在会失败」的过期提醒,记录 M131 真跑证据
- linux-smoke-docker.sh: --bin/产物路径/target 全改 unlucky-launcher-iced(cargo clean -p 同步改
unlucky-app-iced,原来的 unlucky-app 已被 workspace exclude、清不掉陈旧产物)
|
2026-11-05 18:03:20 +08:00 |
|
AskaEth
|
5a9d67530a
|
docs(packaging): M129 r1 P1-1 —— MSA 那段改成 GUI 现有行为,不再写「界面会告诉你怎么配」
复审 r1 把链路走了一遍:core 缺 id 早退(零网络)成立,但 presenter 的 fail() 只把原文
eprintln 进日志,事件只带原因码 Other;账户页据此画通用横幅「Sign-in failed」+「Code: other」,
完整原因在日志里。LaunchMsaNotConfigured 那条 i18n 目前只有定义/单测/golden,GUI 零调用点。
所以上一版「the app says "not configured" (with the command to fix it)」是把设计意图写成了现有行为。
改成分段如实描述:无 id 时在联网之前就停;GUI 显示通用横幅 + Code: other(原因在日志);
`ull accounts add msa` 会打出可照抄的修复命令(map_auth_error 的 hint,含变量名与 cargo build)。
另按 r1 P2-1 给 macOS 补 shasum 校验行(sha256sum 不是 macOS 自带)。
|
2026-11-05 18:00:55 +08:00 |
|
AskaEth
|
59eefdb052
|
docs(packaging): M129 发布说明重写到现行事实(下划线资产名 / MSA client id / 删 Termux 下载引导)
资产名全部改成 make_artifacts.py::asset_stem() 的 `名字_版本号_平台_架构`(下划线):
六行矩阵、ull 资产、tar 包名与解压出的顶层目录、PowerShell 校验命令。旧的连字符名
按文档下载会 404(D49 2026-11-05 改名,文档没跟)。
删掉「微软登录等 Mojang 白名单审批」整条(白名单 2026-11-03 已批准并真机验签),
换成真缺口:发布版不带 Azure 公共客户端 id,要 ULL_MSA_CLIENT_ID(环境变量或构建期
注入),未配置时界面说「未配置」而不是静默失败。不写任何 id 值。
Termux:删掉「下 ull 资产」的引导(ull 的 Linux 资产是 glibc 版,Android/bionic 上跑
不起来),矩阵行只留「构建自源码、GUI 未验证、不在本发布矩阵」。
顺带清掉三处过期陈述:Windows 数据根(原文说有 `portable.marker` 就便携、否则落
%APPDATA%——实际 portable 是默认模式,首次运行在 exe 旁建 .ULL/ 与 .minecraft/);
CLI 子命令表漏了 `pack import`;arm64 行里的内部决策编号 D21。124 → 107 行。
|
2026-11-05 17:54:18 +08:00 |
|
AskaEth
|
bf6b0c4126
|
build(release): workspace 版本 0.1.0 → 0.2.0,README 的 tag 事实改成 v0.2.0 口径
- Cargo.toml [workspace.package] version = 0.2.0;Cargo.lock 由 cargo 重新解出一致
(只有 8 个 unlucky-* 成员条目变动,第三方版本一字未动)
- 各 crate 的 `unlucky-*` path 依赖 `version = "0.1"` 同步提到 "0.2",否则工作区
根本解析不出来(cargo metadata 会报 `failed to select a version for
unlucky-core = "^0.1"`);crates/app 虽被 exclude、cargo 不读,也一并跟上避免将来
重新纳入时立刻解析失败
- core::launch::LauncherConfig 兜底的 launcher_version 改成 env!("CARGO_PKG_VERSION"),
不再是把版本写死一份(CLI / presenter 本来就这么写)
- README.md / README.zh-CN.md:删掉「v0.1.0 是目前唯一的 tag / the only tagged release」
这类随 v0.2.0 发布即变假的陈述,改写成「v0.1.0 是最后一个 Slint 版 tag,v0.2.0 是
重写后的第一个 tag」;所有讲 v0.1.0 资产 / Slint Royalty-Free 义务的历史记录原样保留
- packaging/README.md:命名与校验示例跟当前 tag 走(v0.2.0);§7 实测记录里的 0.1.0
输出加一句「属实测记录、不回填」,并把过期的「四个 workspace member」改成「任何一个」
|
2026-11-05 14:08:37 +08:00 |
|
AskaEth
|
6a5c54102e
|
build(packaging): 产物改名成 名字_版本号_平台_架构
用户令:产物名不带实现细节字样(不出现 iced),格式统一成
`<名字>_<版本号>_<平台>_<架构>`,下划线分段。
- make_artifacts.py 新增 asset_stem() 作为唯一真相源;Windows 裸 exe 那条
路径原来还硬写着旧格式,一并改掉
- release.yml 的 sha256sum 与 assets glob 从 unlucky-launcher-* 改
unlucky-launcher_*(不改会因匹配不到而漏传产物)
- packaging/README.md 矩阵六行同步,并记下:Linux/macOS 仍为 tar.gz,
理由是许可文本随包 + tar 保留 755 可执行位
本地已跑通:unlucky-launcher_0.1.0_windows_x64.exe 14.44 MiB +
ull_0.1.0_windows_x64.exe 6.18 MiB + SHA256SUMS.txt。
|
2026-11-05 11:54:18 +08:00 |
|
AskaEth
|
e827f7a0ef
|
fix(docs): M118 r2 —— 发布页第二形态换成实测可用的 --renderer=cpu,NOTICE 停止声称 RF-2.0 已履行
复审 r2 的 2 条 P1 + 3 条 p2 小账,全部只动文档(5 份,0 个 .rs)。
P1-1(`SLINT_BACKEND` → `ICED_BACKEND` 换了个名字的死开关):
`packaging/release-notes.md` 的「No GPU」小节原来把 `ICED_BACKEND=tiny-skia` 当作
`--software-renderer` 的等价替代命令给用户。实测该值会被本进程无条件覆盖:
- `ICED_BACKEND=tiny-skia ./unlucky-launcher-iced.exe --screenshot …`
→ `[probe] … request=auto -> ICED_BACKEND=wgpu` / `[shot] … renderer=wgpu` / `[backend] final=wgpu`
- `--software-renderer --screenshot …` → `request=cpu -> ICED_BACKEND=tiny-skia` / `renderer=tiny-skia`
- `--renderer=cpu --screenshot …` → `request=cpu -> ICED_BACKEND=tiny-skia` / `renderer=tiny-skia`
所以改成两条都实测可用的形态(`--software-renderer` / `--renderer=cpu`),不再把环境变量当用户开关。
P1-2(RF-2.0 履行方式的措辞与上游 §2 冲突):
`NOTICE` 第 1 条原写「由 v0.1.0 的 NOTICE、发布页说明与本文件的历史记录共同承担」——§2 只承认
(a) AboutSlint 部件 / (b) 公开下载页的官方徽章两种履行,NOTICE 文本不是履行。改为:义务仍挂在
v0.1.0 已发布资产上(条件挂在每次分发,不挂版本号);§2 只承认两种形式;**按本仓库记录,该项义务
在 v0.1.0 上尚未以任一形式落地**(部件一直只有排期,发布页那行是文字链接不是徽章图);NOTICE /
发布页说明 / 本节都只是记录。
p2 小账:
- `NOTICE` 第 3 条的依赖许可:`tiny-skia` 从「Apache-2.0 / MIT」改正为 BSD-3-Clause,并把
winit(Apache-2.0)/ wgpu(MIT OR Apache-2.0)分别写明;README(中英)同款写法一并对齐。
- `packaging/README.md` §4:`libGL/libEGL` 行改成「Slint 版 femtovg / iced 版 wgpu(推断,未实测)」,
并把限定语改成「除标注『推断,未实测』的那一行外,整表是 Slint 版实测」,消除表内与限定语打架。
- `README.md` / `README.zh-CN.md` 的 Slint 义务段补 `v0.1.0` 限定并按 §2 口径重写,避免读者以为
「Made with Slint」说的是下一版。
证据:`git diff --name-only` = NOTICE, README.md, README.zh-CN.md, packaging/README.md,
packaging/release-notes.md;`packaging/README.md` 仍 399 行(守卫上限 400);release body 模板用
`{{VERSION}}=0.2.0` 渲染通过(5956 字符,全篇 Slint 命中 4 行,均在「本版不含 Slint」的解释段)。
|
2026-11-04 00:09:39 +08:00 |
|
AskaEth
|
7704a75424
|
fix(docs): M118 r1 —— release notes / NOTICE 停止自称 Slint 版,packaging README 补两处旧口径限定语
复审 r1 的两条 P2,都只动文档(`packaging/release-notes.md`、`NOTICE`、`packaging/README.md`)。
P2-1(发版阻断项):`packaging/release-notes.md` 是 Release body 模板,`NOTICE` 装在每个 tar.gz 里,
两者都仍自称 Slint 版:
- release notes:首段 `Slint + Metro UI` → `iced 0.14 + Material 3 Expressive UI`;「No GPU」小节从
femtovg / `SLINT_BACKEND=winit-software` 改成 wgpu + tiny-skia / `ICED_BACKEND=tiny-skia`;
删掉页面的 `Made with Slint` 徽章声明,换成「本版所有资产都由 iced 构建、不含 Slint 代码;
Slint 版源码仅作历史参考、不构建不发布;RF-2.0 徽章义务跟着链接 Slint 的二进制走,本版没有」。
- NOTICE:第 1 条标题改「Slint —— 历史源码,不随任何产物分发」,正文明确「当前 GUI 框架是 iced、
二进制不含 Slint 代码;crates/app 已被 workspace exclude,不参与构建/测试/发布」;RF-2.0 义务改成
「对当前产物不适用,仍挂在 v0.1.0 那批已发布资产上」。**没有整条删除**:仓库里确实还有基于 Slint
写的历史源码,且将来若重新链接 Slint 义务要恢复,留记录比删掉更安全——依据写进报告。
另在第 3 条补一句「当前 GUI 框架:iced 0.14(MIT)+ winit / wgpu / tiny-skia」。
P2-2:`packaging/README.md`(净零行,仍 399 ≤400)
- §4 的 `libGL/libEGL` 说明从 femtovg 改成 wgpu 的 GL/EGL 后端 + tiny-skia 软渲染,并加一段
「M118 口径」:那张表与 DT_NEEDED 结论是 Slint 版实测,iced 版**尚未重测**,按「同一族库、细节待验」读。
- §11 的本地复跑命令补限定语:`linux-smoke-docker.sh` 仍编/跑 Slint 版 bin,现在会失败;在它换成
`unlucky-launcher-iced` 之前,本地照 ci.yml 的 runtime-smoke 三步手跑。段落未删。
证据:`git diff --name-only` 仅这三份;release-notes 的 `{{VERSION}}`(15) / `{{SUMS}}`(1) 占位符仍在,
模板渲染走查通过;`packaging/README.md` 399 行(守卫上限 400)。另按复审要求二次单跑
`cargo test -p unlucky-core --test launch pipeline_records_crash_report_artifact` → ok(0.16s)。
|
2026-11-04 00:09:39 +08:00 |
|