18 · 端到端调用链¶
前面的章节按子系统拆开;这一章反过来,从用户可见动作一路追到状态和失败边界。它适合作为排障入口。
Trace A:第一次启动桌面¶
sequenceDiagram
participant P as pacman/installer
participant A as apply-system(root)
participant O as provision-owner
participant F as provision-user
participant S as SDDM/UWSM
participant H as Hyprland
participant Q as Quickshell
P->>A: 安装 packages + 应用系统
A->>A: config/hardware/login/post-install
alt owner 未知
A->>O: 留 pending,跨 reboot
end
O->>F: 以 owner 身份 finalize
F->>F: user config/default apps/migration markers
S->>H: 启动 Omarchy Wayland session
H->>Q: autostart shell
Q->>Q: registry/services/bar
H->>F: first-run in graphical session
F->>Q: 等通知服务,展示 welcome
可观察事实¶
- system 阶段:root 日志与
/var/lib/omarchy/provisioning; - user 阶段:
~/.local/state/omarchy/done/finalize-user; - first-run:独立 marker 与 user units;
- session:
/run/user/<uid>/hypr、user systemd environment; - Shell:
omarchy shell ping。
最常见误诊¶
“包都装了,所以 first-run 也应该完成。”包状态只能证明磁盘基线,不能证明图形用户服务已运行。
Trace B:omarchy theme set nord¶
sequenceDiagram
participant U as 用户
participant R as bin/omarchy
participant T as theme-set
participant FS as state filesystem
participant Q as Quickshell
participant A as 外围应用
U->>R: omarchy theme set nord
R->>R: 最长前缀找到 omarchy-theme-set
R->>T: exec nord
T->>T: 获取锁,验证 source/trust
T->>FS: 构建 next-theme + templates
T->>FS: atomic swap current/theme
T->>Q: applyTheme + wallpaper transition
T->>A: 并行 retint/restart
T->>T: theme-set hook
失败定位¶
- 命令没启动:查 router/可执行权限;
- 报 busy:查 theme lock 与并发切换;
- template 错:current 应仍是旧主题,查 staging/模板;
- 文件已变但 Shell 未变:查
omarchy shell ping/ applyTheme; - 只有某应用颜色旧:查该应用 post action,而非回滚整个主题。
一致性边界¶
原子性只覆盖活动主题文件的 swap;外围应用在锁释放后最终一致。理解这个边界可以避免把正常的短暂延迟当作数据损坏。
Trace C:菜单里安装一个应用¶
sequenceDiagram
participant U as 用户
participant M as Menu plugin
participant G as Guard cache
participant C as install command
participant P as pacman/AUR
participant L as AppLibrary
U->>M: 打开 Install submenu
M->>G: 立即显示 cached installed 状态
M->>G: 后台批量刷新
U->>M: 选择未安装项
M->>C: detached action
C->>P: 探测、安装、验证
C->>L: 刷新 applications(按命令契约)
M->>G: 下次 open 看到已安装
G-->>M: entry disabled + ✓
并发原则¶
UI guard 可能是旧的;安装命令必须再次探测。反过来,命令成功也不意味着当前已打开菜单瞬间更新,除非触发 refresh。这是缓存与真相的正常分工。
Trace D:更新在第 N 个迁移失败¶
sequenceDiagram
participant U as update
participant S as Snapper
participant P as pacman
participant M as migrator
participant F as migration N
participant D as marker dir
U->>S: create snapshot
U->>P: system package transaction
P-->>U: success
U->>M: run pending sorted
M->>F: bash -euo pipefail
F-->>M: non-zero
M--xD: 不写 N marker
M-->>U: failure,停止后续迁移
机器此刻是什么状态¶
- 新 packages 已安装;
- 早于 N 的迁移 marker 已写;
- N 可能有部分副作用,但没有 marker;
- N 之后尚未执行;
- update 的外围 AUR/mise/restart 可能没执行;
- update 前 snapshot 存在。
正确恢复顺序¶
先看 /tmp/omarchy-update.log 找 N 的第一个错误;修复环境或迁移幂等问题;重跑 migrator/update。不要手工 touch marker 来“绕过”,除非已证明 N 的目标状态全部成立。
Trace E:安装并启用第三方插件¶
flowchart TD
URL[git URL] --> Confirm[终端警告/确认]
Confirm --> Clone[clone 到 user plugins]
Clone --> Validate[manifest/entrypoint/no symlink]
Validate --> Disabled[落盘但默认禁用]
Disabled --> Review[用户审代码]
Review --> Enable[shell.json 写启用/位置]
Enable --> Rescan[Registry inotify/rescan]
Rescan --> Load[Qt.createComponent]
Load --> Host[注入 shell/registry/manifest]
信任发生在哪里¶
clone 只是下载;enable 才授权执行。对 full bar,若 load 失败回退内置 bar;对普通插件,仍应从 Shell 日志查看加载错误。插件与 Shell 同进程,没有权限沙箱。
Trace F:窗口间距 toggle¶
sequenceDiagram
participant K as Hyprland keybind
participant C as omarchy-hyprland-toggle
participant St as ~/.local/state
participant H as Hyprland Lua reload
K->>C: 切换 gaps flag
C->>St: 写/删动态 Lua 状态
C->>H: 请求 reload
H->>H: bootstrap 清 module cache
H->>St: state path 优先 require
H-->>K: 新 layout 生效
如果 reload 后恢复旧值,先查 state 文件是否生成,再查 bootstrap/package.path,而不是先修改用户 looknfeel.lua。toggle 是生成状态,不是长期配置。
Trace G:Factory reset¶
sequenceDiagram
participant U as 当前 owner
participant R as reset stage
participant B as Boot/UKI
participant F as early finish service
participant N as 新 owner provisioning
U->>R: 输入 reset + 认证
R->>R: clone @factory / scrub staged root
R->>B: 重建并验证 UKI hash
R->>F: arm wipe-pending
B->>F: reboot 到 staged root
F->>F: 删除旧 root,重建 @home/@log
alt 成功
F->>N: 清 pending,进入 provisioning
else 失败
F->>F: 保留 pending,下次 boot 重试
end
reset 的成功标准不是“当前命令返回 0”,而是下次 boot 的 finish service 完成并清除 wipe marker。跨 boot 操作必须按阶段观察。
用调用链排障的模板¶
遇到任何新问题,可按以下顺序写下事实:
- 入口:谁调用了哪个
omarchy-*/ IPC / unit? - 执行身份:root、普通用户还是图形 session?
- 上一个提交点:lock、snapshot、atomic swap、marker 或 package transaction?
- 目标状态:具体路径、service、QML property 或设备状态?
- 下游确认:退出码、日志、IPC response、systemd state、截图?
- 安全重放范围:哪一步有 marker,哪一步可能已产生部分副作用?
这比“再跑一次看看”多花一分钟,但通常能避免跨错层修复。
下一章把这些机制提炼为可移植的工程经验:19 · 可复用的设计经验。