Merge branch 'feat/m130-readmedoc-fix-readme-claims-about-c'

This commit is contained in:
AskaEth committed 2026-11-05 18:05:41 +08:00
commit 84f85bbc79
2 files changed
+85 -40

No files matched your search

+42 -19
View File
@@ -33,7 +33,11 @@ attached to other agent tooling as an MCP server.
- **Java management**: a Temurin → Oracle → Microsoft → Zulu fallback chain, region-aware. - **Java management**: a Temurin → Oracle → Microsoft → Zulu fallback chain, region-aware.
- **Accounts**: Microsoft sign-in over OAuth 2.0 device code flow → Xbox Live → XSTS → - **Accounts**: Microsoft sign-in over OAuth 2.0 device code flow → Xbox Live → XSTS →
`api.minecraftservices.com`; third-party community auth servers; local offline profiles for `api.minecraftservices.com`; third-party community auth servers; local offline profiles for
isolated testing. Account tokens are kept on this machine only. isolated testing. Account tokens are kept on this machine only. **Microsoft sign-in needs an Azure
public client id, and no release binary carries one** — the id is not in this repo and CI injects
none, so set `ULL_MSA_CLIENT_ID` before launching, or build with it. Without one, pressing sign-in
only raises a generic "Sign-in failed" alert with `Code: other`; nothing on that screen tells you
the id is what is missing. Community auth servers and local profiles need no id.
- **Engine**: multi-source download (health scoring, mirrors, chunked transfers, hash while - **Engine**: multi-source download (health scoring, mirrors, chunked transfers, hash while
downloading) and a YAML rule-based crash diagnosis engine. downloading) and a YAML rule-based crash diagnosis engine.
- **License**: Apache-2.0 © AskaEth (YeiJ). - **License**: Apache-2.0 © AskaEth (YeiJ).
@@ -44,14 +48,23 @@ attached to other agent tooling as an MCP server.
Slint tag. `v0.2.0` is the first tag after the rewrite — the iced line, which is what the release Slint tag. `v0.2.0` is the first tag after the rewrite — the iced line, which is what the release
pipeline builds now. Everything described below lives on that line. pipeline builds now. Everything described below lives on that line.
- **The iced UI is feature-complete**: fourteen pages — instances, version management (three-column - **What the iced UI has**: instances (list-detail), version management (three-column rail layout
rail layout with search), content library (modpacks / mods / resource packs / shaders with source with search), content library (modpacks / mods / resource packs / shaders with source and version
and version filters), logs, settings (general / appearance / Java / downloads), accounts filters), logs, settings (general / appearance / Java / downloads), accounts (Microsoft device
(Microsoft device code, third-party community servers, local profiles), the AI rail and the code, third-party community servers, local profiles), the AI rail and the installer flows — all on
installer flows — on top of one component library and one token set. one component library and one token set. The page list is the one in `presenter::router::Route` —
instances, version management, content library, logs, settings, accounts, instance detail, the AI
page; `pages::Screen::ALL`, the smaller set that has a slug (`--screen=` and the page test matrix,
`crates/app-iced/src/pages/tests.rs`), leaves out accounts, instance detail and the AI page, which
are routed but opened from the nav rail or an instance tile.
- **Localisation follows the system language**: detection, an explicit override in settings, and - **Localisation follows the system language**: detection, an explicit override in settings, and
persistence across restarts. UI copy goes through a single message catalogue; there is no persistence across restarts. UI copy goes through one message catalogue (`crates/i18n`).
hard-coded string in the view layer. - **What the copy guard catches, and what it does not**: a test reads the instances page sources and
fails on any string literal that contains an ASCII word unless it is on a short whitelist, so a
newly hard-coded English string turns red as it lands
(`crates/app-iced/src/pages/instances/tests/i18n.rs`). Known boundary: that scan covers the
instances page rather than every screen, and a hard-coded Chinese literal has no ASCII word to
match, so nothing catches it — that class relies on review and the screenshot run.
- **Appearance**: window background image, per-panel transparency and whole-window transparency - **Appearance**: window background image, per-panel transparency and whole-window transparency
(Windows), light / dark / follow-system, and system window corners where the platform grants them. (Windows), light / dark / follow-system, and system window corners where the platform grants them.
On CPU rendering the translucent layers are switched off and the UI says so. On CPU rendering the translucent layers are switched off and the UI says so.
@@ -66,16 +79,22 @@ Binaries you may run into, so you can tell them apart:
| Binary | Crate | State | | Binary | Crate | State |
|--------|-------|-------| |--------|-------|-------|
| `unlucky-launcher-iced` | `crates/app-iced` (iced 0.14) | the GUI binary the workspace builds; the release pipeline stages it under the public name `unlucky-launcher`; the same binary answers every CLI subcommand | | `unlucky-launcher-iced` | `crates/app-iced` (iced 0.14) | the GUI binary the workspace builds; the release pipeline stages the file as `unlucky-launcher_<version>_<platform>_<arch>` — a bare `.exe` on the two Windows slots, a `.tar.gz` on the four Linux / macOS slots — and the binary inside each archive is named `unlucky-launcher`; the same binary answers every CLI subcommand |
| `unlucky-launcher` | `crates/app` (Slint) | **historical**: that crate is excluded from the workspace, so this binary is no longer built or shipped; the v0.1.0 assets are the last Slint builds | | `unlucky-launcher` | `crates/app` (Slint) | **historical**: that crate is excluded from the workspace, so this binary is no longer built or shipped; the v0.1.0 assets are the last Slint builds |
| `ull` | `crates/cli` | the zero-UI build of the same command set, shipped as its own asset | | `ull` | `crates/cli` | the zero-UI build of the same command set, shipped as its own asset |
`unlucky-launcher` (the GUI) and `ull` are not duplicates. The GUI binary needs the graphics stack The GUI binary and `ull` are not duplicates. An archive extracts the first as `unlucky-launcher`; on
when it opens a window (it `dlopen`s X11 / Wayland / GL, and links `libfontconfig` at load); `ull` Windows it is a bare `unlucky-launcher_<version>_<platform>_<arch>.exe`. The GUI binary needs the
needs nothing beyond glibc, so it runs on a server, a CI container or Termux where no window can graphics stack when it opens a window (it `dlopen`s X11 / Wayland / GL, and links `libfontconfig` at
exist. Pick `ull` when there is no desktop, `unlucky-launcher <command>` when there is. Both print the load); `ull` needs nothing beyond glibc, so it runs on a server or a CI container where no window can
same CLI text and name themselves after the binary you invoked: `unlucky-launcher --help` starts with exist. That floor is glibc ≥ 2.35 (the Linux slots build on Ubuntu 22.04), so an older distribution —
`unlucky-launcher ·`, `ull --help` starts with `ull ·`. and Android/Termux, which is not a released slot at all — needs a source build
(`packaging/README.md` §4, §9). Pick `ull` when there is no desktop, `unlucky-launcher <command>` when
there is. Both print the same CLI text, and each names itself after the file you ran — `argv[0]` with
its directory and a trailing `.exe` removed, and nothing else (`crates/cli/src/cli/program.rs`). So
`ull` prints `ull ·`, the `unlucky-launcher` inside an archive prints `unlucky-launcher ·`, a local
`cargo build` prints `unlucky-launcher-iced ·`, and the bare Windows asset, whose file name keeps the
version segment, prints `unlucky-launcher_<version>_windows_x64 ·`.
### Subcommand dispatch ### Subcommand dispatch
@@ -163,9 +182,12 @@ that crate is kept as source-only reference and can no longer be built as a work
What the build produces: What the build produces:
- `unlucky-launcher-iced` — the GUI (iced). It is also the CLI: the same binary answers every - `unlucky-launcher-iced` — the GUI (iced). It is also the CLI: the same binary answers every
subcommand listed above. The name is temporary — it becomes `unlucky-launcher` at the flip. The subcommand listed above. The `iced` in this name is cargo's, not the download's: renaming the bin
release artifacts already carry the public name: the pipeline builds this bin and is what the "flip" still owes. The release file name carries no implementation detail — the
`packaging/make_artifacts.py` stages it as `unlucky-launcher[.exe]`, so download links never change. pipeline builds this bin and `packaging/make_artifacts.py` stages it as
`unlucky-launcher_<version>_<platform>_<arch>` — a bare `.exe` on the two Windows slots, a
`.tar.gz` on the four Linux / macOS slots — with the binary inside each archive named
`unlucky-launcher`, so download links never carry `iced`.
- `unlucky-launcher` — **historical**: no workspace build produces this binary any more; it belonged - `unlucky-launcher` — **historical**: no workspace build produces this binary any more; it belonged
to `crates/app`, which is excluded. The v0.1.0 assets are the last builds under this name. to `crates/app`, which is excluded. The v0.1.0 assets are the last builds under this name.
- `ull` — the CLI as a standalone, UI-free binary. Same command set, no graphics stack, smaller, and - `ull` — the CLI as a standalone, UI-free binary. Same command set, no graphics stack, smaller, and
@@ -207,7 +229,8 @@ Minimum baseline: **Windows 10**; Windows 8.1 / 8 / 7 are not supported.
X11 is the preferred path today and Wayland is the long-term direction. macOS builds are unsigned, X11 is the preferred path today and Wayland is the long-term direction. macOS builds are unsigned,
so the first launch needs the Gatekeeper quarantine attribute cleared so the first launch needs the Gatekeeper quarantine attribute cleared
(`xattr -d com.apple.quarantine`) (`xattr -d com.apple.quarantine`)
- Android Termux is experimental and not promised: CLI only, GUI unverified - Android Termux is experimental and not promised: no released asset targets it (build from source
there), and the GUI is unverified
- Each platform runs its own test matrix; capability differences use feature gates with runtime - Each platform runs its own test matrix; capability differences use feature gates with runtime
probing. probing.
+43 -21
View File
@@ -13,16 +13,22 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
- **单文件原生二进制**:启动器本体不需要 JVM、不需要 WebView、不带旁挂运行时。游戏要的 JDK 由 - **单文件原生二进制**:启动器本体不需要 JVM、不需要 WebView、不带旁挂运行时。游戏要的 JDK 由
启动器按实例下载管理,不是启动器的依赖。 启动器按实例下载管理,不是启动器的依赖。
- **一壳两形**:GUI 二进制在跑任何 UI 代码之前就认得全部 CLI 子命令——不开窗、不探渲染器、不扫字体。
另有一份更轻的 `ull` 产物,命令集相同,却一个图形栈都不链接。
- **默认构建里只有一套 UI**:UI 是 iced 0.14 + Material 3 Expressive。早先的 Slint 实现 - **默认构建里只有一套 UI**:UI 是 iced 0.14 + Material 3 Expressive。早先的 Slint 实现
(`crates/app`)作为**历史参考**保留源码:已被 workspace `exclude`,默认构建不编、测试不跑、 (`crates/app`)作为**历史参考**保留源码:已被 workspace `exclude`,默认构建不编、测试不跑、
发布不发。`v0.1.0` 那个 tag 发的仍是 Slint 版;iced 重写后的第一个 tag 是 `v0.2.0`(见「当前状态」)。 发布不发。`v0.1.0` 那个 tag 发的仍是 Slint 版;iced 重写后的第一个 tag 是 `v0.2.0`(见「当前状态」)。
- **CPU 软渲染兜底**:`--software-renderer` 让没有可用 GPU 或驱动有问题的老机也能正常显示界面。 - **CPU 软渲染兜底**:`--software-renderer` 让没有可用 GPU 或驱动有问题的老机也能正常显示界面。
- **AI Agent + MCP**:启动器内可对话、改设置、读崩溃诊断;`ull agent serve` 把同一个内核以 MCP - **AI Agent + MCP**:启动器内可对话、改设置、读崩溃诊断;`ull agent serve` 把同一个内核以 MCP
server 形态(stdio 或 Streamable HTTP)开放给外部 Agent 工具。 server 形态(stdio 或 Streamable HTTP)开放给外部 Agent 工具。
- **加载器**:Fabric / Quilt / NeoForge / Forge;整合包与 CurseForge / Modrinth 客户端在 core 里。 - **加载器**:Fabric / Quilt / NeoForge / Forge;CurseForge 清单、Modrinth `.mrpack`、
MultiMC/Prism 整合包导入,mrpack / CurseForge 导出。
- **Java 管理**:Temurin → Oracle → Microsoft → Zulu 回退链,带地区判定。 - **Java 管理**:Temurin → Oracle → Microsoft → Zulu 回退链,带地区判定。
- **账户**:用 Microsoft 账户登录,认证走 OAuth 2.0 device code flow → Xbox Live → XSTS → - **账户**:三轨——Microsoft 账户登录(OAuth 2.0 device code flow → Xbox Live → XSTS →
`api.minecraftservices.com`;账户令牌只保存在本机。 `api.minecraftservices.com`)、第三方社区服、本地离线档案;账户令牌只保存在本机。**微软登录需要
一个 Azure 公共客户端 id,而发布版二进制里没有**——这个 id 不在仓库里,CI 也不注入,所以启动前设
`ULL_MSA_CLIENT_ID`(或构建时注入)才会有;没配时点登录只会弹一条通用的「登录失败」,带
`代码:other`——那句话不会告诉你是缺了 id。第三方社区服与本地档案不需要 id。
- **引擎**:多源下载(健康度评分、镜像、分块传输、边下边算)与 YAML 规则引擎的崩溃诊断。 - **引擎**:多源下载(健康度评分、镜像、分块传输、边下边算)与 YAML 规则引擎的崩溃诊断。
- **许可**:Apache-2.0 © AskaEth (YeiJ)。 - **许可**:Apache-2.0 © AskaEth (YeiJ)。
@@ -32,11 +38,18 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
第一个 tag 是 `v0.2.0`——也就是 iced 这条线,下面说的这套东西都在线上,也正是发布流水线现在会打 第一个 tag 是 `v0.2.0`——也就是 iced 这条线,下面说的这套东西都在线上,也正是发布流水线现在会打
出来的东西。 出来的东西。
- **iced 版界面功能已齐**:十四页——实例、版本管理(三栏 + 搜索)、内容库(整合包 / Mod / 资源包 / - **iced 版界面上有什么**:实例、版本管理(三栏 + 搜索)、内容库(整合包 / Mod / 资源包 / 光影,
光影,带来源与版本筛选)、日志、设置(通用 / 外观 / Java / 下载)、账户(微软设备码、第三方社区服、 带来源与版本筛选)、日志、设置(通用 / 外观 / Java / 下载)、账户(微软设备码、第三方社区服、本地
本地档案)、AI 右栏,以及安装流程——共用一套组件库与一套令牌。 档案)、AI 右栏,以及安装流程——共用一套组件库与一套令牌。页面清单就是 `presenter::router::Route`
- **文案跟随系统语言**:自动探测、设置里可显式切换、重启后保持。界面文案统一走一份消息目录,视图层 里的那些——实例、版本管理、内容库、日志、设置、账户、实例详情、AI 页;`pages::Screen::ALL` 是其中
没有硬编码字符串。 带 slug 的较小一组(`--screen=` 与页面测试矩阵用它,`crates/app-iced/src/pages/tests.rs`),账户、
实例详情与 AI 页不在这一组里——它们能路由到,但入口是导航轨与实例磁贴。
- **文案跟随系统语言**:自动探测、设置里可显式切换、重启后保持。界面文案统一走一份消息目录
(`crates/i18n`)。
- **文案守门抓得住什么、抓不住什么**:有一条测试扫实例页的源码,凡是**带 ASCII 单词**的字符串字面量
不在短白名单里就红——新写一句英文界面文案,落地即红
(`crates/app-iced/src/pages/instances/tests/i18n.rs`)。已知边界:这条扫描只覆盖实例页,不是每一屏;
而且中文写死的字面量里没有 ASCII 单词,扫不到——这一类只能靠 review 与出图。
- **外观**:窗口背景图、面板透明度、整窗透明度(Windows)、浅色 / 深色 / 跟随系统,以及在系统愿意给 - **外观**:窗口背景图、面板透明度、整窗透明度(Windows)、浅色 / 深色 / 跟随系统,以及在系统愿意给
的时候使用系统窗口圆角。CPU 渲染档会关掉半透明层,并在界面上说清楚。 的时候使用系统窗口圆角。CPU 渲染档会关掉半透明层,并在界面上说清楚。
- **整合包与安装链路都在构建里**:CurseForge 清单 / Modrinth `.mrpack` / MultiMC·Prism 导入,mrpack - **整合包与安装链路都在构建里**:CurseForge 清单 / Modrinth `.mrpack` / MultiMC·Prism 导入,mrpack
@@ -44,22 +57,29 @@ Unlucky Launcher(ULL)是一个用 Rust 写的免费开源 Minecraft: Java
- **还没做**:安装器与自动更新通道;Windows 定型后的 macOS 真机复核;整合包导入的**逐文件**冲突策略 - **还没做**:安装器与自动更新通道;Windows 定型后的 macOS 真机复核;整合包导入的**逐文件**冲突策略
(当前只有一份全局策略,界面如实写明而不是假装支持);原生文件选择框(导入支持拖拽与粘贴路径)。 (当前只有一份全局策略,界面如实写明而不是假装支持);原生文件选择框(导入支持拖拽与粘贴路径)。
- **Slint 版已退出构建,只留源码作参考**:`crates/app` 不再是 workspace 成员(M118)——源码留作历史 - **Slint 版已退出构建,只留源码作参考**:`crates/app` 不再是 workspace 成员(M118)——源码留作历史
参考,不编译、不测试、不发布,也不再有可用的构建方式。翻牌只剩**改名**这一步:它的 bin 现在叫 参考,不编译、不测试、不发布,也不再有可用的构建方式。还欠「翻牌」的只有**仓库内的 bin 名**(现在叫
`unlucky-launcher-iced`,发布流水线已经把它按对外名 `unlucky-launcher` 打出去。 `unlucky-launcher-iced`);**产物名不欠**:`packaging/make_artifacts.py` 落盘时用的是
`unlucky-launcher_<版本>_<平台>_<架构>`——两个 Windows 槽是裸 `.exe`,其余四个 Linux / macOS 槽
是 `.tar.gz`——归档里的二进制名是 `unlucky-launcher`。
可能会遇到的 bin,先认清楚: 可能会遇到的 bin,先认清楚:
| 二进制 | crate | 状态 | | 二进制 | crate | 状态 |
|--------|-------|------| |--------|-------|------|
| `unlucky-launcher-iced` | `crates/app-iced`(iced 0.14) | workspace 里**唯一**的 GUI bin;发布流水线把它按对外名 `unlucky-launcher` 落盘;子命令分发同款 | | `unlucky-launcher-iced` | `crates/app-iced`(iced 0.14) | workspace 里**唯一**的 GUI bin;发布流水线把文件落成 `unlucky-launcher_<版本>_<平台>_<架构>`(两个 Windows 槽是裸 `.exe`,其余四个 Linux / macOS 槽是 `.tar.gz`),归档里的二进制名是 `unlucky-launcher`;子命令分发同款 |
| `unlucky-launcher` | `crates/app`(Slint) | **历史**:该 crate 已被 workspace `exclude`,这个 bin 不再被构建或分发;`v0.1.0` 的资产是最后一批 Slint 版 | | `unlucky-launcher` | `crates/app`(Slint) | **历史**:该 crate 已被 workspace `exclude`,这个 bin 不再被构建或分发;`v0.1.0` 的资产是最后一批 Slint 版 |
| `ull` | `crates/cli` | 同一套命令的零 UI 构建,作为独立资产随发布分发 | | `ull` | `crates/cli` | 同一套命令的零 UI 构建,作为独立资产随发布分发 |
`unlucky-launcher` 与 `ull` 不是重复品:开窗时 GUI 二进制要用图形栈(X11 / Wayland / GL 走 GUI 二进制与 `ull` 不是重复品。归档解压出来那个二进制叫 `unlucky-launcher`;Windows 上是裸的
`unlucky-launcher_<版本>_<平台>_<架构>.exe`。开窗时 GUI 二进制要用图形栈(X11 / Wayland / GL 走
`dlopen`,启动时直接链接 `libfontconfig`);`ull` 除了 glibc 什么都不需要,所以在没有窗口的服务器、 `dlopen`,启动时直接链接 `libfontconfig`);`ull` 除了 glibc 什么都不需要,所以在没有窗口的服务器、
CI 容器、Termux 上跑得起来。没有桌面就用 `ull`,有桌面就用 `unlucky-launcher <子命令>`。两者打出来的 CI 容器上跑得起来。这个地板是 glibc ≥ 2.35(Linux 槽位在 Ubuntu 22.04 上构建),更老的发行版——以及
CLI 文案是同一套,自称的名字跟着**你敲的那个二进制**走:`unlucky-launcher --help` 首行是 根本不在发布矩阵里的 Android/Termux——得源码自建(`packaging/README.md` §4、§9)。没有桌面就用 `ull`,
`unlucky-launcher ·`,`ull --help` 首行是 `ull ·`。 有桌面就用 `unlucky-launcher <子命令>`。两者打出来的 CLI 文案是同一套,自称的名字跟着**你敲的那个
文件**走——`argv[0]` 去掉目录与结尾的 `.exe`,别的都不剥(`crates/cli/src/cli/program.rs`)。所以
`ull` 打印 `ull ·`,归档里那个 `unlucky-launcher` 打印 `unlucky-launcher ·`,本地 `cargo build` 出来
的打印 `unlucky-launcher-iced ·`,而 Windows 的裸 exe 文件名带版本段,打印的是
`unlucky-launcher_<版本>_windows_x64 ·`。
### 子命令分发 ### 子命令分发
@@ -84,7 +104,7 @@ unlucky-launcher --version # CLI,输出版本 + 系统摘要
**未知子命令是错误,不是开窗**:`unlucky-launcher lst` 打印「未知命令 `lst`」、提示 **未知子命令是错误,不是开窗**:`unlucky-launcher lst` 打印「未知命令 `lst`」、提示
`unlucky-launcher --help`,以 1 退出。静默开窗会让脚本以为自己那个拼错的参数生效了。子命令表只有 `unlucky-launcher --help`,以 1 退出。静默开窗会让脚本以为自己那个拼错的参数生效了。子命令表只有
一处定义(`crates/cli/src/cli/parse.rs`),所以两个 GUI 二进制和 `ull` 认的命令集天然一致。 一处定义(`crates/cli/src/cli/parse.rs`),所以 GUI 二进制和 `ull` 认的命令集天然一致。
## 模块地图 ## 模块地图
@@ -112,7 +132,7 @@ Unlucky-Launcher (cargo workspace)
| `download` | 多源健康度、镜像、分块下载、边下边算 | | `download` | 多源健康度、镜像、分块下载、边下边算 |
| `game` | 版本/实例仓库、快照与继承解析 | | `game` | 版本/实例仓库、快照与继承解析 |
| `launch` | 10 阶段启动管线、进程、JSONL 事件流 | | `launch` | 10 阶段启动管线、进程、JSONL 事件流 |
| `auth` | Microsoft 账户登录(OAuth 2.0 device code → Xbox Live → XSTS → Minecraft Services) | | `auth` | Microsoft 账户登录(OAuth 2.0 device code → Xbox Live → XSTS → Minecraft Services)、第三方社区服、本地档案 |
| `addon` | 加载器安装、整合包、CurseForge / Modrinth | | `addon` | 加载器安装、整合包、CurseForge / Modrinth |
| `diagnose` | 五类信号采集、YAML 规则引擎、hs_err 解析 | | `diagnose` | 五类信号采集、YAML 规则引擎、hs_err 解析 |
| `platform` | OS 抽象:路径、进程、文件锁、能力探测、运行期 OS 检测 | | `platform` | OS 抽象:路径、进程、文件锁、能力探测、运行期 OS 检测 |
@@ -138,9 +158,11 @@ cargo build --release # bin 落在 target/relea
编出来的 bin: 编出来的 bin:
- `unlucky-launcher-iced`——GUI(iced)。它同时也是 CLI:同一个二进制认上面列的全部子命令。名字是 - `unlucky-launcher-iced`——GUI(iced)。它同时也是 CLI:同一个二进制认上面列的全部子命令。名字里的
临时的,翻牌时才改成 `unlucky-launcher`;发布产物**已经**用对外名:流水线编这个 bin, `iced` 是 cargo 的,不是下载链接的:还欠「翻牌」的只有这个 bin 名;发布文件里不带实现细节——流水线编
`packaging/make_artifacts.py` 落盘时改成 `unlucky-launcher[.exe]`,所以下载链接不用变。 这个 bin,`packaging/make_artifacts.py` 落盘时改成
`unlucky-launcher_<版本>_<平台>_<架构>`——两个 Windows 槽是裸 `.exe`,其余四个 Linux / macOS 槽
是 `.tar.gz`——归档里的二进制名是 `unlucky-launcher`。
- `unlucky-launcher`——**历史**:workspace 构建已不产出它(它属于被排除的 `crates/app`)。 - `unlucky-launcher`——**历史**:workspace 构建已不产出它(它属于被排除的 `crates/app`)。
`v0.1.0` 的资产是最后一批用这个名字发出去的构建。 `v0.1.0` 的资产是最后一批用这个名字发出去的构建。
- `ull`——CLI 的独立无 UI 构建:同一套命令、不链接图形栈、体积更小,给完全没有显示设备的机器用。 - `ull`——CLI 的独立无 UI 构建:同一套命令、不链接图形栈、体积更小,给完全没有显示设备的机器用。
@@ -175,7 +197,7 @@ cargo build --release # bin 落在 target/relea
- macOS 12+(Apple Silicon 与 Intel)与 Linux x64 / arm64 都是支持槽位;Linux 上 X11 是当前首选路径, - macOS 12+(Apple Silicon 与 Intel)与 Linux x64 / arm64 都是支持槽位;Linux 上 X11 是当前首选路径,
Wayland 是大方向。macOS 产物未签名,首次启动要自己清掉 Gatekeeper 隔离标记 Wayland 是大方向。macOS 产物未签名,首次启动要自己清掉 Gatekeeper 隔离标记
(`xattr -d com.apple.quarantine`) (`xattr -d com.apple.quarantine`)
- Android Termux 试验级、不承诺:只保证 CLI,GUI 未验证 - Android Termux 试验级、不承诺:发布矩阵里没有面向它的资产(要在 Termux 上跑得源码自建),GUI 未验证
- 每个平台跑各自的测试矩阵;能力差异用 feature gate + 运行期探测表达。 - 每个平台跑各自的测试矩阵;能力差异用 feature gate + 运行期探测表达。
## 许可证与致谢 ## 许可证与致谢