Commit Graph
10 Commits
Author SHA1 Message Date
AskaEth 2b6dcbed40 fix(m187): r2 复审 p2——截断过的文件也必须脱敏(截断 改到文本流里做)
r2 复审挖到的隐私旁路:上一版在**字节**上切两刀,切在多字节字符中间时
String::from_utf8 失败 ⇒ 整份 entry 走「原样字节」分支,家目录 / 用户名 / 令牌原文
按字节进包,而清单什么也不说。命中的正是最容易超过 4 MiB 的 latest.log 与会话 JSONL;
中文 Windows 用户名(C:\Users\张三)让家目录串本身就是 CJK,切点落在附近必然命中。

修法(比复审给的三条更严一点:先脱敏再截断,避免切点留下半截 secret):
解码(lossy,任何字节都能进脱敏器)→ 脱敏整份 → 按**字符/行边界**截断 → 插截断标记。
新增 crash_bundle/clip.rs(切点逻辑 + 4 条用例),write_bundle 里只剩一条通路,
「二进制原样」这条分支彻底删除。

守卫:truncated_entries_are_still_redacted —— 造一个 '中' 正好跨在 HEAD_BYTES 上的
4 MiB+ 文件,内含注册过的会话 id 与家目录;断言 ①包里找不到原文 ②<home> 在
③尾部 exit 事件仍在。变异(改回字节级截断 + 仅解码成功才脱敏)⇒ 红在「仍带着家目录原文」。

顺带:
- P3-1 启动日志写两遍(WindowHandle(None) 分支重复调 record_boot_log)→ 删掉重复调用。
- P3-2 清单里的截断字节数改成**实际保留量**(原来报的是常量 HEAD_BYTES)。
- P3-4 truncated>0 时界面那句话补用例(拆出 dialog/tests/export.rs,两个文件都 < 400 行)。
- P3-6 BundleSpec::manifest() 自己也过脱敏,去掉「谁调谁泄漏」的口子。
- P3-5 卡片宽度取官方上限 560 的语义在代码里写清(不改行为,登记为台账)。
2026-11-08 23:57:49 +08:00
AskaEth 3cd371b537 fix(m187): r1 复审——深色遮罩提亮、点遮罩关闭、包内条目名、截断保尾、启动日志接线
P1(阻断):遮罩从 Role::OnSurface@32% 换成组件层的不透明预合成
(feedback::dialog::scrim,黑@0.32 叠画布)。深色档此前是「近白@32%」把整窗提亮,
实测 (9,21,28)→(129,138,145);现在 (6,14,19)(= 组件文档预测值),且两后端逐字节相同。
顺带按纪律改用 Component::Dialog + DialogGeometry(半径 28 / 宽 560 / 内距 24),
两后端弹窗图差异从 66% 降到 2.65%(浅)/ 2.76%(深),余量全是文字抗锯齿。

P2-1:卡片那层的命中区改回卡片本身(opaque 只包卡片)。此前 mouse_area 包的是整窗居中
容器 ⇒ 点卡片外先被 Swallow 捕获,遮罩永远收不到,「点遮罩关闭」只在注释里成立。
守卫:断言卡片层的 size_hint 任一维都不是 Fill。

P2-2:条目名与清单**同源**(BundleSpec::entry_names),会话 JSONL 钉成 session/session.jsonl。
此前条目名用原始文件名(会话 id 原样进包)而 manifest 过了 redactor ⇒ 清单指向的条目不存在。
(上一轮报告把这条写反了,本轮以 unzip -l 实输出为准。)

P2-3:截断改「头 + 尾」(MAX_ENTRY_BYTES 一半一半,中间插 <truncated N bytes>),
并在弹窗补一句「有 N 个文件太大,已截断」。此前只留头部 ⇒ 长会话 JSONL 的 exit 事件丢失。

P2-4:app 启动那一拍(主题/语言/路由/窗口/实例数/msa 行)真的写进 launcher_log;
目录仍由 presenter 在首次启动时登记,所以这些行先进 core 缓冲、登记时一次刷出。

P3-1/P3-2:关闭与 Esc 立即重画(否则空闲 1Hz 下弹窗再留 1 秒);导出成败按 write_bundle
真实结果判(不再看 launcher_logs 有没有值)。

用例:新增 5 条(深色遮罩方向、卡片层命中区、条目名与清单一致、截断保尾、启动日志落点),
每条都给了变异证明(只改实现侧,均已还原)。
2026-11-08 23:21:26 +08:00
AskaEth 414f6ff886 feat(m187): 启动失败弹窗 + 诊断包导出,并接通 DialogQueue
用户实测「MC 启动失败找不到崩溃日志」的直接修法:失败时弹一个框,把退出码、
一句人话原因、证据形态、四条真实路径与三个按钮摆在同一个地方。

- app-iced:最小一层模态(遮罩 + 卡片 + 主/次按钮 + Esc/点遮罩关闭),
  消费 presenter 的 DialogQueue(此前全仓零引用,所有弹窗都画不出来);
  队列管弹窗,CrashCard 管这次失败的事实,按 DialogId 绑定。
- 弹窗区分两种失败:游戏自己写了 crash-reports(贴 Description + 栈片段)/
  游戏没来得及写(明说「这次没有生成崩溃报告」并贴出捕获的最后 30 行)/
  什么都没抓到(给最可能原因分类)。绝不对第二种说「找不到日志」。
- 导出诊断包:core 侧新 crash_bundle 写 zip(清单 + 启动器日志 + 会话 JSONL +
  crash-reports/* + hs_err + latest.log + 版本 JSON),落盘即脱敏(家目录 / token /
  会话 id),单文件 4 MiB、总量 48 MiB 上限并在清单记截断。
- 启动器自身日志落盘(core::launch::launcher_log → <.ULL>/logs/launcher.log,
  登记目录前先缓冲),补上「双击启动时诊断行直接蒸发」的缺口。
- i18n:25 条中英文案进 catalog/logs.rs + 金表。
- 取证:ULL_DIALOG_FIXTURE=crash-report|no-logs|export 在临时目录造真文件出图,
  wgpu 与 tiny-skia 各一套,见 DevDocs/artifacts/m187/。

未复现 M190 的「owned 文字在 wgpu 下丢字」:同一串中文两条文字路径、两种后端逐字相同
(ab-wgpu.png / ab-tinyskia.png),因此本轮未改任何渲染路径。
2026-11-08 22:42:00 +08:00
AskaEth ee67965b9b fix(m157): r4 修复未收集的周快照用例 + 两处 clippy 红,并补整环回归(复审 p1-2)
P1-1 crates/core/src/launch/overrides/tests.rs:modded_weekly_snapshot_needs_the_root_version_for_the_gate 原先写在 backend_allowed_combines_capability_and_threshold 函数体内(unnameable_test_items,永不执行)。移到模块层;移动后首次真正执行暴露出用例自身的 EmptyJavaPath(AdapterOptions 默认 java 为空),补 JavaSelection 后绿。--list 现在 10 条 launch::overrides::tests::(含该名字)。

P1-2 clippy -D warnings 两处:cli/commands/instance_launch.rs needless_borrows_for_generic_args(去 &);presenter/mock_data.rs items_after_test_module(mock_launch 移到 mod tests 之前)。

P3-a 新增整环回归 app/tests/instances_save_loop.rs:真 Message → dispatch → 后端回错误 Toast → pump → refresh_view → sync_launch_form,断言 4g 草稿与脏标记都还在。
P3-b LaunchForm::matches 内存改按数值比(解析失败退文本),补 memory_is_compared_by_value_not_by_text(04096 / +4096 / 清空三档)。
P3-c 门槛文案不再在 catalog 硬编码 26.2:InstancesLaunchBackendGated 改用 {min} 占位符,页面从 LaunchFacts::min_version(← core GRAPHICS_BACKEND_MIN_VERSION)代入;金表同步;灰化态截图重拍。
2026-11-07 11:06:18 +08:00
AskaEth 211e07b470 fix(launch): M157 r3 周快照门限按继承根版本 + 保存失败保留草稿(复审 P2-1/P2-2)
P2-1 周快照 + 加载器的 --graphicsBackend 静默丢失:presenter host::launch::build_request 与 cli snapshot::prepare 给 SnapshotInput.game_version 传 None,装配按带加载器后缀的 version_id(26w14a-fabric-0.16.5)判门限,GameVersion::is_weekly_snapshot 的 6 字符形态认不出来。两个调用点改为传继承链的 MC 根版本(25 行注释说明「门槛与拼装必须同一口径」)。回归:core launch::overrides 的周快照实际装配用例(正/负两档)、presenter host::launch::tests、cli snapshot::tests 各一条根版本断言。

P2-2 保存失败丢草稿:app/update/instances.rs 的 Save 分支派发前就把 launch_form.dirty 清掉,失败事件后 pump 用旧快照重建视图并覆盖表单。改为派发不清脏;LaunchForm::sync 只在「回程快照已等于表单」(= 落盘确认)时清脏并重播种,否则保留草稿。回归:failed_save_keeps_the_draft / confirmed_save_clears_dirty_and_reseeds / save_dispatch_keeps_the_dirty_flag。

顺带:launch::overrides 测试拆到 overrides/tests.rs(守 400 行)。
2026-11-07 10:36:37 +08:00
AskaEth e2021645d7 feat(launch): M157 实例级启动参数(五项回落 + graphicsBackend 三态)
core: 新增 game/launch_overrides(LaunchOverrides 五项 All-Option + 三级回落 + 文本补丁校验)与 launch/overrides(拼装落位:全局 java.extra_args 进 user.jvm、实例 jvmArgs 进 override_jvm、gameArgs 进 user.game、memory 进 -Xmx、backend 进 --graphicsBackend 并复用既有版本门槛告警);实例 schema 登记 launch.* 五键。

presenter: dto/LaunchArgsView+LaunchArgsPatch,主机侧读/写与门槛判定(backend_allowed),AppCommand::SetInstanceLaunchArgs。

cli: 新命令 instances launch-args(读/写/--clear),launch 装配链消费回落值。

app-iced: 实例详情页「启动参数」区(JVM/游戏参数、内存、Java、三态后端 chips + 灰化提示 + 保存/恢复),表单状态归 App、i18n 中英文案同步。
2026-11-07 10:36:35 +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 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 6ce825db8d fix(launch): M48 —— POSIX 组杀假成功导致 stop() 空等超时
CI test (ubuntu-latest) 自 M43 起红的根因不是「组杀打到自身进程组」,
而是 procps-ng 的 kill 把裸 `-<pgid>` 当成又一个信号选项吞掉:退出码 0、
什么都没发。旧实现据此提前 return,单 pid 兜底永远不执行,于是
process_smoke::stop_kills_process_tree 与
pipeline_cases::pipeline_stop_records_killed_exit 只能干等
graceful+5s 预算后报「强制结束后进程仍在运行」。

- process.rs:Unix 分支用 CommandExt::process_group(0)(std 1.64+ 安全
  API,无需 pre_exec/unsafe)让子进程自成一个进程组,与 Windows 的
  CREATE_NEW_PROCESS_GROUP 对称;这也让「树」回收真正覆盖后代。
- tree_kill.rs:组杀改用 `kill -TERM -- -<pgid>`(`--` 不可省),并且
  先过 group_kill_target 三重验证——目标必须是自己的进程组组长、必须
  读得到我们自己的组、目标组不能就是我们所在的组;单 pid 兜底改为
  「永远执行」,kill 缺失(NotFound)返回明确错误而不是静默失败。
  pid==0 守卫从 kill_tree 提到 terminate/force_kill 共用入口。
- 测试钉子(Linux 门住):spawn 后子进程 pgid == 自己的 pid 且 !=
  测试进程 pgid;组杀只接受验证过的独立组;组杀覆盖孙进程且不碰我们
  自己的组;同组子进程靠单 pid 兜底仍能被干掉;pid 0 一律拒绝。

验证:rust:1-bookworm 容器(ull-linux-target 热缓存)cargo fmt --check、
cargo clippy --workspace --all-targets -D warnings、cargo test -p
unlucky-core --test launch(82 passed,两条原红灯转绿)、cargo test
--workspace --all-targets --no-fail-fast 不再被 SIGTERM 打断;Windows
本机 fmt/clippy/cargo test -p unlucky-core 全绿。
2026-11-01 10:32:18 +08:00
AskaEth bc41dfcf7d Unlucky Launcher v0.0.1-alpha
CI / fmt (rustfmt --check) (push) Canceled after 0s
CI / clippy (ubuntu-latest) (push) Canceled after 0s
CI / clippy (windows-latest) (push) Canceled after 0s
CI / test (ubuntu-latest) (push) Canceled after 0s
CI / test (windows-latest) (push) Canceled after 0s
CI / build release (ubuntu-latest) (push) Canceled after 0s
CI / build release (windows-latest) (push) Canceled after 0s
Guards / core 零 UI 守门 (push) Canceled after 0s
Guards / 文件行数 ≤400 守门 (push) Canceled after 0s
Guards / 依赖许可与来源(cargo-deny) (push) Canceled after 0s
Rust 原生单文件 Minecraft 启动器:CLI 完整可用(install/launch/accounts/java/diagnose/agent),
MCP server 接入外部 Agent 工具,GUI 开发中。
2026-10-31 21:54:10 +08:00