Skip to content

R20 wave4: Phase 2 剩余前端呈现五线合流 - #15

Merged
mycyg merged 10 commits into
mainfrom
r20/wave4
Jul 18, 2026
Merged

R20 wave4: Phase 2 剩余前端呈现五线合流#15
mycyg merged 10 commits into
mainfrom
r20/wave4

Conversation

@mycyg

@mycyg mycyg commented Jul 18, 2026

Copy link
Copy Markdown
Owner

内容(SSOT: r19-iteration-review/02-ssot-2026-07-17.md)

五条并行线,各自隔离 worktree 施工,负责人逐单审查 diff + 独立红绿复验后串行合流:

  • P2-06 + R19-15(线A): web 会话镜像订阅会话专属 SSE 窄流(逐流 eventTypes 覆写,不污染 me 流窄化面;去抖全量重渲=服务端 seq 权威;connectedCount>1 重连补拉全量对账),web /projects 补个人空间/私聊导航入口(fail-soft 水合,不新增路由)。
  • P2-05(线B): /settings「已登录设备」区块——typed client 五个既有 client-devices 方法首次接线;撤销走 armConfirmButton 两段式确认;web 会话探测「本机」预期 403 已诚实降级为不标注。
  • R19-6(线C): web 成本页补渲 trend/by_workitem/by_team 三维度(桌面早已指路 web 细看,此前指到空白);non-admin 与空数据不伪装 0,截断有诚实提示。
  • R19-1/R19-2(线D): OKR 创建+挂链工作项落项目主页(目标是工作区级,文案不冒称项目目标;服务端无列表端点,会话内列表+诚实空态);AI 预算策略查看/编辑落 /settings(admin SSR 门控,单字段自动保存,PUT 契约 minProperties:1 支持部分更新,失败回滚+显式报错)。
  • P1-08 收尾(线E): roster 行补 is_admin(db→contracts→route→openapi additive 贯穿),web 审批转交选择器从全局 /api/users 切 roster(分页翻到底,顺手修昵称未 escapeHtml);web 内 /api/users 非头像消费仅剩 routes.ts 会话镜像 loader 一处(已记 wave5)。

验证

  • 每线至少一个「基线红/修复后绿」根因测试,负责人在各 worktree 独立复现红绿。
  • 合流树:pnpm -r test / -r typecheck / lint(release-gate+全部 cuu smoke)本地全绿;rust-i18n smoke cargo test executed 绿。
  • 无新增路由(三处路由计数门未动)、无迁移、无 artifacts 变更。

🤖 Generated with Claude Code

mycyg and others added 10 commits July 18, 2026 15:30
后端 apps/api/src/pages/cost.ts 早给管理员填好了 by_workitem/trend/by_team,
桌面端 costView 也已渲染并把用户指到「网页版成本页细看」——但 web 端
renderCostRouteComponent 从未消费这三个字段(trend 只在顶部露过一个计数
徽章),跨端指路断链。补齐三张卡(按工作项分账/按团队分账/花费趋势),
复用既有 wh-r4-route-row / wh-r4-route-meter 视觉语言;trend 不按 isAdmin
收窄(后端已按用户身份筛过),by_workitem/by_team 与 by_user 同门槛,
非管理员时整卡不渲并在 nonAdminNote 里点名,不伪装成空数据。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
client-devices 后端四端点(register/me/current/revoke)完整但从未被任何前端
调用过。web /settings 个人设置网格新增「已登录设备」卡片:SSR 骨架
(renderSettingsDevicesCard,非 admin 分区)+ browser.ts 客户端水合
(bindSettingsDevicesPanel)拉列表、尽力探测本机(GET /current 需要本地
client-token 头,纯网页会话没有——403 时诚实地不标注,不是 bug)、两段式
确认撤销(复用 P2-08 的 armConfirmButton 范式)、撤销失败人话化提示(不静默
吞错)。判定/格式化纯逻辑拆到 apps/web/src/settings-devices.ts 以便单测
(仓库无 jsdom,browser.ts 的 DOM 拼装胶水不单独测,同既有 drive-actions.ts/
browser-action-notice.ts 先例)。

api-client 五个方法(registerClientDevice/listClientDevices/
currentClientDevice/revokeClientDevice/revokeCurrentClientDevice)此前已
齐全,未做改动。
…gate selector off /api/users

P1-08 收尾:GET /api/workspace/roster 每行补 is_admin(users.is_admin 全局管理员标签,additive,
不动隔离/分页语义),web 审批「转交给同事」选择器改用该端点(分页翻到底)取代此前误用的跨租户
/api/users 全局目录。新增 apps/web/src/workspace-roster.ts 承载可脱离 DOM 单测覆盖的分页取全逻辑。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d personal/DM nav entry

P2-06: web 会话镜像页此前刻意不订会话专属 SSE(G-web 窄化),却由外壳「有新动态会自动刷新」宣称
自动刷新。给 web-runtime 增加逐流 eventTypes 覆写与 refreshOnReconnect,会话镜像路由订阅
/api/push/stream/conversation/:id 窄流(只订 conversation.message.created/.updated/.reaction.updated/
.participants.updated),不污染 me 流的全局订阅面。seq 合并=全量重拉服务端权威(去抖窗口把乱序/重复
事件并成一次幂等拉取);断线重连(第 2 次及以后的 connected)触发一次全量对账,补回重连窗口漏掉的事件
(后端 resume_mode:fresh 不按 Last-Event-ID 重放,此前只靠「下一条事件」兜底,无后续事件即漏)。
把 liveStreamTargetsForRoute 抽到可单测的 live-stream-targets.ts。

R19-15: web 端无个人空间/私聊导航入口(桌面有、后端 GET /api/me/personal-projects 与 /api/dm/list
齐备)。在既有项目页(/projects)客户端水合注入「个人空间 / 私聊」入口——不新增路由、不动 gold-path
键/shellPageOrder,不触三处路由计数门。私聊行链只读会话镜像 /conversations/:id,个人空间行链项目主页
/projects/:id;两来源各自 fail-soft。

根因测试(修复前红/修复后绿):
- packages/web-runtime live-runtime.test.ts:逐流 eventTypes 注册会话监听 + 重连补拉 + 切会话不泄漏。
- apps/web live-stream-targets.test.ts:会话路由产出会话 SSE target(带 eventTypes + refreshOnReconnect)。
- apps/web my-conversations.test.ts:入口渲染个人空间/私聊可达链接 + 诚实空态。
全仓 pnpm -r typecheck 绿。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	apps/web/src/browser.ts
…R19-1/R19-2)

Backend endpoints for objectives (POST /api/objectives, POST /api/objectives/:id/link)
and budget policies (GET/PUT /api/cost/policies) already existed but had no frontend
entry point. This wires both into existing routes without adding new ones:

- Project home page gets an "OKR" card: create-objective form (title + optional
  description + key results) plus a per-created-objective "link work item" picker
  sourced from the page's own open_work_items (no extra request). Objectives are
  workspace-scoped (no project_id column), so copy avoids implying project scoping.
  Session-scoped list only — the server has no endpoint to list existing objectives.
- Settings page gets an admin-only "AI budget policies" card (SSR-omitted entirely
  for non-admins, matching the existing members-section precedent and the server's
  own admin-only 403 gate) with per-field autosave against the existing typed
  costPolicies()/updateCostPolicy() client methods.
- api-client gains createObjective/linkObjective typed methods (additive) plus
  matching request/response contracts in a new packages/contracts/src/domain/objective.ts.

Write failures surface visibly (WorkHubApiError message) in both flows; nothing is
swallowed silently.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mycyg
mycyg merged commit eacd71f into main Jul 18, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant