目标
正式接受 HarnessGUI 的 scope placement 与首期组件边界,并跟踪 GUI-B0 工程基线交付。本文档化决定以已合并的 #581 和当前 main 上的 GUI/V3.1 架构文档为依据;本 issue 不把尚未取得的实现或三平台证据表述为已完成。
已接受的架构决定
- 唯一 GUI scope:首期只建立一个 Product-neutral
HarnessGUI,不建立 Coding、Design、Research、PPT 或 Work 等 Product-specific GUI 类别,也不创建前端专用事实权威。
- 唯一 hosted Host:桌面原生进程只承担 presentation/desktop adapter 职责,不新建 Desktop GUI Host。真实连接复用现有 G16 detachable AppService/AppHost application;
AppHost 继续只拥有 canonical admitted Product catalog/routing 与 scoped runtime/binding lifecycle。
- Hosted 多前端关系:
HarnessGUI 与 HarnessTUI Hosted Mux 可以连接同一个 G16 application,但必须使用各自独立的 AppClient scope、attachment generation、cursor 与 presentation state。草稿、焦点、滚动、选择和本地恢复状态不得共享;同 mux 继续遵守 one-controller-per-mux 与 already_attached,首期不引入 observer/takeover。
- Embedded 路径不变:
HarnessTUI Embedded 仍由 Product outer composition 直接绑定 Product/Harness,绕过 AppServer/AppService/AppHost;不得因 GUI 启动而迁移到 hosted boundary,也不得合并其生命周期。G15/G17 foreground child ownership 同样保持不变。
- 共享事实的唯一来源:会话、execution、workspace、changes、artifacts 等事实只通过
AppClientV1、可选 ExecutionClientV1 与版本化 HarnessClient facets 消费;GUI/Hosted Mux 不直接读取 Git 或 Product 内部对象,不建立第二套 provider、registry、权限或运行时。
首期组件边界
GUI-B0 建立一个 gui/ 子工程,首期保持一个前端 package 与一个 Rust crate;只有出现真实第二消费者时才提取 workspace/shared package。
| 组件 |
责任 |
禁止越界 |
| React presentation |
应用壳、布局、控件、Markdown/代码/Diff 受控展示、焦点与滚动 |
不读取 Python Session/Git,不执行 Agent 工具 |
| TypeScript UI state / port / mock |
UI-facing HarnessClient port、reducer/展示缓存、本地草稿与选择、Mock AppClient/fixture |
不猜测服务事实,不用通用 RPC 绕过封闭合同 |
| Tauri bridge |
React 与本机 Rust 之间的类型化、受限 invoke/event adapter |
不暴露通用 shell/文件系统权限,不成为 Product runtime |
| Rust AppClient adapter |
G16 本机认证、framing、请求关联、codec、连接/恢复状态;后续接入 AppClient/Execution/facet 合同 |
不重新定义 mux、Session、审批、controller 或 Product 语义 |
| GUI playback/testing support |
场景、操作、逐步断言、日志/截图/状态证据与失败定位 |
测试入口不得进入正常发布构建;回放不得重跑真实工具/浏览器副作用 |
依赖方向固定为:React/TS 依赖 UI-facing port;Mock 与 Tauri adapter 实现该 port;真实路径由 Tauri bridge 依赖 Rust AppClient adapter,再依赖已接受的 App Contract/G16。AppService 与 AppHost 不导入 GUI/Tauri/React/playback runner。
GUI-B0 范围
- 建立并登记
.worktrees/gui 长期 lane 与 lane/gui 集成分支;更新根 AGENTS.md、lane 管理入口和相关开发文档,使新 lane 不被识别为 extra。
- 初始化同仓
gui/:React + TypeScript + Tauri/Rust 的最小原生窗口;只创建当前交付必需文件。
- 固定并提交经过验证的 Rust stable 版本、rustfmt/Clippy、Node LTS、pnpm 版本,以及
Cargo.lock、pnpm-lock.yaml;不让 CI 跟随浮动 stable/latest。
- 提供三平台语义一致的
doctor、bootstrap、dev:web、dev、check、build 入口;公共编排使用 Node/package scripts,Windows 原生入口不依赖 WSL/Bash/Make。
- 建立 Linux/macOS/Windows GUI CI 初始化、静态检查与最小原生构建矩阵;缓存按 OS/CPU/工具链/锁文件隔离。
- 记录三个具名 OS/CPU 基线、系统依赖、图形会话/driver 条件和环境 owner;每个平台从独立 checkout 使用相同源码与锁文件初始化,凭据、
node_modules、target、构建与测试产物互不复制。
- B0 只建立最小工程和 native window;Mock AppClient、完整 playback 与真实 Rust invoke/event canary 属于 B1,真实 AppService transport 属于 B2。
GUI-B0 退出条件
后续里程碑(不在 B0 内提前声称完成)
- GUI-B1 独立界面与回放:Mock AppClient、文档/会话 shell、L0/L1、三平台最小 L2;每平台至少一个真实 React↔Rust invoke/event canary;双 client fixture 证明 facet/value 语义、不可用降级、本地状态隔离、different-mux 投影和同 mux
already_attached。
- GUI-C1 跨语言契约准备(B0 后可与 B1 并行):冻结 profile/version/capability discovery、完整 payload/codec、认证/framing、Rust↔TS 无损整数 bridge、execution 恢复与拒绝策略,以及 Workspace/ChangeSet identity/source/revision/limits/errors。
- GUI-B2 本机真实连接:三平台通过显式同机 execution profile 接入同一个 G16 detachable application;完成 mux 选择/创建、提交、流式、定向中断、审批、断开重连,以及 dedupe/query/generation/barrier 等真实闭环证据。
- GUI-B3 桌面开发验收:发布 profile 的启动与 L3 桌面体验/离线 canary;保留 GUI/Hosted Mux 共享 application 的原生证据,并证明 Embedded TUI 与 G15/G17 foreground lifecycle 未回归。
非目标
- 浏览器内嵌、多 WebView 浏览器、远程 AppService、多用户/跨机实时 Session。
- GUI 自有 Agent loop、权限系统、Session 数据库、插件运行时、通用 RPC/HTTP bridge 或第二个 Product runtime/Host。
- 完整 IDE、文件编辑器、终端模拟器、PDF/Office 全格式应用。
- Git 暂存、回滚、提交、推送、分支/worktree 创建或 handoff;首期 changes/review 只读且必须来自已接受的 provider/facet。
- 自动安装、启动或升级 Python 后端;后台系统服务、自动更新、签名/公开发行安装包。
- 同 mux observer/takeover、Embedded→Hosted 自动迁移、跨崩溃草稿恢复、富产物/全局历史发现、系统通知与浏览器插件执行。
- 全平台像素完全相同,或以一个平台证据替代另两个平台。
三平台证据记录
| 平台 |
OS/CPU 基线 |
owner |
commit/工具链/系统依赖 |
build/native window 证据 |
状态 |
| Linux |
待 B0 冻结 |
待指派 |
待记录 |
待记录 |
未完成 |
| macOS |
待 B0 冻结 |
待指派 |
待记录 |
待记录 |
未完成 |
| Windows |
待 B0 冻结 |
待指派 |
待记录 |
待记录 |
未完成 |
依据与关联
完成定义
本 tracking issue 仅在 B0 的全部退出条件和 Linux/macOS/Windows 三平台证据均完成后关闭。B1/C1/B2/B3 使用各自交付 issue/PR 继续跟踪;它们的完成不是关闭 B0 的前置条件,也不能被 B0 状态代替。
目标
正式接受 HarnessGUI 的 scope placement 与首期组件边界,并跟踪 GUI-B0 工程基线交付。本文档化决定以已合并的 #581 和当前
main上的 GUI/V3.1 架构文档为依据;本 issue 不把尚未取得的实现或三平台证据表述为已完成。已接受的架构决定
HarnessGUI,不建立 Coding、Design、Research、PPT 或 Work 等 Product-specific GUI 类别,也不创建前端专用事实权威。AppHost继续只拥有 canonical admitted Product catalog/routing 与 scoped runtime/binding lifecycle。HarnessGUI与HarnessTUI Hosted Mux可以连接同一个 G16 application,但必须使用各自独立的 AppClient scope、attachment generation、cursor 与 presentation state。草稿、焦点、滚动、选择和本地恢复状态不得共享;同 mux 继续遵守 one-controller-per-mux 与already_attached,首期不引入 observer/takeover。HarnessTUI Embedded仍由 Product outer composition 直接绑定 Product/Harness,绕过 AppServer/AppService/AppHost;不得因 GUI 启动而迁移到 hosted boundary,也不得合并其生命周期。G15/G17 foreground child ownership 同样保持不变。AppClientV1、可选ExecutionClientV1与版本化 HarnessClient facets 消费;GUI/Hosted Mux 不直接读取 Git 或 Product 内部对象,不建立第二套 provider、registry、权限或运行时。首期组件边界
GUI-B0 建立一个
gui/子工程,首期保持一个前端 package 与一个 Rust crate;只有出现真实第二消费者时才提取 workspace/shared package。依赖方向固定为:React/TS 依赖 UI-facing port;Mock 与 Tauri adapter 实现该 port;真实路径由 Tauri bridge 依赖 Rust AppClient adapter,再依赖已接受的 App Contract/G16。AppService 与 AppHost 不导入 GUI/Tauri/React/playback runner。
GUI-B0 范围
.worktrees/gui长期 lane 与lane/gui集成分支;更新根AGENTS.md、lane 管理入口和相关开发文档,使新 lane 不被识别为extra。gui/:React + TypeScript + Tauri/Rust 的最小原生窗口;只创建当前交付必需文件。Cargo.lock、pnpm-lock.yaml;不让 CI 跟随浮动stable/latest。doctor、bootstrap、dev:web、dev、check、build入口;公共编排使用 Node/package scripts,Windows 原生入口不依赖 WSL/Bash/Make。node_modules、target、构建与测试产物互不复制。GUI-B0 退出条件
gui/的一个前端 package、一个 Rust crate、版本固定与两个锁文件可审核。doctor/dev/check/build等入口在 Linux、macOS、Windows 上语义一致;Windows 入口不依赖 Make/Bash/WSL。后续里程碑(不在 B0 内提前声称完成)
already_attached。非目标
三平台证据记录
依据与关联
完成定义
本 tracking issue 仅在 B0 的全部退出条件和 Linux/macOS/Windows 三平台证据均完成后关闭。B1/C1/B2/B3 使用各自交付 issue/PR 继续跟踪;它们的完成不是关闭 B0 的前置条件,也不能被 B0 状态代替。