# 安装中心模块拆解(2026-10-17) > **范围订正:本文件不再是当前实施任务。** 用户已明确第18项是“设置 → 安全中心”,此前按应用安装管理理解有误。本文件保留历史证据与分析,不作为安全中心的需求、实现方案或完成度。当前入口见[安全中心范围订正与待拆解项](安全中心模块拆解-2026-10-17.md)。已有发现应用功能保留;下文安装/更新/卸载等批次不再列入本次四模块计划。 ## 文档范围与结论 本文只做模块拆解、证据归档和分批实施方案,不实现业务代码,不触发安装、更新、卸载、授权或保存。本文形成后通过 REA 对 WorkBuddy 5.8.3 做了一次只读 target 枚举、一次无操作的声明式探针,以及一次打开设置窗口的声明式探针尝试;没有执行产品写操作,也没有修改 REA 配置。 **当前结论:** - 既有 REA 证据已经证明 WorkBuddy 5.8.3 侧栏“发现应用”浮层的入口、稳定打开态、主要几何、CSS 和客户端请求/授权逻辑。 - 既有证据**没有**采集“设置 → 应用管理/安装中心”的懒加载主页面。现有脚本清单只出现 `BuddyAppsPanel-vC0qX_Oo.js` 和 `BuddyAppsPanel-OzkcFEe0.css` 的文件名,没有这两个资源的正文。 - 2026-10-17 的最新 REA 枚举只返回主窗口 `1CAD78026104DDABDB43F9EB6BA7635D`,没有设置窗口 target。一次无操作声明式探针成功(`ev_a3ca56f518f5c5101d2ae6e64f24794a564956da643c11e622c56b5cbb245000`),但没有导航。 - 打开设置窗口的声明式探针被 REA 以 `invalid_request / invalid_input` 拒绝,未产生 Evidence ID、设置 target 或 `data-settings-tab="buddyApps"` 页面。这次结果只记为工具输入失败,不能反推 WorkBuddy 没有应用管理页,也不能反推 REA 不支持该动作。 - “发现应用”是应用切换/发现浮层,不能据此推定安装中心主页面的列表、已安装状态、版本、更新、卸载、授权按钮和失败恢复。 - YCode 当前只有同壳适配的本地“发现应用”浮层,映射到专家、技能、连接器三个本地能力入口;没有云应用目录、应用详情、安装/更新/卸载、授权、依赖安装或应用管理主页。 - 因此 TODO 18 只能保持“部分实现”。本轮不能把它标记为完成,也不能把浮层通过当作安装中心 1:1 验收。 本文证据标签: | 标签 | 含义 | | --- | --- | | `REA-RUNTIME` | REA 运行时观察到的页面、DOM、布局、视觉或声明式输入结果 | | `REA-STATIC` | REA 保存的 renderer script/CSS/manifest 正文静态结论 | | `YCODE-SOURCE` | 当前 YCode 源码事实 | | `INFERENCE` | 基于证据的工程建议,不能当成原版事实 | ## REA 证据清单 目标版本均为 WorkBuddy 5.8.3,Windows,Chrome 138 / Electron 37.10.3。主要观察在暗色主题、`1336×1240` 主窗口或 `900×680` 设置窗口下完成。 | 用途 | Evidence ID | 保存位置 | 时间(UTC) | 观察范围与边界 | | --- | --- | --- | --- | --- | | 主窗口基线 | `ev_ab93f4313af45f559597bfa886f218257edb9b8c1c1c056c446b2ed26a2352e9` | `.tmp/rea-todo18-main-visual.json`、`.tmp/rea-todo18-main/` | `2026-10-17T05:44:14.389Z` | 暗色主窗口、1336×1240、无浮层的基线。截图 SHA-256 `b561129cfa37a5b6220e449fd13de7eadc2bc88b68cf48b5c647052aff4a8591`。不能证明打开态。 | | 设置窗口基线 | `ev_5b635ae361c0988fa459b5d58897d40ab52ae2e814394b8c21080d1eb9bcb6a1` | `.tmp/rea-todo18-settings.json`、`.tmp/rea-todo18-settings/` | `2026-10-17T05:44:00.912Z` | 暗色设置窗口、900×680,停在“记忆与进化”。截图可见“数据与安全”分组下的“应用管理”导航,但右侧不是应用管理页。截图 SHA-256 `5fe5eb779151e04e1415198cd5e3a2958f02395381cc743713f3cddf9961bc3c`。 | | 打开后复核 | `ev_43e8726c4cfac93184509ea30ae0d1305f4ad9c4a186f6ce7a20a7b16810316c` | `.tmp/rea-todo18-discover-after.json`、`.tmp/rea-todo18-discover-after/` | `2026-10-17T05:45:42.851Z` | 截图 SHA 与主窗口基线完全相同,画面未出现浮层。它不能作为“发现应用”打开态证据。 | | 键盘打开过程 | `ev_d3527391f609e4a8cb4d194a24ee17dcbbdfc0a2d58db240ef3686119694d85f` | `.tmp/rea-todo18-discover-key.json`、`.tmp/rea-todo18-discover-key/` | `2026-10-17T05:49:07.439Z` | REA 对 `.industry-template-switcher__trigger` 执行 Enter,动作完成并等待 500ms;`frame-000.png` 显示浮层。最终截图 SHA `65f7ce3cd1d81f4f01f9fabe745b50c0236831f55e69b2012f0fe4e2135271cc`。只证明入口可打开,不证明搜索、选择、滚动到底和授权。 | | 稳定打开态 | `ev_bd22e46c95d3887daba16dbe319389ad74e10afea8f71af9a7639e8bce95ebb4` | `.tmp/rea-todo18-discover-state.json`、`.tmp/rea-todo18-discover-state/` | `2026-10-17T05:49:49.145Z` | 暗色浮层稳定截图 SHA-256 `f5284085280418769f8c6f022c1e2451f167815783227373c2a90d766ea2bd40`。含布局树,但 REA 布局不含文本/input value,应用名称与描述需结合同次截图。 | | renderer 脚本源 | `ev_2b8db4eb73c59a8d3d80c3e37db5ea9b5bf1d13390d5238d81ff2cc53d11dc09` | `.tmp/rea-todo18-main-scripts.json`;恢复件 `.tmp/rea-todo18-matches/contexts-DgzzFjnf.js` | 采集于 2026-10-17 | REA 捕获 321 个当前已加载脚本。`contexts-DgzzFjnf.js` 为 7,553,508 bytes,SHA-256 `8d0c375f141cf724c7f77233ee1d54dd21c9cc86286b79d119711f34a6236746`。其中包含发现浮层、API、登录、consent、依赖和缓存逻辑。 | | 样式源 | `ev_7eb66ea8d5949eb7d872f1a93a97894a811b3beb7a02eabd81a500409f1045e4` | `.tmp/rea-todo18-styles-current.json`、`.tmp/rea-todo18-current-contexts.css`、`.tmp/rea-todo18-industry.css` | 采集于 2026-10-17 | `contexts-BkjwYSZT.css` 为 1,600,789 bytes,SHA-256 `50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380`。恢复出的行业浮层规则文件为 21,085 bytes,SHA-256 `ab1771d8109a137d566e19d24901fa088f893354553900172e5719684de58a5d`,只是原 CSS 的子集。 | | 当前 target 枚举 | `ev_2504239bed6d570c1e1e274465ffb9989058ba81ea503f7b295db6add4e380f1` | `.tmp/rea-four-modules-install-targets.json` | 采集于 2026-10-17 | WorkBuddy 5.8.3 / Electron 37.10.3;只枚举到主窗口 target `1CAD78026104DDABDB43F9EB6BA7635D`,没有设置窗口。 | | 无操作探针确认 | `ev_a3ca56f518f5c5101d2ae6e64f24794a564956da643c11e622c56b5cbb245000` | `.tmp/rea-four-modules-install-probe-minimal.json` | `2026-10-17T10:04:39.891Z` | 使用仅含 wait 的 REA 声明式探针;`probe.status=completed`,0 个探针帧。视觉 viewport 为 `1336×902`,PNG SHA-256 `d6ef3903bee943b69272a003d8ac7753e7bef882d4949d10104ccac06f70115f`。没有点击、导航或设置窗口证据。 | | 打开设置探针失败 | 无;工具拒绝后未生成 Evidence ID | `.tmp/rea-four-modules-install-open-settings.json`、`.tmp/rea-four-modules-install-open-settings-retry.json` | 2026-10-17 | 两个文件均 295 bytes;返回 `code=invalid_request`、`category=invalid_input`、`message=Analysis input is invalid. Check the arguments and try again.`。没有证据表明点击已执行;失败后停止重试。 | ### 证据边界 1. 没有安装中心主页面 DOM、视觉、CSS 或 lazy chunk 正文。 2. 没有“应用管理”导航的实际点击记录;当前截图只证明导航文字可见。 3. 没有真实 catalog API 响应、账号/企业 header、登录跳转结果或 consent 页面截图。 4. 没有安装、更新、卸载、重装、取消、失败、重试或部分成功的产品运行态。 5. 没有浅色主题下的原版“发现应用”稳定截图;当前浅色验收来自 YCode 自身。 6. REA DOM/layout 会省略文本和输入值,不能从布局节点单独证明中文文案。 7. 运行时截图与 DOM/layout 是顺序观察,不是同一原子帧。 8. 最新打开设置窗口探针在 REA 参数校验阶段失败;没有设置 target、`buddyApps` active 状态或主页面截图。 9. `BuddyAppsPanel-*` 是否已在当前窗口加载仍未证明;没有打开主页面就不能把“未观察到”写成“不存在”。 ## 可用入口与选择器 ### 设置主页面入口 `REA-STATIC` 已从保存的 renderer 正文确认设置导航项稳定带有 `data-settings-tab`: ```css [data-settings-tab="buddyApps"] .settings-navigation__item[data-settings-tab="buddyApps"] .settings-navigation__item--active[data-settings-tab="buddyApps"] ``` 设置窗口外层可用的稳定选择器: ```css body.settings-window .settings-window-root .settings-modal__nav .settings-navigation .settings-modal__content .settings-modal__panel ``` 现有证据截图对应“应用管理”的导航行,但页面未打开。主协调补采时建议: 1. 选择设置窗口自己的 REA target。历史设置 target 为 `8E8A75786E23EA4A57CD049223F7099D`;当前主窗口 target `1CAD78026104DDABDB43F9EB6BA7635D` 不能默认代表设置窗口。 2. 点击 `button[data-settings-tab="buddyApps"]`。 3. 等待 `.settings-navigation__item--active[data-settings-tab="buddyApps"]`。 4. 再等待 500–1000ms,确保 `BuddyAppsPanel-vC0qX_Oo.js` 与其 CSS 懒加载完成。 5. 因主页面根 class 尚未知,先使用 `.settings-modal__panel`、`.settings-modal__content` 和 `.settings-modal__panel > *` 记录页面边界,不要先假定 `.buddy-apps-panel`。 6. 同一次 lifecycle 同时采集视觉、script sources 和 style sources;只采稳定页面,不点击安装、更新、卸载或授权动作。 ### 发现应用浮层 `REA-RUNTIME` 与 `REA-STATIC` 共同确认的稳定选择器: ```css .industry-template-switcher__trigger .industry-template-switcher__trigger--general .industry-template-switcher__trigger--application .industry-template-switcher__reset-button .industry-template-switcher__popover[role="dialog"] .industry-template-switcher__panel .industry-template-switcher__search-header .industry-template-switcher__search .industry-template-switcher__search .wb-input__inner .industry-template-switcher__list .industry-template-switcher__group .industry-template-switcher__group-items .industry-template-switcher__item[data-template-id] .industry-template-switcher__item-action-btn .industry-template-switcher__retry .industry-template-switcher__more .industry-template-switcher__back .industry-template-switcher__recent-grid .industry-template-switcher__empty ``` 说明: - `data-template-id` 在运行时实际承载 `applicationId` 值。 - 选中项在原版是 `role="option"` 的非按钮 `div`,未选中项是可点击 `button`。 - 不应依赖样式哈希类名 `src-*` 或 `_tag_*`,这些类名跨构建不稳定。 ## 原版可证行为 ### 1. 功能开关、登录与入口 `REA-STATIC`: - 设置路由 `buddyApps` 由 feature flag `buddyAppEnabled` 控制是否可见。 - 发现应用根据账号、API route 和 feature flag 决定是否出现。 - 未登录时点击打开入口会先走登录,不会直接展示云目录。 - API route 分个人与企业两种;企业路线把 enterprise id 编入路径。 `REA-RUNTIME`: - 暗色主窗口侧栏顶部存在“发现应用”胶囊入口。 - 当前截图中的入口是通用态,文案“发现应用”,不是已选中某个业务应用的状态。 ### 2. 浮层结构与分组 `REA-RUNTIME` 稳定打开态: | 结构 | 实测 | | --- | --- | | 触发按钮 | `[173.28125,48,98,28]`;12/500/20;暗色背景 `rgb(46,46,46)`;圆角 100px | | 浮层 | `[31,82,240,420]`;固定定位;padding 8;圆角 16;暗色背景 `rgb(36,36,36)` | | 内面板 | `[40,91,222,402]` | | 搜索区 | `[40,91,222,33]`,输入框 `[40,91,222,28]` | | 列表视口 | `[40,128,222,365]`;gap 4;纵向滚动 | | 推荐组 | 标题高 24,条目列表高 960;按 48px 行高可容纳 20 项后继续滚动 | | 条目 | 218×48;padding 8;gap 12;圆角 8 | | 图标 | 24×24;列表中圆形,暗色背景 `rgb(41,41,41)` | | 标题/描述 | 13/16、11/14;描述为 50% 暗色文字 | 当前截图可见的推荐样例为“通达信、企鹅教师助手、美图设计室、腾讯自选股、腾讯电子签AI合同助手、Alpha派 Lite、广发证券”。这些是随账号/服务变化的运行时数据样例,**不得写死为 YCode 目录契约**。 ### 3. 列表、搜索和分页 `REA-STATIC`: - `recent` 与 `recommended` 各按场景请求 20 项。 - 默认只展示 recent 前 6 项;recommended 会过滤掉已在 recent 中出现的 `applicationId`。 - recent 超过 6 项或 `hasMore` 时有“更多”,进入独立 recent 网格视图并可返回。 - 非搜索模式滚动到距底部 80px 内时调用对应场景的 `loadMore()`。 - 搜索输入有 250ms debounce;搜索模式隐藏 recent/recommended 分组,只显示搜索结果。 - 搜索有 loading、error/retry、空结果非搜索和搜索无结果状态。 - 请求使用 owner key 隔离个人/企业账号;旧请求有 generation guard。 `REA-RUNTIME` 只覆盖默认非空推荐列表;上述分页、搜索、错误和空态属于代码事实,未逐态截图。 ### 4. 条目身份与选择 列表 summary 的核心字段来自 `REA-STATIC`: ```ts interface BuddyApplicationSummary { applicationId: string name: string description?: string icon?: string operationTag?: { title: string description: string } } ``` 条目行为: - 未选中行悬停/聚焦显示“进入”动作;选中行显示品牌色对勾与“退出”。 - 选中项由当前应用/模板选择状态决定,不由列表自带 installed 布尔值决定。 - 点击未选中 summary 后,浮层先关闭,再请求 detail。 ### 5. 应用详情、激活与授权 `REA-STATIC` 证明的 detail 字段: ```ts interface BuddyApplicationTemplate { templateId: string applicationId: string name: string templateName: string description?: string category?: string operationTag?: { title: string; description: string } icon?: string schemaVersion: number templateVersion: number versionNo: number requiredScopes: string[] allowedOrigins: string[] templateConfig: unknown releaseNote?: string publishedAt?: string } ``` 上面的 `templateConfig` 在实际代码里还有 schema 校验;这里保留为 `unknown`,避免把未经原文逐项恢复的完整 schema 当成 YCode 契约。 选择流程: 1. 请求 detail。 2. 等待本地选择状态 hydrated,最长 8s。 3. 校验账号在异步过程中没有切换。 4. 调登录/授权状态接口,取得 `authorized`、application、redirect URI 和 granted scopes。 5. 已授权则直接提交本地模板上下文。 6. 未授权则显示 consent;用户可批准或跳过跳转。 7. consent 后获得一次性 code 和 granted scopes。 8. 根据模板配置安装/连接 MCP 依赖,并可能打开外部 authorization URL。 9. 成功后提交模板选择、上报 usage、触发 onboarding,并返回主页。 10. 退出当前应用时清空选择,并尝试移除该应用的 MCP dependency。 全局同一时间只允许一个应用切换流程,避免并发授权。 ### 6. 远程 API 事实 `REA-STATIC` 中可确认的个人账号端点: | 功能 | 方法 | 路径/参数 | | --- | --- | --- | | 场景列表 | GET | `/api/v1/open-platform/buddy_application?limit={limit}&scene={recent\|recommended}[&cursor=...]` | | 搜索 | POST | `/api/v1/open-platform/buddy_application/search`,body `{ keyword }` | | 详情 | POST | `/api/v1/open-platform/buddy_application/detail`,body `{ application_id }` | | 使用上报 | POST | `/api/v2/open-platform/asset-usage/report`,body `{ asset_id, asset_type: "buddy_app" }` | | 入口可用性 | GET | `/api/v2/open-platform/buddy/entrance` | 企业账号使用 `/v2/enterprises/{enterpriseId}` 前缀和对应子路径。 列表响应可确认字段包括 `applications`、`has_more`、`next_cursor`。请求会按需附加 `X-GPU-DEVICE-NAME`。 **目前没有证据证明以下接口:**应用包下载、安装、更新、卸载、版本检查、安装进度、取消、回滚、权限撤销、已安装列表。不能用上述 discovery/usage 端点臆造完整安装 API。 ### 7. 设置页中的应用管理 `REA-STATIC` 已确认: - 设置 route id 为 `buddyApps`。 - 入口是 `button[data-settings-tab="buddyApps"]`,中文截图显示“应用管理”。 - 页面是懒加载 `BuddyAppsPanel-vC0qX_Oo.js`,配套 `BuddyAppsPanel-OzkcFEe0.css`。 - route 可用性受 `buddyAppEnabled` 控制。 **尚不能确认:** - 主页面标题、分组、搜索、筛选和排序。 - 是否显示市场目录、已安装应用或两者共存。 - installed 的判定规则,以及安装与应用激活是否同一概念。 - 版本、更新提示、自动更新、更新检查、发布说明。 - 安装、更新、卸载、打开、停用、退出、重试、取消的入口和确认方式。 - loading、empty、error、partial、offline、unauthorized、dependency-missing 状态。 - 主页面的所有几何、深层深浅主题和动画。 这是主协调下一步最优先的 REA 补采目标。 2026-10-17 补采结果: - 设置窗口 target 不在当前 REA endpoint 的 target 列表中,只有一个主窗口。 - 计划中的 `open-account-menu → open-settings-window` 探针没有进入动作生命周期;REA 在输入校验阶段返回 `invalid_request / invalid_input`,因此没有 Evidence ID 和声明式动作步骤。 - 没有采集 `button[data-settings-tab="buddyApps"]`、`.settings-navigation__item--active[data-settings-tab="buddyApps"]` 或 `.settings-modal__panel` 的主页面内容。 - 本专项按用户要求停止重复尝试。安装中心主页面的布局、状态、版本更新、卸载和错误恢复仍为明确未知,等待后续设置窗口 target 和新 Evidence 补证。 ## YCode 当前状态 ### 已实现 | 能力 | 状态 | 主要源码 | | --- | --- | --- | | “发现应用”入口与浮层 | 已实现可交互壳 | `src/renderer/src/components/AppDiscoverPopover.tsx` | | 浮层几何、搜索、空态、键盘、外部点击、焦点恢复 | 已实现本地版本 | 同上、`app-discover-popover.css` | | 最近使用 | 已实现 localStorage 版,最多 6 个本地能力 ID | `ycode.app-discover.recent.v1` | | 应用选择 | 映射到 experts / skills / connectors 三个本地能力页 | `Sidebar.tsx`、`App.tsx`、`CapabilityCenter.tsx` | | 选中态退出 | 从本地能力页回到聊天 | `AppDiscoverPopover` 的 `onExit` | | 本地能力 | 专家、本地技能、自定义 MCP 已有各自页面和数据层 | `src/renderer/src/capabilities/` | ### 占位 | 能力 | 现状 | | --- | --- | | 技能市场 | 技能页对未连接目录显示本地空态,可导入本地技能 | | 连接器目录 | 当前以自定义 MCP 为主,云目录和第三方 OAuth 未接 | | 最近使用 | 只保存本地三个 capability ID,不是原版账号级应用使用历史 | | 应用图标 | 使用本地 SVG,不是远端应用图标和失败 fallback | ### 缺失 | 能力 | 缺口 | | --- | --- | | 安装中心主页面 | 完全缺失;设置导航中 `buddyApps` 还被用户明确移除 | | 云应用目录 | 无列表、搜索、detail、最近、推荐和分页 API | | 应用身份模型 | 无 `applicationId/templateId/version/scopes` 数据 | | 安装状态机 | 无 installed/installing/updating/uninstalling/failed | | 安装来源 | 无市场、企业、URL、本地包或内置来源模型 | | 更新与版本 | 无版本比较、release note、更新检查 | | 卸载与恢复 | 无卸载确认、部分失败、重试、回滚 | | 授权 | 无 login、consent、scope grant、redirect URI | | 应用依赖 | 无应用级 MCP dependency 安装/移除 | | 使用上报/onboarding | 无 usage report、show observer、onboarding 状态 | | 管理入口 | `SettingsDialog.tsx` 的 `REMOVED_SETTINGS_TABS` 包含 `buddyApps` | ### 需要先决定的产品边界 用户此前要求移除“系统设置 → 应用管理”入口。若后续恢复安装中心,不应静默推翻该决定。可由主协调确认采用下列之一: 1. 保留设置入口移除,只在侧栏“发现应用”中增加管理/浏览入口。 2. 恢复“应用管理”设置页,同时保留“发现应用”作为切换器。 3. 将两者合并为独立安装中心页面,设置与侧栏都指向同一路由。 本拆解建议先按“两个表面、一个状态源”设计:发现浮层负责快速发现/切换,安装中心管理页负责目录、安装、版本、授权和卸载;两侧共享同一 registry,避免出现两套 installed 状态。 ## 建议数据契约 以下是 `INFERENCE`,用于 YCode 后续实现;字段名尽量贴近 REA 静态事实,但不冒充原版完整 schema。 ```ts type BuddyAppSource = 'builtin' | 'marketplace' | 'enterprise' | 'local' type BuddyAppAvailability = 'available' | 'unavailable' | 'entitlement-required' type BuddyAppLifecycle = | 'not-installed' | 'installing' | 'installed' | 'active' | 'updating' | 'update-available' | 'uninstalling' | 'failed' | 'unauthorized' | 'dependency-missing' interface BuddyAppSummary { applicationId: string templateId?: string name: string description?: string iconUrl?: string operationTag?: { title: string; description?: string } source: BuddyAppSource availability?: BuddyAppAvailability } interface BuddyAppDetail extends BuddyAppSummary { name: string versionNo: number templateVersion?: number schemaVersion?: number category?: string requiredScopes: string[] allowedOrigins: string[] templateConfig: unknown releaseNote?: string publishedAt?: string } interface BuddyAppRegistryEntry { applicationId: string templateId?: string installedVersion?: number availableVersion?: number lifecycle: BuddyAppLifecycle source: BuddyAppSource installedAt?: number lastOpenedAt?: number lastError?: string operationId?: string dependencies: BuddyAppDependencyState[] } interface BuddyAppDependencyState { kind: 'mcp' | 'connector' key: string state: 'missing' | 'installing' | 'connected' | 'needs-auth' | 'error' error?: string } interface BuddyAppOperation { operationId: string applicationId: string kind: 'install' | 'update' | 'uninstall' | 'activate' | 'deactivate' phase: 'queued' | 'downloading' | 'verifying' | 'applying' | 'authorizing' | 'connected' | 'done' | 'failed' | 'cancelled' progress?: number message?: string startedAt: number finishedAt?: number } ``` 工程约束: - `applicationId` 与 `templateId` 分开;现有原版列表以 `applicationId` 去重。 - 版本、scope、origin、redirect URI 必须保存快照,避免更新过程中配置变化。 - installed、active、authorized、dependency-ready 必须分开。 - operationId 用于 UI 去重和恢复;不能只靠 loading 布尔值。 - token、authorization code、secret 不进入 renderer 持久状态或日志。 ## 本地功能与远端依赖边界 | 能力 | 本地可完成 | 依赖远端/宿主 | | --- | --- | --- | | 浮层/主页面布局 | 是 | 否 | | 列表缓存、最近使用、当前选择 | 是 | 初次目录数据需要远端 | | 本地 registry 和 operation journal | 是 | 状态变更需要服务端确认 | | 目录列表、搜索、详情 | 否 | 是 | | 登录、consent、scope grant | 否 | 是 | | 应用包下载、校验、安装、更新、卸载 | 否 | 是;若 YCode 自建安装包生态则另立本地协议 | | 应用模板 config 和 allowed origin | 可缓存 | 更新源来自远端 | | MCP dependency 本地注册 | 是 | 授权/远端 connector 仍可能需要服务端 | | usage report、show/click telemetry | 可本地排队 | 上报需要远端 | | entitlement、企业策略、配额 | 否 | 是 | | 错误文案和恢复 UI | 是 | 具体 reason code 来自宿主/服务端 | | 安装 provenance/checksum | 可实现本地校验器 | 可信摘要/签名来源需可信配置 | 原则:没有真实安装结果时,UI 只能显示“未接入/等待服务”,不能显示“安装成功”。 ## 建议模块拆分 ### A. `buddyAppCatalog` 职责: - recent/recommended/search/detail。 - 500ms 内搜索 debounce 的内部实现可沿用 250ms 事实,但需要统一 abort/generation。 - 账号、企业、feature flag 作为请求 key。 - summary/detail 校验、去重、缓存和 stale 响应丢弃。 不负责安装状态。 ### B. `buddyAppRegistry` 职责: - 已安装列表、版本、来源、最近打开时间。 - selected application/template。 - install/update/uninstall/active 状态。 - 操作日志、错误和恢复。 本地 registry 必须可以独立启动;远端 catalog 失败不能让已安装应用消失。 ### C. `buddyAppInstaller` 职责: - 下载、完整性校验、解包/安装、原子切换、失败回滚。 - operation progress/cancel。 - 安装来源差异。 此模块是否存在原版真实包安装流程目前未知;不得把“安装 MCP dependency”改名为“安装应用”。 ### D. `buddyAppAuthorization` 职责: - login/authorized 状态。 - consent、scope diff、grant。 - redirect/MCP 授权的衔接。 - 账号切换取消未完成操作。 ### E. `buddyAppUi` 包含两个 surface: - switcher:快速发现、最近、推荐、搜索、切换/退出。 - manager:已安装、目录、版本、更新、卸载、授权、依赖、错误恢复。 两者共享 Registry/Store,但各自保留 surface-specific UI state。 ### F. `buddyAppObservability` - 展示曝光、点击、进入、consent、授权失败、usage report。 - 事件失败不能破坏业务主流程。 - 脱敏 app id/version,不记录 token/code/secret。 ## 分批任务与验收标准 ### 批次 0:补采应用管理主页面 范围: - 主协调通过现有 REA lifecycle,在设置窗口点击 `[data-settings-tab="buddyApps"]`。 - 同次 capture 开启 scripts、styles、visuals。 验收: - 捕获到 `BuddyAppsPanel-vC0qX_Oo.js` 正文或其新的 build hash。 - 捕获到 `BuddyAppsPanel-*.css` 正文。 - 新 Evidence ID、target、captured_at、script/CSS SHA-256、viewport、theme 全部记录。 - 产出主页面 DOM/layout/稳定截图,至少覆盖默认稳定态。 - 明确没有触发安装、更新、卸载、授权等有副作用动作。 当前状态:**已尝试,未完成。** 最新 target 枚举只有主窗口;打开设置窗口的探针在 REA 参数校验阶段失败,没有设置 target。批次 0 未通过,阻塞条件正是设置页面 source/lifecycle,而不是已有静态结论不足。 取消条件: - 只采到导航 active class,未加载 lazy chunk。 - 只采到 `.settings-modal__panel` 但内容仍为其他设置页。 ### 批次 1:数据契约与只读 registry 范围: - 建 `BuddyAppSummary/Detail/RegistryEntry/Operation/Dependency` 类型。 - 建立按账号/企业隔离的本地 registry。 - 无远端时显示真实“目录未连接”,已安装本地条目仍可展示。 验收: - ID 身份稳定;同 application 不会因 template 版本重复成多张卡。 - 本地 registry 跨重启保留。 - account/enterprise 切换不会串数据。 - 没有真实 installed 数据时不伪造 installed 状态。 ### 批次 2:应用管理页壳与本地状态 范围: - 安装中心主页面骨架、搜索、筛选、分组。 - 列表、空态、加载态、错误态和 operation banner。 - 配置入口决定:独立页或恢复设置入口由主协调拍板。 验收: - 在 900×680 设置窗口和主窗口布局无溢出。 - 浅色/深色、正常/窄宽、空/错/loading 可稳定渲染。 - `[data-settings-tab="buddyApps"]` 或替代入口的导航语义明确。 - 不依赖云端即可打开本地 manager shell。 ### 批次 3:目录列表、搜索和详情 范围: - recent/recommended/search/detail adapter。 - summary 去重、分页、stale guard、请求取消。 验收: - 空查询、250ms 搜索、无结果、失败重试、下一页、末尾停止。 - recent 与 recommended 去重。 - account/enterprise 切换取消旧请求。 - 远端不可达时返回可恢复错误,不显示空目录冒充成功。 ### 批次 4:安装/激活状态机 范围: - `not-installed → installing → installed → active` 等状态。 - 同一 application 的并发操作锁。 - failure、retry、cancel、app restart 恢复。 验收: - 双击安装只产生一个 operation。 - UI 进度来自 operation 状态,不由定时器模拟。 - 失败不会部分标记 installed。 - 重启后未完成操作可查询、恢复或明确标记未知。 - “安装应用”与“安装 MCP dependency”在产品文案和状态上分开。 ### 批次 5:更新、卸载与恢复 范围: - 版本比较、release note、确认流程。 - 卸载对 active 应用、MCP dependency、云端授权和本地数据的影响。 验收: - 同版本、旧版本、新版本、降级、unknown version均有明确状态。 - 更新失败回滚到旧版本和旧 selected template。 - 卸载前明确是否保留本地数据与授权。 - 卸载失败可重试,不把卡片直接删掉。 ### 批次 6:登录、consent、scope 和依赖授权 范围: - login/authorization adapter。 - consent summary、scope diff、取消、拒绝、跳转失败、回到桌面。 - MCP/builtin/custom/joint auth 分支。 验收: - 账号切换时取消旧流程。 - redirect URI、scopes、template version 在授权期间发生变化则拒绝提交。 - 取消/失败不会写入 ready 状态。 - code/token 不落盘、不打印。 - 依赖失败与应用安装状态可区分。 ### 批次 7:像素与全状态验收 范围: - switcher 与 manager 的原版同数据、同主题、同尺寸对照。 验收: - 入口、popover、manager 默认态在浅/深色完成截图和几何比对。 - 搜索、loading、error、empty、scroll、load-more、hover、focus、selected、disabled。 - 安装、更新、卸载、授权、依赖、失败、重启恢复。 - 键盘、focus trap、Escape/外部点击、IME 和窄窗。 - 不以 YCode 专项 PASS 代替 WorkBuddy 同状态 1:1。 ## 精确未知项 ### 主页面与产品信息架构 1. 设置“应用管理”和侧栏“发现应用”是否共享同一个应用实体、选择状态和 installed 列表。 2. 主页面是否只管理已安装应用,还是也展示市场目录。 3. 主页面标题、分组、筛选、排序、搜索和详情进入方式。 4. 是否支持企业目录、内置应用、本地应用和第三方 market 的混合列表。 ### 安装语义 1. “安装”是否下载本地包,还是只创建账号授权/云端绑定。 2. 安装与应用“进入/激活”是否同一操作。 3. 安装成功后是否立即成为当前应用,还是仍展示“进入”。 4. 同一 application 是否可安装多个 template/version。 ### 更新语义 1. 更新源、版本比较规则和自动/手动检查时机。 2. 更新通知显示位置、release note 来源和强制更新规则。 3. 更新中能否使用当前版本,失败时是否回滚。 ### 卸载语义 1. 卸载按钮的确认文案和危险色层级。 2. 本地数据、云端 grant、MCP dependency、recent snapshot 是否一起清除。 3. active 应用或 dependency-disconnected 状态下的卸载限制。 ### 状态与错误 1. 完整状态枚举和 reason codes。 2. 进度是否支持百分比、字节数、阶段文案。 3. 取消、超时、断网、配额不足、企业策略、权限撤销、依赖失败的实际文案。 4. 失败后 operation 是否保留、恢复或可重试次数。 ### 数据与持久化 1. 本机 registry 的 storage key、schema version、账号/企业隔离。 2. 已安装包位置、完整性校验、签名和升级目录。 3. recent/show/usage 的服务端与本地双层缓存。 4. 应用图标 URL、缓存、CSP 和失败 fallback。 ### 视觉 1. “应用管理”主页面完整 DOM/CSS、默认数据量和空数据量。 2. 浅色稳定态和深色稳定态。 3. 安装/更新/卸载/授权弹窗与 toast。 4. 菜单、hover、disabled、focus、loading、滚底、分页。 5. 900×680 设置窗口之外的独立页面尺寸。 ## 补采检查表 主协调下一次统一补采应至少保存: - 设置 target id、窗口 URL 和 viewport。 - `[data-settings-tab="buddyApps"]` 点击前后稳定帧。 - 主页面 `.settings-modal__panel` 的 DOM、layout、可见文本和截图。 - `BuddyAppsPanel-vC0qX_Oo.js`/新 hash 的完整 REA script source。 - `BuddyAppsPanel-OzkcFEe0.css`/新 hash 的完整 REA style source。 - 默认列表数量及至少一个已安装、一个未安装、一个有更新条目的字段。 - 主操作的 DOM selector、文案、disabled 条件和确认弹窗。 - 浅色与深色稳定态;若窗口主题由设置控制,记录切换证据。 - 只读网络/状态来源证据;不在主页面直接执行真实安装或卸载。 建议的探针起点: ```json [ { "kind": "click", "selector": "[data-settings-tab=\"buddyApps\"]", "frames": 0 }, { "kind": "wait", "duration_ms": 750, "frames": 1 } ] ``` 探针完成后以 `.settings-navigation__item--active[data-settings-tab="buddyApps"]` 确认路由,再检查 `.settings-modal__panel` 内是否出现新模块内容。 ## 决策 1. **不把发现浮层等同于安装中心。** 两者共享可能的数据,但当前证据将它们拆为 switcher 与 manager 两个 surface。 2. **不在主页面证据缺失时实现安装按钮。** 后续先建立 registry/operation 状态,再接真实能力。 3. **把 installed、active、authorized、dependency-ready 分开。** 现有原版已证明选择/授权/依赖是独立步骤。 4. **应用 ID 使用 `applicationId` 作为首选去重键。** `templateId`、version 和 schema 另存。 5. **远端目录失败不等于空目录。** 本地已安装 registry 必须离线可见,远端错误必须可恢复。 6. **保留用户移除设置入口的决定。** 安装中心的最终入口位置需要主协调明确,不能擅自恢复 `buddyApps` 设置项。 7. **sample app 名称只作截图样例。** 通达信等运行时条目不得写死。 ## 本轮核对命令 本轮没有运行测试或构建。除下方明确列出的 REA target 枚举和两次声明式探针外,其余核对均为静态读取。 ```text rg --files docs | rg '安装|应用|发现|中心|模块拆解' Get-ChildItem .tmp -Recurse | Where-Object FullName -match 'rea-todo18' rg -n '安装中心|发现应用|Discover|app discover|install' docs src scripts Get-Content docs/复刻待办清单-2026-10-17.md Get-Content src/renderer/src/components/AppDiscoverPopover.tsx Get-Content src/renderer/src/components/app-discover-popover.css Get-Content src/renderer/src/capabilities/CapabilityCenter.tsx Get-Content scripts/verify-app-discover.cjs Get-Content .tmp/rea-todo18-BuddyAppDiscoverPanel.js Get-Content .tmp/rea-todo18-BuddyAppIcon.js Python 解析 .tmp/rea-todo18-*.json 的 evidence_id、target、captured_at、viewport、artifact SHA-256、limitations Python 解析 .tmp/rea-todo18-main-scripts.json 的 contexts-DgzzFjnf.js source artifact Python 解析 .tmp/rea-todo18-styles-current.json 的 contexts-BkjwYSZT.css source artifact Python 解析 .tmp/rea-todo18-discover-state/layout.json 的浮层几何 Python 解析 .tmp/rea-todo18-settings/layout.json 的设置导航结构 Python 在保存的 contexts-DgzzFjnf.js 中检索 API、selection、consent、dependency、settings route ``` 2026-10-17 新增的 REA 读取与失败记录: ```text node .tmp/rea-css-runtime/scripts/rea.mjs list-electron-targets http://127.0.0.1:9223 REA inspect-electron-page:主窗口 + 仅 wait 的 visual_probe REA inspect-electron-page:主窗口 + 打开账户菜单/设置窗口的 visual_probe 结果:target list 成功;无操作探针成功;设置打开探针 invalid_request,未生成 Evidence ID 保存:.tmp/rea-four-modules-install-targets.json .tmp/rea-four-modules-install-probe-minimal.json .tmp/rea-four-modules-install-open-settings.json .tmp/rea-four-modules-install-open-settings-retry.json ``` ## 风险 1. **把浮层当完整安装中心**:会严重高估完成度。 2. **把 MCP 依赖安装冒充应用安装**:原版代码明确区分 dependency 与 application 选择。 3. **恢复已移除设置入口而不确认**:与用户此前要求冲突。 4. **远端服务不可用时伪造状态**:可产生虚假 installed/update 结果。 5. **账号/企业隔离错误**:可能把企业目录、授权或用量混进个人数据。 6. **授权并发和账号切换**:可能出现旧 consent 写入新账号。 7. **安装/更新破坏用户内容**:需要原子操作、备份、回滚和明确确认。 8. **敏感信息泄漏**:authorization code、token、secret 和完整远端 URL 不应进入日志/普通本地状态。 9. **运行时动态条目被写死**:sample app 名称、顺序和描述会随账号/服务变化。 10. **主页面像素误判**:当前没有该页面任何 REA 视觉,不能从浮层几何推导。 ## 交接结论 本轮安装中心专项到此收口:已有足够证据拆出“发现浮层”和“安装中心主页面”两个 surface,以及目录、选择、授权、依赖和未知安装生命周期边界;但安装中心主页面仍没有 REA 运行时证据。下一步需要先获得可操作的原版设置窗口 target,再点击 `[data-settings-tab="buddyApps"]` 并同次采集 DOM、视觉、脚本和样式。补采成功后,优先恢复 `BuddyAppsPanel` 的 DOM/CSS 和页面状态,再决定 manager 的真实信息架构。YCode 已有浮层壳可以保留,但其数据层仍是本地能力适配,必须和后续云应用 registry 解耦。