From ac8111155ca169c9e8c7b3534d54faf6f25a0a04 Mon Sep 17 00:00:00 2001 From: mycyg Date: Fri, 17 Jul 2026 11:21:54 +0800 Subject: [PATCH 1/3] =?UTF-8?q?docs(r19):=20=E5=8D=A1=E7=82=B9=E5=A4=8D?= =?UTF-8?q?=E5=AE=A1=E6=8A=A5=E5=91=8A=E2=80=94=E2=80=9445=20=E6=9D=A1?= =?UTF-8?q?=E7=A1=AE=E8=AE=A4=E5=8F=91=E7=8E=B0(9=E7=BB=B4=E5=BA=A6=20work?= =?UTF-8?q?flow+=E5=AF=B9=E6=8A=97=E6=A0=B8=E5=AE=9E+=E8=B4=9F=E8=B4=A3?= =?UTF-8?q?=E4=BA=BA=E7=BB=88=E5=AE=A1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 基线 main 33f52b16。64 原始→57 去重→47 核实确认→负责人终审撤销 2 条误报 (R19-14 托盘角标、R19-17 全局热键,均为 R15 已交付能力),终 45 条: 0 high / 23 medium / 22 low。含修复批次建议 A-H 与撤销记录。 Co-Authored-By: Claude Fable 5 --- .../00-gap-review-2026-07-17.md | 219 ++ r19-iteration-review/findings.json | 1785 +++++++++++++++++ 2 files changed, 2004 insertions(+) create mode 100644 r19-iteration-review/00-gap-review-2026-07-17.md create mode 100644 r19-iteration-review/findings.json diff --git a/r19-iteration-review/00-gap-review-2026-07-17.md b/r19-iteration-review/00-gap-review-2026-07-17.md new file mode 100644 index 00000000..b6c18250 --- /dev/null +++ b/r19-iteration-review/00-gap-review-2026-07-17.md @@ -0,0 +1,219 @@ +# R19 卡点复审报告(2026-07-17,基线 main 33f52b16) + +## ① 执行摘要 + +本轮对 WorkHub 三端(桌面工作台 / web SPA / API+原生壳)做「前端有设计后端没接 / 后端有设计前端没体现 / 应该有但没有」三视角的卡点复审:64 条原始发现经跨维度去重、逐条对抗核实(驳回 10 条捏造/夸大),再经负责人终审撤销 2 条误报(R19-14/R19-17,见文末撤销记录),最终确认 **45 条真发现,无 high,23 medium,22 low**。主线结论:R15-R18 的后端能力大量落地,但**接线缺口集中在两处**——(1)一批治理/协作类后端端点(OKR 创建、预算策略编辑、AI 改动回滚、团队邀请、指派/认领、项目归档)**在任何前端都无入口**,后端算了没人用;(2)R15 主动性管线(追DDL/关怀/找人卡)**投递成功却没有任何端能提示**,桌宠、rail 红点、OS 通知三个呈现端都只吃 `/stream/me` 的 `notification.created`,而主动会话通道刻意不产通知,导致核心的「主动把事顶到用户面前」在最常见场景(有个人空间但没盯着看)下静默落空。此外原生壳缺 `RunEvent::Reopen`、locale 运行时更新、通知点击深链等 macOS 标准行为,以及数据层有 9+ 张建了从不读写的孤儿表。无 high 意味着没有主流程当场撞死或产错数据,但 medium 群里多条是「用户能看见能力却够不到」「同一事实两套自相矛盾的真相」,属会被反复撞到的残缺与误导。 + +| 类别 | medium | low | 小计 | +|---|---|---|---| +| 前端有设计后端没接(fe-no-backend) | 1 | 1 | 2 | +| 后端有设计前端没体现(be-no-frontend) | 4 | 7 | 11 | +| 应该有但没有(missing) | 7 | 6 | 13 | +| 数据流与一致性(dataflow) | 8 | 7 | 15 | +| UX 打磨(ux) | 3 | 1 | 4 | +| **合计** | **23** | **22** | **45** | + +--- + +## ② 追踪清单 + +### 2.1 前端有设计后端没接 + +| 编号 | 标题 | severity | 证据 file:line | 现状与缺口 | +|---|---|---|---|---| +| R19-5 | 学到的自动通过策略三端不可撤销 | medium | packages/ui/src/gold-path/route-components.ts:4256 / apps/web/src/browser.ts:1103 | web 撤销按钮 `data-requires-desktop` 直接 preventDefault 指向桌面,桌面 grep 无任何渲染/撤销 permission_policies 的代码,DELETE /api/permissions/:id 成三端够不到的治理死胡同。 | +| R19-33 | 设置里「Cuu 主动性」三档是死控件 | low | apps/desktop-webview/src/spotlight/views/settings.ts:149 / apps/api/src/services/proactive-intents.ts:161 | chip 可点且写库、文案承诺「安静=很少主动开口」,但全库无任何行为消费 `cuu_proactivity`,选安静照样收全量主动打扰,调了等于没调。 | + +### 2.2 后端有设计前端没体现 + +| 编号 | 标题 | severity | 证据 file:line | 现状与缺口 | +|---|---|---|---|---| +| R19-1 | Objectives(OKR)创建+关联端点前端不可达 | medium | apps/api/src/routes/objectives.ts:52,81 / route-components.ts:3571 | POST /objectives 与 /:id/link 带完整校验,但 SDK 无方法、三端零调用者,objective 只被只读展示,用户看得见目标却无从创建或挂链。 | +| R19-2 | AI 预算策略查看+编辑无 UI | medium | apps/api/src/routes/cost.ts:82,89 / packages/api-client/src/client.ts:573 | GET/PUT /cost/policies(admin)做原子策略+审计写,SDK costPolicies/updateCostPolicy 零非测试调用者,管理员无 UI 可设/改上限、告警比、耗尽行为。 | +| R19-3 | 「撤销 AI 文件改动」(revert)无按钮 | medium | apps/api/src/routes/audit.ts:106 / packages/ui/src/replay/render.ts:1 | POST /agent-runs/:id/revert 完整实现文件回滚+审计对账(本地门控),但无 SDK 方法、全端无调用者,replay 只读渲快照,用户能看改动却无法回滚。 | +| R19-4 | 团队邀请生命周期(建/接受/撤销)缺接线 | medium | apps/api/src/routes/auth.ts:535,576 / packages/db/src/repositories/invites.ts:31 | 创建/接受端点与契约就绪、revoke 函数已存在,但三端 grep `invite` 全空、无 SDK 包装,也无撤销路由,文档化的成员 onboarding 路径无法从产品走通。 | +| R19-26 | 设置 VM budgets(8 项上限)无渲染 | low | apps/api/src/pages/settings.ts:62 / route-components.ts:4217 | 后端填 8 项 token/成本上限进 SettingsPageVM.budgets,web/桌面设置组件均不渲,是死负载。 | +| R19-27 | 工作项跨 run 审计时间线端点从不渲染 | low | apps/api/src/routes/audit.ts:80 / apps/api/src/routes/pages.ts:666 | GET /workitems/:id/audit 聚合全 run 快照+审计+manifest_facts,但无 SDK、无调用者,客户端只取 per-run replay。 | +| R19-28 | 合并融合 choose/preview 步骤从不被调用 | low | apps/api/src/routes/proposals.ts:1062 / packages/api-client/src/client.ts:497 | /merge-proposals/:id/choose 支持选/预览候选,两端只直接 apply,SDK chooseMergeProposalCandidate 零调用,无法预览备选融合结果。 | +| R19-29 | 三个冗余死读端点无前端消费 | low | apps/api/src/routes/agent-runs.ts:362 / ai-worklog.ts:25 / proposals.ts:1044 | handoff / ai-worklog·today / list-work-item-proposals 数据已由页面/live VM 交付,专用端点+SDK 桩无调用者,死冗余。 | +| R19-30 | 增量 trace 游标(?after=)前端从不传 | low | apps/api/src/routes/agent-runs.ts:331 / packages/ui/src/agent-run/render.ts:125 | trace 端点支持游标增量,前端一律从 VM 渲或订 SSE,分页参数未被消费。 | +| R19-31 | 军团后台主动性透明窗口桌面独占且单薄 | low | apps/desktop-webview/src/workbench/army/render.ts:440 / route-components.ts:5346 | 主动性动态只渲 kind/stage/状态、丢弃已取的 workItemId,无正文/跳转/动作;/api/army/background 有端点但 web 无渲染。 | +| R19-32 | web 找人卡渲成标题张冠李戴的只读摘要 | low | route-components.ts:5176 / apps/api/src/services/proactive-find-owner-card-delivery.ts:74 | mirrorActionCardHtml 对所有 action_card 硬套「Cuu 从讨论里拎出 N 件事」标题+无按钮 chip,找人 decide 卡在 web 无 claim/reassign/defer。 | + +### 2.3 应该有但没有 + +| 编号 | 标题 | severity | 证据 file:line | 现状与缺口 | +|---|---|---|---|---| +| R19-15 | web 端无进入个人空间/私聊的导航 | medium | apps/web/src/routes.ts:187 / packages/ui/src/gold-path/product-shell.ts:270 | 个人空间仅桌面 rail 有入口,web 外壳零个人空间/DM/会话导航,只有需已知 id 的只读镜像,web 用户够不到投给自己的主动消息。 | +| R19-16 | 隐藏的主窗无法点 Dock 图标恢复 | medium | client-tauri/src-tauri/src/main.rs:1515,1424 / browser.ts:1235 | 主窗 decorations:false + 关闭即 hide,`.run(generate_context!())` 无 RunEvent 回调,`Reopen` 未处理,点 Dock 图标无反应,只能靠托盘/深链/通知恢复。 | +| R19-18 | 无人发起的「指派/认领工作项」动作 | medium | packages/db/src/repositories/work-items.ts:310 / apps/api/src/routes/workitems.ts:167 | work_item_assignments 生产零 INSERT、claimedByUserId 唯一写口只服务找人卡,POST /workitems 不收 assignee,归属只能靠系统主动发找人卡被动落地。 | +| R19-19 | 项目无关闭/归档/删除 | medium | apps/api/src/routes/projects.ts:35 / packages/db/src/repositories/projects.ts:92 | archived/deletedAt 列全程只被 WHERE 过滤、无写 true 路径,路由仅 GET / + POST /bootstrap,项目收尾无落点、列表无限堆积。 | +| R19-20 | 文件在线预览只支持纯文本 | medium | apps/api/src/services/drive-pages.ts:230 / apps/api/src/routes/drive.ts:390 | 预览闸门只放行文本族 mime,图片/PDF/Office 三个预览端点一律 415「请下载查看」,以文件为核心的产品无法内联审阅设计图/PDF。 | +| R19-21 | 无工作区级审计/操作日志界面 | medium | packages/db/src/repositories/audit.ts:54 / apps/api/src/routes/audit.ts:80 | 审计仓库只有 forEntity/forWorkItem,路由仅 GET /workitems/:id/audit,写审计带 workspaceId 但无汇总读出口,治理审计只能逐工作项翻。 | +| R19-22 | 工作项无人对人评论/讨论区 | medium | packages/db/src/schema/core.ts:937 / apps/api/src/routes/approvals.ts:200 | 通用 comments 表(work_item_id)全库无任何 insert/select 为死表,人对人评论只覆盖审批与网盘文件,核心协作单元缺最基本讨论串。 | +| R19-41 | 桌面缺自动更新/开机自启/崩溃上报 | low | client-tauri/src-tauri/Cargo.toml:11 / tauri.conf.json:62 | 无 updater/autostart/log 插件、无 updater 端点、无 panic hook,错误 eprintln 到 stderr 在 .app 里不可见,常驻主动/SSE 循环无法随 OS 自启。 | +| R19-42 | 外壳声明拥有 local_file_sync 却无实现 | low | client-tauri/src-tauri/src/lib.rs:31 / docs/workhub/00-overview/glossary-dejargon.md:85 | RUST_SHELL_OWNS 列出 local_file_sync,但 spec_watch.rs 不存在、src 无任何 watcher/sync 代码,契约与文档陈旧误导。 | +| R19-43 | 全产品无数据导出(CSV/报表) | low | apps/api/src/routes/cost.ts:139 / apps/api/src/pages/settings.ts:62 | 成本/用量/审计/工作项均无导出端点,预算只读展示,管理员做核算只能截屏抄数。 | +| R19-44 | 通知偏好只有「按类型静音」一个旋钮 | low | apps/api/src/routes/notifications.ts:26 | 偏好 schema 仅 muted_notification_types,无渠道/免打扰时段/按项目粒度,R15 主动推送上线后颗粒度过粗。 | +| R19-45 | 用户只能停用不能恢复 | low | apps/api/src/routes/auth.ts:796 | 只有 deactivate 端点、无 reactivate/restore,停用为不可逆终态,误操作/回归无法撤销。 | +| R19-46 | 项目无成员/访问控制 | low | apps/desktop-webview/src/workbench/settings/render.ts:319 / packages/db/src/schema/core.ts:326 | 无 project_members 表,访问控制只到工作区级+协同参与者级,做不出保密/受限项目、无法从单项目移除某人(属设计取舍但真实缺口)。 | + +### 2.4 数据流与一致性 + +| 编号 | 标题 | severity | 证据 file:line | 现状与缺口 | +|---|---|---|---|---| +| R19-6 | 成本页 by_workitem/trend/by_team 后端填了 web 不渲 | medium | apps/desktop-webview/src/spotlight/views/dashboards.ts:480 / route-components.ts:4107 | 桌面显式把用户导向网页成本页看逐事项花费,web 成本组件无 by_workitem 卡、trend 只渲裸计数、by_team admin 聚合无处渲,跨端承诺断裂+死负载。 | +| R19-7 | 人工协作工作台三张表全孤儿 | medium | packages/db/src/schema/core.ts:646,665,681 | work_item_workspaces/_items/progress_updates 建模齐全带 FK+索引,repositories/contracts/apps 全库零读写、连 relations 都无,被设计从未接线。 | +| R19-8 | 主动 Cuu 消息投递后无任何端提示 | medium | apps/api/src/services/proactive-cuu-delivery.ts:110 / apps/desktop-webview/src/desktop-cuu-runtime.ts:61 | 主动消息只广播 conversation 话题、刻意不产 notification、不发 topics.user,桌宠/rail/OS 三端只吃 /stream/me,截止提醒与关怀被静默塞进用户可能几天不开的空间。 | +| R19-9 | 项目树主区/协同未读只本地+1,重连不补缺 | medium | apps/desktop-webview/src/workbench/shell.ts:784,665 / chat/stream.ts:7 | 权威 unread 只在 selectProject 拉 VM 时到手,meStream 无 onReconnected、broker resume_mode:fresh 不回放,同项目内漂过的通知永久少算(仅 DM 有 30s 兜底)。 | +| R19-10 | 读完会话只推读游标不清 notification 未读 | medium | apps/api/src/routes/conversation-read.ts:42 / apps/desktop-webview/src/browser.ts:1382 | advanceReadCursor 不碰 notifications,而 Dock 角标=approvals+counts.unread,读完会话红点归零但 Dock/通知中心仍虚高,两套自相矛盾的未读真相。 | +| R19-11 | 在线状态两套各自轮询来源 | medium | apps/desktop-webview/src/workbench/chat/view.ts:658 / rail.ts:1047 | 聊天条私有 onlineUserIds(自带 30s+重连刷)从不回写 store,rail/资料卡读 store.onlineUserIds,同一人两处圆点最长差 30s。 | +| R19-12 | OS 通知点击不打开目标页 | medium | client-tauri/src-tauri/src/notify.rs:126 / apps/desktop-webview/src/pet-surface.ts:1545 | 通知只 .show() 无 action/click handler,路由在创建时随事件发出、唯一生产绑定漏传 onSystemNotification,点击紧急审批通知无法深链,主动推送→行动环断头。 | +| R19-13 | 原生壳 locale 启动即冻结 | medium | client-tauri/src-tauri/src/main.rs:1432,1494 / browser.ts:1327 | WorkHubLocale 仅 setup 写一次、无 setter 命令,webview 切语言只写 localStorage+reload 且无 fs 能力,切英文后托盘/通知仍中文且重启后不一致。 | +| R19-34 | spec_docs 表从不写入,current_spec_id 恒空 | low | packages/db/src/schema/core.ts:1123,336 | spec_docs 全仓无 insert/select,work_items.current_spec_id 只被读进 DTO、无写点,契约导出字段恒 absent。 | +| R19-35 | background_jobs 表从不写入,三处 job_id 恒 NULL | low | core.ts:280,391,590 | 建模了持久化异步队列但零操作,knowledge_ask_runs/meeting_records/task_plans 的 job_id 外键只能 NULL,异步流程实际靠各自 status 列自管。 | +| R19-36 | knowledge_ask_runs 表从不落库 | low | core.ts:384 | 建了 question/answer_md/citations/trace 四索引,全仓零读写,知识问答走事件即时计算,用户拿不到问答历史/引用溯源。 | +| R19-37 | 四张遗留 schema 死表 | low | core.ts:914,877,937,238 | deliveries/attachments/comments/user_profiles 仅有 relations 声明,而 db.query.* 关系查询生产零调用,惰性遗留随迁移携带进 PG。 | +| R19-38 | 三个 SSE 事件类型死枚举 | low | packages/contracts/src/enums.ts:187 / packages/events/src/toCuuState.ts:9,20 | usage.recorded 无发布无消费、confidence.scored/sync.progress 被映射为桌宠态但无发布方,桌宠「思考(打分)」「同步文件」动画永不触发。 | +| R19-39 | step.snapshot 被桌面 run-stream 白名单丢弃 | low | packages/agent/src/loop/loop.ts:907 / desktop-cuu-runtime.ts:1401 | loop 发 stepSnapshot,web 全量订阅能收,桌面具名白名单含 stepToolResult 却漏 stepSnapshot,快照落点桌面实时视图收不到、只能事后 replay。 | +| R19-40 | 全新私聊要等 30s 轮询才进左栏 | low | apps/desktop-webview/src/workbench/shell.ts:707 / rail.ts:205 | me 流对未在 dmList 的会话 bumpDmUnread 是空操作、不补拉列表,normal DM 又不出 OS 通知,首条私聊左栏最长 30s 盲区。 | + +### 2.5 UX 打磨 + +| 编号 | 标题 | severity | 证据 file:line | 现状与缺口 | +|---|---|---|---|---| +| R19-23 | 工作台网盘删除无确认/无回执/无回收站 | medium | apps/desktop-webview/src/workbench/drive/view.ts:158 / drive/render.ts:112 | 删除按钮裸写「删除」一点即删、无确认,列表只渲 folders+files 从不渲 deleted_items,restoreDriveItem 虽 Pick 进客户端却全工作台无调用点,删错文件在工作台内无恢复路径(对照 web「移到回收站可恢复」)。 | +| R19-24 | web 移出成员/退群/工作区移出均无二次确认 | medium | apps/web/src/browser.ts:2765,2963 / chat/render.ts:241 | web 点退出/移出直接发 DELETE、自退不可逆还提示「刷新后无法再看到它」,而桌面同操作有两段式确认,护栏在 web 整体丢失。 | +| R19-25 | 工作台网盘行是不可聚焦 div,键盘无法打开/进子文件夹 | medium | drive/render.ts:96 / files/render.ts:102 | 行为无 role/tabindex 的 div、view.ts 无 keydown,文件夹行常无按钮,键盘用户完全够不到进入子目录(同库 Files 面板用真 button,端内不一致)。 | +| R19-47 | 军团 oldest_blocker 后端给了 href,web 渲成不可点灰字 | low | apps/api/src/pages/agent-army.ts:283 / route-components.ts:3576 | 后端填 href:'/attention',web 只渲 label 成 `

` 丢 href,「有子任务卡住等你」成死文本而非可点入口。 | + +--- + +## ③ 高危与中危逐条展开(无 high,以下 23 条为 medium) + +**R19-1 Objectives(OKR)创建+关联端点前端不可达。** POST /api/objectives(带 key_results 校验)与 POST /:id/link(assertCanMutateWorkItem 门控)在 objectives.ts:52/81 完整实现,但 api-client 无对应 SDK 方法、web/desktop/ui 全量 grep 零调用者。用户在军团计划卡和成本页只能看到 objective 标题+进度%的只读标签(route-components.ts:3571/4034),却永远无法创建一个目标或把工作项挂到目标上——OKR 概念被吊在半空。**修法**:在工作项详情面加「创建目标 / 关联目标」表单,配套新增 SDK 方法;若 OKR 尚未打算发布,则删掉只读标签避免吊胃口。 + +**R19-2 AI 预算策略查看+编辑无 UI。** GET/PUT /api/cost/policies(cost.ts:82/89,admin-only,原子策略+审计写)与 SDK costPolicies/updateCostPolicy(client.ts:573)存在且有 smoke 覆盖,但零非测试调用者。成本页只读渲用量、从不暴露可编辑策略对象,管理员无从设/改预算上限、告警比、耗尽行为。**修法**:在 cost/settings 面加 admin 预算策略编辑器(列表+按 scope 编辑表单),接 costPolicies/updateCostPolicy。 + +**R19-3 「撤销 AI 文件改动」(revert)无按钮。** POST /api/agent-runs/:id/revert(audit.ts:106)完整实现文件快照回滚+审计对账+写 snapshot.reverted 条目,本地客户端门控。但无 SDK revertAgentRun、desktop/web/ui/tauri 全端无调用者,replay 只只读渲快照。用户能看见 AI 改了什么却永远无法在产品内回滚。**修法**:在桌面 replay/快照面加「撤销此改动」(须跑本地客户端)+确认步,接该端点。 + +**R19-4 团队邀请生命周期缺接线。** POST /invites(auth.ts:535 铸 token)、POST /invites/accept(:576)、invites 仓库 revoke(:31)与契约 schema 均就绪,但三端 grep `invite` 全空、无 SDK 包装、也无撤销路由。文档化的 token 成员 onboarding 无法从产品走通,管理员既发不出邀请也撤不掉。**修法**:成员管理/设置面加邀请创建动作+可深链的邀请接受落地页,接两个端点,并补撤销路由。 + +**R19-5 学到的自动通过策略三端不可撤销。** web 设置渲每条自动通过策略的「撤销」按钮带 `data-requires-desktop=true`,browser.ts:1103 在此直接 preventDefault 弹「需在桌面端操作」,从不发 DELETE;而 desktop-webview 与 client-tauri 全库 grep 无任何渲染 permission_policies 或调用撤销的代码(仅测试命中),api-client 也无对应方法。用户能创建常驻自动通过规则,却在任何客户端都撤不掉——治理层死胡同。**修法**:在桌面端补策略列表+撤销控件接 DELETE /api/permissions/:id,并给 api-client 加方法;否则 web 的指路文案是在指向不存在的能力。 + +**R19-6 成本页三维度后端填了 web 不渲。** 桌面 spotlight 成本视图渲 by_workitem 前 5 条并打文案「还有 N 个事项的花费,去网页版成本页细看」(dashboards.ts:480),把用户显式导向 web;但 web 成本组件装配段(route-components.ts:4107-4135)与 React props 均无 by_workitem,trend 只渲一个「趋势:N」裸计数,by_team(admin 聚合)在两端都无处渲。用户按提示跳到 /dashboard/cost 找逐事项明细,那里根本没有——断掉的跨端承诺+死负载。**修法**:web 补「按事项花费」卡渲 vm.by_workitem(admin 可见),或把桌面指路改到确实展示该维度的位置。 + +**R19-7 人工协作工作台三张表全孤儿。** work_item_workspaces(phase/progress/status_note/blocked_reason)、_items(todo+sort_order)、_progress_updates(actor/kind/body 活动流)在 core.ts:646/665/681 建模齐全带 FK+索引,但 apps/repositories/contracts 全部零引用、连 relations 都没声明。任何读 schema 做规划的人会以为进度/协作工作台是真的,实际前后端都不存在。**修法**:确认废弃后从 schema+PG 删除,或补 repository/service/UI 真正落地这套协作进度追踪。 + +**R19-8 主动 Cuu 消息投递后无任何端提示。** ddl-chase 对有责任人工作项的 T-1d/逾期两档、以及全部关怀消息,走 conversation_message 通道由 proactive-cuu-delivery 直接落进个人空间主区,并只向该会话话题广播(delivery.ts 头部明说刻意不落 notification、不发 topics.user)。而桌宠 runtime(只订 /stream/me)、rail 红点(只靠 notification.created 本地+1)、OS 通知三端都吃不到会话话题。用户建过个人空间后,「明天就到期了」「已经逾期了」和关怀被静默塞进一个他可能几天不开的空间,桌宠一声不吭;逾期档的 24h 重复叮嘱在会话通道下天然不生效、suppression_key 保证每件只发一次,连补救的重复提醒也没了——追DDL 的核心目的在最常见场景下完全落空。消息已落库、进空间即可见,故非数据丢失,列 medium。**修法**:主动会话投递成功后额外向 topics.user 广播一条轻量「你的空间有新动态」信号(可做成桌宠轻点头/rail 个人空间行红点),或让桌宠/rail 订阅当前用户个人空间会话话题;至少让逾期档保留可感知的重复提醒。 + +**R19-9 项目树主区/协同未读只本地+1,重连不补缺。** 权威 unread_count 只在 selectProject 拉 workbench VM 时到手(shell.ts:784 唯一调用点),停在同项目期间树叶角标只靠 /me 流 notification.created 本地+1,既无周期重拉也不在重连后补缺(meStream 无 onReconnected,broker resume_mode:fresh 不回放)。rail 30s 轮询只 loadDms、只自愈 DM 未读——注释宣称的「会话列表兜底刷新」对主区/协同叶是空头支票。项目 P 里协同会话 B 收消息时你正开着 A → B 叶+1;期间 /me 流抖动重连漏掉若干通知,B 角标永久少算,只有切走再切回才被新 VM 纠正。DM 能自愈、主区/协同不能。**修法**:给 workbench VM 加 30s/重获焦点重拉,或给 meStream 配 onReconnected 走未读聚合补缺口,让主区/协同叶与 DM 同源自愈。 + +**R19-10 读完会话只推读游标不清 notification 未读。** 每条未读会话消息落一条 severity=normal 的 conversation.message 通知(计入 counts.unread),但工作台打开会话读消息只调 PUT /read→advanceReadCursor(推游标+发 read.updated),完全不碰 notifications。而 Dock/托盘角标=approvals+counts.unread(browser.ts:1382)。别人发你几条消息 → Dock+N、通知中心列 N 条;你在工作台读完 → rail 叶红点归零、别人看到你「已读」,但 Dock 仍显示 N、通知中心仍标未读,非得去主窗手动标已读才消。同一批消息两套矛盾的未读真相。**修法**:读游标推进到会话末尾时,服务端按 conversation_id 批量标该用户该会话的通知已读(或从 counts.unread 口径扣除已读会话),让 Dock/通知中心与读游标同源。 + +**R19-11 在线状态两套各自轮询来源。** chat 视图维护私有 onlineUserIds(view.ts:658)由自己的 30s loadPresence 刷+SSE 重连即时补,聊天成员条/DM 头绿点用它;rail 名册/私聊行/资料卡(profile-popover.ts:49)用另一套 store.onlineUserIds 由 rail 独立 30s 写入。两个消费者各打 GET /presence、相位不同,chat 重连后的更鲜活在线态从不回写 store。对方刚上线,DM 里已显在线,左栏那条 DM 行/资料卡还停在离线,最长差 30s(重连后更久)。同一人同一时刻两颗矛盾的在线点。**修法**:统一 presence 单一来源(chat 刷到的也写回 store,或都从 store 读)。 + +**R19-12 OS 通知点击不打开目标页。** Rust SSE worker 用 notifications.builder().show()(notify.rs:126)显示紧急通知,无 action id/click handler;精心算出的目标路由+window_control 只随 sse_worker.rs:235 的 system-notification 事件走,而唯一生产绑定 pet-surface.ts:1545 未传 onSystemNotification(主窗入口根本不绑 runtime),路由被丢到 no-op。点击「Cuu 需要你审批」通知不深链到审批,主窗又隐藏且无 Reopen,什么都不出现,主动推送→行动环断头;且路由只在创建时交付、不在点击时,无法代表用户点击。**修法**:用 tauri-plugin-notification 的 action/permissions 接收点击事件(或把 plan.route 登记为 pending 深链),点击时 show_main_window+导航到 plan.route。 + +**R19-13 原生壳 locale 启动即冻结。** WorkHubLocale mutex 仅 setup 从 config/env 写一次(main.rs:1433),托盘标签+tooltip 据它构建一次,invoke_handler(1494-1514)无 locale setter,current_workhub_locale 永远返回启动值,驱动托盘文字、深链报错、通知 fallback。webview 切语言只写 localStorage+reload(browser.ts:379)且无 fs 能力(capabilities 仅 core:default),到不了壳。切英文后托盘/tooltip/通知仍中文,且两侧持久化方式不同(config JSON vs localStorage),重启后不一致直到手改 config。**修法**:加 set_shell_locale 命令更新 state 并重建/重标托盘菜单+tooltip,webview 切语言时调它(并/或把 locale 写进 workhub-shell-config.json)。 + +**R19-15 web 端无进入个人空间/私聊的导航。** 个人空间(主动消息落点)只有桌面 rail 有创建入口和导航,web 是项目中心式外壳,product-shell/render 完全无个人空间/私聊/会话列表导航,只有需预知会话 id 的 /conversations/:id 只读镜像。桌面建过个人空间、日常用 web 的用户,其追DDL 与关怀被投进 web 无法导航到的空间;会话通道又不产通知(无 targetUrl),web 用户永远看不到。**修法**:web 外壳补「我的空间/主动动态」入口(列出个人空间主区会话、复用 /conversations 镜像)。 + +**R19-16 隐藏的主窗无法点 Dock 图标恢复。** 主窗 decorations:false + 自定义关闭按钮/Cmd+W 都拦成 hide(用户常规隐藏),但 main() 以 `.run(generate_context!())`(main.rs:1515)结束、无 RunEvent 回调,macOS `RunEvent::Reopen`(Dock 图标点击)从不处理。隐藏后点 Dock 图标——最自然的 macOS 恢复方式——毫无反应,只能靠托盘/深链/通知。**修法**:改 `.build(context)?.run(|app, event| …)` 处理 `RunEvent::Reopen` 调 show_main_window(show+set_focus)。 + +**R19-18 无人发起的「指派/认领工作项」动作。** 人类归属只有 work_item_assignments(多角色)与 claimedByUserId(单认领人)两列;前者生产零 INSERT(唯二 insert 在测试),富模型是死列;后者唯一写口 claimOwnerlessWorkItem 只被 R15 找人卡的 decide 调用,action-cards 路由只暴露 /decide 与 /undo,找人卡本身只由主动扫描管线生成,POST /workitems 也不收 assignee。经理落地计划草案时无法「指派给张三」,成员无法从待领池主动认领,只能等系统碰巧发找人卡才谈归属。**修法**:补人发起的 POST /workitems/:id/assign 与 /claim,在工作项详情/看板卡给按钮;或至少允许经理在计划草案 materialize 时为每条选负责人。 + +**R19-19 项目无关闭/归档/删除。** projects 表预留 archived+deletedAt 列,列表/时间线/网盘全在 WHERE 过滤它们(说明设计预期可归档),但生产无任何路径写 true(唯二在测试),路由只有 GET / + POST /bootstrap,仓库写方法只有 bootstrap*/updateInstructions。经理做完项目想归档、或删掉建错的项目,前后端都无从下手,列表只会无限增长(project-home-pages.ts:176 注释自认 archived 分支「暂不可达」)。**修法**:补 POST /projects/:id/archive 与 /delete(软删),项目主页/设置给按钮,列表加已归档分区。 + +**R19-20 文件在线预览只支持纯文本。** 预览闸门 isTextPreview/isDriveTextPreview 只放行 text/*、json/xml/yaml 及 .csv/.md/.txt 等(drive-pages.ts:230),三个预览端点(网盘 drive.ts:390、交付物 workitems.ts:227、提议变更 proposals.ts)同闸门,非文本一律 415「请下载查看」。而系统本身认识 image/png、application/pdf 等 mime(用于下载头),这些文件真实存在于网盘/交付物。以文件为核心、AI 军团产出交付物的产品,经理审阅设计图/PDF、成员看图片交付物都被迫下载再打开。**修法**:至少为 image/* 与 application/pdf 加内联预览,预览端点按 mime 分派 preview_type 而非只 text。 + +**R19-21 无工作区级审计/操作日志界面。** 审计仓库只有 listAuditLogsForEntity 与 listAuditLogsForWorkItem(audit.ts:54/55),无按工作区/用户/时间范围的列表方法,路由只暴露 GET /workitems/:id/audit。而写审计带 workspaceId(谁邀谁、谁改谁角色、谁批哪次合并、谁停用谁都落审计),数据在但无汇总读出口。管理员想纵览治理审计,只能一个工作项一个工作项翻。**修法**:补 listAuditLogsForWorkspace(actor/action/时间范围过滤)+ 管理员审计页(时间倒序展示全工作区关键操作)。 + +**R19-22 工作项无人对人评论/讨论区。** schema 有一张显然为工作项讨论准备的通用 comments 表(work_item_id+author_nickname+body,core.ts:937),但全库无任何 insert/select(comment 读写都在 project_drive_comments 与 approval_comments 两张不同的表)。人对人评论只存在于网盘文件(主要用于触发 AI 起草)与审批。成员领任务后想在任务下问同事一句、留进展备注,除了跟 Cuu 的 AI 会话外没有轻量的任务级讨论串——核心协作单元缺最基本评论区。**修法**:接上 comments 表补 GET/POST /workitems/:id/comments 与工作项详情讨论串,或在契约明确废弃并说明讨论只在会话进行。 + +**R19-23 工作台网盘删除无确认/无回执/无回收站。** 删除按钮渲危险色、文案裸「删除」,点击直接 deleteDriveItem 无确认,成功只静默 load、无「已移到回收站可恢复」回执;列表只筛 folders+files 渲染、从不渲 deleted_items,restoreDriveItem 虽 Pick 进客户端却全工作台无调用点(唯一真实调用在 spotlight)。工作台删错文件既无撤销也找不到恢复。与产品自身矛盾:同栏「版本回滚」反而两段式确认,web 删除按钮直接叫「移到回收站」且提示可恢复,Spotlight 删除 toast 也说「在回收站可恢复」——唯独主力界面工作台把最破坏性的删除做成无确认/无回执/无恢复+误导性「删除」字样。**修法**:工作台删除加确认步+「已移到回收站,可恢复」回执,渲 deleted_items 恢复区接 restoreDriveItem,并改文案与 web 对齐。 + +**R19-24 web 移出成员/退群/工作区移出均无二次确认。** web 会话镜像点「退出」直接 doRemove(selfUserId,true)、点「移出」直接 doRemove(targetId,false),doRemove 二话不说发 DELETE,无确认;自退不可逆还提示「刷新后你将无法再看到它」。/settings 管理员控制台「移出」工作区成员同理点击即 DELETE /api/workspace/members/:id 把人踢出整个工作区,零确认。而桌面对同类操作有两段式确认(chat/render.ts:241「退出这个群?」「把 TA 移出?」)。web 把护栏整体丢了,破坏性操作与桌面不一致。**修法**:web 的退群/移出成员/工作区移出加二次确认对话框,与桌面两段式对齐。 + +**R19-25 工作台网盘行是不可聚焦 div,键盘无法打开/进子文件夹。** 每行渲成 `

`,openAttr 只是 data-wb-drive-open-item/-folder,无 role=button/tabindex,view.ts 只有容器级 click 委托、无行级 keydown。行内版本/下载/删除是真 button 可聚焦,但「打开预览」「进入文件夹」两个主交互挂在不可聚焦 div 上,尤其文件夹行常无任何按钮,键盘用户完全没有可达控件进子目录。同库右栏 Files 面板把每项渲成真 `