D4:`pick` 的排序键从「来源序」改成「版本距离 → 来源序」,全不满足时选最接近要求的那个 (托管 25 与 JAVA_HOME/扫盘 17 之间选 17,而不是按 rank 选托管)。新增 `select::decide`: 不符且**没有人显式指定 Java** 时 `ull launch` 直接报 `java_mismatch` 不 spawn(`--java` / 实例 `javaPath` 是豁免,只告警)——1.12.2 配 Java 17/25 必然起不来,警告没有信息量。 `JavaMismatch` + `check` 拆到 `mismatch.rs` 并加 `advice()`(mapping.rs 408→282 行)。 D6:`LaunchSession::finish` 的等进程改成**有界**。判据在 `startup_watch.rs`(纯逻辑): ①窗口从未出现且**连续 N 秒没有任何日志**(还在打日志就说明还在加载,慢加载不被判死); ②日志出现关闭标记后 N 秒仍未退出(实机「关窗后 java.exe 仍存活」的形状)。 到点只**停止等待、绝不杀进程**:写 `session_end(still_running)` + 索引 + `launcher.log`, 返回 `LaunchError::Watchdog`,CLI 翻成 `launch_timeout`。两个时长可配 (默认 300s/60s;`ULL_LAUNCH_STARTUP_TIMEOUT_SECS` / `ULL_LAUNCH_SHUTDOWN_GRACE_SECS`, 生效值每次启动写进 launcher.log 与人读输出)。 D10:把「被终止」与「应用错误」分开。①我们自己杀的:`tree_kill` **送达即登记** `kill_registry`(pid 登记簿,取走语义、上限 64),覆盖 GUI 从别的线程 `kill_tree` 的路径, `finish` 据此判 `killed`;②外部强杀:Windows 上「退出码 1 + 零错误输出 + 无崩溃/JVM 关键字」 判 `killed` 并标 `terminated_externally`(任务管理器与 `taskkill /F` 都是 `TerminateProcess(h, 1)`,应用真崩给的是 NTSTATUS 异常码)。 顺带:`SessionHandle` 拆 `session_handle.rs`(launch_session.rs 422→343 行)、 `NativesReport::to_json` 落 core(cli/launch.rs 腾出空间,仍 399 行)。 用例:select 距离/取舍、startup_watch 状态机、watchdog_cases(4 条真进程)、 exit_cases(外部终止与「我们杀的」区分)、pipeline 跨线程 kill。
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 全绿。
Rust 原生单文件 Minecraft 启动器:CLI 完整可用(install/launch/accounts/java/diagnose/agent), MCP server 接入外部 Agent 工具,GUI 开发中。