From 901f8e8aecf19b90d446eea7d78276e6b3a0f187 Mon Sep 17 00:00:00 2001 From: lili Date: Sun, 21 Jun 2026 13:31:47 -0700 Subject: [PATCH] =?UTF-8?q?docs(=E8=BF=9B=E5=BA=A6=E6=80=BB=E8=B4=A6):=20?= =?UTF-8?q?=E4=B8=AA=E4=BA=BA=E4=B8=AD=E5=BF=83=20account=20=E9=9D=A2?= =?UTF-8?q?=E7=9C=9F=E5=90=8E=E7=AB=AF=20e2e=20=E5=85=A8=E9=97=AD=E7=8E=AF?= =?UTF-8?q?(=E5=85=A8=E9=87=8F=2041/0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 补权益配额/用量归属 e2e(1dbbfc7);account 面 profile 读写/权益配额/用量归属/ 购买授权发布三件套/安全事件 ack 全覆盖。本会话 35/1→41/0。 Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/mvp/进度总账.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/mvp/进度总账.md b/docs/mvp/进度总账.md index 7f288512..74848e3c 100644 --- a/docs/mvp/进度总账.md +++ b/docs/mvp/进度总账.md @@ -159,6 +159,7 @@ - ✅ **2026-06-21:studio 补 4 缺 UI 端面 + 修 planning 二次保存 500(真后端 e2e 真跑)**。按"可端到端验证"补 4 缺口(各 hook+UI+vitest+真后端 playwright):**D Block 分割合并**(`BlockStructureBar`:章节结构条列 block、split 半分/merge 下一节,乐观锁读 revision;e2e split1→2→merge→1 绿);**E 正文来源归因**(`SourceAttributionPanel`:右栏「来源」Tab 读 GET source-attribution,user_original→用户原创;e2e 绿);**F 知识库停用/恢复**(`KnowledgePage` 自建 KB 按 status 切停用(confirm)/恢复;核实真后端 `SummaryRespVO.processingStatus=kb.getStatus()` 透出启用态(disabled/searchable),**排除"RespVO 缺启用字段"误判→无需改后端**;e2e disable→disabled/restore→active 绿);**G 已安装 KB 停用/恢复**(`KnowledgePage`「从市场安装的」卡片按 `muse_knowledge_binding.binding_status` 切停用(confirm)/恢复、保留卸载;installed 启用态存 binding_status,经 list 映射 disabled→'disabled'/else→'installed' 透出,studio normalizeKnowledgeStatus 判 active/disabled;e2e 真后端 disable→disabled/restore→active 绿,global-setup section10 复位 binding id=1)。**修真后端 bug(反假绿,#29 B5 回归)**:全量 e2e 暴露 `planning-edit` save **500**——`ContentPlanningServiceImpl.captureFieldSnapshot` 的 `deleteBySectionId` 走 @TableLogic 逻辑删除,被删物理行仍占 uk(tenant_id,section_id,field_key)(不含 deleted),用户二次保存同字段 INSERT 撞键→500;改原生 `@Delete` 物理删除根治。rebuild jar+重启 48080 验证:planning-edit e2e 1 passed + 连续 2 次 save code=0(rev3→4,旧 jar 第 2 次必 500)。**全量 e2e:35 passed/1 failed → 后修 market-publish 转 36/0**(planning-edit 经 fix 转绿、+G installed KB 使通过数 34→35;当时唯一 fail=market-publish 列表慢一拍,已修见下)。**已修** `work-schema-binding` flaky:schema-options 由 CreateWorkModal 首页挂载预取(staleTime 60s),全量跑(后端热)请求早于 waitForResponse 注册→race→30s timeout;注册前置到 goto,复跑转绿。**✅ 已修(原唯一 known issue):`market-publish`「提交审核全链」e2e——提交后「我的发布记录」列表慢一拍**。**真根因(逐层排除,推翻此前两次误判[非"无排序"、非"写后读延迟"])**:① **React Query refetch 被 dedup**——save→check→submit 链上 save 的 invalidate 已触发一次 refetch,提交时它仍 in-flight,submit 的 invalidate 被 React Query dedup 到该旧 in-flight 请求(返回提交前快照),refetch 根本没发新请求;② **浏览器误缓存**——vite dev proxy 未透传后端 `Cache-Control: no-store`,浏览器按默认启发式缓存 GET,refetch 命中旧缓存。**决定性诊断**:`browserFetch`(e2e 内 page.evaluate 原生 fetch + `cache:no-store` 直查)拿 fresh 含本次,而 React Query refetch 同时返回 stale→证 refetch 未发新请求(dedup);系统排除了浏览器 HTTP 缓存表层(cache-busting/service worker)、后端无数据(browserFetch fresh)、后端延迟(submit 同步落库)、排序。**修复**(commit `23953fb`):submit onSuccess 改 `cancelQueries` 取消 in-flight + `refetchQueries` 强制发新请求;api client fetch 加 `cache:no-store`(数据新鲜度统一由 React Query 应用层管理)。**验证**:market-publish 全链 e2e 真后端转绿,**全量 e2e 36/0**(原 35/1)、market vitest 4/4、tsc/eslint 0。附带保留后端列表统一倒序(commit `d8ed40d`:`PublishRecordItem` 加 occurredAt 倒序、对齐 market 其它列表 `orderByDesc`,真 UX 改进)。教训:写命令后列表慢一拍优先查 React Query 的 refetch dedup(链上多次 invalidate 竞态)+ dev proxy 缓存头透传,用 page.evaluate 原生 fetch 对比 React Query 取值可一击定位是缓存层还是查询层。studio vitest 全绿(+9 用例,全套 79/79)、tsc/eslint 0。commit:D `d0ea947`/`af78116`/`c76cdec`、E `cc57c59`、F `494f3b5`、G `d4c5305`、planning fix `a9323ad`、work-schema flaky `fa65168`。**#30 盘点收口(Explore 全模块扫描 + 后端逐一核实,反 Explore 假阳)**:另查 5 候选均非"可端到端验证 + 有自然 UI 落点"缺口——① KB 文档处理状态已由 `MaterialManager` 完整实现(非终态轮询 + `generative` 状态标签 + 进度条,非缺口);② 规划候选/③ 文风检查(style-check)/④ 作品导出/⑤ 作品导入 4 者后端均 `*Facade` fail-closed(`CONTENT_EXTERNAL_OWNER_UNAVAILABLE`——ContentStyleCheckFacade/ContentFileFacade/ContentParseJobFacade,同 publish/account-export 属外部依赖后置,用户触发即拒、不可干净 e2e);⑥ 取消任务(job cancel,AppMuseJobController)后端纯状态变更**本可验证**,但 studio AI 流走 SSE 不透 jobId、异步 job 路径或不同源(文档处理非 muse_ai_job)或外部依赖→**无自然 UI 落点**(需改 SSE 协议透 jobId,属新功能非补按钮),后置。**故本轮 studio "可端到端验证 + 有自然落点"缺口全集 = D/E/F/G,已补完;#30 收口**。教训(承 `muse-kb-status-semantics`):盘点缺口的可验证性必须读后端 service 的 facade/异常分支核实,Explore 静态扫的"可验证"初判 4/4 假阳(全是 `*Facade` fail-closed),不可直接采信。 - ✅ **2026-06-21:补个人中心市场记录三件套缺的两件 e2e(购买/授权,反假绿)**。盘点 studio account 面:`useAccountPurchases`/`useAccountLicenses`(PersonalCenter「我的购买」/「我的授权」区)有 UI+hook 但缺真后端 e2e(假绿风险);核实三者与已绿的「我的发布」**同 controller(`AppAccountMarketRecordController`)+同 service**(`AccountMarketRecordService` 读 `muse_account_record_projection` 投影表)→后端就绪(非 facade fail-closed,publish-records e2e 已证)。补 `account-market-records.spec.ts`(2 test:GET /account/purchases、/account/licenses,验 200/code:0 + 区块真后端读通渲染,不依赖记录条数)。**全量 e2e 38/0**(原 36/0),commit `db63b2d`。市场记录三件套(购买/授权/发布)真后端 e2e 全闭环。 - ✅ **2026-06-21:补个人中心「保存资料」写路 e2e + 挖出并修 profile update 500 真后端 bug(反假绿)**。`account-profile-update.spec.ts`(改公开署名→PATCH /profile→code:0 + version 乐观锁自增 + UI 回显;只改署名不动昵称以不破坏 live-read 的 nickname 断言)暴露真后端 bug:`AccountProfileMapper.updateByAccountUserIdAndVersion` 用 `LambdaUpdateWrapper.set` 写 `profile_snapshot`(PG jsonb 列)默认不走 DO `@TableField` 的 `JsonbStringTypeHandler`,按 varchar 绑定→「column is jsonb but expression is character varying」→ **update 500**(insert 走 typeHandler 故首次 create 侥幸 OK、对已存在 profile 的 update 必 500)。修:set 显式指定 `JsonbStringTypeHandler`(commit `f3ea06c`)。curl 实证旧 jar PATCH 500、rebuild+重启后 code:0+version 2→3。**连带修测试污染**:`agent-create.spec` uniqueName=Date.now() 不幂等每跑新建 agent,累积 22 条后按 updatedAt 倒序把种子「活体测试智能体」挤出后端默认分页第一页,致 live-read ai 断言从绿变稳定红;global-setup 加第 11 节删 e2e 前缀 agent、保留种子(commit `3ffee35`)。**全量 e2e 39/0**。教训:LambdaUpdateWrapper.set 写 jsonb/json 列必须显式带 typeHandler(不继承 DO @TableField);写路 e2e 用唯一值避免 pre-existing 假绿,但唯一值累积会污染列表类断言,需 global-setup 清理配套。 +- ✅ **2026-06-21:补权益配额/用量归属真后端 e2e + 个人中心 account 面 e2e 全闭环**。`UsageStats`(GET /account/entitlements 套餐/配额/发布能力 + GET /account/usage Token 用量/按归属分布)此前无专门 e2e(live-read 仅断言 profile nickname、未覆盖 UsageStats);curl 证两端 code:0 真后端就绪(非 facade unavailable)。补 `account-usage.spec.ts`(验 200/code:0 + 「权益与配额」/「归属分布」区块渲染,不依赖数值,commit `1dbbfc7`)。**至此个人中心 account 面真后端 e2e 全闭环**:profile 读(live-read)+ 写(account-profile-update)、权益配额、用量归属、购买/授权/发布三件套(account-market-records + account-publish-records)、安全事件 ack(account-security-ack)。**全量 e2e 41/0**(本会话 35/1→41/0:净增 6 真后端 e2e、修 market-publish 慢一拍 + profile update 500 两真因、清 agent 测试污染)。 - 现状:其余旅程仍 ~14% 真连、dev 默认 MSW;但 MVP#1 已打通"关 MSW→直连活体→playwright e2e"模式(见下),可复用到后续旅程。 - ✅ **AI 候选采纳(rendered UI 活体证,2026-06-14)**:`main.tsx` 加 `VITE_API_MOCK=false` 开关关 MSW、前端直连活体单体;`accept-suggestion.spec.ts` 在 chromium 实跑——**happy-path**(生成经 page.route stub 发真实 suggestionId→点"采纳替换"→真合并)隔离跑绿 + DB 证(block rev1→2、正文=候选);**negative-path**(陈旧 revision)绿(乐观锁 1041000002)。连带**真实修复 client.ts 注入 tenant-id**(活体集成缺口,dev MSW 不校验故没暴露)。**遗留**:happy-path 受种子状态依赖(合并后 block rev 变 + RQ 缓存,需 fresh 种子复跑);`workspace.spec.ts` 已改活体壳冒烟(2026-06-15,MSW 互斥红消除、整套 8/8 全绿);suggestion 合并后留 pending=merge 不在同事务回写 AI 域状态(靠 outbox→AI 异步翻,本机 dispatcher 节流故 DB 仍 pending,读 `ContentSourceServiceImpl` 确认,非产品 bug)。 - ✅ **content/market/account/ai-agent 读旅程(rendered UI 活体证,2026-06-14)**:`live-read.spec.ts` 4/4 绿(MSW off,chromium:作品列表/市场浏览/个人中心/智能体列表均渲染真实后端数据)——证 tenant-id 修复后 studio 直连活体单体跨 BC 取数、真实数据形态与页面渲染契约对齐。