Skip to content

feat(desktop): 用 Tauri v2 交付独立 OPC 桌面 App #30

Description

@coconilu

Problem

Issue #25 / PR #27 已交付独立于 Agent 会话的 OPC App 控制平面,但当前产品入口仍是 Python 启动器 + loopback 浏览器页面。用户需要预装 Python、通过命令行启动,并在浏览器标签页中使用;它还不是一个可双击启动、带独立窗口和安装包的桌面应用。

ADR-0017 当时因缺少交互与分发证据而明确未采用 Tauri。现在用户已明确选择 Tauri 作为桌面产品方向,因此必须以新 ADR 记录边界变化,不能把桌面壳静默塞入既有 Python runtime,也不能复制 Snapshot、脱敏、Adapter 或治理规则形成第二实现。

Desired outcome

交付一个 Windows-first 的 Tauri v2 OPC 桌面 App MVP:

用户安装并双击 OPC App
  → Tauri 单实例启动
  → 启动随包、受管的 OPC Python sidecar
  → sidecar 仅绑定随机 loopback 端口
  → Tauri 窗口加载现有 OPC App UI
  → 退出窗口时可靠回收 sidecar

安装后的用户不需要系统 Python、Node、Codex、Claude 或 Kimi 会话即可打开控制台。现有 Python App、Dashboard、Plugin、Skills 和 CLI 入口继续兼容;File/Git knowledge 仍是唯一权威源。

Scope

  • 新增 ADR,说明为何现在接受 Tauri、桌面壳与 Python sidecar 的责任边界、信任边界、失败恢复、升级/卸载和回滚策略。
  • 在独立目录中新增 Tauri v2 工程,复用现有 HTML/CSS/JS 和 opc_app.py API,不复制 Snapshot、脱敏、项目清单或 Adapter 业务逻辑。
  • 使用隔离、可重复的构建步骤把当前 Python App 与所需模块/静态资源打包为 Tauri external binary;生成的 sidecar 二进制和构建缓存不得提交仓库。
  • Tauri Rust 层独占 sidecar 生命周期:
    • 启动时使用 --no-open --port 0
    • 只接受 sidecar 输出的精确 http://127.0.0.1:<port>/
    • 等待健康可用后再展示主窗口;
    • 启动失败、异常退出和 App 关闭时给出可解释状态并回收子进程。
  • 启用单实例保护,避免两个桌面进程同时写同一 OPC_APP_HOME
  • 不向前端开放任意 shell、文件系统、网络、进程或命令执行能力;sidecar 只能由 Rust 层以固定程序和固定参数启动。
  • 保持 loopback、Host、Origin、CSRF、CSP、no-CORS、无遥测和脱敏响应边界。
  • 提供 Windows per-user NSIS 开发安装包和未签名状态说明;安装/卸载不能删除 App 状态、项目 .opc、File/Git knowledge、Git 历史、Agent 配置或可选 Mem0 数据。
  • 提供开发、构建、运行、故障诊断、卸载和回滚文档,并更新中英文入口。
  • 增加 Windows 自动化和独立安装态 QA;Linux/macOS 至少保证代码结构和边界文档不虚假宣称已支持。

Acceptance criteria

  • 新 ADR 被索引并明确:Tauri 只是桌面生命周期/窗口/分发层,不是 Agent Harness,不复制 OPC 业务事实或治理规则。
  • npm/Cargo/Tauri 与 Python sidecar 构建依赖钉住版本并有 lockfile;构建产物、缓存、用户路径、签名材料和 runtime state 均被忽略且通过隐私扫描。
  • Windows 构建从干净 checkout 生成 Tauri 可执行文件和 per-user NSIS 安装包;仓库不提交生成的 EXE、installer、WebView2、Python runtime 或 sidecar binary。
  • 安装后的 App 在没有系统 Python、Node 或活动 Agent 会话的隔离环境中启动成功。
  • 桌面 App 使用已有 opc_app.py/Snapshot/Adapter 契约;同一 synthetic fixture 下,桌面入口与 Python App 的 DTO、脱敏和状态语义一致。
  • sidecar 只绑定 127.0.0.1 的 OS 分配端口;远程 bind、非精确启动 URL、端口抢占和伪造 stdout 均 fail closed。
  • 同一 App 状态根只允许一个桌面实例;第二实例不会启动第二个 sidecar,也不会造成 settings 丢失更新。
  • 正常退出、窗口关闭、sidecar 启动失败、sidecar 运行中崩溃和 Tauri 异常退出测试证明不会遗留必须常驻的 OPC sidecar;无法自动回收时显示明确恢复指引。
  • 前端 capabilities 不允许任意 shell、任意 sidecar 参数、文件系统遍历、远程 HTTP、打开外部命令或扩大治理写权限。
  • 根页面、项目接入、项目切换、Dashboard、Adapters 预览/确认/回滚入口在真实 Tauri WebView 中可用;键盘、窗口缩放、窄窗口、零横向溢出和零 console error 通过。
  • 安装、升级、回滚和卸载不会删除或覆盖 App 状态、项目 .opc、File/Git knowledge、Git 历史、用户 Agent 配置或 Mem0 数据。
  • 未签名开发安装包明确标记为非正式发行;没有代码签名和发布证据时不得宣称生产就绪或发布到 Microsoft Store。
  • 以下验证全部通过:
    • python scripts/validate_repo.py
    • python -m unittest discover -s tests -p "test_*.py" -v
    • python scripts/privacy_scan.py
    • 官方 Plugin Validator 与全部 Skill quick validator
    • Tauri frontend/build checks、Cargo tests/clippy
    • Windows 安装 → 新进程启动 → UI/API → 退出 → 卸载的数据保留验收
    • 独立 Reviewer 对 exact HEAD 的代码、安装态和 UI 验收

Non-goals

  • 不把 Python Snapshot、治理、Memory 或 Adapter 逻辑重写为 Rust。
  • 不加入聊天、模型循环、工具执行、Agent 编排或后台自治服务。
  • 不在本 Issue 中实现自动更新服务器、远程访问、多用户、云同步或开机自启。
  • 不在本 Issue 中交付 Microsoft Store、代码签名证书、正式发布通道或生产级自动更新。
  • 不承诺 macOS/Linux 安装包;跨平台发行应在 Windows MVP 验证后另立 Issue。
  • 不把系统 Python、Node、Cargo、Codex、Claude 或 Kimi 作为已安装 App 的运行依赖。
  • 不提交生成二进制、私有签名材料、真实用户目录、项目数据、知识、日志或会话信息。

Dependencies and risks

Evidence

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions