Files
ycode/docs/项目模块拆解-2026-10-17.md

327 lines
43 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 更多 → 项目:REA 拆解进度
> 当前开发执行入口:[三模块开发计划](三模块开发计划-2026-10-17.md)。先收口现有项目链路:首次发送失败补偿、运行标识、真实状态筛选、详情指令保存同步,再接配置与后续数据页。本轮为源码核对与准备,未修复这些问题。
> 新增资料/待办核对:[对话资料沉淀与任务引用](对话资料沉淀与任务引用确认-2026-10-17.md)。已证显式todo引用和项目资料上传/选择范围;默认tdrive-root仅在teams/cloud发送链路证实,本地路径是否由adapter/内核补入仍待证。不可把scope指针当全量资料读取,也不能按名称断言项目资产与资料库的后台存储关系。
当前状态(2026-10-17 系统拆解轮):已实现并验证“本地单用户项目 + 项目任务关系 + 项目指令注入”的基础闭环;项目协作、动态、计划、资产、成员权限和云传输仍是占位或未实现。属于主待办 TODO 20,整个模块保持未完成、未做完整 1:1 验收。
说明:以下历史章节按时间记录取证和实现过程,其中“尚未实现”“仍待接线”等语句反映当时状态,不代表本文件末尾“本轮系统拆解”的最新结论。
## 本地存储基础
- `src/shared/projects.ts`:独立项目 ID、本地 transport、名称、指令、模板 ID、专家/技能来源及连接器关联;不将空间记录冒充项目。
- `src/main/projects.ts`:`ProjectRepository` 串行创建、临时文件原子替换、重新读取持久化配置、拒绝覆盖损坏配置。项目名称 trim 后非空且最多 15 个 UTF-16 单元;能力引用保留来源与 provider,并去除同身份重复引用。
- 创建表单源码 `CreateProjectDialog` 使用 15 字输入限制、trim 非空条件;提交区分 customExperts/customSkills 与市场 experts/skills,连接器采用 personal auth。YCode 当前契约仅保存引用,尚未实现授权及能力解析,不能称这些能力已生效。
- `node scripts/verify-project-storage.cjs` 通过:12 次并发创建无丢失、ID 唯一、实例重建后恢复、指令/能力关联保存、非法输入阻断、失败后队列可恢复、损坏文件保持原内容。`npm run typecheck` 通过。
- 下一步接入主进程 IPC、preload 和原版页面;项目指令进入真实对话及项目删除/任务历史关系仍需单独实现和验收。
### IPC 与样式接线准备
- 已新增 `YCodeApi.projects.list/create`、preload 对应 `projects:list/create` 调用,以及主进程 `ProjectRepository(userData/projects.json)` handlers。`npm run typecheck`、`npm run build` 和存储回归通过;尚未进行真实 renderer → preload → IPC 的窗口回归,不能据此称创建交互已验收。
- `scripts/rea/recover-project-styles.cjs` 从固定弹窗 REA Evidence 中恢复 `collab-YMJYRnW_.css`,源 SHA `4737f6a8f8f993de933e5ebae0d94b96cb39788e160470490f607508537e5377`。705 条规则限定在 `.yc-project-surface` 后代,保留媒体条件和 keyframe 正文;生成到 `src/renderer/src/projects/source-projects-recovered.css`。生成及 `--check` 一致性检查通过。该 CSS 暂未挂载,不能当作页面视觉已完成。
- 下一步恢复项目页面 DOM、图标和插图,挂载上述规则并接 IPC;然后验证真实创建、重载、筛选与错误状态,继续项目会话关联。
### 项目页插图
- 原版加载图像经 REA `ev_d740e73903dd69444105e2509b238e5912f2c93d3adaa183b05ec7221512ef7a` 采集,`.tmp/rea-todo20-project-hero.json`;源文件名 `landing-hero-B6659kdy.png`。
- `scripts/rea/recover-project-hero.cjs` 只消费该证据的图像正文,校验 PNG、629281 字节长度及 SHA `b382831ec55658c051fed7031302c37e9af8c9199a4becdf8277f962419d1b47`,恢复至 `src/renderer/src/projects/assets/landing-hero.png`;生成与 `--check` 均通过。
- 采集时新建弹窗仍在,REA 标记插图可见性 covered;本记录仅证明加载资源字节恢复,页面上的稳定可见外观以前述项目首页证据为准。
### 页面组件第一批(尚未挂载)
- `ProjectListPage.tsx` 已接真实列表、名称搜索、创建 IPC 与失败信息;新建弹窗保留原版主结构、名称计数及指令字段。类型检查通过。
- 仍缺模板、三类能力选择、项目图标、列表操作和详情/任务关联,组件暂未挂入 App 路由,不能称用户端已交付或创建交互已验收。加载/空态与部分文案仍待按原版恢复。
- 样式生成器补回同一 REA Evidence 内的 26 条共享 modal 规则(逐份 SHA 验证),现共 731 条;修正 body/html 主题选择器被错误放到页面内部导致无法匹配的问题。生成与 `--check` 通过。
### 模板与图标恢复
- `scripts/rea/recover-project-templates.cjs` 静态解析固定项目首页 REA Evidence 的 `project-list-page-DpHRTtk8.js` 与 `zh-cn-C7BTHfrQ.js`,逐份校验正文 SHA;不执行原模块。五类模板的 ID、中文标题/描述、完整指令和专家/技能/连接器关联恢复到 `project-templates.json`;生成与 `--check` 通过。
- 首页模板卡片现按原版 `landing-templates-head/list` 结构生成,点击预填完整指令,创建载荷携带 templateId 与能力引用。引用尚未解析/授权,不代表这些市场能力在本地存在或可调用;尤其连接器必须在后续选择器接入时按实际 registry 过滤,不能将模板 ID 当作已安装连接器。
- `scripts/rea/recover-project-icon.cjs` 从同份首页 layout/svg_nodes 恢复项目 SVG 至 `ProjectIcon.tsx`,每个组件使用独立 clip ID,避免重复卡片引用冲突;生成、`--check` 与 `npm run typecheck` 通过。
- 当前仍未挂载 App 路由,未进行窗口视觉或真实点击创建验收。
### 首页挂载与真实创建回归
- App 增加 projects 路由,Sidebar 普通/窄屏复用 `ProjectMenu`,悬停入口及点击项目进入真实列表;当前菜单仅包含项目,原版其余外部应用入口尚未接入,菜单几何和关闭时序仍是待对齐的适配实现。
- `node scripts/verify-project-page.cjs` 在隔离 Electron、真实 preload/IPC/文件系统中通过:五模板显示、空名称禁用提交、填写名称后创建、磁盘一条真实项目、重载完成后重新导航可恢复项目、renderer 错误为零。生产构建通过。报告 `.tmp/project-page-aaCZyO/report.json`,截图 `project-page.png`。
- 修正测试重载等待:必须等待 `did-finish-load` 后操作,避免旧 DOM 断言成功却采到首页的竞态;最终截图人工检查确为项目页。
- 当前截图显示共享 UI kit 按钮/输入框样式和文字/背景 token 尚未完整进入此作用域;页面顶部几何、项目卡图标/时间、模板弹层/能力选择、详情操作仍未对齐。因此本轮只证明功能入口和创建持久化,不能称视觉 1:1 或整个项目模块完成。
### 共享控件样式修复
- `recover-project-controls.cjs` 从固定弹窗 Evidence 的 `tokens-Df-i-zsO.css` 与 `src-Bh3YZ35H.css` 恢复作用域 token 和按钮/输入框/textarea 规则,共 301 顶层区块;逐份源 SHA 与生成 `--check` 通过。保留浅色默认及 `[data-theme=dark]` 覆盖。
- 首轮仅选含正文颜色的 token 区块导致按钮独立 token 缺失;已改为恢复全部相关 root/dark 自定义属性区块,截图确认新建按钮与搜索输入框恢复尺寸、底色与边框。
- `npm run build` 与真实项目页回归再次通过,最终报告/截图 `.tmp/project-page-Waid6s/`;仅验证浅色功能及画面,深色/精确几何/卡片元信息和全模块仍待验收。
### 顶栏与项目卡片结构
- 固定首页 Evidence 显示 workbuddy-collab 内先有 64px workbuddy-topbar,之后 landing,后者内部顶部 padding 56px。已补回空顶栏 DOM,恢复相应共享规则;共享默认 56px 与项目实测 64px 不同,`project-layout.css` 按运行态明确项目变体为 64px,而非给内容追加偏移。
- 项目卡片补回 36px 图标容器与恢复 SVG,描述改为根据真实 createdAt 生成“添加于…”相对时间,沿用源分钟/小时/天/30天月的分段;不再用项目指令填充该行。
- `verify-project-page.cjs` 新增顶栏64px、header 相对 topbar+64+56、卡片80px、图标36px、添加时间断言。首轮断言发现默认56px,修正后生产构建与真实窗口创建/重载/几何检查通过,报告 `.tmp/project-page-3HpYwT/report.json`。仍未进行同主题逐像素比对或深色验收。
### 深色及能力配置行
- 已接原版深色 hero 声明到 YCode html[data-theme] 主题归属;真实窗口测试新增深色卡片、插图反色/opacity、640px 深色弹窗和15字符输入检查,并输出深色首页/弹窗截图。最终生产构建及回归通过,报告 `.tmp/project-page-CMmzDh/report.json`。
- 创建弹窗补连接器、专家、技能三行及可移除引用;添加从真实 MCP、专家、技能 IPC 列表取得本地能力,可勾选并写入项目引用。模板市场引用明确 title 标注尚未本地执行;模板连接器按实际 registry 过滤。目录加载中禁止提交,读取失败且仍有连接器时阻断提交,避免绕过 registry 校验。
- 本地选择器当前为行内复选列表,尚未复刻原版独立选择窗口,且未完成带真实能力的点击/重载专项回归;不能称选择器 1:1 或能力运行接通。原版模板切换浮层、modal 精确几何与图标、市场引用解析、项目对话接入仍待完成。
### 连接器选择回归与模板切换
- 真实窗口回归先通过 MCP IPC 保存禁用的 stdio 连接器(不连接、不执行),在创建弹窗点击选择、移除、再次选择并提交,断言项目磁盘记录的 connector ID 等于实际 registry ID。最终构建及回归通过,报告 `.tmp/project-page-kf1YKd/report.json`;此证据覆盖引用选择和持久化,不证明工具执行。
- 已补模板切换,沿用现有 REA 恢复 SourceSelect 控件:选择模板替换指令/能力,切换自定义清空指令和能力,保留项目名称;连接器仅保留实际目录可匹配 ID。SourceSelect 与原版此处 Dropdown 是不同组件,当前尚未逐像素等价,也未做模板切换全路径真实窗口专项验收。
- `recover-project-templates.cjs --check` 再次通过;不修改源模板指令以适配本地能力缺失。
### 模板切换实际交互验收
- `verify-project-page.cjs` 新增真实 renderer 选择器交互:等待 registry 就绪后展开六项列表,键盘选择产品需求模板,确认完整角色指令及专家 chips 出现;再选择自定义,确认指令和全部 chips 清空,两次切换项目名称均保留。
- 与既有真实连接器选择/移除/重选/落盘、创建重载及深浅主题回归一同通过,最终报告 `.tmp/project-page-Q8G5qN/report.json`。本测试使用实际页面 Select 状态机,未改写 React 状态或伪造模板保存。
- 此更新关闭“模板切换全路径未经实际交互验收”缺口;仍不关闭原版 Dropdown 外观差异、独立能力选择窗口、项目详情/任务关联及能力执行的缺口。
### 项目详情取证及任务归属
- WorkBuddy 5.8.3 项目详情稳定页 REA `ev_ca0195278ba08b57f2d847e4d96e3a35490f26367b71b810563b01b03470d000`,`.tmp/rea-todo20-project-detail.json` / `.png`:动态、计划、任务、资产四页签;右侧项目配置含指令、连接器、专家、技能和定时任务。未创建原版任务或修改项目。
- 任务页稳定证据 `ev_beb6214ec8bd412a2fe93beefdead0c4416f37dd4246d964f9c5f65aee240f69`,`.tmp/rea-todo20-project-tasks.json` / `.png`:全部任务、全部来源筛选与任务搜索;底部共用输入区,本地任务及工作空间选择在下方。
- 详情源码 `project-detail-page-DdYKdEkr.js` SHA `a5630ae6ad4e053e8d085a569a67c102c4226a14c7f27a3e62e69601d0f8d2c1`(上述固定详情 Evidence)确认本地 `createConversation(cwd,{projectId,...})`,工作目录和项目 ID 为独立字段。
- YCode `SessionContext` / `SessionMeta` 增加 projectId,贯通 session:create、列表、上下文及更新结果投影;创建时核对真实项目 registry,拒绝不存在项目。保留空间/目录语义,不用 projectId 替换 workspaceId。
- 生产构建与真实窗口回归通过,新增 IPC 创建项目任务及列表重载 projectId 一致、无效项目 ID 被拒绝,报告 `.tmp/project-page-SKUgRA/report.json`。仅完成任务归属数据通路;详情 UI、项目任务发消息、指令/能力进入内核仍未完成。
### 项目指令请求接线
- 每轮 chat:send 根据 session.projectId 读取真实项目,`buildProjectPrompt` 将项目名称和完整指令附加到现有 promptText;OMP 与备用通路共用该请求文本。市场能力引用不会被当成执行指令或声称已加载。此为 YCode 宿主适配,尚未证明与 WorkBuddy 内核注入方式等价。
- session:update-context 拒绝改变现有项目归属,目录/模型等更新保留 projectId。缺失项目在发送前报错。
- `verify-project-storage.cjs` 增加按ID读取/缺失项目、空指令及完整指令构造断言,通过。
- `test:conversation-ipc` 新增项目→任务→chat:send→OMP adapter prompt 回归,确认 PROJECT-CONTEXT 指令抵达受控内核替身、用户消息正文仍保持原文、跨项目改归属拒绝。全套回归通过;没有发送真实远程模型请求,不能据此声称真实模型遵循指令或完整内核等价。
### 项目配置更新通路
- `ProjectRepository.update` 与 projects:update IPC/preload 接通名称、指令、模板及能力引用的部分更新;串行读改写、完整输入校验、拒绝未知字段和不存在项目,保留 projectId、transport、createdAt。
- 存储回归验证并发改名/改指令合并、重新实例化后恢复、能力保留、非法更新不落盘。对话 IPC 回归新增更新指令后的下一轮请求,确认实际 OMP 适配器提示包含 UPDATED-PROJECT-CONTEXT。两套回归均通过。
- 项目指令编辑 UI 的下一步集成见下节;详情任务页、配置其他字段与原版像素不属于上述 repository 回归覆盖范围。
### 项目指令编辑入口
- `ProjectInstructionDrawer.tsx` 复用已从 REA 恢复的项目指令抽屉结构:800×560、说明、textarea、字符计数、取消/保存。打开入口暂放在项目卡片更多位置,保存调用正式 `projects.update`,成功刷新列表记录,失败保留输入并显示错误。
- 主进程统一限制 instructions 不超过 10,000 字符。`npm run typecheck` 通过;本轮未运行真实窗口交互回归,编辑保存 UI 及深浅色像素仍待验收。
## 原版运行态
- WorkBuddy 5.8.3 / Electron 37.10.3,REA target `7BBA9C2FB14CBDC4404347707DA76722`。
- Escape 关闭发现应用并等待稳定帧:`ev_1fe35225981ea05e20e4b7d6fa99981830ce9b5342045b22c5ca41b17463f1eb`,归档 `.tmp/rea-todo20-project-closed.json` / `.png`。
- 更多菜单打开帧:`ev_d1a438b97437b2f6a98f5dddcc5c3385184e24a439c5a351365fbbefc39e457d`,归档 `.tmp/rea-todo20-more-open.json` / `.png`。可见项目(BETA)、我的邮箱、腾讯文档、ima、乐享知识库、灵感社区。
- 限制:打开及等待步骤成功,最终 neutral-pointer 清理因操作取消失败;不能把整个探针称为成功。布局快照未包含打开后的浮层,截图证明打开态,不能由本快照推导浮层 computed style。
- 可复跑探针:`scripts/rea/probe-todo20-close-discover.json`、`probe-todo20-open-more.json`。
## 已回收源码结论
来源:REA `ev_2b8db4eb73c59a8d3d80c3e37db5ea9b5bf1d13390d5238d81ff2cc53d11dc09`,`.tmp/rea-todo18-main-scripts.json`。
- `contexts-DgzzFjnf.js` 的 SidebarNavigation 使用 `conversation-list-more-dropdown`,右侧起点定位、hover 触发、portal 到 body。点击不是唯一触发方式,YCode 应保留悬停交互。
- `conversation-route-redirect-9iisDdJA.js`(正文 SHA-256 `85ba8228584ffe57a6c1343ea26f6ed98090f9e1099aa578ba745c55c4e04b97`)的 `resolveProjectConversationRoute`:要求 conversationId 和 projectId;cloud transport 返回 `/projects?projectId=…&collabTaskId=…` 且不恢复本地 session;本地 transport 返回 `/task/…` 且需要恢复 session。
- 路由清单引用 `projects-75rC88eE.js`、`project-BAAnDO1E.js`、`use-project-local-chat-config-Bal9cCUM.css`。这里只证明引用存在,不代表已取得模块正文或已观察页面行为。
- 项目具有独立 ID、传输类型与会话关系,不能直接把 YCode 工作空间列表更名来代替项目实现。具体项目创建、配置与删除语义仍待取证。
## 项目详情和任务页补采
- 项目详情稳定运行态:REA `ev_ca0195278ba08b57f2d847e4d96e3a35490f26367b71b810563b01b03470d000`,WorkBuddy 5.8.3。显示「动态 / 计划 / 任务 / 资产」四页签,右侧项目配置含指令、连接器、专家、技能和定时任务;指令抽屉尺寸 800×560、textarea 750×358、计数上限 10,000,保存按钮 76×36。项目指令抽屉组件已按此接入主进程更新接口,类型检查通过,但无窗口保存回归。
- 任务页稳定运行态:REA `ev_beb6214ec8bd412a2fe93beefdead0c4416f37dd4246d964f9c5f65aee240f69`,完整 DOM/样式补采 `ev_8782905c492acd1618e137480a3da8a8d7eba56e8f328e4856b008e1dd7f34ea`。任务页 bounds `[289.28,142,721.70,572]`;toolbar 48px,两个 94×32 筛选按钮、任务私密提示、240×32 搜索框;任务行 691.70×57,前导图标、标题/状态点、协作者头像组、相对时间和 24px 更多入口;输入区约 172px 固定在内容底部。证据截图 `.tmp/rea-todo20-project-tasks-full.png`。
- `scripts/rea/recover-project-detail-styles.cjs` 根据 REA 样式正文 SHA 恢复372条作用域规则到 `source-project-detail-recovered.css`。
- YCode 新增详情页:四页签外观、任务过滤与本地标题搜索、按 `projectId` 筛选真实会话、项目任务输入区、项目配置栏与指令编辑;创建会话时校验项目归属并使用项目工作空间,发送走现有聊天通路。项目归属及项目指令进入受控 OMP 请求已有 IPC 回归。
- 当前差异:动态、计划、资产为未接数据占位;筛选状态选项尚未与运行/终态数据打通;成员邀请、协作者头像、卡片更多菜单和项目完整配置选择尚未实现。项目详情真实窗口全状态、任务输入框几何及项目路径系统性回归本轮未执行,不能标为1:1。
## 下一步与当前限制
1. 恢复 WorkBuddy 调试运行态后,通过 REA 重新采集更多菜单稳定布局,进入项目列表。
2. 回收项目页面及关联配置模块,确认项目、空间、本地目录、任务的数据关系及管理操作。
3. 再确定 YCode 持久化契约、页面实现与真实窗口验收。
本轮后续 REA 复采返回 `provider_unavailable / endpoint_unreachable`;同时 `Get-Process WorkBuddy` 未找到进程。失败记录 `.tmp/rea-todo20-more-stable.json`。这不影响已保存证据的使用,也不证明项目页面不可复刻。
## 调试恢复后的补采
- REA lifecycle `ev_86650169a0ebc57f6a06e45c136f957e24e47233f49166ca4730d567fafbc7d7` 启动 PID 111900,端口 9223;REA target list `ev_24e56f79198d0fe7757d6c4ccc53d7da3168fd91aa77a6f372ed8a7dd5fecec6` 确认 WorkBuddy 5.8.3,新 target `41DA5D1989571E35EEB83ADEF03B5B47`。此前端点阻塞已解除。
- 项目导航动作 `ev_64bd69418b96a024c53141f7a26624ed513746a0fa3dadd95643026a95e766b3`:悬停更多 → 等待 → 点击首个 `.conversation-list-more-dropdown .wb-dropdown__item` → 等待,四步成功。
- 独立稳定页采集 `ev_89843a8b67f411d3297b5f3e428830393cd0fe8712603816cf8b7bbe442064d9`:`.tmp/rea-todo20-project-page.json` / `.png`。页面包含项目标题、副标题、新建项目、我的项目、搜索项目与五类模板(产品需求全流程、市场调研与竞品分析、团队知识库、项目交付、Bug 跟踪/测试验收)。本次没有创建或删除原版项目。
- 从上述 REA 证据正文导出 `project-list-page-DpHRTtk8.js`(51964 字符,SHA `2576827ec29d651f1ff1325ccd7f76f4ab62a3466afb8e341f4595f7bd3ef3b0`)和 `use-project-local-chat-config-DqSrAK4B.js`(45898 字符,SHA `e6e153194a543b5cdc52c5cac1f96727571aa2ca9b2ab78bf6c79bc35d05f636`),本地片段保存在 `.tmp/todo20-<模块名>`。未执行回收模块。
- 新建项目弹窗独立稳定证据 `ev_bc0f5546bb714cad4634168969a115be8f34e307bc09f51caf1457f5d3ed61ec`:`.tmp/rea-todo20-new-project-dialog.json` / `.png`。容器 640×560(1336×902 视口),项目名称输入 590×34、计数 0/15,指令 textarea 590×122;模板选择以及连接器、专家、技能三个可选选择区;取消和确定按钮。下一步分析校验、模板与能力关联,再实现本地项目契约。仍未验收整个 TODO 20。
## 本轮系统拆解(2026-10-17,只读核对)
### 口径
- 本轮没有启动 WorkBuddy、没有操作原版运行态、没有读取 WorkBuddy 安装包,也没有直连 CDP。原版事实仅来自项目内已保存的 REA Evidence、其 DOM/CSS/脚本导出和据此生成的静态恢复物。
- YCode 事实来自当前工作树的页面、共享契约、主进程、preload 和专项脚本的只读核对。本轮没有运行 build、Electron 或 UI 验收。
- “原版已观察”只表示固定版本和固定场景下有一条可追溯证据;“原版未知”不能由现有 YCode 行为反推。
- “YCode 已实现”只表示当前代码存在真实数据通路;“已验收”只引用文件中已有的专项结果。二者都不等于完整 1:1。
### 原版事实与证据账本
固定版本为 **WorkBuddy 5.8.3**。本轮复用的主要 Evidence 如下:
| 范围 | Evidence | 已保存证据/用途 | 明确覆盖与限制 |
| --- | --- | --- | --- |
| 更多菜单 | `ev_d1a438b97437b2f6a98f5dddcc5c3385184e24a439c5a351365fbbefc39e457d` | `.tmp/rea-todo20-more-open.json` / `.png` | 观察到菜单打开帧及“项目(BETA)”等入口;最终 neutral-pointer 清理失败,且布局快照不含打开后的完整浮层 computed style。 |
| 项目列表页 | `ev_89843a8b67f411d3297b5f3e428830393cd0fe8712603816cf8b7bbe442064d9` | `.tmp/rea-todo20-project-page.json` / `.png` | 观察到一个稳定列表页;包含项目标题、副标题、新建入口、我的项目、搜索框和五类模板。未覆盖空态、加载失败、搜索无结果、卡片全部操作和响应式。 |
| 新建项目弹窗 | `ev_bc0f5546bb714cad4634168969a115be8f34e307bc09f51caf1457f5d3ed61ec` | `.tmp/rea-todo20-new-project-dialog.json` / `.png` | 观察到 640×560 弹窗、名称、指令、模板、连接器/专家/技能选择区及底部按钮;未逐一操作三个选择器,未验证提交失败、重名和网络/权限错误。 |
| 项目详情 | `ev_ca0195278ba08b57f2d847e4d96e3a35490f26367b71b810563b01b03470d000` | `.tmp/rea-todo20-project-detail.json` / `.png` | 观察到“动态 / 计划 / 任务 / 资产”四页签及右侧配置栏;脚本静态恢复中可确认本地 `createConversation(cwd,{projectId,...})`。未创建原版任务,未操作非任务页签。 |
| 项目任务页 | `ev_beb6214ec8bd412a2fe93beefdead0c4416f37dd4246d964f9c5f65aee240f69` | `.tmp/rea-todo20-project-tasks.json` / `.png` | 观察到全部任务、全部来源、搜索、项目私密提示、任务行和底部输入区。只覆盖当前账号/数据/主题/窗口下的稳定画面,不证明所有筛选、菜单或状态。 |
| 任务页完整 DOM/CSS | `ev_8782905c492acd1618e137480a3da8a8d7eba56e8f328e4856b008e1dd7f34ea` | `.tmp/rea-todo20-project-tasks-full.json` / `.png` 及 `source-project-detail-recovered.css` | 恢复 372 条项目详情作用域规则;只负责已加载样式所覆盖的选择器,不证明未出现状态。 |
| 项目路由/传输源码 | `ev_2b8db4eb73c59a8d3d80c3e37db5ea9b5bf1d13390d5238d81ff2cc53d11dc09` | `.tmp/rea-todo18-main-scripts.json` | 已保存脚本正文中的 `resolveProjectConversationRoute` 表明项目对话路由同时要求 `conversationId` 与 `projectId`;cloud 路由带 `projectId`/`collabTaskId`,local 路由返回本地 task 并恢复 session。只覆盖该路由函数及其调用可见信息。 |
| 项目插图资源 | `ev_d740e73903dd69444105e2509b238e5912f2c93d3adaa183b05ec7221512ef7a` | `.tmp/rea-todo20-project-hero.json` | 仅证明 `landing-hero-B6659kdy.png` 资源字节及 SHA,不单独证明页面运行态可见性。 |
原版页面和交互清单,按“已观察”与“仅源码/静态恢复”分开:
| 区域 | 原版已观察或固定证据可确认 | 当前仍是未知 |
| --- | --- | --- |
| 更多入口 | “项目(BETA)”位于更多菜单;菜单可打开。 | BETA 徽标条件、菜单键盘/Hover 时序、边缘翻转、点击后窗口/路由切换过程。 |
| 项目列表 | 标题、副标题、新建按钮、我的项目、搜索、五类模板。 | 空列表、无搜索结果、加载、错误、重试、卡片 Hover/焦点、卡片更多菜单、排序/分页、项目数量上限。 |
| 新建项目 | 项目名 15 字计数;完整指令;模板;连接器、专家、技能选择;取消/确定。 | 重名策略、空白/超限错误文案、三个选择器完整交互、能力授权失败、模板切换副作用、保存成功/失败反馈。 |
| 项目详情 | 动态、计划、任务、资产四页签;右侧配置可见指令、连接器、专家、技能和定时任务。 | 项目重命名、删除/归档、分享、邀请成员、成员角色与权限、配置各字段编辑流程。 |
| 任务页 | “全部任务/全部来源”筛选、任务搜索、私密提示、任务行、相对时间、协作者头像组、24px 更多入口、底部输入区。 | 每个筛选的真实枚举和语义、任务状态定义、更多菜单动作、任务归属变更、云/本地来源差异、无权限态。 |
| 任务创建 | 静态源码可确认本地任务创建时 `cwd` 与 `projectId` 为独立字段。 | 新任务标题生成、工作目录选择、首个发送前后的状态、失败补偿、项目与空间冲突时的原版反馈。 |
| 动态 | 页签存在。 | 发布留言、评论、成员动态、与我相关、编辑/删除、空/加载/错误和实时刷新。 |
| 计划 | 页签存在。 | 计划对象、状态、负责人、时间、与任务/资产关系、创建和变更流程。 |
| 资产 | 页签存在;任务输入提示可引用资产文件、项目待办或技能。 | 上传/导入/预览/删除、文件来源、项目资料库关系、权限、版本、空态/无数据状态。 |
| 成员与协作 | 任务行可见协作者头像组。 | 邀请、接受、移除、角色、负责人/关注人、可见范围、账号/企业策略和通知。 |
原版数据关系的已证实部分:
- 项目拥有独立 `projectId`,还区分 local/cloud transport;项目关系不能用一个“空间”记录替代。
- 项目任务仍是一条 conversation/task,并同时携带项目归属与工作目录。项目 ID 和 `cwd` 不能合并成同一字段。
- local 项目的任务路由回到本地 task;cloud 项目路由可能使用 `projectId + collabTaskId`。这证明至少存在两条传输语义,尚不能据此列出全部云 API。
- 固定详情与任务页表明项目详情至少聚合项目配置、任务和协作者信息;动态、计划、资产的具体存储关系尚未取得。
### YCode 当前实现真相
页面和入口:
| 能力 | 当前状态 | 代码/验证依据 | 明确边界 |
| --- | --- | --- | --- |
| 侧栏“更多 → 项目” | 真实现 | `ProjectMenu.tsx`;点击进入 `projects` 路由 | 当前只有“项目 BETA”一项;保留 Hover、点击、外部点击、Escape 和 resize 关闭,几何/时序未与原版全状态比较。 |
| 项目列表 | 真实现 | `ProjectListPage.tsx`、`projects:list` | 真实读取 `userData/projects.json`;名称搜索;卡片可在 Enter/Space 打开详情。无专用空列表/无搜索结果态,加载中与实际空数组可能视觉上难区分。 |
| 五类模板 | 真实现为固定恢复配置 | `project-templates.json`;`recover-project-templates.cjs` | 5 个模板的标题、描述、完整中文指令、专家/技能/连接器引用来自固定 Evidence。市场能力只保存引用,不保证本机已安装或可执行。 |
| 新建项目 | 真实现 | `projects:create`、创建弹窗、`ProjectRepository.create` | 真实持久化;名称 trim 后 1–15 个 UTF-16 单元;指令最多 10,000;模板切换会更新指令和能力;当前界面没有显式项目/工作空间选择。 |
| 连接器选择 | 真实现为本地 registry 引用 | MCP `list/save` 与创建弹窗 | 选择并保存真实本地 connector ID;测试使用禁用的 stdio 连接器,证明引用/持久化,不证明项目任务实际启用或调用该连接器。 |
| 专家/技能选择 | 真实现为本地引用 | experts/skills IPC 与创建弹窗 | 当前行内复选列表,不是原版独立选择窗口;模板中的 market 引用标题标注“尚未接入本地执行”,没有能力解析或执行证明。 |
| 项目详情框架 | 真实现 | `ProjectDetailPage.tsx` | 四页签、面包屑、邀请按钮、右栏配置存在;邀请按钮禁用。 |
| 动态页 | 占位 | `ProjectDetailPage.tsx` activity 分支 | 发布留言、与我相关、成员动态按钮均禁用;固定显示“暂无项目动态”。无动态数据、IPC 或云服务。 |
| 计划页 | 占位 | `ProjectDetailPage.tsx` plan 分支 | 固定显示“项目计划尚未配置”;无 plan 类型、存储或交互。 |
| 任务页 | 部分真实现 | `ProjectDetailPage.tsx`、`session:list/create`、`chat:send` | 按 `SessionMeta.projectId` 展示任务,标题搜索可用,任务可打开;状态筛选状态值未参与过滤,来源筛选的 `all` 与 `local` 在当前本地数据上等价。 |
| 任务行 | 部分实现 | `ProjectDetailPage.tsx` | 标题、相对时间、运行中/非运行中点可显示;没有原版协作者头像组和任务行更多菜单。 |
| 项目任务输入 | 部分真实现 | `ProjectDetailPage.tsx`、会话与对话 IPC | 输入会先创建带 `projectId/workspaceId` 的会话,再打开任务并发送首条消息;失败会回显错误。完整输入区能力、准备阶段、取消和真实远端模型尚未专项验收。 |
| 资产页 | 占位 | `ProjectDetailPage.tsx` assets 分支 | 固定显示“项目资产尚未配置”;没有上传、引用、预览或数据模型。 |
| 项目标题/副标题/英雄图 | 部分实现 | 列表页和恢复 CSS/PNG | 页头结构和插图已挂载,已有真实窗口浅/深色、64px topbar 与基础几何回归;没有完成原版同数据整页像素比较。 |
| 项目卡片更多 | 适配占位 | `ProjectListPage.tsx` | 唯一动作是“项目指令”;没有原版卡片完整更多菜单,也不能从该入口改名、删除、归档或分享项目。 |
| 项目指令抽屉 | 真实现,专项验收未闭环 | `ProjectInstructionDrawer.tsx`、`projects:update` | 800×560 结构、10,000 字符限制、取消/保存、错误和保存中状态已接;本轮未运行窗口保存回归,不能把静态结构当成交互完成。 |
| 项目右栏配置 | 部分实现 | `ProjectDetailPage.tsx` | 指令可打开抽屉保存;连接器/专家/技能只显示已有 ID 列表,配置卡无编辑动作;定时任务未渲染。 |
| 成员/协作者 | 未实现 | 邀请按钮禁用;无 member API/type | 没有项目成员、角色、关注人、头像、通知或权限模型。 |
| 项目生命周期 | 未实现 | projects API 只有 list/create/update | 没有项目删除、归档、恢复、重命名 UI、复制、分享或导出;`update` 后端支持改名但未暴露入口。 |
项目详情目前由列表组件内的 `detailProjectId` 状态打开,没有独立 URL、刷新恢复或原版式深链。任务输入区位于四页签共享的详情底部并始终渲染;原版在动态、计划、资产页签是否保留同一输入区、各页签动作是否不同,现有证据尚未确认。
数据与契约:
```text
Space/Workspace 1 ── 0..n Project
Project 1 ── 0..n Task(Session)
Project 1 ── 0..n CapabilityRef(connector | expert | skill)
Task 1 ── 0..n Message
Task n ── 1 Workspace/CWD
```
建议的目标关系如下,表内除已证实项目/任务关系外均为设计建议,不是从原版运行态推得的事实:
| 实体 | 建议关系 | 当前状态/未知 |
| --- | --- | --- |
| 成员 Member | User n ── n Project,成员可拥有 owner/admin/member 等角色 | 原版有协作者头像迹象,角色与权限未知;YCode 未建模。 |
| 动态 Activity | Activity n ── 1 Project,可关联 Task/User/Asset | 页签存在但不清楚事件种类和存储;YCode 为占位。 |
| 计划 Plan | Plan n ── 1 Project,是否关联 Task/Asset/时间轴待证 | 页签存在但对象语义未知;YCode 为占位。 |
| 资产 Asset | Asset n ── 1 Project,可被 Task/Message/Plan 引用 | 原版输入提示出现“资产文件”,具体实体和引用关系未知;YCode 未建模。 |
| 配置 Config | 1 Project ── 1 ProjectConfig,含指令与连接器/专家/技能引用 | YCode 已保存指令和三类能力引用;原版配置接口和权限限制未知。 |
| 定时任务 | ProjectConfig 1 ── 0..n Schedule 或独立服务记录 | 原版右栏出现入口;YCode 未建模,不能与普通项目任务混为一类。 |
- `ProjectRecord` 当前字段:`projectId`、`transport:'local'`、可选 `workspaceId`、`name`、`instructions`、可选 `templateId`、`experts[]`、`skills[]`、`connectors[]`、`createdAt`、`updatedAt`。
- 项目创建时缺省采用当前选中的 workspace;主进程先解析真实 workspace root,再写入项目。项目一旦创建,`projects:update` 不允许更新 `workspaceId`。
- 项目任务通过 `SessionMeta.projectId` 和 `SessionRecord.projectId` 关联项目;同时保存 `workspaceId` 与 `cwd`。项目任务创建会拒绝不存在的 `projectId`,也会拒绝项目 workspace 与传入 workspace 不一致的组合。
- 项目任务不能通过 `session:update-context` 改到另一项目;跨项目必须新建任务。切换 workspace/cwd 也沿用“新建任务”约束。
- 项目指令通过 `buildProjectPrompt()` 进入每轮用户消息的 `capabilityContext/promptContext`,名称为“项目 X”加完整指令。该项目上下文会被冻结进消息,后续历史重建可复用。当前只注入指令,不自动加载项目的专家、技能或连接器。
- 项目配置把连接器、专家、技能作为引用保存;local/market 来源不同,但当前没有统一的“项目能力运行时”把这些引用转换成真实工具或专家激活。
- 成员、动态、计划、资产、项目级定时任务目前都没有 YCode 数据类型、持久化容器或 IPC。
已有验证事实:
- `scripts/verify-project-storage.cjs`:验证串行并发创建、重载、原子写、ID、名称/指令校验、能力引用、更新合并、非法更新不落盘和损坏文件不被覆盖。它验证 repository 纯存储,不验证页面。
- `scripts/verify-project-page.cjs`:历史上在隔离 Electron 中验证侧栏进入、五模板、创建、真实 connector 选择/移除/重选、磁盘落盘、项目任务 `projectId`、重载恢复、基础几何、深色和模板切换;没有覆盖详情四页签、任务发送、筛选、成员、动态、计划、资产或指令抽屉保存。
- `test:conversation-ipc` 已历史覆盖项目→任务→`chat:send` 的项目指令到达受控 OMP adapter,以及跨项目改归属拒绝。它不是远端模型遵循指令的验收。
- 本轮按要求没有重跑上述脚本;这些是已有工件和代码路径事实。
### 云端与外部依赖
| 依赖面 | 为什么需要单独建模 | 当前可做范围 | 未实现前不得声称 |
| --- | --- | --- | --- |
| 成员、邀请、角色与权限 | 原版任务行已显示协作者头像组,路由存在 cloud transport;固定证据尚未给出权限矩阵。 | 本地 owner-only 项目的明确只读/禁用态。 | 多人协作、共享可见、负责人/关注人、企业策略。 |
| 动态流 | 原版有不依赖固定数量的动态/成员动态入口;存储和服务语义未观察。 | 本地占位或明确空态。 | 评论、提及、实时更新、通知。 |
| 云端计划与资产 | 页签存在,但无法从固定画面证明它们是本地文件、云文档还是项目服务对象。 | 本地 plan/asset 自有 schema,或继续明确占位。 | 上传、预览、版本、权限和跨端同步。 |
| 市场模板能力 | 模板中的 experts/skills/connectors 多带平台 ID 和远程图标;当前设备未必安装。 | 保存引用、按本地 registry 过滤 connector、显著标记不可执行引用。 | 模板创建后所有能力自动可用。 |
| 云项目与 `collabTaskId` | `resolveProjectConversationRoute` 明确存在 cloud 分支。 | 以 local transport 实现清楚的项目/任务关系。 | 本地 `/task` 路由等价于 cloud project route。 |
| 项目定时任务 | 原版右栏配置可见定时任务,但项目级任务模型未采集。 | 先作为未知项,或接 YCode 自有 automations 后另证。 | 已实现项目自动化。 |
### 未知项与下一轮 REA 取证要求
以下均为原版未知,需要协调者统一通过 REA 操作原版运行态补采;本轮明确不操作:
1. **项目生命周期**:非常规命名、重名、15 字边界、删除/归档/恢复/分享、运行中任务存在时的限制与确认框。
2. **列表全状态**:空项目、搜索无结果、加载、失败/重试、卡片 Hover/Focus/更多菜单、排序与长列表。
3. **新建弹窗全交互**:模板切换前后、三个能力选择器、选择后芯片、取消/返回、保存成功与各类失败。
4. **详情与配置**:页签切换、指令/连接器/专家/技能/定时任务配置、保存/取消/失败、项目重命名、邀请按钮。
5. **任务筛选与行**:两个下拉的完整枚举、筛选组合、任务搜索无结果、运行/完成/失败、协作者头像、任务更多菜单和私密提示。
6. **项目输入区**:首条任务创建前后的占位/加载/错误、工作空间选择、附件/资产/技能/项目待办引用、发送与取消。
7. **动态**:发布、评论、筛选、成员动态、与我相关、空/错误/滚动加载、实时更新。
8. **计划**:对象字段、状态、负责人、时间、与任务/资产关系、创建/编辑/删除和空态。
9. **资产**:来源、上传、预览、引用、版本、删除、权限、失败和空态。
10. **成员与权限**:邀请方式、成员列表、角色、移除、owner/admin/member 能力、企业限制和通知。
11. **云/本地传输**:项目 route 参数、cloud project 列表/详情/任务/成员 API、本地项目同步边界、`collabTaskId` 生命周期。
12. **视觉全状态**:浅/深色、1336×902 以及窄/矮窗口、Hover/Focus/Disabled、菜单/弹窗 collision、图片和字体、动效时序。
每组证据至少应包含:固定版本、Evidence ID、输入和前置数据、观察窗口、DOM/layout、可见截图、交互步骤、失败/未知状态。只有截图而没有可操作流程,不足以验收交互;只有源码分支而没有运行态,不足以判定状态外观。
### 推荐任务分批与验收
以下编号和分批是本轮的设计建议,不是原版事实。
| 批次 | 目标 | 主要交付 | 验收门槛 |
| --- | --- | --- | --- |
| P0 契约冻结 | 先消除空间、项目、任务、成员和能力的歧义 | 完整 `ProjectRecord` schema;get/update/delete/archive 契约;成员/活动/计划/资产是明确本地 schema 还是云占位;迁移与损坏恢复 | 单元回归覆盖一对一/一对多关系、不可跨项目改任务、删除/归档不误删任务与目录;新字段有兼容迁移;不与 workspace 混用。 |
| P1 列表与创建 1:1 | 完成“更多→项目→列表→新建”主链 | 空/加载/失败/无搜索结果;卡片操作;新建弹窗和能力选择;模板切换;浅深色和响应式 | 真实 Electron 逐状态覆盖;同一 REA 输入下截图像素与几何有报告;键盘、Escape、外部点击和焦点闭环。 |
| P2 详情骨架 | 四页签、右栏、响应式、配置入口 | 项目 breadcrumb;页签状态;右栏所有配置卡;指令抽屉保存;标题/邀请按钮状态 | 真实窗口覆盖四页签切换、指令保存/取消/失败、深色和窄窗口;未实现配置不能伪装可点击。 |
| P3 项目任务 | 项目内任务真实闭环 | 状态/来源筛选;搜索;运行/完成状态;协作者;行更多菜单;打开任务;输入区创建并发送 | 新建任务携带正确 project/workspace/cwd;项目指令进入模型请求;筛选跨刷新稳定;停止/失败/重载不串项目;至少一条受控模型端到端。 |
| P4 成员与动态 | 协作主链 | 成员查询/邀请/接受/角色;动态发布、评论、筛选与通知策略 | 本地 owner-only 与云可用态清楚;权限拒绝有明确 UI;成员操作不破坏任务归属;若云服务不可接,必须保留可验证禁用态而非 mock 成功。 |
| P5 计划与资产 | 补齐两个数据页 | plan/asset schema、列表、详情、创建/删除、任务引用 | 计划与任务、资产与任务/消息的引用可追踪;权限、空态、失败、重载、跨项目隔离通过。 |
| P6 传输与云适配 | 分离 local/cloud transport | local repository adapter;cloud adapter/gateway 接口;route 解析和迁移 | same-project、cross-project、cloud task ID、断网/401/403/超时、重试和回滚均有契约测试;不能把 cloud mock 记为真实云验收。 |
| P7 全状态视觉验收 | 最终 1:1 收口 | 所有固定状态和过渡状态截图、几何、样式、键盘、动效 | 每项有 REA Evidence 对照;0 容差优先;任何容差、mask 和动态排除都逐项说明;所有专项与相关回归通过后再勾选 TODO 20。 |
建议先做 P0 和 P1;P2/P3 可并行但共享项目详情契约;P4–P6 需要先决定自建本地能力还是等待原版云接口证据。若继续按“云端暂不管”,P4 的成员/动态和 P6 的 cloud adapter 应明确停留在只读禁用或占位,并不得勾选模块完成。
### 本轮核对命令与限制
只读核对命令包括:
```powershell
Get-Content -LiteralPath 'docs\项目模块拆解-2026-10-17.md' -Raw
Get-Content -LiteralPath 'src\shared\projects.ts' -Raw
Get-Content -LiteralPath 'src\main\projects.ts' -Raw
Get-Content -LiteralPath 'src\renderer\src\projects\ProjectListPage.tsx' -Raw
Get-Content -LiteralPath 'src\renderer\src\projects\ProjectDetailPage.tsx' -Raw
Get-Content -LiteralPath 'scripts\verify-project-storage.cjs' -Raw
Get-Content -LiteralPath 'scripts\verify-project-page.cjs' -Raw
```
并对 `.tmp/rea-todo20-project-page.json`、`new-project-dialog.json`、`project-detail.json`、`project-tasks-full.json` 的顶层 Evidence、覆盖率、限制和页面节点做只读解析;未执行其中脚本。
限制:
- 没有新的 WorkBuddy 运行态证据,不能把“未观察到”填成“原版没有”。
- 没有执行 build、Electron、UI 专项或代码修改;当前测试结论只引用历史工件。
- 现有固定页面证据主要覆盖一个当前账号、一种数据状态和有限窗口/主题,无法证明所有用户、企业策略、空态、错误态和响应式。
- 动态、计划、资产和成员的具体服务端语义仍未知;本文列出的数据关系和分批方案是工程建议。