7 Commits

Author SHA1 Message Date
Gloridust
d29ea66730 docs(p0): 记录 QEMU OOM 的最终解决——改用原生 arm64 runner(v1.4.4 闭环) 2026-07-08 03:57:12 +08:00
Gloridust
9981e9a5dc feat(design): 设计系统文档 doc/dev/design.md + 无障碍基线(焦点环/动效降级)
- doc/dev/design.md:把牛奶布艺设计语言正式沉淀为规范——设计哲学、令牌表(色彩/圆角/
  阴影高光/动效曲线,含深浅色)、布局与三 Tab 信息架构、逐组件规范(卡片/按钮三级/输入框/
  徽标体系/分段 Tab/折叠菜单/空状态/Toast/进度/模态)、动效、无障碍、文案、反例、落地清单。
  令牌与 class 名与 styles.css 一一对应,是可执行的活规范而非抽象理论。
- 无障碍基线(此前为 0):全局 :focus-visible 绿色焦点环(仅键盘导航出现,鼠标不触发;
  无边框拟物 UI 尤其需要);prefers-reduced-motion 降级(去装饰动效、保留 spinner/进度的
  必要循环)。已用真实构建 CSS 截图验证焦点环不被按钮 overflow:hidden 裁剪、贴合胶囊圆角。
2026-07-08 03:13:09 +08:00
Gloridust
fda9522b78 fix(critical): 实例镜像 arm64 构建 OOM + 版本耦合无兜底致面板锁死(v1.4.1 连环 P0)
v1.4.1 只发布了面板、实例镜像 CI 失败,叠加版本耦合无兜底 → 用户升级指示器消失、
实例卡在坏的 1.4.0、浏览器仍黑屏。两处修复:

① Dockerfile arm64 OOM:CI 的 QEMU arm64 下第二个 apt 层 OOM(两次 apt-get update +
snapshot 源被后续层反复拉取)。合并为单层一次 update+install、装完即移除 snapshot 源、
Acquire::Languages=none + Retries=3,砍掉内存/网络峰值。本机原生 arm64 构建 + 全套探针
(Chromium 149 / DPI 98304 / CEF 连跑两次 / 30s 零崩溃 / 窗口可见)已验证通过。

② 版本耦合安全兜底:面板偏好「与自身同版本」的实例镜像 tag,但该 tag 在本地和 registry
都不存在时(CI 部分失败/发布时序),原先会指向不存在的 tag → 检测恒空、升级拉不到。
新增 resolveInstanceImage():不可达则回退 :latest,功能永不因版本错配而瘫痪(已运行时验证
9.9.9→latest)。启动时与 ensureImage 前各解析一次。

P0 复盘记录连环成因;待办:改用原生 arm64 runner 替代 QEMU、matrix 失败联动。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 12:11:16 +08:00
Gloridust
4d9cc1015a fix(critical): Chromium 版本锚定(snapshot) + CI 产物门禁 + 面板/实例版本耦合 + 声音重连修复
v1.4.0 三项反馈的修复:

① 浏览器实例仍黑屏(P0):CI 构建时 apt 拉到 Chromium 150(本地验证的是 149 缓存层)。
实测 150 在本栈上「非首次启动」路径(--no-first-run / First Run 哨兵 / 同 profile 第二次启动)
与 --start-maximized 均直接 SIGTRAP —— 首跑正常、之后必崩,无任何 flag 可绕。修复:
- Dockerfile 从 snapshot.debian.org 固定快照(20260704T180435Z)锚定安装 149.0.7827.196(R1);
  升级 chromium = 显式改快照+版本并过全套门禁。已验证:锚定镜像 DPI ✓、CEF 连跑两次 ✓、
  30s 零崩溃 ✓、窗口可见 ✓。
- release.yml 产物门禁:先构建 amd64 在 runner 上跑四项探针(DPI/CEF两次启动/崩溃循环/微信模式),
  全过才推送——「验证的东西和发布的东西必须是同一个 artifact」(v1.4.0 的流程教训)。
- 本地门禁 CEF 探针升级为连跑两次(单次恰好漏掉非首跑崩溃)。

② 面板/实例版本耦合(R1):正式版面板把实例镜像 :latest 改写为与自身相同的版本 tag,
同版本一起验证发布,杜绝「低版本面板 × 高版本实例」未验证组合;env 显式锁其它 tag 则尊重、
dev 面板保持 latest。配套:本地缺该版本镜像但远端存在时,升级引导也会亮起。

③ VNC 声音大概率无声:vncAudio 的 opened 标志断线不复位 → socket 重连后跳过 emit('open'),
kclient 永不重新推流 → 实例升级/重启/面板更新/网络抖动后全程静音。修:disconnect 时复位。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:55:08 +08:00
Gloridust
9ec3ea2d73 docs+fix: 稳定性设计文档(远程桌面/升级链路决策全记录)+ 重置设备ID 也走 keepImage
- doc/dev/稳定性设计.md:两条命脉链路的现行设计、每个决策的原因(含故意不做的事:
  单会话互踢、页内软重连、激进健康探测)、已知单点(KasmVNC 进程级卡死只能重启容器)。
- regenInstanceMachineId 补上 keepImage(恢复类操作幂等,R10 的最后一处漏网)。
- 发布门禁全项通过:DPI=98304、CEF 探针存活、30s 零崩溃、微信模式就绪、
  升级路径(keepImage 保版本 → 升级换 latest → LogConfig 20m×2 生效)、面板部署 0 错误。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:10:03 +08:00
Gloridust
7dc2053c0b fix(stability): 重启/自愈幂等(keepImage)+ 代理双侧 TCP keepalive —— 远程桌面稳定性审查
重大逻辑问题:「重启」「卡死自愈」「看门狗自愈」都走 runInstance 按本地 :latest 重建——
只要本地镜像被任何一次拉取更新过(新建实例/升级任一实例),下一次重启/自愈就把该实例
【隐式换镜像】。若本地新镜像恰好是坏的(如 v1.3.0 时期),一次看门狗自愈就能弄坏一个
从没点过升级的实例("我什么都没动它怎么坏了")。修:runInstance 增加 keepImage 选项,
重启/自愈沿用容器当前镜像重建(且跳过 ensureImage,离线也能重启);换镜像只走显式升级。
已实测:keepImage 重建后镜像不变;不带 keepImage(升级)换到 latest;新容器 LogConfig 生效。
守则新增 R10(重启必须幂等)。

代理加固:面板↔实例 双侧 ws 套接字启用 TCP keepalive(30s)。客户端断网/切网(WiFi→4G、
NAS 休眠)时 TCP 不会主动通知,半开死连接可挂数小时——对 KasmVNC 表现为幽灵会话占坑,
与新连接并存正是历史上"Xvnc 卡死需重启容器"的诱因之一;30s 探测让死连接分钟级回收。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 00:05:06 +08:00
Gloridust
7ec79314bb docs(dev): 架构守则 + 发布门禁 + P0复盘簿 —— 把历次 P0 的学费固化成硬约束
从 v1.2.6 自更新黑屏、v1.2.9~v1.3.1 DPI 单位事故、磁盘暴涨、升级卡死等真实 P0 中
蒸馏出 9 条架构不变式(R1~R9):版本锚定可回滚、声明式自重建、资源必有边界、
长任务异步化、面板×实例兼容矩阵、根因=解释全部症状+A/B实证、AI PR 审语义、
发布节奏(特性不当天发)、冒烟测用户动作。发布门禁给出逐条可执行的命令清单
(含微信 CEF 等价探针、升级路径测试);P0 复盘簿记录每次事故的流程性成因。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 23:37:48 +08:00